[haiku-commits] haiku: hrev52120 - src/kits/tracker headers/os/add-ons/tracker

  • From: waddlesplash <waddlesplash@xxxxxxxxx>
  • To: haiku-commits@xxxxxxxxxxxxx
  • Date: Thu, 19 Jul 2018 10:00:52 -0400 (EDT)

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, &params, mimeTypes);
+       EachAddon(AddOneAddon, &params, 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*);
 };
 
 


Other related posts:

  • » [haiku-commits] haiku: hrev52120 - src/kits/tracker headers/os/add-ons/tracker - waddlesplash