hrev52120 adds 1 changeset to branch 'master'
old head: d632c685a0d89a074e7004bb31849fee8d1f871b
new head: bc8427c52293af9ae9ac4f4ec9b3e32fe41aa7e5
overview:
https://git.haiku-os.org/haiku/log/?qt=range&q=bc8427c52293+%5Ed632c685a0d8
----------------------------------------------------------------------------
bc8427c52293: Tracker: Allow add-ons to dynamically extend popup menu.
An add-on may now add custom entries to the popup menu, in order
to provide more than one action.
Change-Id: Ib4726c0c1e70c59e3ba4d752df24b76cfee1c4a4
[ Hrishi Hiraskar <hrishihiraskar@xxxxxxxxx> ]
----------------------------------------------------------------------------
Revision: hrev52120
Commit: bc8427c52293af9ae9ac4f4ec9b3e32fe41aa7e5
URL: https://git.haiku-os.org/haiku/commit/?id=bc8427c52293
Author: Hrishi Hiraskar <hrishihiraskar@xxxxxxxxx>
Date: Fri May 4 18:35:28 2018 UTC
Committer: waddlesplash <waddlesplash@xxxxxxxxx>
Commit-Date: Thu Jul 19 14:00:48 2018 UTC
----------------------------------------------------------------------------
4 files changed, 155 insertions(+), 23 deletions(-)
headers/os/add-ons/tracker/TrackerAddOn.h | 9 +-
headers/os/app/AppDefs.h | 1 +
src/kits/tracker/ContainerWindow.cpp | 161 ++++++++++++++++++++++----
src/kits/tracker/ContainerWindow.h | 7 +-
----------------------------------------------------------------------------
diff --git a/headers/os/add-ons/tracker/TrackerAddOn.h
b/headers/os/add-ons/tracker/TrackerAddOn.h
index f8e18650a0..d1c2ffff6e 100644
--- a/headers/os/add-ons/tracker/TrackerAddOn.h
+++ b/headers/os/add-ons/tracker/TrackerAddOn.h
@@ -7,8 +7,13 @@
struct entry_ref;
class BMessage;
+class BMenu;
+class BHandler;
-extern "C" void process_refs(entry_ref directory, BMessage* refs,
- void* reserved);
+extern "C" {
+ void process_refs(entry_ref directory, BMessage* refs, void* reserved);
+ void populate_menu(BMessage* msg, BMenu* menu, BHandler* handler);
+ void message_received(BMessage* msg);
+}
#endif // _TRACKER_ADDON_H
diff --git a/headers/os/app/AppDefs.h b/headers/os/app/AppDefs.h
index d48c58580a..0533c327cb 100644
--- a/headers/os/app/AppDefs.h
+++ b/headers/os/app/AppDefs.h
@@ -69,6 +69,7 @@ enum {
B_ZOOM = '_WZM',
B_COLORS_UPDATED = '_CLU',
B_FONTS_UPDATED = '_FNU',
+ B_TRACKER_ADDON_MESSAGE = '_TAM',
_APP_MENU_ = '_AMN',
_BROWSER_MENUS_ = '_BRM',
_MENU_EVENT_ = '_MEV',
diff --git a/src/kits/tracker/ContainerWindow.cpp
b/src/kits/tracker/ContainerWindow.cpp
index a95d9d9975..7e7781245e 100644
--- a/src/kits/tracker/ContainerWindow.cpp
+++ b/src/kits/tracker/ContainerWindow.cpp
@@ -178,9 +178,100 @@ CompareLabels(const BMenuItem* item1, const BMenuItem*
item2)
} // namespace BPrivate
+static int32
+AddOnMenuGenerate(const entry_ref* addonRef, BMenu* menu,
+ BContainerWindow* window)
+{
+ BEntry entry(addonRef);
+ BPath path;
+ status_t result = entry.InitCheck();
+ if (result != B_OK)
+ return result;
+
+ result = entry.GetPath(&path);
+ if (result != B_OK)
+ return result;
+
+ image_id addonImage = load_add_on(path.Path());
+ if (addonImage < 0)
+ return addonImage;
+
+ void (*populateMenu)(BMessage*, BMenu*, BHandler*);
+ result = get_image_symbol(addonImage, "populate_menu", 2,
+ (void**)&populateMenu);
+ if (result < 0) {
+ PRINT(("Couldn't find populate_menu\n"));
+ unload_add_on(addonImage);
+ return result;
+ }
+
+ BMessage* message = window->AddOnMessage(B_TRACKER_ADDON_MESSAGE);
+ message->AddRef("addon_ref", addonRef);
+
+ // call add-on code
+ (*populateMenu)(message, menu, window->PoseView());
+
+ unload_add_on(addonImage);
+ return B_OK;
+}
+
+
+static status_t
+RunAddOnMessageThread(BMessage *message, void *)
+{
+ entry_ref addonRef;
+ BEntry entry;
+ BPath path;
+ status_t result = message->FindRef("addon_ref", &addonRef);
+ if (result != B_OK)
+ goto end;
+
+ entry = BEntry(&addonRef);
+ result = entry.InitCheck();
+ if (result != B_OK)
+ goto end;
+
+ result = entry.GetPath(&path);
+ if (result != B_OK)
+ goto end;
+
+ image_id addonImage = load_add_on(path.Path());
+ if (addonImage < 0) {
+ result = addonImage;
+ goto end;
+ }
+ void (*messageReceived)(BMessage*);
+ result = get_image_symbol(addonImage, "message_received", 2,
+ (void**)&messageReceived);
+
+ if (result < 0) {
+ PRINT(("Couldn't find populate_menu\n"));
+ unload_add_on(addonImage);
+ goto end;
+ }
+ // call add-on code
+ (*messageReceived)(message);
+ unload_add_on(addonImage);
+ return B_OK;
+
+end:
+ BString buffer(B_TRANSLATE("Error %error loading add-On %name."));
+ buffer.ReplaceFirst("%error", strerror(result));
+ buffer.ReplaceFirst("%name", addonRef.name);
+
+ BAlert* alert = new BAlert("", buffer.String(), B_TRANSLATE("Cancel"),
+ 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT);
+ alert->SetFlags(alert->Flags() | B_CLOSE_ON_ESCAPE);
+ alert->Go();
+
+ return result;
+}
+
+
static bool
AddOneAddon(const Model* model, const char* name, uint32 shortcut,
- uint32 modifiers, bool primary, void* context)
+ uint32 modifiers, bool primary, void* context,
+ BContainerWindow* window, BMenu* menu)
{
AddOneAddonParams* params = (AddOneAddonParams*)context;
@@ -190,6 +281,9 @@ AddOneAddon(const Model* model, const char* name, uint32
shortcut,
ModelMenuItem* item = new ModelMenuItem(model, name, message,
(char)shortcut, modifiers);
+ const entry_ref* addonRef = model->EntryRef();
+ AddOnMenuGenerate(addonRef, menu, window);
+
if (primary)
params->primaryList->AddItem(item);
else
@@ -1613,6 +1707,12 @@ BContainerWindow::MessageReceived(BMessage* message)
}
break;
+ case B_TRACKER_ADDON_MESSAGE:
+ {
+ _PassMessageToAddOn(message);
+ break;
+ }
+
case B_OBSERVER_NOTICE_CHANGE:
{
int32 observerWhat;
@@ -2981,8 +3081,9 @@ BContainerWindow::AddTrashContextMenus(BMenu* menu)
void
BContainerWindow::EachAddon(bool (*eachAddon)(const Model*, const char*,
- uint32 shortcut, uint32 modifiers, bool primary, void* context),
- void* passThru, BStringList& mimeTypes)
+ uint32 shortcut, uint32 modifiers, bool primary, void* context,
+ BContainerWindow* window, BMenu* menu),
+ void* passThru, BStringList& mimeTypes, BMenu* menu)
{
AutoLock<LockingList<AddonShortcut> > lock(fAddonsList);
if (lock.IsLocked()) {
@@ -3029,7 +3130,7 @@ BContainerWindow::EachAddon(bool (*eachAddon)(const
Model*, const char*,
}
}
((eachAddon)(item->model, item->model->Name(),
item->key,
- item->modifiers, primary, passThru));
+ item->modifiers, primary, passThru, this,
menu));
}
}
}
@@ -3062,22 +3163,22 @@ BContainerWindow::BuildMimeTypeList(BStringList&
mimeTypes)
void
-BContainerWindow::BuildAddOnMenu(BMenu* menu)
+BContainerWindow::BuildAddOnMenu(BMenu* parentMenu)
{
- BMenuItem* item = menu->FindItem(B_TRANSLATE("Add-ons"));
- if (menu->IndexOf(item) == 0) {
+ BMenuItem* item = parentMenu->FindItem(B_TRANSLATE("Add-ons"));
+ if (parentMenu->IndexOf(item) == 0) {
// the folder of the context menu seems to be named "Add-Ons"
// so we just take the last menu item, which is correct if not
// build with debug option
- item = menu->ItemAt(menu->CountItems() - 1);
+ item = parentMenu->ItemAt(parentMenu->CountItems() - 1);
}
if (item == NULL)
return;
BFont font;
- menu->GetFont(&font);
+ parentMenu->GetFont(&font);
- menu = item->Submenu();
+ BMenu* menu = item->Submenu();
if (menu == NULL)
return;
@@ -3102,7 +3203,7 @@ BContainerWindow::BuildAddOnMenu(BMenu* menu)
// build a list of the MIME types of the selected items
- EachAddon(AddOneAddon, ¶ms, mimeTypes);
+ EachAddon(AddOneAddon, ¶ms, mimeTypes, parentMenu);
primaryList.SortItems(CompareLabels);
secondaryList.SortItems(CompareLabels);
@@ -3256,6 +3357,26 @@ BContainerWindow::UpdateMenu(BMenu* menu,
UpdateMenuContext context)
}
+BMessage*
+BContainerWindow::AddOnMessage(int32 what)
+{
+ BMessage* message = new BMessage(what);
+
+ // add selected refs to message
+ BObjectList<BPose>* selectionList = PoseView()->SelectionList();
+
+ int32 index = 0;
+ BPose* pose;
+ while ((pose = selectionList->ItemAt(index++)) != NULL)
+ message->AddRef("refs", pose->TargetModel()->EntryRef());
+
+ message->AddRef("dir_ref", TargetModel()->EntryRef());
+ message->AddMessenger("TrackerViewToken", BMessenger(PoseView()));
+
+ return message;
+}
+
+
void
BContainerWindow::LoadAddOn(BMessage* message)
{
@@ -3276,15 +3397,7 @@ BContainerWindow::LoadAddOn(BMessage* message)
}
// add selected refs to message
- BMessage* refs = new BMessage(B_REFS_RECEIVED);
- BObjectList<BPose>* selectionList = PoseView()->SelectionList();
-
- int32 index = 0;
- BPose* pose;
- while ((pose = selectionList->ItemAt(index++)) != NULL)
- refs->AddRef("refs", pose->TargetModel()->EntryRef());
-
- refs->AddMessenger("TrackerViewToken", BMessenger(PoseView()));
+ BMessage* refs = AddOnMessage(B_REFS_RECEIVED);
LaunchInNewThread("Add-on", B_NORMAL_PRIORITY, &AddOnThread, refs,
addonRef, *TargetModel()->EntryRef());
@@ -3342,6 +3455,14 @@ BContainerWindow::_AddFolderIcon()
}
+void
+BContainerWindow::_PassMessageToAddOn(BMessage* message)
+{
+ LaunchInNewThread("Add-on-Pass-Message", B_NORMAL_PRIORITY,
+ &RunAddOnMessageThread, new BMessage(*message), (void*)NULL);
+}
+
+
BMenuItem*
BContainerWindow::NewAttributeMenuItem(const char* label, const char* name,
int32 type, float width, int32 align, bool editable, bool statField)
diff --git a/src/kits/tracker/ContainerWindow.h
b/src/kits/tracker/ContainerWindow.h
index 39fd9a225f..b556f8e082 100644
--- a/src/kits/tracker/ContainerWindow.h
+++ b/src/kits/tracker/ContainerWindow.h
@@ -189,7 +189,11 @@ public:
// add-on iteration
void EachAddon(bool (*)(const Model*, const char*, uint32 shortcut,
- uint32 modifiers, bool primary, void*), void*, BStringList&);
+ uint32 modifiers, bool primary, void*,
BContainerWindow*, BMenu*),
+ void*, BStringList&, BMenu*);
+
+ BMessage* AddOnMessage(int32);
+ entry_ref GetCurrentDirRef();
BPopUpMenu* ContextMenu();
@@ -342,6 +346,7 @@ private:
void _UpdateSelectionMIMEInfo();
void _AddFolderIcon();
+ void _PassMessageToAddOn(BMessage*);
};