ShowImage: Add "Open with..." menu

Populate a new sub-menu with all applications that support the current
image's MIME type. Launch the chosen app with the image entry_ref as
B_REFS_RECEIVED message.

The sub-menu listing supporting apps is separated into apps supporting
the supertype ("image/" and full support (e.g. "image/png").

Add the new "Open with..." menu to the "File" menu and the context menu
of the image.

Most of the code was grabbed from the FileType prefs PreferredAppMenu,
therefore its copyright was copied and extended.

Change-Id: I0190cf4b78c59e429f4e67654665598340653c5d
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7072
Reviewed-by: Axel Dörfler <axeld@pinc-software.de>
Tested-by: Commit checker robot <no-reply+buildbot@haiku-os.org>
Reviewed-by: waddlesplash <waddlesplash@gmail.com>
This commit is contained in:
Humdinger 2023-10-28 11:57:58 +02:00 committed by waddlesplash
parent e39fc9c4bd
commit 32ed03a521
5 changed files with 166 additions and 0 deletions

View File

@ -21,6 +21,7 @@ Application ShowImage :
ShowImageStatusView.cpp
ShowImageView.cpp
ShowImageWindow.cpp
SupportingAppsMenu.cpp
ToolBarIcons.cpp
: shared be game tracker translation localestub
[ TargetLibstdc++ ] [ TargetLibsupc++ ]

View File

@ -57,6 +57,7 @@
#include "ShowImageConstants.h"
#include "ShowImageStatusView.h"
#include "ShowImageView.h"
#include "SupportingAppsMenu.h"
#include "ToolBarIcons.h"
@ -377,10 +378,22 @@ ShowImageWindow::_BuildViewMenu(BMenu* menu, bool popupMenu)
menu->AddSeparatorItem();
_AddItemMenu(menu, B_TRANSLATE("Use as background" B_UTF8_ELLIPSIS),
MSG_DESKTOP_BACKGROUND, 0, 0, this);
BMenu* openWithMenu = new BMenu(B_TRANSLATE("Open with" B_UTF8_ELLIPSIS));
_UpdateOpenWithMenu(openWithMenu);
BMenuItem* item = new BMenuItem(openWithMenu, NULL);
menu->AddItem(item);
}
}
void
ShowImageWindow::_UpdateOpenWithMenu(BMenu* menu)
{
update_supporting_apps_menu(menu, fMimeType, MSG_OPEN_WITH, this);
}
BMenu*
ShowImageWindow::_BuildRatingMenu()
{
@ -410,8 +423,13 @@ ShowImageWindow::_AddMenus(BMenuBar* bar)
item->SetShortcut('O', 0);
item->SetTarget(be_app);
menu->AddItem(item);
menu->AddSeparatorItem();
fOpenWithMenu = new BMenu(B_TRANSLATE("Open with" B_UTF8_ELLIPSIS));
item = new BMenuItem(fOpenWithMenu, NULL);
menu->AddItem(item);
BMenu* menuSaveAs = new BMenu(B_TRANSLATE("Save as" B_UTF8_ELLIPSIS),
B_ITEMS_IN_COLUMN);
BTranslationUtils::AddTranslationItems(menuSaveAs, B_TRANSLATOR_BITMAP);
@ -675,6 +693,9 @@ ShowImageWindow::MessageReceived(BMessage* message)
// to receive key messages
Show();
}
fMimeType = new BMimeType(message->FindString("mime"));
_UpdateOpenWithMenu(fOpenWithMenu);
_UpdateRatingMenu();
// Set width and height attributes of the currently showed file.
// This should only be a temporary solution.
@ -777,6 +798,17 @@ ShowImageWindow::MessageReceived(BMessage* message)
break;
}
case MSG_OPEN_WITH:
{
BString appSig = "";
message->FindString("signature", &appSig);
entry_ref ref = fNavigator.CurrentRef();
BMessage openMsg(B_REFS_RECEIVED);
openMsg.AddRef("refs", &ref);
be_roster->Launch(appSig.String(), &openMsg);
break;
}
case MSG_SELECTION:
{
// The view sends this message when a selection is

View File

@ -23,6 +23,8 @@ class BMenu;
class BMenuBar;
class BMenuItem;
class BMessageRunner;
class BMessageRunner;
class BMimeType;
class BScrollBar;
class ProgressWindow;
class ShowImageView;
@ -36,6 +38,7 @@ enum {
MSG_UPDATE_STATUS_TEXT = 'mUPT',
MSG_UPDATE_STATUS_ZOOM = 'mUPZ',
MSG_SELECTION = 'mSEL',
MSG_OPEN_WITH = 'mOPW',
MSG_FILE_NEXT = 'mFLN',
MSG_FILE_PREV = 'mFLP',
kMsgDeleteCurrentFile = 'mDcF',
@ -66,6 +69,8 @@ private:
void _AddMenus(BMenuBar* bar);
void _ResizeWindowToImage();
void _BuildViewMenu(BMenu* menu, bool popupMenu);
void _UpdateOpenWithMenu(BMenu* menu);
BMenu* _BuildRatingMenu();
BMenuItem* _AddItemMenu(BMenu* menu, const char* label,
uint32 what, char shortcut, uint32 modifier,
@ -120,6 +125,7 @@ private:
BMenu* fGoToPageMenu;
BMenu* fSlideShowDelayMenu;
BMenu* fRatingMenu;
BMenu* fOpenWithMenu;
BToolBar* fToolBar;
bool fToolBarVisible;
BView* fScrollArea;
@ -136,6 +142,7 @@ private:
PrintOptions fPrintOptions;
BString fImageType;
BMimeType* fMimeType;
BMessageRunner* fSlideShowRunner;
bigtime_t fSlideShowDelay;

View File

@ -0,0 +1,106 @@
/*
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2023, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#include "SupportingAppsMenu.h"
#include <AppFileInfo.h>
#include <Menu.h>
#include <MenuItem.h>
static int
compare_menu_items(const void* _a, const void* _b)
{
BMenuItem* a = *(BMenuItem**)_a;
BMenuItem* b = *(BMenuItem**)_b;
return strcasecmp(a->Label(), b->Label());
}
static BMenuItem*
create_application_item(const char* signature, uint32 what)
{
char name[B_FILE_NAME_LENGTH];
BMessage* message = new BMessage(what);
message->AddString("signature", signature);
BMimeType applicationType(signature);
if (applicationType.GetShortDescription(name) == B_OK)
return new BMenuItem(name, message);
return new BMenuItem(signature, message);
}
// #pragma mark - Public functions
void
update_supporting_apps_menu(BMenu* menu, BMimeType* type, uint32 what, BHandler* target)
{
// clear menu
for (int32 i = menu->CountItems(); i-- > 0;)
delete menu->RemoveItem(i);
// fill it again
BMessage applications;
if (type == NULL || type->GetSupportingApps(&applications) != B_OK)
return;
int32 lastFullSupport;
if (applications.FindInt32("be:sub", &lastFullSupport) != B_OK)
lastFullSupport = -1;
BList subList;
BList superList;
const char* signature;
int32 i = 0;
while (applications.FindString("applications", i, &signature) == B_OK) {
if (!strcasecmp(signature, kApplicationSignature)) {
i++;
continue;
}
BMenuItem* item = create_application_item(signature, what);
item->SetTarget(target);
if (i < lastFullSupport)
subList.AddItem(item);
else
superList.AddItem(item);
i++;
}
// sort lists
subList.SortItems(compare_menu_items);
superList.SortItems(compare_menu_items);
// add lists to the menu
for (int32 i = 0; i < subList.CountItems(); i++)
menu->AddItem((BMenuItem*)subList.ItemAt(i));
// Add type separator
if (superList.CountItems() != 0 && subList.CountItems() != 0)
menu->AddSeparatorItem();
for (int32 i = 0; i < superList.CountItems(); i++)
menu->AddItem((BMenuItem*)superList.ItemAt(i));
for (int32 index = 0; index < menu->CountItems(); index++) {
BMenuItem* item = menu->ItemAt(index);
if (item == NULL)
continue;
if (item->Message() == NULL
|| item->Message()->FindString("signature", &signature) != B_OK)
continue;
}
}

View File

@ -0,0 +1,20 @@
/*
* Copyright 2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
* Copyright 2023, Haiku, Inc.
* Distributed under the terms of the MIT License.
*/
#ifndef SUPPORTING_APPS_MENU_H
#define SUPPORTING_APPS_MENU_H
#include <SupportDefs.h>
class BHandler;
class BMenu;
class BMimeType;
extern const char* kApplicationSignature;
void update_supporting_apps_menu(BMenu* menu, BMimeType* type, uint32 what, BHandler* target);
#endif // SUPPORTING_APPS_MENU_H