#include <Application.h>
#include <Catalog.h>
#include <Directory.h>
#include <FindDirectory.h>
#include <Locale.h>
#include <MenuItem.h>
#include <Message.h>
#include <Mime.h>
#include <NodeInfo.h>
#include <Path.h>
#include <Query.h>
#include <Roster.h>
#include <String.h>
#include <kernel/fs_attr.h>
#include "Attributes.h"
#include "Commands.h"
#include "IconMenuItem.h"
#include "MimeTypes.h"
#include "TemplatesMenu.h"
#undef B_TRANSLATION_CONTEXT
#define B_TRANSLATION_CONTEXT "TemplatesMenu"
namespace BPrivate {
const char* kTemplatesDirectory = "Tracker/Tracker New Templates";
}
TemplatesMenu::TemplatesMenu(const BMessenger& target, const char* label)
:
BMenu(label),
fTarget(target),
fOpenItem(NULL),
fTemplateCount(0)
{
}
TemplatesMenu::~TemplatesMenu()
{
}
void
TemplatesMenu::AttachedToWindow()
{
BuildMenu();
BMenu::AttachedToWindow();
SetTargetForItems(fTarget);
}
status_t
TemplatesMenu::SetTargetForItems(BHandler* target)
{
status_t result = BMenu::SetTargetForItems(target);
if (result != B_OK)
return result;
for (int i = 0; i < CountItems(); i++) {
BMenu* submenu = ItemAt(i)->Submenu();
if (submenu != NULL) {
result = SetTargetForSubmenuItems(submenu, target);
if (result != B_OK)
return result;
}
}
if (fOpenItem)
fOpenItem->SetTarget(be_app_messenger);
return result;
}
status_t
TemplatesMenu::SetTargetForItems(BMessenger messenger)
{
status_t result = BMenu::SetTargetForItems(messenger);
if (result != B_OK)
return result;
for (int i = 0; i < CountItems(); i++) {
BMenu* submenu = ItemAt(i)->Submenu();
if (submenu != NULL) {
result = SetTargetForSubmenuItems(submenu, messenger);
if (result != B_OK)
return result;
}
}
if (fOpenItem)
fOpenItem->SetTarget(be_app_messenger);
return result;
}
bool
TemplatesMenu::BuildMenu(bool addItems)
{
fOpenItem = NULL;
fTemplateCount = CountItems();
while (fTemplateCount--)
delete RemoveItem((int32)0);
IconMenuItem* menuItem = new IconMenuItem(B_TRANSLATE("New folder"),
new BMessage(kNewFolder), B_DIR_MIMETYPE, B_MINI_ICON);
AddItem(menuItem);
menuItem->SetShortcut('N', 0);
AddSeparatorItem();
BPath path;
find_directory (B_USER_SETTINGS_DIRECTORY, &path, true);
path.Append(kTemplatesDirectory);
mkdir(path.Path(), 0777);
fTemplateCount = 0;
fTemplateCount += IterateTemplateDirectory(addItems, &path, this);
BDirectory templatesDir(path.Path());
BMessage* message = new BMessage(B_REFS_RECEIVED);
BEntry entry;
entry_ref dirRef;
if (templatesDir.GetEntry(&entry) == B_OK)
entry.GetRef(&dirRef);
message->AddRef("refs", &dirRef);
fOpenItem = new BMenuItem(B_TRANSLATE("Edit templates" B_UTF8_ELLIPSIS), message);
AddItem(fOpenItem);
if (dirRef == entry_ref())
fOpenItem->SetEnabled(false);
return fTemplateCount > 0;
}
BMenuItem*
TemplatesMenu::NewSubmenuItem(BPath subdirPath)
{
BDirectory templatesDir(subdirPath.Path());
BEntry entry;
entry_ref dirRef;
if (templatesDir.GetEntry(&entry) == B_OK)
entry.GetRef(&dirRef);
BMessage* message = new BMessage(kNewTemplateSubmenu);
message->AddRef("refs", &dirRef);
BMenuItem* submenuItem = new BMenuItem(B_TRANSLATE("Add new submenu" B_UTF8_ELLIPSIS), message);
if (dirRef == entry_ref())
submenuItem->SetEnabled(false);
return submenuItem;
}
void
TemplatesMenu::UpdateMenuState()
{
BuildMenu(false);
}
int
TemplatesMenu::IterateTemplateDirectory(bool addItems, BPath* path, BMenu* menu)
{
fTemplateCount = 0;
if (path == NULL || menu == NULL)
return fTemplateCount;
BEntry entry;
BList subMenus;
BList subDirs;
BList files;
BDirectory templatesDir(path->Path());
while (templatesDir.GetNextEntry(&entry) == B_OK) {
BNode node(&entry);
BNodeInfo nodeInfo(&node);
char fileName[B_FILE_NAME_LENGTH];
entry.GetName(fileName);
if (nodeInfo.InitCheck() == B_OK) {
char mimeType[B_MIME_TYPE_LENGTH];
nodeInfo.GetType(mimeType);
BMimeType mime(mimeType);
if (mime.IsValid()) {
fTemplateCount++;
if (!addItems)
return fTemplateCount;
entry_ref ref;
entry.GetRef(&ref);
BDirectory dir(&entry);
if (dir.InitCheck() == B_OK) {
attr_info attrInfo;
if (node.GetAttrInfo(kAttrTemplateSubMenu, &attrInfo) == B_OK) {
ssize_t size;
bool value;
size = node.ReadAttr(kAttrTemplateSubMenu, B_BOOL_TYPE, 0, &value,
sizeof(bool));
if (size == sizeof(bool) && value == true) {
BPath subdirPath;
if (entry.GetPath(&subdirPath) == B_OK) {
BMenu* subMenu = new BMenu(fileName);
fTemplateCount
+= IterateTemplateDirectory(addItems, &subdirPath, subMenu);
subMenus.AddItem((void*)subMenu);
continue;
}
continue;
}
} else {
BMessage* message = new BMessage(kNewEntryFromTemplate);
message->AddRef("refs_template", &ref);
message->AddString("name", fileName);
subDirs.AddItem(new IconMenuItem(fileName, message, &nodeInfo,
B_MINI_ICON));
continue;
}
}
BMessage* message = new BMessage(kNewEntryFromTemplate);
message->AddRef("refs_template", &ref);
message->AddString("name", fileName);
files.AddItem(new IconMenuItem(fileName, message, &nodeInfo, B_MINI_ICON));
}
}
}
int32 itemCount = subMenus.CountItems();
for (int32 i = 0; i < itemCount; i++)
menu->AddItem((BMenu*)subMenus.ItemAt(i));
if (itemCount > 0)
menu->AddSeparatorItem();
itemCount = subDirs.CountItems();
for (int32 i = 0; i < itemCount; i++)
menu->AddItem((BMenuItem*)subDirs.ItemAt(i));
if (itemCount > 0)
menu->AddSeparatorItem();
itemCount = files.CountItems();
for (int32 i = 0; i < itemCount; i++)
menu->AddItem((BMenuItem*)files.ItemAt(i));
if (itemCount > 0)
menu->AddSeparatorItem();
menu->AddItem(NewSubmenuItem(*path));
return fTemplateCount > 0;
}
status_t
TemplatesMenu::SetTargetForSubmenuItems(BMenu* menu, BMessenger messenger)
{
if (!menu)
return B_ERROR;
status_t result;
result = menu->SetTargetForItems(messenger);
if (result != B_OK)
return result;
for (int i = 0; i < menu->CountItems(); i++) {
BMenu* submenu = menu->ItemAt(i)->Submenu();
if (submenu != NULL) {
result = SetTargetForSubmenuItems(submenu, messenger);
if (result != B_OK)
return result;
}
}
return result;
}
status_t
TemplatesMenu::SetTargetForSubmenuItems(BMenu* menu, BHandler* target)
{
if (!menu || !target)
return B_ERROR;
status_t result;
result = menu->SetTargetForItems(target);
if (result != B_OK)
return result;
for (int i = 0; i < menu->CountItems(); i++) {
BMenu* submenu = menu->ItemAt(i)->Submenu();
if (submenu != NULL) {
result = SetTargetForSubmenuItems(submenu, target);
if (result != B_OK)
return result;
}
}
return result;
}