From e46d9f45b8274b5985362104fbe2451e0cc037a6 Mon Sep 17 00:00:00 2001 From: John Scipione Date: Wed, 4 Sep 2024 13:44:54 -0400 Subject: [PATCH] Tracker: Shortcuts refactor Create TShortcuts class that builds shortcut menu items and updates label, modifiers, enabled status and target. Not every Tracker shortcut is present but ones used multiple times and many others are. Update shortcuts in ContainerWindow, DeskWindow, FilePanelPriv, QueryContainerWindow, VirtualDirectoryWindow and GetInfo HeaderView. There are two versions of the TShortcuts class, one with a window and one without. The without-window version is used in the GetInfo window, everywhere else uses the "smart" window version. This patch is organizational except fixing two small BeOS bugs: * Edit query item is always between Open and Open with... * Repopulate menus when you switch directories in file panels. Enable "Open parent" item in spatial mode as well as navigation mode unless in Root, Desktop (Query or Query template) or volume root if not in "Show disks" mode. Hold down control to override. BContainerWindow updates: * Absorb Set...Item() methods into TShortcuts. Add UpdateMoveToTrashItem() for "Move to Trash"/"Delete" and many more. * Absorb ShowContextMenu() improvements from Disks patch. * Create AddIconSizeMenu() and eliminate duplicate shortcut handling. * Put icon size menu in radio mode and refactor item marking. Replace "New folder" with "New >" menu automatically. Create member vars and convenience methods to facilitate this. Simplifies building menus, adding a "New folder" item will automatically be updated to "New >" if templates are available (except in FilePanel and on the minimal build you'll just get "New folder"). Refactor Arrange by and Attributes menus. Create support methods. Create menu on add, populate on update. Do cleanup of detached menu on Quit(). Refactor SetupOpenWithMenu(). SetupEditQueryItem() got a similar refactor to be added and removed dynamically. Add FSIsQueriesDir() to FSUtils used to detect queries directory for Edit query. * "Edit query" goes between Open and "Open with..." (long story). UpdateMenu() calls Shortcut()->Update() for all known shortcuts. Optimize adding/removing dynamic menus so that they are created and destroyed once and reused again and again. AddFile...(), fFile... and "FileContext" becomes UpdatePose...(), fPose... and "PoseContext". TTracker changes: * Skip Desktop in OpenContainerWindow() we setup pose view earlier. * Move DeskWindow init into DeskWindow constructor and call Init(). DeskWindow changes: * Replace icon size menu with BContainerWindow::AddIconSizeMenu(). * Remove WindowContextMenu(), handle in BContainerWindow instead. BPoseView changes: * Rename kEditItem to kEditName -- better name. Save for Edit someday. * Use BMessenger::SendMessage() instead of PostMessage(), safer. BFilePanel updates: Create the FilePanel menus fresh by overriding the AddMenus() method instead of copying from BContainerWindow and deleting the items it doesn't need. This allows us to omit most of the file panel checks. Add UpdateFileMenu() to update the file menu on RepopulateMenus() and MenusBeginning(). * Create an AddFavoritesMenu() method and use it to add the menu. * Override RepopulateMenus() to update just the File and context menus. * Create Update...Methods() overloading the BContainerWindow versions. * SetTo() becomes SwitchDirectory() Unify OpenParent() so that we can call BPoseView::OpenParent() and it will call the container window or the file panel where appropriate. Remove BPoseView::ParentIsRoot() and make CanOpenParent() work in both cases. This means we don't have to check if you are in a file panel or not when enabling/disabling the "Open parent" item and the Shortcuts class can simply check CanOpenParent(). Call _inherited SwitchDirectory() to RepopulateMenus() on Root, Trash and Volumes in FilePanel. This fixes a 25+ year old BeOS bug by repopulating menus when you switch directories in file panels. Trash, files in Trash and Root will get the appropriate menu options. For example "Delete"/"Restore" instead of "Duplicate"/"Move to Trash". Change-Id: Ic41b148cb6bcf14288cb5588038c13ea12426dc2 Reviewed-on: https://review.haiku-os.org/c/haiku/+/7197 Reviewed-by: John Scipione Tested-by: Commit checker robot --- src/kits/tracker/Commands.h | 2 +- src/kits/tracker/ContainerWindow.cpp | 2172 +++++++++---------- src/kits/tracker/ContainerWindow.h | 89 +- src/kits/tracker/DeskWindow.cpp | 147 +- src/kits/tracker/DeskWindow.h | 1 - src/kits/tracker/FilePanel.cpp | 4 +- src/kits/tracker/FilePanelPriv.cpp | 683 +++--- src/kits/tracker/FilePanelPriv.h | 30 +- src/kits/tracker/Jamfile | 2 + src/kits/tracker/PoseView.cpp | 113 +- src/kits/tracker/PoseView.h | 2 +- src/kits/tracker/QueryContainerWindow.cpp | 28 +- src/kits/tracker/Shortcuts.cpp | 1488 +++++++++++++ src/kits/tracker/Shortcuts.h | 230 ++ src/kits/tracker/Tracker.cpp | 40 +- src/kits/tracker/VirtualDirectoryWindow.cpp | 31 +- src/kits/tracker/infowindow/HeaderView.cpp | 18 +- src/kits/tracker/infowindow/InfoWindow.cpp | 4 +- 18 files changed, 3259 insertions(+), 1825 deletions(-) create mode 100644 src/kits/tracker/Shortcuts.cpp create mode 100644 src/kits/tracker/Shortcuts.h diff --git a/src/kits/tracker/Commands.h b/src/kits/tracker/Commands.h index 120d39f910..10a4d9934e 100644 --- a/src/kits/tracker/Commands.h +++ b/src/kits/tracker/Commands.h @@ -68,7 +68,7 @@ const uint32 kPasteLinksFromClipboard = 'Tplc'; const uint32 kCancelSelectionToClipboard = 'Tesc'; const uint32 kClipboardPosesChanged = 'Tcpc'; -const uint32 kEditItem = 'Tedt'; +const uint32 kEditName = 'Tedt'; const uint32 kEditQuery = 'Qedt'; const uint32 kNewFolder = 'Tnwf'; const uint32 kNewEntryFromTemplate = 'Tnwe'; diff --git a/src/kits/tracker/ContainerWindow.cpp b/src/kits/tracker/ContainerWindow.cpp index c549f2fcd6..5ee876870b 100644 --- a/src/kits/tracker/ContainerWindow.cpp +++ b/src/kits/tracker/ContainerWindow.cpp @@ -88,6 +88,7 @@ All rights reserved. #include "PoseView.h" #include "QueryContainerWindow.h" #include "SelectionWindow.h" +#include "Shortcuts.h" #include "TemplatesMenu.h" #include "Thread.h" #include "TitleView.h" @@ -178,8 +179,7 @@ AddOnMenuGenerate(const entry_ref* addOnRef, BMenu* menu, BContainerWindow* wind return addOnImage; void (*populateMenu)(BMessage*, BMenu*, BHandler*); - result = get_image_symbol(addOnImage, "populate_menu", 2, - (void**)&populateMenu); + result = get_image_symbol(addOnImage, "populate_menu", 2, (void**)&populateMenu); if (result < 0) { PRINT(("Couldn't find populate_menu\n")); unload_add_on(addOnImage); @@ -263,8 +263,7 @@ AddOneAddOn(const Model* model, const char* name, uint32 shortcut, ModelMenuItem* item; try { - item = new ModelMenuItem(model, name, message, - (char)shortcut, modifiers); + item = new ModelMenuItem(model, name, message, (char)shortcut, modifiers); } catch (...) { delete message; return; @@ -385,8 +384,9 @@ BContainerWindow::BContainerWindow(LockingList* list, uint32 openFlags, fBorderedView(NULL), fVScrollBarContainer(NULL), fCountContainer(NULL), + fShortcuts(NULL), fContextMenu(NULL), - fFileContextMenu(NULL), + fPoseContextMenu(NULL), fWindowContextMenu(NULL), fDropContextMenu(NULL), fVolumeContextMenu(NULL), @@ -396,7 +396,9 @@ BContainerWindow::BContainerWindow(LockingList* list, uint32 openFlags, fCopyToItem(NULL), fCreateLinkItem(NULL), fOpenWithItem(NULL), + fEditQueryItem(NULL), fNavigationItem(NULL), + fNewTemplatesItem(NULL), fMenuBar(NULL), fDraggableIcon(NULL), fNavigator(NULL), @@ -404,7 +406,7 @@ BContainerWindow::BContainerWindow(LockingList* list, uint32 openFlags, fAttrMenu(NULL), fWindowMenu(NULL), fFileMenu(NULL), - fArrangeByMenu(NULL), + fArrangeByItem(NULL), fSelectionWindow(NULL), fTaskLoop(NULL), fStateNeedsSaving(false), @@ -480,6 +482,7 @@ BContainerWindow::~BContainerWindow() delete fBackgroundImage; delete fDragMessage; delete fCachedTypesList; + delete fShortcuts; if (fSelectionWindow != NULL && fSelectionWindow->Lock()) fSelectionWindow->Quit(); @@ -539,58 +542,39 @@ BContainerWindow::QuitRequested() void BContainerWindow::Quit() { - // get rid of context menus - if (fNavigationItem) { - BMenu* menu = fNavigationItem->Menu(); - if (menu != NULL) - menu->RemoveItem(fNavigationItem); + // delete detached menus in reverse chronological order + // we're quitting, don't bother setting NULL - delete fNavigationItem; - fNavigationItem = NULL; - } - - if (fOpenWithItem != NULL && fOpenWithItem->Menu() == NULL) { - delete fOpenWithItem; - fOpenWithItem = NULL; - } - - if (fMoveToItem != NULL && fMoveToItem->Menu() == NULL) { - delete fMoveToItem; - fMoveToItem = NULL; - } - - if (fCopyToItem != NULL && fCopyToItem->Menu() == NULL) { - delete fCopyToItem; - fCopyToItem = NULL; - } - - if (fCreateLinkItem != NULL && fCreateLinkItem->Menu() == NULL) { + if (fCreateLinkItem != NULL && fCreateLinkItem->Menu() == NULL) delete fCreateLinkItem; - fCreateLinkItem = NULL; - } + if (fCopyToItem != NULL && fCopyToItem->Menu() == NULL) + delete fCopyToItem; + if (fMoveToItem != NULL && fMoveToItem->Menu() == NULL) + delete fMoveToItem; - if (fAttrMenu != NULL && fAttrMenu->Supermenu() == NULL) { + if (fOpenWithItem != NULL && fOpenWithItem->Menu() == NULL) + delete fOpenWithItem; + if (fEditQueryItem != NULL && fEditQueryItem->Menu() == NULL) + delete fEditQueryItem; + + if (fNewTemplatesItem != NULL && fNewTemplatesItem->Menu() == NULL) + delete fNewTemplatesItem; + + if (fNavigationItem != NULL && fNavigationItem->Menu() == NULL) + delete fNavigationItem; + + if (fAttrMenu != NULL && fAttrMenu->Supermenu() == NULL) delete fAttrMenu; - fAttrMenu = NULL; - } - delete fFileContextMenu; - fFileContextMenu = NULL; + if (fArrangeByItem != NULL && fArrangeByItem->Menu() == NULL) + delete fArrangeByItem; + delete fPoseContextMenu; delete fWindowContextMenu; - fWindowContextMenu = NULL; - delete fDropContextMenu; - fDropContextMenu = NULL; - delete fVolumeContextMenu; - fVolumeContextMenu = NULL; - delete fDragContextMenu; - fDragContextMenu = NULL; - delete fTrashContextMenu; - fTrashContextMenu = NULL; int32 windowCount = 0; @@ -646,93 +630,89 @@ void BContainerWindow::AddContextMenus() { // create context sensitive menus - fFileContextMenu = new BPopUpMenu("FileContext", false, false); - AddFileContextMenus(fFileContextMenu); + fPoseContextMenu = new BPopUpMenu("PoseContext", false, false); + AddPoseContextMenu(fPoseContextMenu); fVolumeContextMenu = new BPopUpMenu("VolumeContext", false, false); - AddVolumeContextMenus(fVolumeContextMenu); + AddVolumeContextMenu(fVolumeContextMenu); fWindowContextMenu = new BPopUpMenu("WindowContext", false, false); - AddWindowContextMenus(fWindowContextMenu); + AddWindowContextMenu(fWindowContextMenu); fDropContextMenu = new BPopUpMenu("DropContext", false, false); - AddDropContextMenus(fDropContextMenu); + AddDropContextMenu(fDropContextMenu); fDragContextMenu = new BPopUpNavMenu("DragContext"); // will get added and built dynamically in ShowContextMenu fTrashContextMenu = new BPopUpMenu("TrashContext", false, false); - AddTrashContextMenus(fTrashContextMenu); + AddTrashContextMenu(fTrashContextMenu); +} + + +void +BContainerWindow::DetachSubmenus() +{ + // detach menus in reverse chronological order + if (fCreateLinkItem != NULL && fCreateLinkItem->Menu() != NULL) + fCreateLinkItem->Menu()->RemoveItem(fCreateLinkItem); + if (fCopyToItem != NULL && fCopyToItem->Menu() != NULL) + fCopyToItem->Menu()->RemoveItem(fCopyToItem); + if (fMoveToItem != NULL && fMoveToItem->Menu() != NULL) + fMoveToItem->Menu()->RemoveItem(fMoveToItem); + + if (fOpenWithItem != NULL && fOpenWithItem->Menu() != NULL) + fOpenWithItem->Menu()->RemoveItem(fOpenWithItem); + if (fEditQueryItem != NULL && fEditQueryItem->Menu() != NULL) + fEditQueryItem->Menu()->RemoveItem(fEditQueryItem); + + if (fNewTemplatesItem != NULL && fNewTemplatesItem->Menu() != NULL) + fNewTemplatesItem->Menu()->RemoveItem(fNewTemplatesItem); + + if (fNavigationItem != NULL && fNavigationItem->Menu() != NULL) { + // delete separator first + delete fNavigationItem->Menu()->RemoveItem( + fNavigationItem->Menu()->IndexOf(fNavigationItem) + 1); + fNavigationItem->Menu()->RemoveItem(fNavigationItem); + } } void BContainerWindow::RepopulateMenus() { - // Avoid these menus to be destroyed: - if (fMoveToItem != NULL && fMoveToItem->Menu() != NULL) - fMoveToItem->Menu()->RemoveItem(fMoveToItem); + DetachSubmenus(); - if (fCopyToItem != NULL && fCopyToItem->Menu() != NULL) - fCopyToItem->Menu()->RemoveItem(fCopyToItem); + if (fMenuBar != NULL) { + if (fFileMenu != NULL) { + fMenuBar->RemoveItem(fFileMenu); + delete fFileMenu; + } - if (fCreateLinkItem != NULL && fCreateLinkItem->Menu() != NULL) - fCreateLinkItem->Menu()->RemoveItem(fCreateLinkItem); + if (fWindowMenu != NULL) { + fMenuBar->RemoveItem(fWindowMenu); + delete fWindowMenu; + } - if (fOpenWithItem != NULL && fOpenWithItem->Menu() != NULL) { - fOpenWithItem->Menu()->RemoveItem(fOpenWithItem); - delete fOpenWithItem; - fOpenWithItem = NULL; - } + if (fAttrMenu != NULL) { + fMenuBar->RemoveItem(fAttrMenu); + delete fAttrMenu; + } - if (fNavigationItem != NULL) { - BMenu* menu = fNavigationItem->Menu(); - if (menu != NULL) { - menu->RemoveItem(fNavigationItem); - BMenuItem* item = menu->RemoveItem((int32)0); - ASSERT(item != fNavigationItem); - delete item; + if (ShouldAddMenus()) { + AddMenus(); + if (PoseView()->ViewMode() == kListMode) + fMenuBar->AddItem(fAttrMenu); } } - delete fFileContextMenu; - fFileContextMenu = new BPopUpMenu("FileContext", false, false); - AddFileContextMenus(fFileContextMenu); + delete fPoseContextMenu; + fPoseContextMenu = new BPopUpMenu("PoseContext", false, false); + AddPoseContextMenu(fPoseContextMenu); delete fWindowContextMenu; fWindowContextMenu = new BPopUpMenu("WindowContext", false, false); - AddWindowContextMenus(fWindowContextMenu); - - if (fMenuBar != NULL) { - fMenuBar->RemoveItem(fFileMenu); - delete fFileMenu; - fFileMenu = new BMenu(B_TRANSLATE("File")); - AddFileMenu(fFileMenu); - fMenuBar->AddItem(fFileMenu); - - fMenuBar->RemoveItem(fWindowMenu); - delete fWindowMenu; - fWindowMenu = new BMenu(B_TRANSLATE("Window")); - fMenuBar->AddItem(fWindowMenu); - AddWindowMenu(fWindowMenu); - - // just create the attribute, decide to add it later - fMenuBar->RemoveItem(fAttrMenu); - delete fAttrMenu; - fAttrMenu = new BMenu(B_TRANSLATE("Attributes")); - NewAttributesMenu(fAttrMenu); - if (PoseView()->ViewMode() == kListMode) - ShowAttributesMenu(); - - PopulateArrangeByMenu(fArrangeByMenu); - - int32 selectCount = PoseView()->CountSelected(); - - SetupOpenWithMenu(fFileMenu); - SetupMoveCopyMenus(selectCount ? PoseView()->SelectionList() - ->FirstItem()->TargetModel()->EntryRef() : NULL, - fFileMenu); - } + AddWindowContextMenu(fWindowContextMenu); } @@ -750,12 +730,19 @@ BContainerWindow::Init(const BMessage* message) if (ShouldAddScrollBars()) PoseView()->AddScrollBars(); - fMoveToItem = new BMenuItem(new BNavMenu(B_TRANSLATE("Move to"), - kMoveSelectionTo, this)); - fCopyToItem = new BMenuItem(new BNavMenu(B_TRANSLATE("Copy to"), - kCopySelectionTo, this)); - fCreateLinkItem = new BMenuItem(new BNavMenu(B_TRANSLATE("Create link"), - kCreateLink, this), new BMessage(kCreateLink)); + fShortcuts = new TShortcuts(this); + + fEditQueryItem = Shortcuts()->EditQueryItem(); + + const char* name = Shortcuts()->MoveToLabel(); + fMoveToItem = Shortcuts()->MoveToItem(new BNavMenu(name, kMoveSelectionTo, this)); + name = Shortcuts()->CopyToLabel(); + fCopyToItem = Shortcuts()->CopyToItem(new BNavMenu(name, kCopySelectionTo, this)); + name = Shortcuts()->CreateLinkLabel(); + fCreateLinkItem = Shortcuts()->CreateLinkItem(new BNavMenu(name, kCreateLink, this)); + + name = Shortcuts()->NewTemplatesLabel(); + fNewTemplatesItem = Shortcuts()->NewTemplatesItem(new TemplatesMenu(PoseView(), name)); TrackerSettings settings; @@ -934,6 +921,89 @@ BContainerWindow::RestoreStateCommon() } +void +BContainerWindow::OpenParent() +{ + BEntry entry(TargetModel()->EntryRef()); + if (entry.InitCheck() != B_OK) + return; + + BEntry parentEntry; + if (FSGetParentVirtualDirectoryAware(entry, parentEntry) != B_OK) + return; + + entry_ref setToRef; + parentEntry.GetRef(&setToRef); + const entry_ref* parent = &setToRef; + + // need to send switch message for spatial mode + BMessage message(kSwitchDirectory); + message.AddRef("refs", parent); + MessageReceived(&message); +} + + +void +BContainerWindow::SwitchDirectory(const entry_ref* ref) +{ + BEntry entry; + if (entry.SetTo(ref, true) != B_OK || entry.InitCheck() != B_OK) + return; + + if (StateNeedsSaving()) + SaveState(false); + + bool wasInTrash = TargetModel()->IsTrash() || TargetModel()->InTrash(); + bool wasRoot = TargetModel()->IsRoot(); + bool wasVolume = TargetModel()->IsVolume(); + + // Switch dir and apply new state + WindowStateNodeOpener opener(this, false); + opener.SetTo(&entry, false); + + // Update pose view and set directory type + PoseView()->SwitchDir(ref, opener.StreamNode()); + + if (wasInTrash ^ (TargetModel()->IsTrash() || TargetModel()->InTrash()) + || wasRoot != TargetModel()->IsRoot() || wasVolume != TargetModel()->IsVolume()) { + RepopulateMenus(); + } + + // skip the rest on file panel + if (PoseView()->IsFilePanel()) + return; + + TrackerSettings settings; + if (settings.ShowNavigator() || settings.ShowFullPathInTitleBar()) + SetPathWatchingEnabled(true); + + SetSingleWindowBrowseShortcuts(settings.SingleWindowBrowse()); + + // Update draggable folder icon + if (fMenuBar != NULL) { + if (!TargetModel()->IsRoot() && !TargetModel()->IsTrash()) { + // Folder icon should be visible, but in single + // window navigation, it might not be. + if (fDraggableIcon != NULL) { + IconCache::sIconCache->IconChanged(TargetModel()); + if (fDraggableIcon->IsHidden()) + fDraggableIcon->Show(); + fDraggableIcon->Invalidate(); + } else { + // draggable icon visible + _AddFolderIcon(); + } + } else if (fDraggableIcon != NULL) { + // hide for Root or Trash + fDraggableIcon->Hide(); + } + } + + // Update window title + UpdateTitle(); +} + + void BContainerWindow::UpdateTitle() { @@ -963,16 +1033,16 @@ BContainerWindow::UpdateBackgroundImage() if (!TargetModel()->IsRoot() && opener.Node() != NULL) { fBackgroundImage = BackgroundImage::Refresh(fBackgroundImage, opener.Node(), - PoseView()->IsDesktop(), PoseView()); + TargetModel()->IsDesktop(), PoseView()); } // look for background image info in the window's node BNode defaultingNode; - if (!fBackgroundImage && !PoseView()->IsDesktop() + if (!fBackgroundImage && !TargetModel()->IsDesktop() && DefaultStateSourceNode(kDefaultFolderTemplate, &defaultingNode)) { // look for background image info in the source for defaults fBackgroundImage = BackgroundImage::Refresh(fBackgroundImage, &defaultingNode, - PoseView()->IsDesktop(), PoseView()); + TargetModel()->IsDesktop(), PoseView()); } } @@ -980,7 +1050,7 @@ BContainerWindow::UpdateBackgroundImage() void BContainerWindow::FrameResized(float, float) { - if (PoseView() != NULL && !PoseView()->IsDesktop()) { + if (PoseView() != NULL && !TargetModel()->IsDesktop()) { BRect extent = PoseView()->Extent(); float offsetX = extent.left - PoseView()->Bounds().left; float offsetY = extent.top - PoseView()->Bounds().top; @@ -1322,7 +1392,7 @@ BContainerWindow::MessageReceived(BMessage* message) } case kOpenParentDir: - PostMessage(message, PoseView()); + OpenParent(); break; case kNewFolder: @@ -1438,95 +1508,53 @@ BContainerWindow::MessageReceived(BMessage* message) if (message->FindRef("refs", &ref) != B_OK) break; - BEntry entry; - if (entry.SetTo(&ref) != B_OK) - break; + if (!PoseView()->IsFilePanel() && !TrackerSettings().SingleWindowBrowse()) { + message->what = B_REFS_RECEIVED; + const node_ref* nodeRef = TargetModel()->NodeRef(); - if (StateNeedsSaving()) - SaveState(false); + // add information about the child, so that we can select it in the parent view + message->AddData("nodeRefToSelect", B_RAW_TYPE, nodeRef, sizeof(node_ref)); - bool wasInTrash = TargetModel()->IsTrash() || TargetModel()->InTrash(); - bool wasRoot = TargetModel()->IsRoot(); - bool wasVolume = TargetModel()->IsVolume(); + if ((modifiers() & B_OPTION_KEY) != 0) { + // if option down, add instructions to close the parent + message->AddData("nodeRefsToClose", B_RAW_TYPE, nodeRef, sizeof(node_ref)); + } - // Switch dir and apply new state - WindowStateNodeOpener opener(this, false); - opener.SetTo(&entry, false); + be_app->PostMessage(message); + } else { + SwitchDirectory(&ref); - // Update pose view and set directory type - PoseView()->SwitchDir(&ref, opener.StreamNode()); - - if (wasInTrash ^ (TargetModel()->IsTrash() || TargetModel()->InTrash()) - || wasRoot != TargetModel()->IsRoot() || wasVolume != TargetModel()->IsVolume()) { - RepopulateMenus(); - } - - // skip the rest for file panel - if (PoseView()->IsFilePanel()) - break; - - if (Navigator() != NULL) { - // update Navigation bar - int32 action = message->GetInt32("action", kActionSet); - Navigator()->UpdateLocation(TargetModel(), action); - } - - TrackerSettings settings; - if (settings.ShowNavigator() || settings.ShowFullPathInTitleBar()) - SetPathWatchingEnabled(true); - - SetSingleWindowBrowseShortcuts(settings.SingleWindowBrowse()); - - // Update draggable folder icon - if (fMenuBar != NULL) { - if (!TargetModel()->IsRoot() && !TargetModel()->IsTrash()) { - // Folder icon should be visible, but in single - // window navigation, it might not be. - if (fDraggableIcon != NULL) { - IconCache::sIconCache->IconChanged(TargetModel()); - if (fDraggableIcon->IsHidden()) - fDraggableIcon->Show(); - fDraggableIcon->Invalidate(); - } else { - // draggable icon visible - _AddFolderIcon(); - } - } else if (fDraggableIcon != NULL) { - // hide for Root or Trash - fDraggableIcon->Hide(); + if (Navigator() != NULL) { + // update Navigation bar + int32 action = message->GetInt32("action", kActionSet); + Navigator()->UpdateLocation(TargetModel(), action); } } - - // Update window title - UpdateTitle(); break; } case B_REFS_RECEIVED: - if (Dragging()) { - // ref in this message is the target, - // the end point of the drag + { + if (!Dragging()) + break; - entry_ref ref; - if (message->FindRef("refs", &ref) == B_OK) { - fWaitingForRefs = false; - BEntry entry(&ref, true); - // don't copy to printers dir - if (!FSIsPrintersDir(&entry)) { - if (entry.InitCheck() == B_OK - && entry.IsDirectory()) { - Model targetModel(&entry, true, false); - BPoint dropPoint; - uint32 buttons; - PoseView()->GetMouse(&dropPoint, &buttons, true); - PoseView()->HandleDropCommon(fDragMessage, - &targetModel, NULL, PoseView(), dropPoint); - } - } + // ref in this message is the target, the end point of the drag + entry_ref ref; + if (message->FindRef("refs", &ref) == B_OK) { + fWaitingForRefs = false; + BEntry entry(&ref, true); + // don't copy to printers dir + if (entry.InitCheck() == B_OK && entry.IsDirectory() && !FSIsPrintersDir(&entry)) { + Model target(&entry, true, false); + BPoint where; + uint32 buttons; + PoseView()->GetMouse(&where, &buttons, true); + PoseView()->HandleDropCommon(fDragMessage, &target, NULL, PoseView(), where); } - DragStop(); } + DragStop(); break; + } case B_TRACKER_ADDON_MESSAGE: { @@ -1643,147 +1671,6 @@ BContainerWindow::MessageReceived(BMessage* message) } -void -BContainerWindow::SetCutItem(BMenu* menu) -{ - BMenuItem* item; - if ((item = menu->FindItem(B_CUT)) == NULL - && (item = menu->FindItem(kCutMoreSelectionToClipboard)) == NULL) { - return; - } - - if (PoseView() != CurrentFocus()) - item->SetEnabled(dynamic_cast(CurrentFocus()) != NULL); - else { - if (TargetModel()->IsRoot() || TargetModel()->IsTrash() - || TargetModel()->IsVirtualDirectory()) { - // cannot cut files in root, trash or in a virtual directory - item->SetEnabled(false); - } else { - item->SetEnabled(PoseView()->CountSelected() > 0 - && !PoseView()->SelectedVolumeIsReadOnly()); - } - } - - if ((modifiers() & B_SHIFT_KEY) != 0) { - item->SetLabel(B_TRANSLATE("Cut more")); - item->SetShortcut('X', B_COMMAND_KEY | B_SHIFT_KEY); - item->SetMessage(new BMessage(kCutMoreSelectionToClipboard)); - } else { - item->SetLabel(B_TRANSLATE("Cut")); - item->SetShortcut('X', B_COMMAND_KEY); - item->SetMessage(new BMessage(B_CUT)); - } -} - - -void -BContainerWindow::SetCopyItem(BMenu* menu) -{ - BMenuItem* item; - if ((item = menu->FindItem(B_COPY)) == NULL - && (item = menu->FindItem(kCopyMoreSelectionToClipboard)) == NULL) { - return; - } - - if (PoseView() != CurrentFocus()) - item->SetEnabled(dynamic_cast(CurrentFocus()) != NULL); - else - item->SetEnabled(PoseView()->CountSelected() > 0); - - if ((modifiers() & B_SHIFT_KEY) != 0) { - item->SetLabel(B_TRANSLATE("Copy more")); - item->SetShortcut('C', B_COMMAND_KEY | B_SHIFT_KEY); - item->SetMessage(new BMessage(kCopyMoreSelectionToClipboard)); - } else { - item->SetLabel(B_TRANSLATE("Copy")); - item->SetShortcut('C', B_COMMAND_KEY); - item->SetMessage(new BMessage(B_COPY)); - } -} - - -void -BContainerWindow::SetPasteItem(BMenu* menu) -{ - BMenuItem* item; - if ((item = menu->FindItem(B_PASTE)) == NULL - && (item = menu->FindItem(kPasteLinksFromClipboard)) == NULL) { - return; - } - - if (PoseView() != CurrentFocus()) - item->SetEnabled(dynamic_cast(CurrentFocus()) != NULL); - else { - item->SetEnabled(FSClipboardHasRefs() - && !PoseView()->TargetVolumeIsReadOnly()); - } - - if ((modifiers() & B_SHIFT_KEY) != 0) { - item->SetLabel(B_TRANSLATE("Paste links")); - item->SetShortcut('V', B_COMMAND_KEY | B_SHIFT_KEY); - item->SetMessage(new BMessage(kPasteLinksFromClipboard)); - } else { - item->SetLabel(B_TRANSLATE("Paste")); - item->SetShortcut('V', B_COMMAND_KEY); - item->SetMessage(new BMessage(B_PASTE)); - } -} - - -void -BContainerWindow::SetArrangeMenu(BMenu* menu) -{ - BMenuItem* item; - if ((item = menu->FindItem(kCleanup)) == NULL - && (item = menu->FindItem(kCleanupAll)) == NULL) { - return; - } - - item->Menu()->SetEnabled(PoseView()->CountItems() > 0 - && (PoseView()->ViewMode() != kListMode)); - - BMenu* arrangeMenu; - - if ((modifiers() & B_SHIFT_KEY) != 0) { - item->SetLabel(B_TRANSLATE("Clean up all")); - item->SetShortcut('K', B_COMMAND_KEY | B_SHIFT_KEY); - item->SetMessage(new BMessage(kCleanupAll)); - arrangeMenu = item->Menu(); - } else { - item->SetLabel(B_TRANSLATE("Clean up")); - item->SetShortcut('K', B_COMMAND_KEY); - item->SetMessage(new BMessage(kCleanup)); - arrangeMenu = item->Menu(); - } - - MarkArrangeByMenu(arrangeMenu); -} - - -void -BContainerWindow::SetCloseItem(BMenu* menu) -{ - BMenuItem* item; - if ((item = menu->FindItem(B_QUIT_REQUESTED)) == NULL - && (item = menu->FindItem(kCloseAllWindows)) == NULL) { - return; - } - - if ((modifiers() & B_SHIFT_KEY) != 0) { - item->SetLabel(B_TRANSLATE("Close all")); - item->SetShortcut('W', B_COMMAND_KEY | B_SHIFT_KEY); - item->SetTarget(be_app); - item->SetMessage(new BMessage(kCloseAllWindows)); - } else { - item->SetLabel(B_TRANSLATE("Close")); - item->SetShortcut('W', B_COMMAND_KEY); - item->SetTarget(this); - item->SetMessage(new BMessage(B_QUIT_REQUESTED)); - } -} - - bool BContainerWindow::IsShowing(const node_ref* node) const { @@ -1804,145 +1691,133 @@ BContainerWindow::AddMenus() fFileMenu = new BMenu(B_TRANSLATE("File")); AddFileMenu(fFileMenu); fMenuBar->AddItem(fFileMenu); + fWindowMenu = new BMenu(B_TRANSLATE("Window")); fMenuBar->AddItem(fWindowMenu); AddWindowMenu(fWindowMenu); - // just create the attribute, decide to add it later + + // create Attributes menu, add it later fAttrMenu = new BMenu(B_TRANSLATE("Attributes")); NewAttributesMenu(fAttrMenu); - PopulateArrangeByMenu(fArrangeByMenu); + + // create "Arrange By >" menu, add it later + fArrangeByItem = NewArrangeByMenu(); } void BContainerWindow::AddFileMenu(BMenu* menu) { - BMenuItem* item; - - if (!PoseView()->IsFilePanel()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Find" B_UTF8_ELLIPSIS), - new BMessage(kFindButton), 'F')); + if (TargetModel()->IsTrash()) { + // add as first item in menu + menu->AddItem(Shortcuts()->EmptyTrashItem()); + menu->AddItem(new BSeparatorItem()); + } else if (TargetModel()->IsPrintersDir()) { + // add as first item in menu + menu->AddItem(Shortcuts()->AddPrinterItem()); + menu->AddItem(new BSeparatorItem()); } - if (!TargetModel()->IsQuery() && !TargetModel()->IsVirtualDirectory() - && !TargetModel()->IsTrash() && !TargetModel()->IsPrintersDir() - && !TargetModel()->IsRoot()) { - if (!PoseView()->IsFilePanel()) { - TemplatesMenu* templatesMenu = new TemplatesMenu(PoseView(), - B_TRANSLATE("New")); - menu->AddItem(templatesMenu); - templatesMenu->SetTargetForItems(PoseView()); - } else { - item = new BMenuItem(B_TRANSLATE("New folder"), - new BMessage(kNewFolder), 'N'); - menu->AddItem(item); - } - } + menu->AddItem(Shortcuts()->FindItem()); + if (ShouldHaveNewFolderItem()) + menu->AddItem(Shortcuts()->NewFolderItem()); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), - new BMessage(kOpenSelection), 'O')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), - new BMessage(kGetInfo), 'I')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), - new BMessage(kEditItem), 'E')); + menu->AddItem(Shortcuts()->OpenItem()); + // "Edit query" and "Open with..." inserted here, + // see UpdateMenu(), SetupEditQueryItem() and SetupOpenWithMenu() + menu->AddItem(Shortcuts()->GetInfoItem()); + menu->AddItem(Shortcuts()->EditNameItem()); + + if (TargetModel()->IsPrintersDir()) { + menu->AddItem(Shortcuts()->MakeActivePrinterItem()); + return; // we're done with printers directory + } + + if (TargetModel()->IsRoot()) { + menu->AddItem(Shortcuts()->UnmountItem()); + menu->AddItem(new BMenuItem(B_TRANSLATE("Mount settings" B_UTF8_ELLIPSIS), + new BMessage(kRunAutomounterSettings))); + } if (TargetModel()->IsTrash() || TargetModel()->InTrash()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Restore"), - new BMessage(kRestoreFromTrash))); - if (TargetModel()->IsTrash()) { - // add as first item in menu - menu->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), - new BMessage(kEmptyTrash)), 0); - menu->AddItem(new BSeparatorItem(), 1); - } - } else if (TargetModel()->IsPrintersDir()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Add printer" B_UTF8_ELLIPSIS), - new BMessage(kAddPrinter), 'N'), 0); - menu->AddItem(new BSeparatorItem(), 1); - menu->AddItem(new BMenuItem(B_TRANSLATE("Make active printer"), - new BMessage(kMakeActivePrinter))); - } else if (TargetModel()->IsRoot()) { - item = new BMenuItem(B_TRANSLATE("Unmount"), - new BMessage(kUnmountVolume), 'U'); - item->SetEnabled(false); - menu->AddItem(item); - menu->AddItem(new BMenuItem( - B_TRANSLATE("Mount settings" B_UTF8_ELLIPSIS), - new BMessage(kRunAutomounterSettings))); + menu->AddItem(Shortcuts()->DeleteItem()); + menu->AddItem(Shortcuts()->RestoreItem()); } else { - item = new BMenuItem(B_TRANSLATE("Duplicate"), - new BMessage(kDuplicateSelection), 'D'); - item->SetEnabled(PoseView()->CanMoveToTrashOrDuplicate()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Move to Trash"), - new BMessage(kMoveSelectionToTrash), 'T'); - item->SetEnabled(PoseView()->CanMoveToTrashOrDuplicate()); - menu->AddItem(item); - - menu->AddSeparatorItem(); - - // The "Move To", "Copy To", "Create Link" menus are inserted - // at this place, have a look at: - // BContainerWindow::SetupMoveCopyMenus() + menu->AddItem(Shortcuts()->DuplicateItem()); + menu->AddItem(Shortcuts()->MoveToTrashItem()); } - BMenuItem* cutItem = NULL; - BMenuItem* copyItem = NULL; - BMenuItem* pasteItem = NULL; - if (!TargetModel()->IsPrintersDir()) { + menu->AddSeparatorItem(); + + // The "Move To", "Copy To", "Create Link" menus are inserted here, + // have a look at UpdateMenu() and SetupMoveCopyMenus(). + + if (!TargetModel()->IsRoot() && !TargetModel()->IsTrash() && !TargetModel()->InTrash()) { + menu->AddItem(Shortcuts()->CutItem()); + menu->AddItem(Shortcuts()->CopyItem()); + menu->AddItem(Shortcuts()->PasteItem()); menu->AddSeparatorItem(); - - if (!TargetModel()->IsRoot()) { - cutItem = new(std::nothrow) BMenuItem(B_TRANSLATE("Cut"), - new BMessage(B_CUT), 'X'); - menu->AddItem(cutItem); - copyItem = new(std::nothrow) BMenuItem(B_TRANSLATE("Copy"), - new BMessage(B_COPY), 'C'); - menu->AddItem(copyItem); - pasteItem = new(std::nothrow) BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V'); - menu->AddItem(pasteItem); - menu->AddSeparatorItem(); - - menu->AddItem(new BMenuItem(B_TRANSLATE("Identify"), - new BMessage(kIdentifyEntry))); - } - BMenu* addOnMenuItem = new BMenu(B_TRANSLATE("Add-ons")); - menu->AddItem(addOnMenuItem); } - menu->SetTargetForItems(PoseView()); - if (cutItem != NULL) - cutItem->SetTarget(this); - - if (copyItem != NULL) - copyItem->SetTarget(this); - - if (pasteItem != NULL) - pasteItem->SetTarget(this); + if (!TargetModel()->IsRoot()) + menu->AddItem(Shortcuts()->IdentifyItem()); + menu->AddItem(new BMenuItem(new BMenu(Shortcuts()->AddOnsLabel()))); } void BContainerWindow::AddWindowMenu(BMenu* menu) { + AddIconSizeMenu(menu); + + BMenuItem* item = new BMenuItem(B_TRANSLATE("List view"), new BMessage(kListMode), '3'); + item->SetTarget(PoseView()); + menu->AddItem(item); + menu->AddSeparatorItem(); + + menu->AddItem(Shortcuts()->ResizeToFitItem()); + // "Arrange by >" menu inserted here, + // see UpdateMenu() and SetupArrangeByMenu() + menu->AddItem(Shortcuts()->SelectItem()); + menu->AddItem(Shortcuts()->SelectAllItem()); + menu->AddItem(Shortcuts()->InvertSelectionItem()); + if (!TargetModel()->IsTrash()) + menu->AddItem(Shortcuts()->OpenParentItem()); + menu->AddItem(Shortcuts()->CloseItem()); + menu->AddItem(Shortcuts()->CloseAllInWorkspaceItem()); + menu->AddSeparatorItem(); + + item = new BMenuItem("Preferences" B_UTF8_ELLIPSIS, new BMessage(kShowSettingsWindow), ','); + item->SetTarget(be_app); + menu->AddItem(item); +} + + +void +BContainerWindow::AddIconSizeMenu(BMenu* menu) +{ + if (menu == NULL) + return; + BMenuItem* item; - - BMenu* iconSizeMenu = new BMenu(B_TRANSLATE("Icon view")); - - static const uint32 kIconSizes[] = { 32, 40, 48, 64, 96, 128 }; BMessage* message; + BMenu* iconSizeMenu = new BMenu(B_TRANSLATE("Icon view")); + iconSizeMenu->SetRadioMode(true); + + static const uint32 kIconSizes[] = { 32, 40, 48, 64, 96, 128 }; + + BString label; + const char* format; + const char* comment = "The '×' is the Unicode multiplication sign U+00D7"; + uint32 iconSize; for (uint32 i = 0; i < sizeof(kIconSizes) / sizeof(uint32); ++i) { - uint32 iconSize = kIconSizes[i]; + iconSize = kIconSizes[i]; message = new BMessage(kIconMode); message->AddInt32("size", iconSize); - BString label; - label.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32, - "The '×' is the Unicode multiplication sign U+00D7"), - iconSize, iconSize); + format = B_TRANSLATE_COMMENT("%" B_PRId32 " × %" B_PRId32, comment); + label.SetToFormat(format, iconSize, iconSize); item = new BMenuItem(label, message); item->SetTarget(PoseView()); iconSizeMenu->AddItem(item); @@ -1964,67 +1839,15 @@ BContainerWindow::AddWindowMenu(BMenu* menu) // A sub menu where the super item can be invoked. menu->AddItem(iconSizeMenu); - iconSizeMenu->Superitem()->SetShortcut('1', B_COMMAND_KEY); - iconSizeMenu->Superitem()->SetMessage(new BMessage(kIconMode)); - iconSizeMenu->Superitem()->SetTarget(PoseView()); - - item = new BMenuItem(B_TRANSLATE("Mini icon view"), - new BMessage(kMiniIconMode), '2'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("List view"), - new BMessage(kListMode), '3'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - menu->AddSeparatorItem(); - - item = new BMenuItem(B_TRANSLATE("Resize to fit"), - new BMessage(kResizeToFit), 'Y'); - item->SetTarget(this); - menu->AddItem(item); - - fArrangeByMenu = new BMenu(B_TRANSLATE("Arrange by")); - menu->AddItem(fArrangeByMenu); - - item = new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A'); - item->SetTarget(this); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Invert selection"), - new BMessage(kInvertSelection), 'S'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - if (!TargetModel()->IsTrash()) { - item = new BMenuItem(B_TRANSLATE("Open parent"), - new BMessage(kOpenParentDir), B_UP_ARROW); - item->SetTarget(PoseView()); - menu->AddItem(item); + BMenuItem* iconSizeSuperItem = iconSizeMenu->Superitem(); + if (iconSizeSuperItem != NULL) { + iconSizeSuperItem->SetShortcut('1', B_COMMAND_KEY); + iconSizeSuperItem->SetMessage(new BMessage(kIconMode)); + iconSizeSuperItem->SetTarget(PoseView()); } - item = new BMenuItem(B_TRANSLATE("Close"), - new BMessage(B_QUIT_REQUESTED), 'W'); - item->SetTarget(this); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Close all in workspace"), - new BMessage(kCloseAllInWorkspace), 'Q'); - item->SetTarget(be_app); - menu->AddItem(item); - - menu->AddSeparatorItem(); - - item = new BMenuItem(B_TRANSLATE("Preferences" B_UTF8_ELLIPSIS), - new BMessage(kShowSettingsWindow), ','); - item->SetTarget(be_app); + item = new BMenuItem(B_TRANSLATE("Mini icon view"), new BMessage(kMiniIconMode), '2'); + item->SetTarget(PoseView()); menu->AddItem(item); } @@ -2042,38 +1865,23 @@ BContainerWindow::AddShortcuts() new BMessage(kCutMoreSelectionToClipboard), this); AddShortcut('C', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kCopyMoreSelectionToClipboard), this); - AddShortcut('F', B_COMMAND_KEY, - new BMessage(kFindButton), PoseView()); - AddShortcut('N', B_COMMAND_KEY, - new BMessage(kNewFolder), PoseView()); - AddShortcut('O', B_COMMAND_KEY, - new BMessage(kOpenSelection), PoseView()); - AddShortcut('I', B_COMMAND_KEY, - new BMessage(kGetInfo), PoseView()); - AddShortcut('E', B_COMMAND_KEY, - new BMessage(kEditItem), PoseView()); - AddShortcut('D', B_COMMAND_KEY, - new BMessage(kDuplicateSelection), PoseView()); - AddShortcut('T', B_COMMAND_KEY, - new BMessage(kMoveSelectionToTrash), PoseView()); - AddShortcut('K', B_COMMAND_KEY, - new BMessage(kCleanup), PoseView()); - AddShortcut('A', B_COMMAND_KEY, - new BMessage(B_SELECT_ALL), PoseView()); - AddShortcut('S', B_COMMAND_KEY, - new BMessage(kInvertSelection), PoseView()); - AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY, - new BMessage(kShowSelectionWindow), PoseView()); - AddShortcut('G', B_COMMAND_KEY, - new BMessage(kEditQuery), PoseView()); + AddShortcut('F', B_COMMAND_KEY, new BMessage(kFindButton), PoseView()); + AddShortcut('N', B_COMMAND_KEY, new BMessage(kNewFolder), PoseView()); + AddShortcut('O', B_COMMAND_KEY, new BMessage(kOpenSelection), PoseView()); + AddShortcut('I', B_COMMAND_KEY, new BMessage(kGetInfo), PoseView()); + AddShortcut('E', B_COMMAND_KEY, new BMessage(kEditName), PoseView()); + AddShortcut('D', B_COMMAND_KEY, new BMessage(kDuplicateSelection), PoseView()); + AddShortcut('T', B_COMMAND_KEY, new BMessage(kMoveSelectionToTrash), PoseView()); + AddShortcut('K', B_COMMAND_KEY, new BMessage(kCleanup), PoseView()); + AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), PoseView()); + AddShortcut('S', B_COMMAND_KEY, new BMessage(kInvertSelection), PoseView()); + AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kShowSelectionWindow), PoseView()); + AddShortcut('G', B_COMMAND_KEY, new BMessage(kEditQuery), PoseView()); // it is ok to add a global Edit query shortcut here, PoseView will // filter out cases where selected pose is not a query - AddShortcut('U', B_COMMAND_KEY, - new BMessage(kUnmountVolume), PoseView()); - AddShortcut(B_UP_ARROW, B_COMMAND_KEY, - new BMessage(kOpenParentDir), PoseView()); - AddShortcut('O', B_COMMAND_KEY | B_CONTROL_KEY, - new BMessage(kOpenSelectionWith), PoseView()); + AddShortcut('U', B_COMMAND_KEY, new BMessage(kUnmountVolume), PoseView()); + AddShortcut(B_UP_ARROW, B_COMMAND_KEY, new BMessage(kOpenParentDir), PoseView()); + AddShortcut('O', B_COMMAND_KEY | B_CONTROL_KEY, new BMessage(kOpenSelectionWith), PoseView()); BMessage* decreaseSize = new BMessage(kIconMode); decreaseSize->AddInt32("scale", 0); @@ -2097,42 +1905,11 @@ BContainerWindow::MenusBeginning() PoseView()->CommitActivePose(); } - // File menu - int32 selectCount = PoseView()->SelectionList()->CountItems(); + if (fFileMenu != NULL) + UpdateMenu(fFileMenu, kFileMenuContext); - SetupOpenWithMenu(fFileMenu); - SetupMoveCopyMenus(selectCount - ? PoseView()->SelectionList()->FirstItem()->TargetModel()->EntryRef() - : NULL, fFileMenu); - - if (TargetModel()->IsRoot()) { - BVolume boot; - BVolumeRoster().GetBootVolume(&boot); - - bool ejectableVolumeSelected = false; - for (int32 index = 0; index < selectCount; index++) { - Model* model - = PoseView()->SelectionList()->ItemAt(index)->TargetModel(); - if (model->IsVolume()) { - BVolume volume; - volume.SetTo(model->NodeRef()->device); - if (volume != boot) { - ejectableVolumeSelected = true; - break; - } - } - } - BMenuItem* item = fMenuBar->FindItem(kUnmountVolume); - if (item != NULL) - item->SetEnabled(ejectableVolumeSelected); - } - - UpdateMenu(fMenuBar, kMenuBarContext); - - AddMimeTypesToMenu(fAttrMenu); - - if (TargetModel()->IsPrintersDir()) - EnableNamedMenuItem(fFileMenu, kMakeActivePrinter, selectCount == 1); + if (fWindowMenu != NULL) + UpdateMenu(fWindowMenu, kWindowMenuContext); } @@ -2140,32 +1917,35 @@ void BContainerWindow::MenusEnded() { // when we're done we want to clear nav menus for next time - DeleteSubmenu(fNavigationItem); - DeleteSubmenu(fMoveToItem); - DeleteSubmenu(fCopyToItem); DeleteSubmenu(fCreateLinkItem); + DeleteSubmenu(fCopyToItem); + DeleteSubmenu(fMoveToItem); DeleteSubmenu(fOpenWithItem); + DeleteSubmenu(fNavigationItem); } void -BContainerWindow::SetupNavigationMenu(const entry_ref* ref, BMenu* parent) +BContainerWindow::SetupNavigationMenu(BMenu* parent, const entry_ref* ref) { + ASSERT(parent); + // start by removing nav item (and separator) from old menu - if (fNavigationItem != NULL) { - BMenu* menu = fNavigationItem->Menu(); - if (menu != NULL) { - menu->RemoveItem(fNavigationItem); - BMenuItem* item = menu->RemoveItem((int32)0); - ASSERT(item != fNavigationItem); - delete item; - } + if (fNavigationItem != NULL && fNavigationItem->Menu() != NULL) { + // delete separator first + delete fNavigationItem->Menu()->RemoveItem( + fNavigationItem->Menu()->IndexOf(fNavigationItem) + 1); + fNavigationItem->Menu()->RemoveItem(fNavigationItem); } // if we weren't passed a ref then we're navigating this window if (ref == NULL) ref = TargetModel()->EntryRef(); + // bail out if we shouldn't have a navigation item + if (!ShouldHaveNavigationMenu(ref)) + return; + BEntry entry; if (entry.SetTo(ref) != B_OK) return; @@ -2191,10 +1971,10 @@ BContainerWindow::SetupNavigationMenu(const entry_ref* ref, BMenu* parent) ref = &resolvedRef; } - if (fNavigationItem == NULL) { - fNavigationItem = new ModelMenuItem(&model, - new BNavMenu(model.Name(), B_REFS_RECEIVED, be_app, this)); - } + // always build a fresh navigation menu + delete fNavigationItem; + fNavigationItem + = new ModelMenuItem(&model, new BNavMenu(model.Name(), B_REFS_RECEIVED, be_app, this)); // setup a navigation menu item which will dynamically load items // as menu items are traversed @@ -2217,106 +1997,153 @@ BContainerWindow::SetupNavigationMenu(const entry_ref* ref, BMenu* parent) void -BContainerWindow::SetupEditQueryItem(BMenu* menu) +BContainerWindow::SetupEditQueryItem(BMenu* parent) { - ASSERT(menu); - // File menu - int32 selectCount = PoseView()->CountSelected(); + SetupEditQueryItem(parent, TargetModel()->EntryRef()); +} - // add Edit query if appropriate - bool queryInSelection = false; - if (selectCount && selectCount < 100) { - // only do this for a limited number of selected poses - // if any queries selected, add an edit query menu item - for (int32 index = 0; index < selectCount; index++) { - BPose* pose = PoseView()->SelectionList()->ItemAt(index); - Model model(pose->TargetModel()->EntryRef(), true); - if (model.InitCheck() != B_OK) - continue; +void +BContainerWindow::SetupEditQueryItem(BMenu* parent, const entry_ref* ref) +{ + ASSERT(parent); - if (model.IsQuery() || model.IsQueryTemplate()) { - queryInSelection = true; - break; - } - } - } + // start by removing "Edit query" from old menu + if (fEditQueryItem != NULL && fEditQueryItem->Menu() != NULL) + fEditQueryItem->Menu()->RemoveItem(fEditQueryItem); - bool poseViewIsQuery = TargetModel()->IsQuery(); - // if the view is a query pose view, add edit query menu item + // if ref unset assume window ref + if (ref == NULL) + ref = TargetModel()->EntryRef(); - BMenuItem* item = menu->FindItem(kEditQuery); - if (!poseViewIsQuery && !queryInSelection && item != NULL) - item->Menu()->RemoveItem(item); - else if ((poseViewIsQuery || queryInSelection) && item == NULL) { - // add edit query item after Open - item = menu->FindItem(kOpenSelection); - if (item) { - int32 itemIndex = item->Menu()->IndexOf(item); - BMenuItem* query = new BMenuItem(B_TRANSLATE("Edit query"), - new BMessage(kEditQuery), 'G'); - item->Menu()->AddItem(query, itemIndex + 1); - query->SetTarget(PoseView()); - } - } + ASSERT(ref); + + // bail out if "Open" item or index not found + BMenuItem* openItem = parent->FindItem(kOpenSelection); + int32 openIndex = parent->IndexOf(openItem); + if (openItem == NULL || openIndex == B_ERROR) + return; + + // add "Edit query" item between "Open" and "Open with..." + parent->AddItem(fEditQueryItem, openIndex + 1); + + Shortcuts()->UpdateEditQueryItem(fEditQueryItem); } void BContainerWindow::SetupOpenWithMenu(BMenu* parent) { - // start by removing nav item (and separator) from old menu - if (fOpenWithItem) { - BMenu* menu = fOpenWithItem->Menu(); - if (menu != NULL) - menu->RemoveItem(fOpenWithItem); + SetupOpenWithMenu(parent, TargetModel()->EntryRef()); +} - delete fOpenWithItem; - fOpenWithItem = 0; - } - int32 selectCount = PoseView()->CountSelected(); - if (selectCount <= 0) { - // no selection, nothing to open - return; - } +void +BContainerWindow::SetupOpenWithMenu(BMenu* parent, const entry_ref* ref) +{ + ASSERT(parent); - if (TargetModel()->IsRoot()) { - // don't add ourselves if we are root - return; - } + // start by removing "Open with..." item from old menu + if (fOpenWithItem != NULL && fOpenWithItem->Menu() != NULL) + fOpenWithItem->Menu()->RemoveItem(fOpenWithItem); // ToDo: // check if only item in selection list is the root // and do not add if true - // add after "Open" - BMenuItem* item = parent->FindItem(kOpenSelection); + // if ref unset assume window ref + if (ref == NULL) + ref = TargetModel()->EntryRef(); + + ASSERT(ref); + + // bail out if we shouldn't have an "Open with..." parent + if (!ShouldHaveOpenWithMenu(ref)) + return; + + // bail out if "Open" item not found + BMenuItem* openItem = parent->FindItem(kOpenSelection); + if (openItem == NULL) + return; + + // bail out if index of "Open" item not found + int32 openIndex = parent->IndexOf(openItem); + if (openIndex == B_ERROR) + return; // build a list of all refs to open BMessage message(B_REFS_RECEIVED); + BPose* pose; + int32 selectCount = PoseView()->CountSelected(); for (int32 index = 0; index < selectCount; index++) { - BPose* pose = PoseView()->SelectionList()->ItemAt(index); + pose = PoseView()->SelectionList()->ItemAt(index); message.AddRef("refs", pose->TargetModel()->EntryRef()); } // add Tracker token so that refs received recipients can script us message.AddMessenger("TrackerViewToken", BMessenger(PoseView())); - int32 index = item->Menu()->IndexOf(item); - fOpenWithItem = new BMenuItem( - new OpenWithMenu(B_TRANSLATE("Open with" B_UTF8_ELLIPSIS), - &message, this, be_app), new BMessage(kOpenSelectionWith)); - fOpenWithItem->SetTarget(PoseView()); - fOpenWithItem->SetShortcut('O', B_COMMAND_KEY | B_CONTROL_KEY); + // always build a fresh "Open with..." menu + delete fOpenWithItem; + fOpenWithItem = Shortcuts()->OpenWithItem( + new OpenWithMenu(Shortcuts()->OpenWithLabel(), &message, this, be_app)); - item->Menu()->AddItem(fOpenWithItem, index + 1); + parent->AddItem(fOpenWithItem, openIndex + 1); + Shortcuts()->UpdateOpenWithItem(fOpenWithItem); } void -BContainerWindow::PopulateMoveCopyNavMenu(BNavMenu* navMenu, uint32 what, - const entry_ref* ref, bool addLocalOnly) +BContainerWindow::SetupNewTemplatesMenu(BMenu* parent, MenuContext context) +{ + ASSERT(parent); + + // start by removing "New >" item from the old menu + if (fNewTemplatesItem != NULL && fNewTemplatesItem->Menu() != NULL) + fNewTemplatesItem->Menu()->RemoveItem(fNewTemplatesItem); + + // no "New folder" item or menu for this window type, bail + if (!ShouldHaveNewFolderItem()) + return; + + // file panel does not have a menu, only "New folder" + BMenuItem* newFolderItem = parent->FindItem(kNewFolder); + if (PoseView()->IsFilePanel()) + return Shortcuts()->UpdateNewFolderItem(newFolderItem); + + // we should have a "New >" menu at this point + TemplatesMenu* newTemplatesMenu = (TemplatesMenu*)fNewTemplatesItem->Submenu(); + ASSERT(newTemplatesMenu); + + // update templates menu state + newTemplatesMenu->UpdateMenuState(); + + // no templates found, update "New folder" instead, bail + if (newTemplatesMenu->CountTemplates() == 0) + return Shortcuts()->UpdateNewFolderItem(newFolderItem); + + int32 newFolderIndex = parent->IndexOf(newFolderItem); + if (newFolderItem != NULL && newFolderIndex != B_ERROR) { + // replace "New folder" with "New >" menu + parent->RemoveItem(newFolderItem); + parent->AddItem(fNewTemplatesItem, newFolderIndex); + delete newFolderItem; + } else { + // we already have a "New >" menu + if (context == kWindowPopUpContext) + parent->AddItem(fNewTemplatesItem, 2); + else if (context == kFileMenuContext) + parent->AddItem(fNewTemplatesItem, 1); + } + + // update "New >" menu status + Shortcuts()->UpdateNewTemplatesItem(fNewTemplatesItem); +} + + +void +BContainerWindow::PopulateMoveCopyNavMenu(BNavMenu* navMenu, uint32 what, const entry_ref* ref, + bool addLocalOnly) { BVolume volume; BVolumeRoster volumeRoster; @@ -2419,102 +2246,79 @@ BContainerWindow::PopulateMoveCopyNavMenu(BNavMenu* navMenu, uint32 what, void -BContainerWindow::SetupMoveCopyMenus(const entry_ref* item_ref, BMenu* parent) +BContainerWindow::SetupMoveCopyMenus(BMenu* parent, const entry_ref* ref) { - if (TargetModel()->IsTrash() || TargetModel()->InTrash() || TargetModel()->IsPrintersDir() - || fMoveToItem == NULL || fCopyToItem == NULL || fCreateLinkItem == NULL - || TargetModel()->IsRoot()) { + // bail out if items are not setup yet, this should never happen + if (fMoveToItem == NULL || fCopyToItem == NULL || fCreateLinkItem == NULL) return; + + // start off by removing the items from the old menu + if (fMoveToItem->Menu() != NULL) + fMoveToItem->Menu()->RemoveItem(fMoveToItem); + if (fCopyToItem->Menu() != NULL) + fCopyToItem->Menu()->RemoveItem(fCopyToItem); + if (fCreateLinkItem->Menu() != NULL) { + // remove and delete separator first + delete fCreateLinkItem->Menu()->RemoveItem( + fCreateLinkItem->Menu()->IndexOf(fCreateLinkItem) + 1); + fCreateLinkItem->Menu()->RemoveItem(fCreateLinkItem); } + // if ref unset assume window ref + if (ref == NULL) + ref = TargetModel()->EntryRef(); + + // bail out if we shouldn't have "Move to/Copy to/Create Link" menus + if (!ShouldHaveMoveCopyMenus(ref)) + return; + + // bail out if "Move to Trash" or "Delete" item not found + BMenuItem* moveToTrashItem + = Shortcuts()->FindItem(parent, kMoveSelectionToTrash, kDeleteSelection); + int32 index = parent->IndexOf(moveToTrashItem); + if (moveToTrashItem == NULL || index == B_ERROR) + return; + + // skip past "Move to Trash" and separator + index += 2; + // re-parent items to this menu since they're shared - BMenuItem* trash = parent->FindItem(kMoveSelectionToTrash); - int32 index = trash != NULL ? parent->IndexOf(trash) + 2 : 0; - - if (fMoveToItem->Menu() != parent) { - if (fMoveToItem->Menu() != NULL) - fMoveToItem->Menu()->RemoveItem(fMoveToItem); - - parent->AddItem(fMoveToItem, index++); - } - - if (fCopyToItem->Menu() != parent) { - if (fCopyToItem->Menu() != NULL) - fCopyToItem->Menu()->RemoveItem(fCopyToItem); - - parent->AddItem(fCopyToItem, index++); - } - - if (fCreateLinkItem->Menu() != parent) { - if (fCreateLinkItem->Menu() != NULL) - fCreateLinkItem->Menu()->RemoveItem(fCreateLinkItem); - - parent->AddItem(fCreateLinkItem, index); - } + parent->AddItem(fMoveToItem, index++); + parent->AddItem(fCopyToItem, index++); + parent->AddItem(fCreateLinkItem, index++); + parent->AddItem(new BSeparatorItem(), index); // Set the "Create Link" item label here so it // appears correctly when menus are disabled, too. - if ((modifiers() & B_SHIFT_KEY) != 0) - fCreateLinkItem->SetLabel(B_TRANSLATE("Create relative link")); - else - fCreateLinkItem->SetLabel(B_TRANSLATE("Create link")); + Shortcuts()->UpdateCreateLinkItem(fCreateLinkItem); // only enable once the menus are built fMoveToItem->SetEnabled(false); fCopyToItem->SetEnabled(false); fCreateLinkItem->SetEnabled(false); - // get ref for item which is selected - BEntry entry; - if (entry.SetTo(item_ref) != B_OK) - return; - - Model tempModel(&entry); - if (tempModel.InitCheck() != B_OK) - return; - - if (tempModel.IsRoot() || tempModel.IsVolume()) + // not for root or Trash or trashed items + Model model(ref); + if (model.IsRoot() || model.IsTrash() || model.InTrash()) return; // configure "Move to" menu item - PopulateMoveCopyNavMenu(dynamic_cast(fMoveToItem->Submenu()), - kMoveSelectionTo, item_ref, true); + PopulateMoveCopyNavMenu(dynamic_cast(fMoveToItem->Submenu()), kMoveSelectionTo, ref, + true); // configure "Copy to" menu item // add all mounted volumes (except the one this item lives on) - PopulateMoveCopyNavMenu(dynamic_cast(fCopyToItem->Submenu()), - kCopySelectionTo, item_ref, false); + PopulateMoveCopyNavMenu(dynamic_cast(fCopyToItem->Submenu()), kCopySelectionTo, ref, + false); // Set "Create Link" menu item message and // add all mounted volumes (except the one this item lives on) - if ((modifiers() & B_SHIFT_KEY) != 0) { - fCreateLinkItem->SetMessage(new BMessage(kCreateRelativeLink)); - PopulateMoveCopyNavMenu(dynamic_cast - (fCreateLinkItem->Submenu()), - kCreateRelativeLink, item_ref, false); - } else { - fCreateLinkItem->SetMessage(new BMessage(kCreateLink)); - PopulateMoveCopyNavMenu(dynamic_cast - (fCreateLinkItem->Submenu()), - kCreateLink, item_ref, false); - } + PopulateMoveCopyNavMenu(dynamic_cast(fCreateLinkItem->Submenu()), + (modifiers() & B_SHIFT_KEY) != 0 ? kCreateRelativeLink : kCreateLink, ref, false); - fMoveToItem->SetEnabled(PoseView()->CountSelected() > 0 - && !PoseView()->SelectedVolumeIsReadOnly()); - fCopyToItem->SetEnabled(PoseView()->CountSelected() > 0); - fCreateLinkItem->SetEnabled(PoseView()->CountSelected() > 0); - - // Set the "Identify" item label - BMenuItem* identifyItem = parent->FindItem(kIdentifyEntry); - if (identifyItem != NULL) { - if ((modifiers() & B_SHIFT_KEY) != 0) { - identifyItem->SetLabel(B_TRANSLATE("Force identify")); - identifyItem->Message()->ReplaceBool("force", true); - } else { - identifyItem->SetLabel(B_TRANSLATE("Identify")); - identifyItem->Message()->ReplaceBool("force", false); - } - } + Shortcuts()->UpdateMoveToItem(parent->FindItem(kMoveSelectionTo)); + Shortcuts()->UpdateCopyToItem(parent->FindItem(kCopySelectionTo)); + Shortcuts()->UpdateCreateLinkItem(parent->FindItem(Shortcuts()->CreateLinkCommand())); } @@ -2526,32 +2330,22 @@ BContainerWindow::ShowDropContextMenu(BPoint where, BPoseView* source) PoseView()->ConvertToScreen(&global); PoseView()->CommitActivePose(); - // Change the "Create Link" item - allow user to - // create relative links with the Shift key down. - BMenuItem* item = fDropContextMenu->FindItem(kCreateLink); - if (item == NULL) - item = fDropContextMenu->FindItem(kCreateRelativeLink); + Shortcuts()->UpdateCreateLinkHereItem( + fDropContextMenu->FindItem(Shortcuts()->CreateLinkHereCommand())); - if (item != NULL && (modifiers() & B_SHIFT_KEY) != 0) { - item->SetLabel(B_TRANSLATE("Create relative link here")); - item->SetMessage(new BMessage(kCreateRelativeLink)); - } else if (item != NULL) { - item->SetLabel(B_TRANSLATE("Create link here")); - item->SetMessage(new BMessage(kCreateLink)); - } + BMenuItem* item; int32 itemCount = fDropContextMenu->CountItems(); - for(int32 i = 0; i < itemCount - 2; i++) { + for (int32 index = 0; index < itemCount - 2; index++) { // separator item and Cancel item are skipped - item = fDropContextMenu->ItemAt(i); + item = fDropContextMenu->ItemAt(index); if (item == NULL) break; - if (item->Command() == kMoveSelectionTo && source != NULL) { - item->SetEnabled(!source->SelectedVolumeIsReadOnly() - && !PoseView()->TargetVolumeIsReadOnly()); - } else - item->SetEnabled(!PoseView()->TargetVolumeIsReadOnly()); + if (item->Command() == kMoveSelectionTo && source != NULL) + Shortcuts()->UpdateMoveToItem(item); + else + item->SetEnabled(PoseView()->TargetVolumeIsReadOnly() == false); } item = fDropContextMenu->Go(global, true, true); @@ -2573,127 +2367,77 @@ BContainerWindow::ShowContextMenu(BPoint where, const entry_ref* ref) if (ref != NULL) { // clicked on a pose, show file or volume context menu Model model(ref); + if (model.InitCheck() != B_OK) + return; // bail out, do not show context menu - if (model.IsTrash()) { - if (fTrashContextMenu->Window() || Dragging()) - return; + if (Dragging()) { + fContextMenu = NULL; - DeleteSubmenu(fNavigationItem); + BEntry entry; + model.GetEntry(&entry); - // selected item was trash, show the trash context menu instead + // only show for directories (directory, volume, root) + // + // don't show a popup for the trash or printers + // trash is handled in DeskWindow + // + // since this menu is opened asynchronously + // we need to make sure we don't open it more + // than once, the IsShowing flag is set in + // SlowContextPopup::AttachedToWindow and + // reset in DetachedFromWindow + // see the notes in SlowContextPopup::AttachedToWindow - EnableNamedMenuItem(fTrashContextMenu, kEmptyTrash, - static_cast(be_app)->TrashFull()); + if (!FSIsPrintersDir(&entry) && !fDragContextMenu->IsShowing()) { + fDragContextMenu->ClearMenu(); - SetupNavigationMenu(ref, fTrashContextMenu); + // in case the ref is a symlink, resolve it + // only pop open for directories + BEntry resolvedEntry(ref, true); + if (!resolvedEntry.IsDirectory()) + return; - fContextMenu = fTrashContextMenu; - } else { - bool showAsVolume = false; - bool isFilePanel = PoseView()->IsFilePanel(); + entry_ref resolvedRef; + resolvedEntry.GetRef(&resolvedRef); - if (Dragging()) { - fContextMenu = NULL; - - BEntry entry; - model.GetEntry(&entry); - - // only show for directories (directory, volume, root) - // - // don't show a popup for the trash or printers - // trash is handled in DeskWindow - // - // since this menu is opened asynchronously - // we need to make sure we don't open it more - // than once, the IsShowing flag is set in - // SlowContextPopup::AttachedToWindow and - // reset in DetachedFromWindow - // see the notes in SlowContextPopup::AttachedToWindow - - if (!FSIsPrintersDir(&entry) - && !fDragContextMenu->IsShowing()) { - //printf("ShowContextMenu - target is %s %i\n", - // ref->name, IsShowing(ref)); - fDragContextMenu->ClearMenu(); - - // in case the ref is a symlink, resolve it - // only pop open for directories - BEntry resolvedEntry(ref, true); - if (!resolvedEntry.IsDirectory()) - return; - - entry_ref resolvedRef; - resolvedEntry.GetRef(&resolvedRef); - - // use the resolved ref for the menu - fDragContextMenu->SetNavDir(&resolvedRef); - fDragContextMenu->SetTypesList(fCachedTypesList); - fDragContextMenu->SetTarget(BMessenger(this)); - BPoseView* poseView = PoseView(); - if (poseView != NULL) { - BMessenger target(poseView); - fDragContextMenu->InitTrackingHook( - &BPoseView::MenuTrackingHook, &target, - fDragMessage); - } - - // this is now asynchronous so that we don't - // deadlock in Window::Quit, - fDragContextMenu->Go(global); + // use the resolved ref for the menu + fDragContextMenu->SetNavDir(&resolvedRef); + fDragContextMenu->SetTypesList(fCachedTypesList); + fDragContextMenu->SetTarget(BMessenger(this)); + BPoseView* poseView = PoseView(); + if (poseView != NULL) { + BMessenger target(poseView); + fDragContextMenu->InitTrackingHook(&BPoseView::MenuTrackingHook, &target, + fDragMessage); } - return; - } else if (model.IsRoot() || model.IsVolume()) { - fContextMenu = fVolumeContextMenu; - showAsVolume = true; - } else { - fContextMenu = fFileContextMenu; + // this is now asynchronous so that we don't + // deadlock in Window::Quit, + fDragContextMenu->Go(global); } - if (fContextMenu == NULL) - return; - - // bail out before cleanup if popup window is already open - if (fContextMenu->Window() != NULL) - return; - - // clean up items from last context menu - MenusEnded(); - - if (fContextMenu == fFileContextMenu) { - // Add all mounted volumes (except the one this item lives on.) - BNavMenu* navMenu = dynamic_cast( - fCreateLinkItem->Submenu()); - PopulateMoveCopyNavMenu(navMenu, - fCreateLinkItem->Message()->what, ref, false); - } else if (showAsVolume) { - // non-volume enable/disable copy, move, identify - EnableNamedMenuItem(fContextMenu, kDuplicateSelection, false); - EnableNamedMenuItem(fContextMenu, kMoveSelectionToTrash, false); - EnableNamedMenuItem(fContextMenu, kIdentifyEntry, false); - - // volume model, enable/disable the Unmount item - bool ejectableVolumeSelected = false; - - BVolume boot; - BVolumeRoster().GetBootVolume(&boot); - BVolume volume; - volume.SetTo(model.NodeRef()->device); - if (volume != boot) - ejectableVolumeSelected = true; - - EnableNamedMenuItem(fContextMenu, - B_TRANSLATE("Unmount"), ejectableVolumeSelected); - } - - SetupNavigationMenu(ref, fContextMenu); - if (!showAsVolume && !isFilePanel) { - SetupMoveCopyMenus(ref, fContextMenu); - SetupOpenWithMenu(fContextMenu); - } - - UpdateMenu(fContextMenu, kPosePopUpContext); + return; } + + if (model.IsTrash()) + fContextMenu = fTrashContextMenu; + else if (model.IsVolume()) + fContextMenu = fVolumeContextMenu; + else + fContextMenu = fPoseContextMenu; + + // bail out before cleanup if popup window is already open + if (fContextMenu->Window() != NULL) + return; + + // clean up items from last context menu + MenusEnded(); + + // setup nav menu + SetupNavigationMenu(fContextMenu, ref); + + // update the rest + UpdateMenu(fContextMenu, kPosePopUpContext, ref); } else if (fWindowContextMenu != NULL) { // clicked on a window, show window context menu fContextMenu = fWindowContextMenu; @@ -2706,213 +2450,146 @@ BContainerWindow::ShowContextMenu(BPoint where, const entry_ref* ref) MenusEnded(); // setup nav menu - SetupNavigationMenu(TargetModel()->EntryRef(), fContextMenu); + SetupNavigationMenu(fContextMenu, TargetModel()->EntryRef()); // update the rest UpdateMenu(fContextMenu, kWindowPopUpContext); } - // context menu invalid or popup window is already open - if (fContextMenu == NULL || fContextMenu->Window() != NULL) - return; - + // synchronous Go() fContextMenu->Go(global, true, true, true); fContextMenu = NULL; } void -BContainerWindow::AddFileContextMenus(BMenu* menu) +BContainerWindow::AddPoseContextMenu(BMenu* menu) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), - new BMessage(kOpenSelection), 'O')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), - new BMessage(kGetInfo), 'I')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), - new BMessage(kEditItem), 'E')); + menu->AddItem(Shortcuts()->OpenItem()); + // "Edit query" and "Open with..." inserted here, + // see UpdateMenus(), SetupEditQueryItem() and SetupOpenWithMenu() + menu->AddItem(Shortcuts()->GetInfoItem()); + menu->AddItem(Shortcuts()->EditNameItem()); - BMessage* message = new BMessage(kDuplicateSelection); - if (!(TargetModel()->IsTrash() || TargetModel()->InTrash() || TargetModel()->IsPrintersDir())) - menu->AddItem(new BMenuItem(B_TRANSLATE("Duplicate"), message, 'D')); - - if (!(TargetModel()->IsTrash() || TargetModel()->InTrash())) { - message = new BMessage(kMoveSelectionToTrash); - menu->AddItem( new BMenuItem(B_TRANSLATE("Move to Trash"), message, 'T')); - if (!TargetModel()->IsPrintersDir()) { - // add separator for copy to/move to items (navigation items) - menu->AddSeparatorItem(); - } - } else { - message = new BMessage(kDeleteSelection); - menu->AddItem(new BMenuItem(B_TRANSLATE("Delete"), message, 0)); - message = new BMessage(kRestoreSelectionFromTrash); - menu->AddItem(new BMenuItem(B_TRANSLATE("Restore"), message, 0)); + if (TargetModel()->InTrash()) { + menu->AddItem(Shortcuts()->DeleteItem()); + menu->AddItem(Shortcuts()->RestoreItem()); + } else if (!TargetModel()->InTrash()) { + menu->AddItem(Shortcuts()->DuplicateItem()); + menu->AddItem(Shortcuts()->MoveToTrashItem()); } - -#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU - menu->AddSeparatorItem(); - BMenuItem* cutItem = new BMenuItem(B_TRANSLATE("Cut"), - new BMessage(B_CUT), 'X'); - menu->AddItem(cutItem); - BMenuItem* copyItem = new BMenuItem(B_TRANSLATE("Copy"), - new BMessage(B_COPY), 'C'); - menu->AddItem(copyItem); - BMenuItem* pasteItem = new BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V'); - menu->AddItem(pasteItem); -#endif menu->AddSeparatorItem(); - message = new BMessage(kIdentifyEntry); - message->AddBool("force", false); - menu->AddItem(new BMenuItem(B_TRANSLATE("Identify"), message)); + // The "Move To", "Copy To", "Create Link" menus are inserted here, + // have a look at UpdateMenu() and SetupMoveCopyMenus(). - BMenu* addOnMenuItem = new BMenu(B_TRANSLATE("Add-ons")); - menu->AddItem(addOnMenuItem); - - // set targets as needed - menu->SetTargetForItems(PoseView()); #ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU - cutItem->SetTarget(this); - copyItem->SetTarget(this); - pasteItem->SetTarget(this); + if (!TargetModel()->IsPrintersDir() && !TargetModel()->IsRoot() && !TargetModel()->IsTrash() + && !TargetModel()->InTrash()) { + menu->AddItem(Shortcuts()->CutItem()); + menu->AddItem(Shortcuts()->CopyItem()); + menu->AddItem(Shortcuts()->PasteItem()); + menu->AddSeparatorItem(); + } #endif + + menu->AddItem(Shortcuts()->IdentifyItem()); + menu->AddItem(new BMenuItem(new BMenu(Shortcuts()->AddOnsLabel()))); } void -BContainerWindow::AddVolumeContextMenus(BMenu* menu) +BContainerWindow::AddVolumeContextMenu(BMenu* menu) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), - new BMessage(kOpenSelection), 'O')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), - new BMessage(kGetInfo), 'I')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), - new BMessage(kEditItem), 'E')); - - menu->AddSeparatorItem(); - menu->AddItem(new MountMenu(B_TRANSLATE("Mount"))); - - BMenuItem* item = new BMenuItem(B_TRANSLATE("Unmount"), - new BMessage(kUnmountVolume), 'U'); - item->SetEnabled(false); - menu->AddItem(item); + menu->AddItem(Shortcuts()->OpenItem()); + menu->AddItem(Shortcuts()->GetInfoItem()); + menu->AddItem(Shortcuts()->EditNameItem()); menu->AddSeparatorItem(); -#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU - menu->AddItem(new BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V')); + menu->AddItem(Shortcuts()->MountItem(new MountMenu(Shortcuts()->MountLabel()))); + menu->AddItem(Shortcuts()->UnmountItem()); menu->AddSeparatorItem(); -#endif - menu->AddItem(new BMenu(B_TRANSLATE("Add-ons"))); - - menu->SetTargetForItems(PoseView()); + menu->AddItem(new BMenuItem(new BMenu(Shortcuts()->AddOnsLabel()))); } void -BContainerWindow::AddWindowContextMenus(BMenu* menu) +BContainerWindow::AddWindowContextMenu(BMenu* menu) { // create context sensitive menu for empty area of window // since we check view mode before display, this should be a radio // mode menu - Model* targetModel = TargetModel(); - ASSERT(targetModel != NULL); - - bool needSeparator = true; if (TargetModel()->IsTrash()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), - new BMessage(kEmptyTrash))); - } else if (TargetModel()->IsPrintersDir()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Add printer" B_UTF8_ELLIPSIS), - new BMessage(kAddPrinter), 'N')); - } else if (targetModel->InTrash() || targetModel->IsRoot()) { - needSeparator = false; - } else if (!PoseView()->IsFilePanel()) { - TemplatesMenu* templatesMenu = new TemplatesMenu(PoseView(), B_TRANSLATE("New")); - menu->AddItem(templatesMenu); - templatesMenu->SetTargetForItems(PoseView()); - } else { - menu->AddItem(new BMenuItem(B_TRANSLATE("New folder"), new BMessage(kNewFolder), 'N')); + menu->AddItem(Shortcuts()->EmptyTrashItem()); + menu->AddSeparatorItem(); } - if (needSeparator) + if (ShouldHaveNewFolderItem()) { + menu->AddItem(Shortcuts()->NewFolderItem()); menu->AddSeparatorItem(); + } + + if (TargetModel()->IsDesktop()) { + AddIconSizeMenu(menu); + menu->AddSeparatorItem(); + } #ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU - BMenuItem* pasteItem = new BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V'); - pasteItem->SetEnabled(FSClipboardHasRefs() - && !PoseView()->TargetVolumeIsReadOnly()); - menu->AddItem(pasteItem); - menu->AddSeparatorItem(); + if (!(TargetModel()->IsPrintersDir() || TargetModel()->IsVolume() || TargetModel()->IsRoot() + || TargetModel()->IsTrash() || TargetModel()->InTrash())) { + menu->AddItem(Shortcuts()->PasteItem()); + menu->AddSeparatorItem(); + } #endif - BMenu* arrangeBy = new BMenu(B_TRANSLATE("Arrange by")); - PopulateArrangeByMenu(arrangeBy); - menu->AddItem(arrangeBy); - - menu->AddItem(new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A')); - if (!TargetModel()->IsTrash()) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Open parent"), - new BMessage(kOpenParentDir), B_UP_ARROW)); - } - - if (targetModel->IsRoot()) { - menu->AddSeparatorItem(); - menu->AddItem(new MountMenu(B_TRANSLATE("Mount"))); - } - + if (TargetModel()->IsDesktop()) // "Clean up" on Desktop + menu->AddItem(Shortcuts()->CleanupItem()); + // else "Arrange by >" menu inserted here, + // see UpdateMenu() and SetupArrangeByMenu() + menu->AddItem(Shortcuts()->SelectItem()); + menu->AddItem(Shortcuts()->SelectAllItem()); + if (!TargetModel()->IsTrash() && !TargetModel()->IsDesktop()) + menu->AddItem(Shortcuts()->OpenParentItem()); menu->AddSeparatorItem(); - BMenu* addOnMenuItem = new BMenu(B_TRANSLATE("Add-ons")); - menu->AddItem(addOnMenuItem); + + if (!PoseView()->IsFilePanel()) { + if (TargetModel()->IsRoot() || TargetModel()->IsDesktop()) { + menu->AddItem(Shortcuts()->MountItem(new MountMenu(Shortcuts()->MountLabel()))); + menu->AddSeparatorItem(); + } + } + + menu->AddItem(new BMenuItem(new BMenu(Shortcuts()->AddOnsLabel()))); #if DEBUG menu->AddSeparatorItem(); BMenuItem* testing = new BMenuItem("Test icon cache", new BMessage(kTestIconCache)); menu->AddItem(testing); -#endif - - // target items as needed - menu->SetTargetForItems(PoseView()); -#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU - pasteItem->SetTarget(this); + testing->SetTarget(PoseView()); #endif } void -BContainerWindow::AddDropContextMenus(BMenu* menu) +BContainerWindow::AddDropContextMenu(BMenu* menu) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Move here"), - new BMessage(kMoveSelectionTo))); - menu->AddItem(new BMenuItem(B_TRANSLATE("Copy here"), - new BMessage(kCopySelectionTo))); - menu->AddItem(new BMenuItem(B_TRANSLATE("Create link here"), - new BMessage(kCreateLink))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Move here"), new BMessage(kMoveSelectionTo))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Copy here"), new BMessage(kCopySelectionTo))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Create link here"), new BMessage(kCreateLink))); menu->AddSeparatorItem(); - menu->AddItem(new BMenuItem(B_TRANSLATE("Cancel"), - new BMessage(kCancelButton))); + menu->AddItem(new BMenuItem(B_TRANSLATE("Cancel"), new BMessage(kCancelButton))); } void -BContainerWindow::AddTrashContextMenus(BMenu* menu) +BContainerWindow::AddTrashContextMenu(BMenu* menu) { - // setup special trash context menu - menu->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), - new BMessage(kEmptyTrash))); - menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), - new BMessage(kOpenSelection), 'O')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), - new BMessage(kGetInfo), 'I')); - menu->SetTargetForItems(PoseView()); + menu->AddItem(Shortcuts()->EmptyTrashItem()); + menu->AddItem(Shortcuts()->OpenItem()); + menu->AddItem(Shortcuts()->GetInfoItem()); } @@ -2942,16 +2619,13 @@ BContainerWindow::EachAddOn(void (*eachAddOn)(const Model*, const char*, if (info.GetSupportedTypes(&message) == B_OK) { type_code typeCode; int32 count; - if (message.GetInfo("types", &typeCode, - &count) == B_OK) { + if (message.GetInfo("types", &typeCode, &count) == B_OK) secondary = false; - } } // check all supported types if it has some set if (!secondary) { - for (int32 i = mimeTypes.CountStrings(); - !primary && i-- > 0;) { + for (int32 i = mimeTypes.CountStrings(); !primary && i-- > 0;) { BString type = mimeTypes.StringAt(i); if (info.IsSupportedType(type.String())) { BMimeType mimeType(type.String()); @@ -3001,33 +2675,40 @@ BContainerWindow::BuildMimeTypeList(BStringList& mimeTypes) void -BContainerWindow::BuildAddOnsMenu(BMenu* parentMenu) +BContainerWindow::BuildAddOnsMenu(BMenu* parent) { - BMenuItem* item = parentMenu->FindItem(B_TRANSLATE("Add-ons")); - if (parentMenu->IndexOf(item) == 0) { + BMenuItem* addOnsItem = parent->FindItem(Shortcuts()->AddOnsLabel()); + if (parent->IndexOf(addOnsItem) == 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 = parentMenu->ItemAt(parentMenu->CountItems() - 1); - } - if (item == NULL) - return; - - BFont font; { - AutoLock _(parentMenu->Looper()); - parentMenu->GetFont(&font); +#if DEBUG + addOnsItem = parent->ItemAt(parent->CountItems() - 3); +#else + addOnsItem = parent->ItemAt(parent->CountItems() - 1); +#endif } - BMenu* menu = item->Submenu(); - if (menu == NULL) + if (addOnsItem == NULL) return; - menu->SetFont(&font); + BMenu* addOnsMenu = addOnsItem->Submenu(); + if (addOnsMenu == NULL) + return; + + // use a scope block for AutoLock + { + BFont font; + AutoLock _(parent->Looper()); + parent->GetFont(&font); + addOnsMenu->SetFont(&font); + } // found add-ons menu, empty it first + BMenuItem* item; for (;;) { - item = menu->RemoveItem((int32)0); - if (!item) + item = addOnsMenu->RemoveItem((int32)0); + if (item == NULL) break; delete item; } @@ -3043,108 +2724,168 @@ BContainerWindow::BuildAddOnsMenu(BMenu* parentMenu) // build a list of the MIME types of the selected items - EachAddOn(AddOneAddOn, ¶ms, mimeTypes, parentMenu); + EachAddOn(AddOneAddOn, ¶ms, mimeTypes, parent); primaryList.SortItems(CompareLabels); secondaryList.SortItems(CompareLabels); int32 count = primaryList.CountItems(); for (int32 index = 0; index < count; index++) - menu->AddItem(primaryList.ItemAt(index)); + addOnsMenu->AddItem(primaryList.ItemAt(index)); if (count > 0) - menu->AddSeparatorItem(); + addOnsMenu->AddSeparatorItem(); count = secondaryList.CountItems(); for (int32 index = 0; index < count; index++) - menu->AddItem(secondaryList.ItemAt(index)); + addOnsMenu->AddItem(secondaryList.ItemAt(index)); - menu->SetTargetForItems(this); + Shortcuts()->UpdateAddOnsItem(addOnsItem); } void -BContainerWindow::UpdateMenu(BMenu* menu, UpdateMenuContext context) +BContainerWindow::UpdateMenu(BMenu* menu, MenuContext context, const entry_ref* ref) { - const int32 selectCount = PoseView()->CountSelected(); - const int32 poseCount = PoseView()->CountItems(); + // update shared shortcut item's target and enabled state + Shortcuts()->Update(menu); - if (context == kMenuBarContext) { - EnableNamedMenuItem(menu, kOpenSelection, selectCount > 0); - EnableNamedMenuItem(menu, kIdentifyEntry, selectCount > 0); - EnableNamedMenuItem(menu, kRestoreFromTrash, selectCount > 0); - EnableNamedMenuItem(menu, kDeleteSelection, PoseView()->CanMoveToTrashOrDuplicate()); + if (context == kFileMenuContext) + UpdateFileMenu(menu); + else if (context == kWindowMenuContext) + UpdateWindowMenu(menu); + else if (context == kPosePopUpContext) + UpdatePoseContextMenu(menu, ref); + else if (context == kWindowPopUpContext) + UpdateWindowContextMenu(menu); +} + + +void +BContainerWindow::UpdateFileMenu(BMenu* menu) +{ + SetupNewTemplatesMenu(menu, kFileMenuContext); + + UpdateFileMenuOrPoseContextMenu(menu, kFileMenuContext); +} + + +void +BContainerWindow::UpdatePoseContextMenu(BMenu* menu, const entry_ref* ref) +{ + // ref must be set in pose pop up context + ASSERT(ref); + + UpdateFileMenuOrPoseContextMenu(menu, kPosePopUpContext, ref); +} + + +void +BContainerWindow::UpdateFileMenuOrPoseContextMenu(BMenu* menu, MenuContext context, + const entry_ref* ref) +{ + // ref must be set in pose pop up context + if (context == kPosePopUpContext) + ASSERT(ref); + + // if ref unset assume window ref + if (ref == NULL) + ref = TargetModel()->EntryRef(); + + // "Open with..." menu inserted after Open + if (context == kPosePopUpContext) { + if (ShouldHaveOpenWithMenu(ref)) + SetupOpenWithMenu(menu, ref); + } else if (context == kFileMenuContext) { + if (ShouldHaveOpenWithMenu()) + SetupOpenWithMenu(menu); } - if (context == kMenuBarContext || context == kPosePopUpContext) { - SetupEditQueryItem(menu); - - EnableNamedMenuItem(menu, kEditItem, PoseView()->CanEditName()); - EnableNamedMenuItem(menu, kMoveSelectionToTrash, PoseView()->CanMoveToTrashOrDuplicate()); - EnableNamedMenuItem(menu, kDuplicateSelection, PoseView()->CanMoveToTrashOrDuplicate()); - - SetCutItem(menu); - SetCopyItem(menu); - SetPasteItem(menu); + // "Edit query" inserted before "Open with..." + if (context == kPosePopUpContext) { + if (ShouldHaveEditQueryItem(ref)) + SetupEditQueryItem(menu, ref); + } else { + if (ShouldHaveEditQueryItem()) + SetupEditQueryItem(menu); } - if (context == kMenuBarContext || context == kWindowPopUpContext) { - if (!PoseView()->IsFilePanel()) - EnableNamedMenuItem(menu, B_TRANSLATE("New"), !PoseView()->TargetVolumeIsReadOnly()); - else - EnableNamedMenuItem(menu, kNewFolder, !PoseView()->TargetVolumeIsReadOnly()); + // "Move To", "Copy To", "Create Link" menus inserted after "Move to Trash" + if (ShouldHaveMoveCopyMenus(ref)) + SetupMoveCopyMenus(menu, ref); - uint32 viewMode = PoseView()->ViewMode(); + BuildAddOnsMenu(menu); +} - BMenu* iconSizeMenu = NULL; - if (BMenuItem* item = menu->FindItem(kIconMode)) - iconSizeMenu = item->Submenu(); +void +BContainerWindow::UpdateWindowMenu(BMenu* menu) +{ + UpdateWindowMenuOrWindowContextMenu(menu, kWindowMenuContext); +} + + +void +BContainerWindow::UpdateWindowContextMenu(BMenu* menu) +{ + SetupNewTemplatesMenu(menu, kWindowPopUpContext); + + UpdateWindowMenuOrWindowContextMenu(menu, kWindowPopUpContext); + + BuildAddOnsMenu(menu); +} + + +void +BContainerWindow::UpdateWindowMenuOrWindowContextMenu(BMenu* menu, MenuContext context) +{ + // insert "Arrange by >" menu before "Select ..." + SetupArrangeByMenu(menu); + + // update icon menus + uint32 viewMode = PoseView()->ViewMode(); + + // update icon size submenu + BMenuItem* iconModeItem = menu->FindItem(kIconMode); + if (iconModeItem != NULL) { + BMenu* iconSizeMenu = iconModeItem->Submenu(); if (iconSizeMenu != NULL) { if (viewMode == kIconMode) { + // mark the current icon size + BMenuItem* item; + BMessage* message; int32 iconSize = PoseView()->UnscaledIconSizeInt(); - BMenuItem* item = iconSizeMenu->ItemAt(0); - for (int32 i = 0; (item = iconSizeMenu->ItemAt(i)) != NULL; - i++) { - BMessage* message = item->Message(); + int32 itemCount = iconSizeMenu->CountItems(); + for (int32 index = 0; index < itemCount; index++) { + item = iconSizeMenu->ItemAt(index); + if (item == NULL) + continue; + + message = item->Message(); if (message == NULL) { item->SetMarked(false); continue; } - int32 size; - if (message->FindInt32("size", &size) != B_OK) - size = -1; - item->SetMarked(iconSize == size); + + bool sizeMatches = (iconSize == message->GetInt32("size", -1)); + item->SetMarked(sizeMatches); + + // radio mode + if (sizeMatches) + break; } } else { - BMenuItem* item; - for (int32 i = 0; (item = iconSizeMenu->ItemAt(i)) != NULL; i++) - item->SetMarked(false); + // unmark the marked item + BMenuItem* marked = iconSizeMenu->FindMarked(); + if (marked != NULL) + marked->SetMarked(false); } } - - MarkNamedMenuItem(menu, kIconMode, viewMode == kIconMode); - MarkNamedMenuItem(menu, kListMode, viewMode == kListMode); - MarkNamedMenuItem(menu, kMiniIconMode, viewMode == kMiniIconMode); - - SetCloseItem(menu); - SetArrangeMenu(menu); - SetPasteItem(menu); - - EnableNamedMenuItem(menu, kOpenParentDir, !PoseView()->ParentIsRoot()); - EnableNamedMenuItem(menu, kEmptyTrash, poseCount > 0); - EnableNamedMenuItem(menu, B_SELECT_ALL, poseCount > 0); - - BMenuItem* item = menu->FindItem(B_TRANSLATE("New")); - if (item != NULL) { - TemplatesMenu* templatesMenu = dynamic_cast( - item->Submenu()); - if (templatesMenu != NULL) - templatesMenu->UpdateMenuState(); - } } - BuildAddOnsMenu(menu); + MarkNamedMenuItem(menu, kIconMode, viewMode == kIconMode); + MarkNamedMenuItem(menu, kListMode, viewMode == kListMode); + MarkNamedMenuItem(menu, kMiniIconMode, viewMode == kMiniIconMode); } @@ -3195,6 +2936,76 @@ BContainerWindow::LoadAddOn(BMessage* message) } +bool +BContainerWindow::ShouldHaveNavigationMenu(const entry_ref* ref) +{ + if (ref == NULL) { + if (PoseView()->CountSelected() > 0) + ref = PoseView()->SelectionList()->FirstItem()->TargetModel()->EntryRef(); + else + ref = TargetModel()->EntryRef(); + } + + return !PoseView()->IsFilePanel() && !Model(ref).IsQuery(); +} + + +bool +BContainerWindow::ShouldHaveOpenWithMenu(const entry_ref* ref) +{ + if (PoseView()->IsFilePanel()) + return false; + + if (ref == NULL) + ref = TargetModel()->EntryRef(); + + Model model(ref); + if (model.IsPrintersDir()) + return false; + + return !(model.InTrash() || model.IsTrash() || model.IsRoot() || model.IsVolume()); +} + + +bool +BContainerWindow::ShouldHaveEditQueryItem(const entry_ref* ref) +{ + if (ref == NULL) + return FSIsQueriesDir(TargetModel()->EntryRef()); + + Model model(ref); + return model.IsQuery() || model.IsQueryTemplate(); +} + + +bool +BContainerWindow::ShouldHaveMoveCopyMenus(const entry_ref* ref) +{ + if (PoseView()->IsFilePanel()) + return false; + + if (ref == NULL) + ref = TargetModel()->EntryRef(); + + Model model(ref); + if (model.IsPrintersDir()) + return false; + + return !(model.IsTrash() || model.InTrash()); +} + + +bool +BContainerWindow::ShouldHaveNewFolderItem() +{ + if (TargetModel()->IsPrintersDir()) + return false; + + return !(TargetModel()->IsQuery() || TargetModel()->IsRoot() || TargetModel()->IsTrash() + || TargetModel()->InTrash() || TargetModel()->IsVirtualDirectory()); +} + + // #pragma mark - BContainerWindow private methods @@ -3318,12 +3129,28 @@ BContainerWindow::NewAttributeMenuItem(const char* label, const char* name, } +void +BContainerWindow::NewAttributesMenu() +{ + if (fAttrMenu != NULL) + delete fAttrMenu; + + fAttrMenu = new BMenu(B_TRANSLATE("Attributes")); + + NewAttributesMenu(fAttrMenu); +} + + void BContainerWindow::NewAttributesMenu(BMenu* menu) { ASSERT(PoseView()); + // empty menu BMenuItem* item; + while ((item = menu->RemoveItem((int32)0)) != NULL) + delete item; + menu->AddItem(item = new BMenuItem(B_TRANSLATE("Copy layout"), new BMessage(kCopyAttributes))); item->SetTarget(PoseView()); @@ -3371,6 +3198,8 @@ BContainerWindow::NewAttributesMenu(BMenu* menu) menu->AddItem(NewAttributeMenuItem(B_TRANSLATE("Permissions"), kAttrStatMode, B_STRING_TYPE, 80, B_ALIGN_LEFT, false, true)); + + MarkAttributesMenu(menu); } @@ -3403,9 +3232,12 @@ BContainerWindow::MarkAttributesMenu(BMenu* menu) if (menu == NULL) return; - int32 count = menu->CountItems(); - for (int32 index = 0; index < count; index++) { - BMenuItem* item = menu->ItemAt(index); + BMenuItem* item; + BMenu* submenu; + int32 submenuCount; + int32 itemCount = menu->CountItems(); + for (int32 index = 0; index < itemCount; index++) { + item = menu->ItemAt(index); int32 attrHash; if (item->Message() != NULL) { if (item->Message()->FindInt32("attr_hash", &attrHash) == B_OK) @@ -3414,53 +3246,24 @@ BContainerWindow::MarkAttributesMenu(BMenu* menu) item->SetMarked(false); } - BMenu* submenu = item->Submenu(); - if (submenu != NULL) { - int32 count2 = submenu->CountItems(); - for (int32 subindex = 0; subindex < count2; subindex++) { - item = submenu->ItemAt(subindex); - if (item->Message() != NULL) { - if (item->Message()->FindInt32("attr_hash", &attrHash) - == B_OK) { - item->SetMarked(PoseView()->ColumnFor((uint32)attrHash) - != 0); - } else - item->SetMarked(false); - } - } + submenu = item->Submenu(); + if (submenu == NULL) + continue; + + submenuCount = submenu->CountItems(); + for (int32 subindex = 0; subindex < submenuCount; subindex++) { + item = submenu->ItemAt(subindex); + if (item == NULL || item->Message() == NULL) + continue; + if (item->Message()->FindInt32("attr_hash", &attrHash) == B_OK) + item->SetMarked(PoseView()->ColumnFor((uint32)attrHash) != 0); + else + item->SetMarked(false); } } } -void -BContainerWindow::MarkArrangeByMenu(BMenu* menu) -{ - if (menu == NULL) - return; - - int32 count = menu->CountItems(); - for (int32 index = 0; index < count; index++) { - BMenuItem* item = menu->ItemAt(index); - if (item->Message() != NULL) { - uint32 attrHash; - if (item->Message()->FindInt32("attr_hash", - (int32*)&attrHash) == B_OK) { - item->SetMarked(PoseView()->PrimarySort() == attrHash); - } else if (item->Command() == kArrangeReverseOrder) - item->SetMarked(PoseView()->ReverseSort()); - } - } -} - - -void -BContainerWindow::AddMimeTypesToMenu() -{ - AddMimeTypesToMenu(fAttrMenu); -} - - // Adds a menu for a specific MIME type if it doesn't exist already. // Returns the menu, if it existed or not. BMenu* @@ -3556,6 +3359,89 @@ BContainerWindow::AddMimeMenu(const BMimeType& mimeType, bool isSuperType, } +BMenuItem* +BContainerWindow::NewArrangeByMenu() +{ + // must have an Attributes menu for "Arrange by >" + ASSERT(fAttrMenu); + + // create a new "Arrange by >" menu + BMenu* menu = new BMenu(Shortcuts()->ArrangeByLabel()); + + // add Attributes items to "Arrange by >" + BMenuItem* item; + int32 attrCount = fAttrMenu->CountItems(); + for (int32 i = 3; i < attrCount; i++) { + // skip over "Copy layout", "Paste layout" and separator + item = fAttrMenu->ItemAt(i); + if (item == NULL || item->Message() == NULL) + continue; + + item = new BMenuItem(item->Label(), new BMessage(*item->Message())); + item->Message()->what = kArrangeBy; + menu->AddItem(item); + } + menu->AddSeparatorItem(); + + menu->AddItem(Shortcuts()->ReverseOrderItem()); + menu->AddSeparatorItem(); + + menu->AddItem(Shortcuts()->CleanupItem()); + + return new BMenuItem(menu); +} + + +void +BContainerWindow::SetupArrangeByMenu(BMenu* parent) +{ + // first remove "Arrange by >" from the old menu + if (fArrangeByItem != NULL && fArrangeByItem->Menu() != NULL) + fArrangeByItem->Menu()->RemoveItem(fArrangeByItem); + + // bail out if no parent menu to add to + if (parent == NULL) + return; + + // update "Clean up" on Desktop and bail out + if (TargetModel()->IsDesktop()) { + Shortcuts()->UpdateCleanupItem(Shortcuts()->FindItem(parent, kCleanup, kCleanupAll)); + return; + } + + // bail out if no "Select ..." item found + int32 selectIndex = parent->IndexOf(parent->FindItem(kShowSelectionWindow)); + if (selectIndex == B_ERROR) + return; + + // add "Arrange by >" menu before "Select..." + parent->AddItem(fArrangeByItem, selectIndex); + + // mark items + uint32 attrHash; + int32 itemCount = fArrangeByItem->Submenu()->CountItems(); + for (int32 index = 0; index < itemCount; index++) { + BMenuItem* item = fArrangeByItem->Submenu()->ItemAt(index); + if (item == NULL || item->Message() == NULL) + continue; + + if (item->Message()->FindInt32("attr_hash", (int32*)&attrHash) == B_OK) + item->SetMarked(PoseView()->PrimarySort() == attrHash); + else if (item->Message()->what == kArrangeReverseOrder) + item->SetMarked(PoseView()->ReverseSort()); + } + + Shortcuts()->UpdateArrangeByItem(fArrangeByItem); +} + + +void +BContainerWindow::AddMimeTypesToMenu() +{ + AddMimeTypesToMenu(fAttrMenu); +} + + void BContainerWindow::AddMimeTypesToMenu(BMenu* menu) { @@ -3800,7 +3686,7 @@ BContainerWindow::SetupDefaultState() return; } - if (PoseView()->IsDesktop()) { + if (TargetModel()->IsDesktop()) { // don't copy over the attributes if we are the Desktop return; } @@ -3841,7 +3727,7 @@ BContainerWindow::SetupDefaultState() void BContainerWindow::RestoreWindowState(AttributeStreamNode* node) { - if (node == NULL || PoseView()->IsDesktop()) { + if (node == NULL || TargetModel()->IsDesktop()) { // don't restore any window state if we are the Desktop return; } @@ -3899,7 +3785,7 @@ BContainerWindow::RestoreWindowState(AttributeStreamNode* node) void BContainerWindow::RestoreWindowState(const BMessage& message) { - if (PoseView()->IsDesktop()) { + if (TargetModel()->IsDesktop()) { // don't restore any window state if we are the Desktop return; } @@ -4081,11 +3967,11 @@ BContainerWindow::ShowSelectionWindow() void BContainerWindow::ShowNavigator(bool show) { - if (PoseView()->IsDesktop() || !TargetModel()->IsDirectory() || PoseView()->IsFilePanel()) + if (TargetModel()->IsDesktop() || !TargetModel()->IsDirectory() || PoseView()->IsFilePanel()) return; if (show) { - if (Navigator() != NULL && !Navigator()->IsHidden()) + if (Navigator() && !Navigator()->IsHidden()) return; if (Navigator() == NULL) { @@ -4099,7 +3985,7 @@ BContainerWindow::ShowNavigator(bool show) if (PoseView()->VScrollBar()) PoseView()->UpdateScrollRange(); } else { - if (Navigator() == NULL || Navigator()->IsHidden()) + if (!Navigator() || Navigator()->IsHidden()) return; if (PoseView()->VScrollBar()) @@ -4113,11 +3999,11 @@ BContainerWindow::ShowNavigator(bool show) void BContainerWindow::SetSingleWindowBrowseShortcuts(bool enabled) { - if (PoseView()->IsDesktop()) + if (TargetModel()->IsDesktop()) return; if (enabled) { - if (Navigator() == NULL) + if (!Navigator()) return; RemoveShortcut(B_DOWN_ARROW, B_COMMAND_KEY | B_OPTION_KEY); @@ -4211,44 +4097,6 @@ BContainerWindow::PulseTaskLoop() } -void -BContainerWindow::PopulateArrangeByMenu(BMenu* menu) -{ - if (!fAttrMenu || !menu) - return; - // empty fArrangeByMenu... - BMenuItem* item; - while ((item = menu->RemoveItem((int32)0)) != NULL) - delete item; - - int32 itemCount = fAttrMenu->CountItems(); - for (int32 i = 0; i < itemCount; i++) { - item = fAttrMenu->ItemAt(i); - if (item->Command() == kAttributeItem) { - BMessage* message = new BMessage(*(item->Message())); - message->what = kArrangeBy; - BMenuItem* newItem = new BMenuItem(item->Label(), message); - newItem->SetTarget(PoseView()); - menu->AddItem(newItem); - } - } - - menu->AddSeparatorItem(); - - item = new BMenuItem(B_TRANSLATE("Reverse order"), - new BMessage(kArrangeReverseOrder)); - - item->SetTarget(PoseView()); - menu->AddItem(item); - - menu->AddSeparatorItem(); - - item = new BMenuItem(B_TRANSLATE("Clean up"), new BMessage(kCleanup), 'K'); - item->SetTarget(PoseView()); - menu->AddItem(item); -} - - // #pragma mark - WindowStateNodeOpener diff --git a/src/kits/tracker/ContainerWindow.h b/src/kits/tracker/ContainerWindow.h index 3bf1935d74..c3c2e18d85 100644 --- a/src/kits/tracker/ContainerWindow.h +++ b/src/kits/tracker/ContainerWindow.h @@ -63,6 +63,8 @@ class Model; class ModelNodeLazyOpener; class BorderedView; class SelectionWindow; +class TShortcuts; +class TemplatesMenu; #define kDefaultFolderTemplate "DefaultFolderTemplate" @@ -132,6 +134,7 @@ public: Model* TargetModel() const; BPoseView* PoseView() const; + TShortcuts* Shortcuts() const; BNavigator* Navigator() const; virtual void SelectionChanged(); @@ -142,6 +145,8 @@ public: void RestoreStateCommon(); virtual void SaveState(bool hide = true); virtual void SaveState(BMessage &) const; + virtual void SwitchDirectory(const entry_ref* ref); + virtual void OpenParent(); void UpdateTitle(); bool StateNeedsSaving() const; @@ -155,21 +160,27 @@ public: // calls for inheriting window size, attribute layout, etc. // deprecated - virtual void AddMimeTypesToMenu(BMenu*); void AddMimeTypesToMenu(); - virtual void MarkAttributesMenu(BMenu*); - void MarkAttributesMenu(); + void AddMimeTypesToMenu(BMenu*); + + BMenuItem* NewArrangeByMenu(); + virtual void SetupArrangeByMenu(BMenu*); void MarkArrangeByMenu(BMenu*); + BMenuItem* NewAttributeMenuItem(const char* label, const char* name, int32 type, float width, int32 align, bool editable, bool statField); BMenuItem* NewAttributeMenuItem(const char* label, const char* name, int32 type, const char* displayAs, float width, int32 align, bool editable, bool statField); - virtual void NewAttributesMenu(BMenu*); + void NewAttributesMenu(); + virtual void NewAttributesMenu(BMenu*); + void MarkAttributesMenu(); + virtual void MarkAttributesMenu(BMenu*); void HideAttributesMenu(); void ShowAttributesMenu(); + PiggybackTaskLoop* DelayedTaskLoop(); // use for RunLater queueing void PulseTaskLoop(); @@ -196,6 +207,14 @@ public: void SetPathWatchingEnabled(bool); bool IsPathWatchingEnabled(void) const; +protected: + enum MenuContext { + kFileMenuContext, + kWindowMenuContext, + kPosePopUpContext, + kWindowPopUpContext + }; + protected: virtual BPoseView* NewPoseView(Model*, uint32); // instantiate a different flavor of BPoseView for different @@ -217,42 +236,42 @@ protected: // desktop window virtual void AddFileMenu(BMenu* menu); virtual void AddWindowMenu(BMenu* menu); + virtual void AddIconSizeMenu(BMenu* menu); virtual void AddContextMenus(); + virtual void AddPoseContextMenu(BMenu*); + virtual void AddWindowContextMenu(BMenu*); + virtual void AddVolumeContextMenu(BMenu*); + virtual void AddDropContextMenu(BMenu*); + virtual void AddTrashContextMenu(BMenu*); - virtual void AddFileContextMenus(BMenu*); - virtual void AddWindowContextMenus(BMenu*); - virtual void AddVolumeContextMenus(BMenu*); - virtual void AddDropContextMenus(BMenu*); - virtual void AddTrashContextMenus(BMenu*); - + virtual void DetachSubmenus(); virtual void RepopulateMenus(); - void PopulateArrangeByMenu(BMenu*); - virtual void SetCutItem(BMenu*); - virtual void SetCopyItem(BMenu*); - virtual void SetPasteItem(BMenu*); - virtual void SetArrangeMenu(BMenu*); - virtual void SetCloseItem(BMenu*); - virtual void SetupNavigationMenu(const entry_ref*, BMenu*); - virtual void SetupMoveCopyMenus(const entry_ref*, BMenu*); + virtual void SetupNavigationMenu(BMenu*, const entry_ref*); + virtual void SetupMoveCopyMenus(BMenu*, const entry_ref*); virtual void PopulateMoveCopyNavMenu(BNavMenu*, uint32, const entry_ref*, bool); virtual void SetupOpenWithMenu(BMenu*); + virtual void SetupOpenWithMenu(BMenu*, const entry_ref* ref); + virtual void SetupNewTemplatesMenu(BMenu*, MenuContext context); virtual void SetupEditQueryItem(BMenu*); + virtual void SetupEditQueryItem(BMenu*, const entry_ref* ref); virtual void SetupDiskMenu(BMenu*); virtual void BuildAddOnsMenu(BMenu*); void BuildMimeTypeList(BStringList& mimeTypes); - enum UpdateMenuContext { - kMenuBarContext, - kPosePopUpContext, - kWindowPopUpContext - }; - - virtual void UpdateMenu(BMenu* menu, UpdateMenuContext context); + virtual void UpdateMenu(BMenu* menu, MenuContext context, + const entry_ref* ref = NULL); + virtual void UpdateFileMenu(BMenu* menu); + virtual void UpdatePoseContextMenu(BMenu* menu, const entry_ref* ref); + virtual void UpdateFileMenuOrPoseContextMenu(BMenu* menu, MenuContext context, + const entry_ref* ref = NULL); + virtual void UpdateWindowMenu(BMenu* menu); + virtual void UpdateWindowContextMenu(BMenu* menu); + virtual void UpdateWindowMenuOrWindowContextMenu(BMenu* menu, MenuContext context); BMenu* AddMimeMenu(const BMimeType& mimeType, bool isSuperType, BMenu* menu, int32 start); @@ -270,6 +289,12 @@ protected: uint32 fOpenFlags; bool fUsesLayout; + bool ShouldHaveNavigationMenu(const entry_ref* = NULL); + bool ShouldHaveOpenWithMenu(const entry_ref* = NULL); + bool ShouldHaveEditQueryItem(const entry_ref* = NULL); + bool ShouldHaveMoveCopyMenus(const entry_ref* = NULL); + bool ShouldHaveNewFolderItem(); + BGroupLayout* fRootLayout; BGroupView* fMenuContainer; BGridView* fPoseContainer; @@ -277,8 +302,9 @@ protected: BGroupView* fVScrollBarContainer; BGroupView* fCountContainer; + TShortcuts* fShortcuts; BPopUpMenu* fContextMenu; - BPopUpMenu* fFileContextMenu; + BPopUpMenu* fPoseContextMenu; BPopUpMenu* fWindowContextMenu; BPopUpMenu* fDropContextMenu; BPopUpMenu* fVolumeContextMenu; @@ -288,7 +314,9 @@ protected: BMenuItem* fCopyToItem; BMenuItem* fCreateLinkItem; BMenuItem* fOpenWithItem; + BMenuItem* fEditQueryItem; ModelMenuItem* fNavigationItem; + BMenuItem* fNewTemplatesItem; BMenuBar* fMenuBar; DraggableContainerIcon* fDraggableIcon; BNavigator* fNavigator; @@ -296,7 +324,7 @@ protected: BMenu* fAttrMenu; BMenu* fWindowMenu; BMenu* fFileMenu; - BMenu* fArrangeByMenu; + BMenuItem* fArrangeByItem; SelectionWindow* fSelectionWindow; @@ -391,6 +419,13 @@ BContainerWindow::PoseView() const } +inline TShortcuts* +BContainerWindow::Shortcuts() const +{ + return fShortcuts; +} + + inline void BContainerWindow::SetupDiskMenu(BMenu*) { diff --git a/src/kits/tracker/DeskWindow.cpp b/src/kits/tracker/DeskWindow.cpp index a6f9d04cf4..979cf3c488 100644 --- a/src/kits/tracker/DeskWindow.cpp +++ b/src/kits/tracker/DeskWindow.cpp @@ -64,6 +64,7 @@ All rights reserved. #include "KeyInfos.h" #include "MountMenu.h" #include "PoseView.h" +#include "Shortcuts.h" #include "TemplatesMenu.h" #include "Tracker.h" @@ -194,21 +195,17 @@ BDeskWindow::BDeskWindow(LockingList* windowList, uint32 openFlags) fNodeRef(NULL), fShortcutsSettings(NULL) { - // Add icon view switching shortcuts. These are displayed in the context - // menu, although they obviously don't work from those menu items. - BMessage* message = new BMessage(kIconMode); - AddShortcut('1', B_COMMAND_KEY, message, PoseView()); - - message = new BMessage(kMiniIconMode); - AddShortcut('2', B_COMMAND_KEY, message, PoseView()); - - message = new BMessage(kIconMode); - message->AddInt32("scale", 1); - AddShortcut('+', B_COMMAND_KEY, message, PoseView()); - - message = new BMessage(kIconMode); - message->AddInt32("scale", 0); - AddShortcut('-', B_COMMAND_KEY, message, PoseView()); + // create pose view + BDirectory deskDir; + if (FSGetDeskDir(&deskDir) == B_OK) { + BEntry entry; + deskDir.GetEntry(&entry); + Model* model = new Model(&entry, true); + if (model->InitCheck() == B_OK) + CreatePoseView(model); + else + delete model; + } } @@ -254,6 +251,40 @@ BDeskWindow::Init(const BMessage*) if (fDeskShelf != NULL) fDeskShelf->SetDisplaysZombies(true); } + + // Add icon view switching shortcuts. These are displayed in the context + // menu, although they obviously don't work from those menu items. + BMessage* message = new BMessage(kIconMode); + AddShortcut('1', B_COMMAND_KEY, message, PoseView()); + + message = new BMessage(kMiniIconMode); + AddShortcut('2', B_COMMAND_KEY, message, PoseView()); + + message = new BMessage(kIconMode); + message->AddInt32("scale", 1); + AddShortcut('+', B_COMMAND_KEY, message, PoseView()); + + message = new BMessage(kIconMode); + message->AddInt32("scale", 0); + AddShortcut('-', B_COMMAND_KEY, message, PoseView()); + + if (TrackerSettings().ShowDisksIcon()) { + // create model for root of everything + BEntry entry("/"); + Model model(&entry); + if (model.InitCheck() == B_OK) { + // add the root icon to desktop window + BMessage message; + message.what = B_NODE_MONITOR; + message.AddInt32("opcode", B_ENTRY_CREATED); + message.AddInt32("device", model.NodeRef()->device); + message.AddInt64("node", model.NodeRef()->node); + message.AddInt64("directory", model.EntryRef()->directory); + message.AddString("name", model.EntryRef()->name); + + PostMessage(&message, PoseView()); + } + } } @@ -435,92 +466,6 @@ BDeskWindow::CreatePoseView(Model* model) } -void -BDeskWindow::AddWindowContextMenus(BMenu* menu) -{ - TemplatesMenu* tempateMenu = new TemplatesMenu(PoseView(), - B_TRANSLATE("New")); - - menu->AddItem(tempateMenu); - tempateMenu->SetTargetForItems(PoseView()); - - menu->AddSeparatorItem(); - - BMenu* iconSizeMenu = new BMenu(B_TRANSLATE("Icon view")); - BMenuItem* item; - - static const uint32 kIconSizes[] = { 32, 40, 48, 64, 96, 128 }; - BMessage* message; - - for (uint32 i = 0; i < sizeof(kIconSizes) / sizeof(uint32); ++i) { - uint32 iconSize = kIconSizes[i]; - message = new BMessage(kIconMode); - message->AddInt32("size", iconSize); - BString label; - label.SetToFormat(B_TRANSLATE_COMMENT("%" B_PRId32" × %" B_PRId32, - "The '×' is the Unicode multiplication sign U+00D7"), - iconSize, iconSize); - item = new BMenuItem(label, message); - item->SetMarked(PoseView()->IconSizeInt() == iconSize); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - } - - iconSizeMenu->AddSeparatorItem(); - - message = new BMessage(kIconMode); - message->AddInt32("scale", 0); - item = new BMenuItem(B_TRANSLATE("Decrease size"), message, '-'); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - message = new BMessage(kIconMode); - message->AddInt32("scale", 1); - item = new BMenuItem(B_TRANSLATE("Increase size"), message, '+'); - item->SetTarget(PoseView()); - iconSizeMenu->AddItem(item); - - // A sub menu where the super item can be invoked. - menu->AddItem(iconSizeMenu); - iconSizeMenu->Superitem()->SetShortcut('1', B_COMMAND_KEY); - iconSizeMenu->Superitem()->SetMessage(new BMessage(kIconMode)); - iconSizeMenu->Superitem()->SetTarget(PoseView()); - iconSizeMenu->Superitem()->SetMarked(PoseView()->ViewMode() == kIconMode); - - item = new BMenuItem(B_TRANSLATE("Mini icon view"), - new BMessage(kMiniIconMode), '2'); - item->SetMarked(PoseView()->ViewMode() == kMiniIconMode); - menu->AddItem(item); - - menu->AddSeparatorItem(); - -#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU - BMenuItem* pasteItem = new BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V'); - menu->AddItem(pasteItem); - menu->AddSeparatorItem(); -#endif - menu->AddItem(new BMenuItem(B_TRANSLATE("Clean up"), - new BMessage(kCleanup), 'K')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A')); - - menu->AddSeparatorItem(); - menu->AddItem(new MountMenu(B_TRANSLATE("Mount"))); - - menu->AddSeparatorItem(); - menu->AddItem(new BMenu(B_TRANSLATE("Add-ons"))); - - // target items as needed - menu->SetTargetForItems(PoseView()); -#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU - pasteItem->SetTarget(this); -#endif -} - - void BDeskWindow::WorkspaceActivated(int32 workspace, bool state) { diff --git a/src/kits/tracker/DeskWindow.h b/src/kits/tracker/DeskWindow.h index a535673810..dc63f34b0f 100644 --- a/src/kits/tracker/DeskWindow.h +++ b/src/kits/tracker/DeskWindow.h @@ -71,7 +71,6 @@ public: void SaveDesktopPoseLocations(); protected: - virtual void AddWindowContextMenus(BMenu*); virtual BPoseView* NewPoseView(Model*, uint32); virtual void WorkspaceActivated(int32, bool); diff --git a/src/kits/tracker/FilePanel.cpp b/src/kits/tracker/FilePanel.cpp index 749ef04568..7ca770c06b 100644 --- a/src/kits/tracker/FilePanel.cpp +++ b/src/kits/tracker/FilePanel.cpp @@ -296,7 +296,7 @@ BFilePanel::SetPanelDirectory(const entry_ref* ref) if (!lock) return; - static_cast(fWindow)->SetTo(ref); + static_cast(fWindow)->SwitchDirectory(ref); } @@ -312,7 +312,7 @@ BFilePanel::SetPanelDirectory(const char* path) if (!lock) return; - static_cast(fWindow)->SetTo(&ref); + static_cast(fWindow)->SwitchDirectory(&ref); } diff --git a/src/kits/tracker/FilePanelPriv.cpp b/src/kits/tracker/FilePanelPriv.cpp index aef5a354e5..37399b6ae2 100644 --- a/src/kits/tracker/FilePanelPriv.cpp +++ b/src/kits/tracker/FilePanelPriv.cpp @@ -77,6 +77,7 @@ All rights reserved. #include "IconMenuItem.h" #include "MimeTypes.h" #include "NavMenu.h" +#include "Shortcuts.h" #include "Tracker.h" #include "Utilities.h" @@ -114,11 +115,7 @@ key_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter) if (filter == NULL) return B_DISPATCH_MESSAGE; - BLooper* looper = filter->Looper(); - if (looper == NULL) - return B_DISPATCH_MESSAGE; - - TFilePanel* panel = dynamic_cast(looper); + TFilePanel* panel = dynamic_cast(filter->Looper()); if (panel == NULL || panel->TrackingMenu()) return B_DISPATCH_MESSAGE; @@ -135,11 +132,11 @@ key_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter) if ((modifiers & B_COMMAND_KEY) != 0) { switch (key) { case B_UP_ARROW: - looper->PostMessage(kOpenParentDir); + BMessenger(panel).SendMessage(kOpenParentDir); return B_SKIP_MESSAGE; case 'w': - looper->PostMessage(kCancelButton); + BMessenger(panel).SendMessage(kCancelButton); return B_SKIP_MESSAGE; default: @@ -151,9 +148,9 @@ key_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter) if (view->ActivePose() != NULL) view->CommitActivePose(false); else if (view->IsTypeAheadFiltering()) - looper->PostMessage(B_CANCEL, *handler); + BMessenger(panel).SendMessage(B_CANCEL, *handler); else - looper->PostMessage(kCancelButton); + BMessenger(panel).SendMessage(kCancelButton); return B_SKIP_MESSAGE; } @@ -183,6 +180,7 @@ TFilePanel::TFilePanel(file_panel_mode mode, BMessenger* target, const BEntry* s fClientObject(NULL), fSelectionIterator(0), fMessage(NULL), + fFavoritesMenu(NULL), fHideWhenDone(hideWhenDone), fIsTrackingMenu(false), fDefaultStateRestored(false) @@ -212,8 +210,10 @@ TFilePanel::TFilePanel(file_panel_mode mode, BMessenger* target, const BEntry* s else fMessage = new BMessage(B_REFS_RECEIVED); - gLocalizedNamePreferred - = BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); + // no new template menu in file panel + fNewTemplatesItem = NULL; + + gLocalizedNamePreferred = BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); // check for legal starting directory Model* model = new Model(); @@ -357,21 +357,18 @@ TFilePanel::MessageDropFilter(BMessage* message, BHandler**, BMessageFilter* fil entry.GetRef(&ref); - panel->fTaskLoop->RunLater(NewMemberFunctionObjectWithResult - (&TFilePanel::SelectChildInParent, panel, - const_cast(&ref), - const_cast(&child)), - ref == *panel->TargetModel()->EntryRef() ? 0 : 100000, 200000, - 5000000); - // if the target directory is already current, we won't - // delay the initial selection try + // don't delay the initial selection try if the target directory is already current + panel->fTaskLoop->RunLater( + NewMemberFunctionObjectWithResult(&TFilePanel::SelectChildInParent, panel, + const_cast(&ref), const_cast(&child)), + ref == *panel->TargetModel()->EntryRef() ? 0 : 100000, 200000, 5000000); // also set the save name to the dragged in entry if (panel->IsSavePanel()) panel->SetSaveText(path.Leaf()); } - panel->SetTo(&ref); + panel->SwitchDirectory(&ref); return B_SKIP_MESSAGE; } @@ -412,7 +409,7 @@ TFilePanel::FSFilter(BMessage* message, BHandler**, BMessageFilter* filter) // but not wind title if (*(panel->TargetModel()->NodeRef()) == itemNode) { panel->TargetModel()->UpdateEntryRef(&dirNode, name); - panel->SetTo(panel->TargetModel()->EntryRef()); + panel->SwitchDirectory(panel->TargetModel()->EntryRef()); return B_SKIP_MESSAGE; } break; @@ -439,9 +436,7 @@ TFilePanel::FSFilter(BMessage* message, BHandler**, BMessageFilter* filter) root.GetEntry(&entry); entry.GetRef(&ref); - panel->SwitchDirToDesktopIfNeeded(ref); - - panel->SetTo(&ref); + panel->SwitchDirectory(&ref); return B_SKIP_MESSAGE; } break; @@ -544,25 +539,37 @@ TFilePanel::SetRefFilter(BRefFilter* filter) void -TFilePanel::SetTo(const entry_ref* ref) +TFilePanel::SwitchDirectory(const entry_ref* ref) { if (ref == NULL) return; entry_ref setToRef(*ref); bool isDesktop = SwitchDirToDesktopIfNeeded(setToRef); - BEntry entry(&setToRef); - if (entry.InitCheck() != B_OK || !entry.IsDirectory()) + BEntry entry(&setToRef, true); + if (entry.InitCheck() != B_OK) return; PoseView()->SetIsDesktop(isDesktop); - PoseView()->SwitchDir(&setToRef); - SwitchDirMenuTo(&setToRef); + _inherited::SwitchDirectory(&setToRef); AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome)); // our shortcut got possibly removed because the home // menu item got removed - we shouldn't really have to do // this - this is a workaround for a kit bug. + + // update the menu field + for (int32 index = fDirMenu->CountItems() - 1; index >= 0; index--) + delete fDirMenu->RemoveItem(index); + + fDirMenuField->MenuBar()->RemoveItem((int32)0); + fDirMenu->Populate(&entry, 0, true, true, false, true); + + ModelMenuItem* item = dynamic_cast(fDirMenuField->MenuBar()->ItemAt(0)); + ASSERT(item); + + // set dir menu to the new directory + item->SetEntry(&entry); } @@ -711,8 +718,7 @@ TFilePanel::Init(const BMessage*) fDirMenuField->MenuBar()->SetMaxContentWidth(rect.Width() - 26.0f); // Make room for the icon - fDirMenu = new BDirMenu(fDirMenuField->MenuBar(), - this, kSwitchDirectory, "refs"); + fDirMenu = new BDirMenu(fDirMenuField->MenuBar(), this, kSwitchDirectory, "refs"); BEntry entry(TargetModel()->EntryRef()); if (entry.InitCheck() == B_OK) @@ -786,20 +792,18 @@ TFilePanel::Init(const BMessage*) else fBackView->AddChild(fPoseContainer); + fShortcuts = new TShortcuts(this); + AddShortcut('W', B_COMMAND_KEY, new BMessage(kCancelButton)); AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome)); - AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY, - new BMessage(kShowSelectionWindow)); + AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kShowSelectionWindow)); AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), this); - AddShortcut('S', B_COMMAND_KEY, new BMessage(kInvertSelection), - PoseView()); + AddShortcut('S', B_COMMAND_KEY, new BMessage(kInvertSelection), PoseView()); AddShortcut('Y', B_COMMAND_KEY, new BMessage(kResizeToFit), PoseView()); AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY, new BMessage(kOpenDir)); - AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY | B_OPTION_KEY, - new BMessage(kOpenDir)); + AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY | B_OPTION_KEY, new BMessage(kOpenDir)); AddShortcut(B_UP_ARROW, B_COMMAND_KEY, new BMessage(kOpenParentDir)); - AddShortcut(B_UP_ARROW, B_COMMAND_KEY | B_OPTION_KEY, - new BMessage(kOpenParentDir)); + AddShortcut(B_UP_ARROW, B_COMMAND_KEY | B_OPTION_KEY, new BMessage(kOpenParentDir)); if (!fIsSavePanel && (fNodeFlavors & B_DIRECTORY_NODE) == 0) default_button->SetEnabled(false); @@ -808,54 +812,10 @@ TFilePanel::Init(const BMessage*) RestoreState(); - AddMenus(); + if (ShouldAddMenus()) + AddMenus(); AddContextMenus(); - FavoritesMenu* favorites = new FavoritesMenu(B_TRANSLATE("Favorites"), - new BMessage(kSwitchDirectory), new BMessage(B_REFS_RECEIVED), - BMessenger(this), IsSavePanel(), fPoseView->RefFilter()); - favorites->AddItem(new BMenuItem(B_TRANSLATE("Add current folder"), - new BMessage(kAddCurrentDir))); - favorites->AddItem(new BMenuItem( - B_TRANSLATE("Edit favorites" B_UTF8_ELLIPSIS), - new BMessage(kEditFavorites))); - - fMenuBar->AddItem(favorites); - - // configure menus - BMenuItem* item = fMenuBar->FindItem(B_TRANSLATE("Window")); - if (item) { - fMenuBar->RemoveItem(item); - delete item; - } - - item = fMenuBar->FindItem(B_TRANSLATE("File")); - if (item) { - BMenu* menu = item->Submenu(); - if (menu) { - item = menu->FindItem(kOpenSelection); - if (item && menu->RemoveItem(item)) - delete item; - - // remove add-ons menu, identifier menu, separator - item = menu->FindItem(B_TRANSLATE("Add-ons")); - if (item) { - int32 index = menu->IndexOf(item); - delete menu->RemoveItem(index); - delete menu->RemoveItem(--index); - delete menu->RemoveItem(--index); - } - - // remove separator - item = menu->FindItem(B_CUT); - if (item) { - item = menu->ItemAt(menu->IndexOf(item)-1); - if (item && menu->RemoveItem(item)) - delete item; - } - } - } - PoseView()->ScrollTo(B_ORIGIN); PoseView()->UpdateScrollRange(); PoseView()->ScrollTo(B_ORIGIN); @@ -886,6 +846,67 @@ TFilePanel::Init(const BMessage*) } +void +TFilePanel::AddMenus() +{ + // File + + fFileMenu = new BMenu(B_TRANSLATE("File")); + AddFileMenu(fFileMenu); + fMenuBar->AddItem(fFileMenu); + + // Favorites + + fFavoritesMenu = new FavoritesMenu(B_TRANSLATE("Favorites"), new BMessage(kSwitchDirectory), + new BMessage(B_REFS_RECEIVED), BMessenger(this), IsSavePanel(), Filter()); + AddFavoritesMenu(fFavoritesMenu); + fMenuBar->AddItem(fFavoritesMenu); +} + + +void +TFilePanel::AddFileMenu(BMenu* menu) +{ + menu->AddItem(Shortcuts()->NewFolderItem()); + menu->AddItem(new BSeparatorItem()); + + menu->AddItem(Shortcuts()->GetInfoItem()); + menu->AddItem(Shortcuts()->EditNameItem()); + if (TargetModel()->IsTrash() || TargetModel()->InTrash()) { + menu->AddItem(Shortcuts()->DeleteItem()); + menu->AddItem(Shortcuts()->RestoreItem()); + } else { + menu->AddItem(Shortcuts()->DuplicateItem()); + menu->AddItem(Shortcuts()->MoveToTrashItem()); + } + + if (!TargetModel()->IsPrintersDir() || TargetModel()->IsRoot() || TargetModel()->IsTrash() + || TargetModel()->InTrash()) { + menu->AddSeparatorItem(); + menu->AddItem(Shortcuts()->CutItem()); + menu->AddItem(Shortcuts()->CopyItem()); + menu->AddItem(Shortcuts()->PasteItem()); + } +} + + +void +TFilePanel::AddWindowMenu(BMenu* menu) +{ + // no window menu on file panel +} + + +void +TFilePanel::AddFavoritesMenu(BMenu* menu) +{ + const char* name = B_TRANSLATE("Add current folder"); + menu->AddItem(new BMenuItem(name, new BMessage(kAddCurrentDir))); + name = B_TRANSLATE("Edit favorites" B_UTF8_ELLIPSIS); + menu->AddItem(new BMenuItem(name, new BMessage(kEditFavorites))); +} + + void TFilePanel::RestoreState() { @@ -961,103 +982,71 @@ TFilePanel::RestoreWindowState(const BMessage &message) void -TFilePanel::AddFileContextMenus(BMenu* menu) +TFilePanel::AddPoseContextMenu(BMenu* menu) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), - new BMessage(kGetInfo), 'I')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), - new BMessage(kEditItem), 'E')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Duplicate"), - new BMessage(kDuplicateSelection), 'D')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Move to Trash"), - new BMessage(kMoveSelectionToTrash), 'T')); + menu->AddItem(Shortcuts()->GetInfoItem()); + menu->AddItem(Shortcuts()->EditNameItem()); + if (TargetModel()->InTrash()) { + menu->AddItem(Shortcuts()->DeleteItem()); + menu->AddItem(Shortcuts()->RestoreItem()); + } else { + menu->AddItem(Shortcuts()->DuplicateItem()); + menu->AddItem(Shortcuts()->MoveToTrashItem()); + } menu->AddSeparatorItem(); - BMenuItem* cutItem = new BMenuItem(B_TRANSLATE("Cut"), - new BMessage(B_CUT), 'X'); - menu->AddItem(cutItem); - BMenuItem* copyItem = new BMenuItem(B_TRANSLATE("Copy"), - new BMessage(B_COPY), 'C'); - menu->AddItem(copyItem); -#if CUT_COPY_PASTE_IN_CONTEXT_MENU - BMenuItem* pasteItem = new BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V'); - menu->AddItem(pasteItem); -#endif - - menu->SetTargetForItems(PoseView()); - cutItem->SetTarget(this); - copyItem->SetTarget(this); -#if CUT_COPY_PASTE_IN_CONTEXT_MENU - pasteItem->SetTarget(this); + menu->AddItem(Shortcuts()->CutItem()); + menu->AddItem(Shortcuts()->CopyItem()); +#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU + menu->AddItem(Shortcuts()->PasteItem()); #endif } void -TFilePanel::AddVolumeContextMenus(BMenu* menu) +TFilePanel::AddVolumeContextMenu(BMenu* menu) { - menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), - new BMessage(kOpenSelection), 'O')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), - new BMessage(kGetInfo), 'I')); - menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), - new BMessage(kEditItem), 'E')); + menu->AddItem(Shortcuts()->OpenItem()); + menu->AddItem(Shortcuts()->GetInfoItem()); + menu->AddItem(Shortcuts()->EditNameItem()); -#if CUT_COPY_PASTE_IN_CONTEXT_MENU +#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU menu->AddSeparatorItem(); - BMenuItem* pasteItem = new BMenuItem(B_TRANSLATE("Paste"), - new BMessage(B_PASTE), 'V'); -#endif - - menu->SetTargetForItems(PoseView()); -#if CUT_COPY_PASTE_IN_CONTEXT_MENU - pasteItem->SetTarget(this); + menu->AddItem(Shortcuts()->PasteItem()); #endif } void -TFilePanel::AddWindowContextMenus(BMenu* menu) +TFilePanel::AddWindowContextMenu(BMenu* menu) { - BMenuItem* item = new BMenuItem(B_TRANSLATE("New folder"), - new BMessage(kNewFolder), 'N'); - item->SetTarget(PoseView()); - menu->AddItem(item); - menu->AddSeparatorItem(); + menu->AddItem(Shortcuts()->NewFolderItem()); + menu->AddItem(new BSeparatorItem()); -#if CUT_COPY_PASTE_IN_CONTEXT_MENU - item = new BMenuItem(B_TRANSLATE("Paste"), new BMessage(B_PASTE), 'V'); - item->SetTarget(this); - menu->AddItem(item); +#ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU + menu->AddItem(Shortcuts()->PasteItem()); menu->AddSeparatorItem(); #endif - item = new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A'); - item->SetTarget(this); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Invert selection"), - new BMessage(kInvertSelection), 'S'); - item->SetTarget(PoseView()); - menu->AddItem(item); - - item = new BMenuItem(B_TRANSLATE("Go to parent"), - new BMessage(kOpenParentDir), B_UP_ARROW); - item->SetTarget(this); - menu->AddItem(item); + menu->AddItem(Shortcuts()->SelectItem()); + menu->AddItem(Shortcuts()->SelectAllItem()); + menu->AddItem(Shortcuts()->InvertSelectionItem()); + menu->AddItem(Shortcuts()->OpenParentItem()); } void -TFilePanel::AddDropContextMenus(BMenu*) +TFilePanel::AddTrashContextMenu(BMenu* menu) { + // use default window context menu on Trash + AddWindowContextMenu(menu); +} + + +void +TFilePanel::AddDropContextMenu(BMenu*) +{ + // do nothing here so drop context menu doesn't get added } @@ -1073,17 +1062,7 @@ TFilePanel::MenusBeginning() PoseView()->CommitActivePose(); } - EnableNamedMenuItem(fMenuBar, kNewFolder, !TargetModel()->IsRoot() - && !PoseView()->TargetVolumeIsReadOnly()); - EnableNamedMenuItem(fMenuBar, kDuplicateSelection, - PoseView()->CanMoveToTrashOrDuplicate()); - EnableNamedMenuItem(fMenuBar, kMoveSelectionToTrash, - PoseView()->CanMoveToTrashOrDuplicate()); - EnableNamedMenuItem(fMenuBar, kEditItem, PoseView()->CanEditName()); - - SetCutItem(fMenuBar); - SetCopyItem(fMenuBar); - SetPasteItem(fMenuBar); + UpdateMenu(fFileMenu, kFileMenuContext); fIsTrackingMenu = true; } @@ -1097,64 +1076,74 @@ TFilePanel::MenusEnded() void -TFilePanel::ShowContextMenu(BPoint where, const entry_ref* ref) +TFilePanel::DetachSubmenus() { - ASSERT(IsLocked()); - BPoint global(where); - PoseView()->ConvertToScreen(&global); - PoseView()->CommitActivePose(); - - if (ref != NULL) { - // clicked on a pose, show file or volume context menu - Model model(ref); - if (model.InitCheck() != B_OK) - return; // bail out, do not show context menu - - if (TargetModel()->IsRoot() || model.IsVolume()) { - // Volume context menu - fContextMenu = fVolumeContextMenu; - EnableNamedMenuItem(fContextMenu, kOpenSelection, true); - EnableNamedMenuItem(fContextMenu, kEditItem, - PoseView()->CanEditName()); - - SetPasteItem(fContextMenu); - } else { - // File context menu - fContextMenu = fFileContextMenu; - EnableNamedMenuItem(fContextMenu, kEditItem, - PoseView()->CanEditName()); - EnableNamedMenuItem(fContextMenu, kDuplicateSelection, - PoseView()->CanMoveToTrashOrDuplicate()); - EnableNamedMenuItem(fContextMenu, kMoveSelectionToTrash, - PoseView()->CanMoveToTrashOrDuplicate()); - - SetCutItem(fContextMenu); - SetCopyItem(fContextMenu); - SetPasteItem(fContextMenu); - } - } else { - // Window context menu - fContextMenu = fWindowContextMenu; - EnableNamedMenuItem(fContextMenu, kNewFolder, - !TargetModel()->IsRoot() - && !PoseView()->TargetVolumeIsReadOnly()); - EnableNamedMenuItem(fContextMenu, kOpenParentDir, - !TargetModel()->IsRoot()); - - SetPasteItem(fContextMenu); - } - - // context menu invalid or popup window is already open - if (fContextMenu == NULL || fContextMenu->Window() != NULL) - return; - - fContextMenu->Go(global, true, true, true); - fContextMenu = NULL; + // no submenus to detatch in file panel } void -TFilePanel::SetupNavigationMenu(const entry_ref*, BMenu*) +TFilePanel::UpdateFileMenu(BMenu*) +{ + // nothing more to do +} + + +void +TFilePanel::UpdateFileMenuOrPoseContextMenu(BMenu*, MenuContext, const entry_ref*) +{ + // nothing more to do +} + + +void +TFilePanel::UpdateWindowMenu(BMenu*) +{ + // no window menu on file panel +} + + +void +TFilePanel::UpdateWindowContextMenu(BMenu*) +{ + // nothing more to do +} + + +void +TFilePanel::UpdateWindowMenuOrWindowContextMenu(BMenu*, MenuContext) +{ + // nothing more to do +} + + +void +TFilePanel::RepopulateMenus() +{ + if (fMenuBar != NULL && fFileMenu != NULL) { + fMenuBar->RemoveItem(fFileMenu); + delete fFileMenu; + if (ShouldAddMenus()) { + fFileMenu = new BMenu(B_TRANSLATE("File")); + TFilePanel::AddFileMenu(fFileMenu); + fMenuBar->AddItem(fFileMenu, 0); + } + } + + delete fPoseContextMenu; + fPoseContextMenu = new BPopUpMenu("PoseContext", false, false); + fPoseContextMenu->SetFont(be_plain_font); + TFilePanel::AddPoseContextMenu(fPoseContextMenu); + + delete fWindowContextMenu; + fWindowContextMenu = new BPopUpMenu("WindowContext", false, false); + fWindowContextMenu->SetFont(be_plain_font); + TFilePanel::AddWindowContextMenu(fWindowContextMenu); +} + + +void +TFilePanel::SetupNavigationMenu(BMenu*, const entry_ref*) { // do nothing here so nav menu doesn't get added } @@ -1230,84 +1219,77 @@ TFilePanel::MessageReceived(BMessage* message) switch (message->what) { case B_REFS_RECEIVED: + { // item was double clicked in file panel (PoseView) or from the favorites menu - if (message->FindRef("refs", &ref) == B_OK) { - BEntry entry(&ref, true); - if (entry.InitCheck() == B_OK) { - // Double-click on dir or link-to-dir ALWAYS opens the - // dir. If more than one dir is selected, the first is - // entered. - if (entry.IsDirectory()) { - entry.GetRef(&ref); - bool isDesktop = SwitchDirToDesktopIfNeeded(ref); + if (message->FindRef("refs", &ref) != B_OK) + break; - PoseView()->SetIsDesktop(isDesktop); - entry.SetTo(&ref); - PoseView()->SwitchDir(&ref); - SwitchDirMenuTo(&ref); - } else { - // Otherwise, we have a file or a link to a file. - // AdjustButton has already tested the flavor if it comes from the file - // panel; all we have to do is see if the button is enabled. - // In other cases, however, we can't rely on that. So first check for - // TrackerViewToken in the message to see if it's coming from the pose view - if (message->HasMessenger("TrackerViewToken")) { - BButton* button = dynamic_cast(FindView("default button")); - if (button == NULL || !button->IsEnabled()) - break; - } + BEntry entry(&ref, true); + if (entry.InitCheck() != B_OK) + break; - if (IsSavePanel()) { - int32 count = 0; - type_code type; - message->GetInfo("refs", &type, &count); - - // Don't allow saves of multiple files - if (count > 1) { - ShowCenteredAlert( - B_TRANSLATE( - "Sorry, saving more than one " - "item is not allowed."), - B_TRANSLATE("Cancel")); - } else { - // if we are a savepanel, set up the - // filepanel correctly then pass control - // so we follow the same path as if the user - // clicked the save button - - // set the 'name' fld to the current ref's - // name notify the panel that the default - // button should be enabled - SetSaveText(ref.name); - SelectionChanged(); - - HandleSaveButton(); - } - break; - } - - // send handler a message and close - BMessage openMessage(*fMessage); - for (int32 index = 0; ; index++) { - if (message->FindRef("refs", index, &ref) != B_OK) - break; - openMessage.AddRef("refs", &ref); - } - OpenSelectionCommon(&openMessage); - } + // Double-click on dir or link-to-dir ALWAYS opens the dir. + // If more than one dir is selected the first one is opened. + if (entry.IsDirectory()) { + SwitchDirectory(&ref); + } else { + // Otherwise, we have a file or a link to a file. + // AdjustButton has already tested the flavor if it comes from the file + // panel; all we have to do is see if the button is enabled. + // In other cases, however, we can't rely on that. So first check for + // TrackerViewToken in the message to see if it's coming from the pose view + if (message->HasMessenger("TrackerViewToken")) { + BButton* button = dynamic_cast(FindView("default button")); + if (button == NULL || !button->IsEnabled()) + break; } + + if (IsSavePanel()) { + int32 count = 0; + type_code type; + message->GetInfo("refs", &type, &count); + + // Don't allow saves of multiple files + if (count > 1) { + const char* sorry + = B_TRANSLATE("Sorry, saving more than one item is not allowed."); + ShowCenteredAlert(sorry, B_TRANSLATE("Cancel")); + } else { + // if we are a savepanel, set up the + // filepanel correctly then pass control + // so we follow the same path as if the user + // clicked the save button + + // set the 'name' fld to the current ref's + // name notify the panel that the default + // button should be enabled + SetSaveText(ref.name); + SelectionChanged(); + + HandleSaveButton(); + } + break; + } + + // send handler a message and close + BMessage openMessage(*fMessage); + for (int32 index = 0;; index++) { + if (message->FindRef("refs", index, &ref) != B_OK) + break; + openMessage.AddRef("refs", &ref); + } + OpenSelectionCommon(&openMessage); } break; + } case kSwitchDirectory: { entry_ref ref; - // this comes from dir menu or nav menu, so switch directories - if (message->FindRef("refs", &ref) == B_OK) { - BEntry entry(&ref, true); - if (entry.GetRef(&ref) == B_OK) - SetTo(&ref); - } + if (message->FindRef("refs", &ref) != B_OK) + break; + + SwitchDirectory(&ref); break; } @@ -1320,7 +1302,7 @@ TFilePanel::MessageReceived(BMessage* message) break; } - SetTo(&ref); + SwitchDirectory(&ref); break; } @@ -1387,8 +1369,7 @@ TFilePanel::MessageReceived(BMessage* message) if (fIsSavePanel) { if (PoseView()->IsFocus() && PoseView()->CountSelected() == 1) { - Model* model = (PoseView()->SelectionList()-> - FirstItem())->TargetModel(); + Model* model = (PoseView()->SelectionList()->FirstItem())->TargetModel(); if (model->ResolveIfLink()->IsDirectory()) { PoseView()->CommitActivePose(); PoseView()->OpenSelection(); @@ -1404,20 +1385,21 @@ TFilePanel::MessageReceived(BMessage* message) case B_OBSERVER_NOTICE_CHANGE: { int32 observerWhat; - if (message->FindInt32("be:observe_change_what", &observerWhat) - == B_OK) { + if (message->FindInt32("be:observe_change_what", &observerWhat) == B_OK) { switch (observerWhat) { case kDesktopFilePanelRootChanged: { - bool desktopIsRoot = true; - if (message->FindBool("DesktopFilePanelRoot", - &desktopIsRoot) == B_OK) { - TrackerSettings(). - SetDesktopFilePanelRoot(desktopIsRoot); + bool desktopIsRoot; + if (message->FindBool("DesktopFilePanelRoot", &desktopIsRoot) == B_OK + && TrackerSettings().DesktopFilePanelRoot() != desktopIsRoot) { + TrackerSettings().SetDesktopFilePanelRoot(desktopIsRoot); + SwitchDirectory(TargetModel()->EntryRef()); } - SetTo(TargetModel()->EntryRef()); break; } + + default: + break; } } break; @@ -1441,7 +1423,7 @@ TFilePanel::OpenDirectory() if (model->ResolveIfLink()->IsDirectory()) { BMessage message(B_REFS_RECEIVED); message.AddRef("refs", model->EntryRef()); - PostMessage(&message); + BMessenger(this).SendMessage(&message); } } @@ -1449,52 +1431,29 @@ TFilePanel::OpenDirectory() void TFilePanel::OpenParent() { - if (!CanOpenParent()) - return; + BEntry entry(TargetModel()->EntryRef()); + Model oldModel(*PoseView()->TargetModel()); + const node_ref* oldNode = oldModel.NodeRef(); BEntry parentEntry; - BDirectory dir; - - Model oldModel(*PoseView()->TargetModel()); - BEntry entry(oldModel.EntryRef()); - - if (entry.InitCheck() == B_OK - && entry.GetParent(&dir) == B_OK - && dir.GetEntry(&parentEntry) == B_OK - && entry != parentEntry) { - - entry_ref ref; - parentEntry.GetRef(&ref); - - PoseView()->SetIsDesktop(SwitchDirToDesktopIfNeeded(ref)); - PoseView()->SwitchDir(&ref); - SwitchDirMenuTo(&ref); - - // Make sure the child gets selected in the new view - // once it shows up. - fTaskLoop->RunLater(NewMemberFunctionObjectWithResult - (&TFilePanel::SelectChildInParent, this, - const_cast(&ref), - oldModel.NodeRef()), 100000, 200000, 5000000); - } -} - - -bool -TFilePanel::CanOpenParent() const -{ - if (TrackerSettings().DesktopFilePanelRoot()) { - // don't allow opening Desktop folder's parent - if (TargetModel()->IsDesktop()) - return false; + if (TrackerSettings().DesktopFilePanelRoot() && FSIsRootDir(&entry)) { + // open parent on root, set to Desktop + BDirectory desktopDir; + if (FSGetDeskDir(&desktopDir) != B_OK || desktopDir.GetEntry(&parentEntry) != B_OK) + return; + } else if (FSGetParentVirtualDirectoryAware(entry, parentEntry) != B_OK) { + return; } - // block on "/" - BEntry root("/"); - node_ref rootRef; - root.GetNodeRef(&rootRef); + entry_ref setToRef; + parentEntry.GetRef(&setToRef); + const entry_ref* parent = &setToRef; + SwitchDirectory(parent); - return rootRef != *TargetModel()->NodeRef(); + // Make sure the child gets selected in the new view once it shows up. + fTaskLoop->RunLater( + NewMemberFunctionObjectWithResult(&TFilePanel::SelectChildInParent, this, parent, oldNode), + 100000, 200000, 5000000); } @@ -1510,19 +1469,17 @@ TFilePanel::SwitchDirToDesktopIfNeeded(entry_ref &ref) return false; BEntry entry(&ref); - BEntry root("/"); BDirectory desktopDir; FSGetDeskDir(&desktopDir); - if (FSIsDeskDir(&entry) - // navigated into non-boot desktop, switch to boot desktop - || (entry == root && !settings.ShowDisksIcon())) { - // hit "/" level, map to desktop + if (FSIsDeskDir(&entry) || (!settings.ShowDisksIcon() && FSIsRootDir(&entry))) { + // navigated into desktop folder or hit "root" level, switch to Desktop desktopDir.GetEntry(&entry); entry.GetRef(&ref); return true; } + return FSIsDeskDir(&entry); } @@ -1723,25 +1680,6 @@ TFilePanel::HandleOpenButton() } -void -TFilePanel::SwitchDirMenuTo(const entry_ref* ref) -{ - BEntry entry(ref); - for (int32 index = fDirMenu->CountItems() - 1; index >= 0; index--) - delete fDirMenu->RemoveItem(index); - - fDirMenuField->MenuBar()->RemoveItem((int32)0); - fDirMenu->Populate(&entry, 0, true, true, false, true); - - ModelMenuItem* item = dynamic_cast( - fDirMenuField->MenuBar()->ItemAt(0)); - ASSERT(item != NULL); - - if (item != NULL) - item->SetEntry(&entry); -} - - void TFilePanel::WindowActivated(bool active) { @@ -1897,9 +1835,9 @@ BFilePanelPoseView::ShowVolumes(bool visible, bool showShared) AddRootPoses(true, showShared); } - TFilePanel* filepanel = dynamic_cast(Window()); - if (filepanel != NULL && TargetModel() != NULL) - filepanel->SetTo(TargetModel()->EntryRef()); + TFilePanel* panel = dynamic_cast(Window()); + if (panel != NULL && TargetModel() != NULL) + panel->SwitchDirectory(TargetModel()->EntryRef()); } @@ -1912,8 +1850,7 @@ BFilePanelPoseView::AdaptToVolumeChange(BMessage* message) message->FindBool("ShowDisksIcon", &showDisksIcon); message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop); - message->FindBool("MountSharedVolumesOntoDesktop", - &mountSharedVolumesOntoDesktop); + message->FindBool("MountSharedVolumesOntoDesktop", &mountSharedVolumesOntoDesktop); BEntry entry("/"); Model model(&entry); @@ -1931,8 +1868,7 @@ BFilePanelPoseView::AdaptToVolumeChange(BMessage* message) monitorMsg.AddInt64("directory", model.EntryRef()->directory); monitorMsg.AddString("name", model.EntryRef()->name); TrackerSettings().SetShowDisksIcon(showDisksIcon); - if (Window() != NULL) - Window()->PostMessage(&monitorMsg, this); + Window()->PostMessage(&monitorMsg, this); } ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop); @@ -1946,8 +1882,7 @@ BFilePanelPoseView::AdaptToDesktopIntegrationChange(BMessage* message) bool mountSharedVolumesOntoDesktop = true; message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop); - message->FindBool("MountSharedVolumesOntoDesktop", - &mountSharedVolumesOntoDesktop); + message->FindBool("MountSharedVolumesOntoDesktop", &mountSharedVolumesOntoDesktop); ShowVolumes(false, mountSharedVolumesOntoDesktop); ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop); diff --git a/src/kits/tracker/FilePanelPriv.h b/src/kits/tracker/FilePanelPriv.h index bfbc000bfa..341a48a397 100644 --- a/src/kits/tracker/FilePanelPriv.h +++ b/src/kits/tracker/FilePanelPriv.h @@ -73,14 +73,13 @@ public: virtual void MenusBeginning(); virtual void MenusEnded(); virtual void DispatchMessage(BMessage* message, BHandler* handler); - virtual void ShowContextMenu(BPoint, const entry_ref*); void SetClientObject(BFilePanel*); void SetRefFilter(BRefFilter*); void SetNodeFlavors(uint32 nodeFlavors) { fNodeFlavors = nodeFlavors; } void SetSaveText(const char* text); void SetButtonLabel(file_panel_button, const char* text); - void SetTo(const entry_ref* ref); + virtual void SwitchDirectory(const entry_ref*); virtual void SelectionChanged(); void HandleOpenButton(); void HandleSaveButton(); @@ -115,12 +114,26 @@ protected: virtual void RestoreWindowState(const BMessage&); virtual void RestoreState(const BMessage&); - virtual void AddFileContextMenus(BMenu*); - virtual void AddVolumeContextMenus(BMenu*); - virtual void AddWindowContextMenus(BMenu*); - virtual void AddDropContextMenus(BMenu*); + virtual void AddMenus(); + virtual void AddFileMenu(BMenu* menu); + virtual void AddWindowMenu(BMenu* menu); + virtual void AddFavoritesMenu(BMenu* menu); - virtual void SetupNavigationMenu(const entry_ref*, BMenu*); + virtual void AddPoseContextMenu(BMenu*); + virtual void AddVolumeContextMenu(BMenu*); + virtual void AddWindowContextMenu(BMenu*); + virtual void AddDropContextMenu(BMenu*); + virtual void AddTrashContextMenu(BMenu*); + + virtual void UpdateFileMenu(BMenu*); + virtual void UpdateFileMenuOrPoseContextMenu(BMenu*, MenuContext, const entry_ref* = NULL); + virtual void UpdateWindowMenu(BMenu*); + virtual void UpdateWindowContextMenu(BMenu*); + virtual void UpdateWindowMenuOrWindowContextMenu(BMenu*, MenuContext); + + virtual void DetachSubmenus(); + virtual void RepopulateMenus(); + virtual void SetupNavigationMenu(BMenu*, const entry_ref*); virtual void OpenDirectory(); virtual void OpenParent(); virtual void WindowActivated(bool state); @@ -134,8 +147,6 @@ protected: private: bool SwitchDirToDesktopIfNeeded(entry_ref &ref); - bool CanOpenParent() const; - void SwitchDirMenuTo(const entry_ref* ref); void AdjustButton(); bool SelectChildInParent(const entry_ref* parent, const node_ref* child); void OpenSelectionCommon(BMessage*); @@ -150,6 +161,7 @@ private: BFilePanel* fClientObject; int32 fSelectionIterator; BMessage* fMessage; + BMenu* fFavoritesMenu; BString fButtonText; bool fHideWhenDone; bool fIsTrackingMenu; diff --git a/src/kits/tracker/Jamfile b/src/kits/tracker/Jamfile index f9fead87f7..f29fa14677 100644 --- a/src/kits/tracker/Jamfile +++ b/src/kits/tracker/Jamfile @@ -74,6 +74,7 @@ for architectureObject in [ MultiArchSubDirSetup ] { SelectionWindow.cpp Settings.cpp SettingsViews.cpp + Shortcuts.cpp SlowMenu.cpp StatusWindow.cpp TaskLoop.cpp @@ -138,6 +139,7 @@ DoCatalogs libtracker.so : RegExp.cpp SelectionWindow.cpp SettingsViews.cpp + Shortcuts.cpp StatusWindow.cpp TemplatesMenu.cpp TextWidget.cpp diff --git a/src/kits/tracker/PoseView.cpp b/src/kits/tracker/PoseView.cpp index 3734df9f49..1703e7078c 100644 --- a/src/kits/tracker/PoseView.cpp +++ b/src/kits/tracker/PoseView.cpp @@ -92,6 +92,7 @@ All rights reserved. #include "MimeTypes.h" #include "Navigator.h" #include "Pose.h" +#include "Shortcuts.h" #include "Tests.h" #include "Thread.h" #include "Tracker.h" @@ -1656,7 +1657,7 @@ void BPoseView::AddPosesCompleted() { BContainerWindow* window = ContainerWindow(); - if (window != NULL) + if (window != NULL && window->ShouldAddMenus()) window->AddMimeTypesToMenu(); // if we're not in icon mode then we need to check for poses that @@ -2440,7 +2441,7 @@ BPoseView::MessageReceived(BMessage* message) IdentifySelection(message->GetBool("force", false)); break; - case kEditItem: + case kEditName: { if (ActivePose()) break; @@ -6232,17 +6233,14 @@ BPoseView::DeleteSelection(bool selectNext, bool confirm) if (selectCount <= 0) return; - if (!CheckVolumeReadOnly( - fSelectionList->ItemAt(0)->TargetModel()->EntryRef())) { + if (!CheckVolumeReadOnly(fSelectionList->ItemAt(0)->TargetModel()->EntryRef())) return; - } - BObjectList* entriesToDelete - = new BObjectList(selectCount, true); + BObjectList* entriesToDelete = new BObjectList(selectCount, true); for (int32 index = 0; index < selectCount; index++) { - entriesToDelete->AddItem(new entry_ref( - *fSelectionList->ItemAt(index)->TargetModel()->EntryRef())); + entry_ref* ref = new entry_ref(*fSelectionList->ItemAt(index)->TargetModel()->EntryRef()); + entriesToDelete->AddItem(ref); } Delete(entriesToDelete, selectNext, confirm); @@ -6271,8 +6269,7 @@ BPoseView::RestoreSelectionFromTrash(bool selectNext) void BPoseView::Delete(const entry_ref &ref, bool selectNext, bool confirm) { - BObjectList* entriesToDelete - = new BObjectList(1, true); + BObjectList* entriesToDelete = new BObjectList(1, true); entriesToDelete->AddItem(new entry_ref(ref)); Delete(entriesToDelete, selectNext, confirm); @@ -6287,8 +6284,7 @@ BPoseView::Delete(BObjectList* list, bool selectNext, bool confirm) return; } - BObjectList* taskList = - new BObjectList(2, true); + BObjectList* taskList = new BObjectList(2, true); // first move selection to trash, taskList->AddItem(NewFunctionObject(FSDeleteRefList, list, false, confirm)); @@ -6311,8 +6307,7 @@ BPoseView::Delete(BObjectList* list, bool selectNext, bool confirm) // deleted Model* targetModel = TargetModel(); ASSERT(targetModel != NULL); - taskList->AddItem(NewMemberFunctionObject( - &TTracker::SelectPoseAtLocationSoon, tracker, + taskList->AddItem(NewMemberFunctionObject(&TTracker::SelectPoseAtLocationSoon, tracker, *targetModel->NodeRef(), pointInPose)); } } @@ -6330,8 +6325,7 @@ BPoseView::RestoreItemsFromTrash(BObjectList* list, bool selectNext) return; } - BObjectList* taskList = - new BObjectList(2, true); + BObjectList* taskList = new BObjectList(2, true); // first restoree selection taskList->AddItem(NewFunctionObject(FSRestoreRefList, list, false)); @@ -6354,8 +6348,7 @@ BPoseView::RestoreItemsFromTrash(BObjectList* list, bool selectNext) // restored Model* targetModel = TargetModel(); ASSERT(targetModel != NULL); - taskList->AddItem(NewMemberFunctionObject( - &TTracker::SelectPoseAtLocationSoon, tracker, + taskList->AddItem(NewMemberFunctionObject(&TTracker::SelectPoseAtLocationSoon, tracker, *targetModel->NodeRef(), pointInPose)); } } @@ -6391,8 +6384,7 @@ BPoseView::DoMoveToTrash() if (TargetModel()->IsTrash()) return DeleteSelection(true, false); - bool shiftDown = (Window()->CurrentMessage()->FindInt32("modifiers") - & B_SHIFT_KEY) != 0; + bool shiftDown = (Window()->CurrentMessage()->FindInt32("modifiers") & B_SHIFT_KEY) != 0; if (shiftDown) DeleteSelection(); else @@ -6751,7 +6743,7 @@ BPoseView::KeyDown(const char* bytes, int32 count) if (message != NULL) { int32 key; if (message->FindInt32("key", &key) == B_OK && key == B_F2_KEY) - Window()->PostMessage(kEditItem, this); + Window()->PostMessage(kEditName, this); } break; } @@ -7472,7 +7464,7 @@ BPoseView::WasClickInPath(const BPose* pose, int32 index, if (entry.GetRef(&ref) == B_OK) { BMessage message(B_REFS_RECEIVED); message.AddRef("refs", &ref); - be_app->PostMessage(&message); + Window()->PostMessage(&message); return true; } @@ -8596,54 +8588,53 @@ BPoseView::SetDefaultPrinter() void BPoseView::OpenParent() { - if (ParentIsRoot()) + if (!CanOpenParent()) return; - BEntry entry(TargetModel()->EntryRef()); - entry_ref ref; - if (FSGetParentVirtualDirectoryAware(entry, entry) != B_OK || entry.GetRef(&ref) != B_OK) - return; - - BMessage message(B_REFS_RECEIVED); - message.AddRef("refs", &ref); - - if (dynamic_cast(be_app) != NULL) { - // add information about the child, so that we can select it in the parent view - message.AddData("nodeRefToSelect", B_RAW_TYPE, TargetModel()->NodeRef(), sizeof(node_ref)); - - if ((modifiers() & B_OPTION_KEY) != 0 && !IsFilePanel()) { - // if option down, add instructions to close the parent - message.AddData("nodeRefsToClose", B_RAW_TYPE, TargetModel()->NodeRef(), - sizeof(node_ref)); - } - } - - if (TrackerSettings().SingleWindowBrowse()) { - BMessage msg(kSwitchDirectory); - msg.AddRef("refs", &ref); - Window()->PostMessage(&msg); - } else { - be_app->PostMessage(&message); - } + BMessage message(kOpenParentDir); + message.AddRef("refs", TargetModel()->EntryRef()); + Window()->PostMessage(&message); } bool -BPoseView::ParentIsRoot() +BPoseView::CanOpenParent() { - if (IsDesktop() || TargetModel()->IsRoot()) - return true; + TrackerSettings settings; + BEntry entry(TargetModel()->EntryRef()); + + // first determine if current entry is root + if (IsFilePanel()) { + if (settings.DesktopFilePanelRoot()) { + if (TargetModel()->IsDesktop()) + return false; + } else if (TargetModel()->IsRoot()) { + return false; + } + } else { + // deny Desktop, allow Desktop folder + if (IsDesktop() || TargetModel()->IsRoot()) + return false; + } // override by holding control key if ((modifiers() & B_CONTROL_KEY) != 0) + return true; + + // file panel can go below root to Desktop + if (IsFilePanel() && settings.DesktopFilePanelRoot()) + return true; + + BEntry parentEntry; + if (FSGetParentVirtualDirectoryAware(entry, parentEntry) != B_OK) return false; - BEntry entry(TargetModel()->EntryRef()); - bool isRoot = FSGetParentVirtualDirectoryAware(entry, entry) == B_OK && FSIsRootDir(&entry); - if (isRoot && (TrackerSettings().SingleWindowBrowse() || TrackerSettings().ShowDisksIcon())) - return false; + // if show disks is on still one more level to go + bool parentIsRoot = FSIsRootDir(&parentEntry); + if (parentIsRoot && settings.ShowDisksIcon()) + return true; - return isRoot; + return !parentIsRoot; } @@ -8692,8 +8683,7 @@ BPoseView::ClearSelection() break; } } else { - int32 startIndex = FirstIndexAtOrBelow( - (int32)(bounds.top - IconPoseHeight()), true); + int32 startIndex = FirstIndexAtOrBelow((int32)(bounds.top - IconPoseHeight()), true); int32 poseCount = fVSPoseList->CountItems(); for (int32 index = startIndex; index < poseCount; index++) { BPose* pose = fVSPoseList->ItemAt(index); @@ -8758,8 +8748,7 @@ BPoseView::ShowSelection(bool show) break; } } else { - int32 startIndex = FirstIndexAtOrBelow( - (int32)(bounds.top - IconPoseHeight()), true); + int32 startIndex = FirstIndexAtOrBelow((int32)(bounds.top - IconPoseHeight()), true); int32 poseCount = fVSPoseList->CountItems(); for (int32 index = startIndex; index < poseCount; index++) { BPose* pose = fVSPoseList->ItemAt(index); diff --git a/src/kits/tracker/PoseView.h b/src/kits/tracker/PoseView.h index c52e049a0f..eb19c5f398 100644 --- a/src/kits/tracker/PoseView.h +++ b/src/kits/tracker/PoseView.h @@ -276,7 +276,7 @@ public: void UnmountSelectedVolumes(); virtual void OpenParent(); - virtual bool ParentIsRoot(); + virtual bool CanOpenParent(); virtual void OpenSelection(BPose* clicked_pose = NULL, int32* index = NULL); diff --git a/src/kits/tracker/QueryContainerWindow.cpp b/src/kits/tracker/QueryContainerWindow.cpp index 63aaf05f69..2f15548025 100644 --- a/src/kits/tracker/QueryContainerWindow.cpp +++ b/src/kits/tracker/QueryContainerWindow.cpp @@ -46,6 +46,7 @@ All rights reserved. #include "Commands.h" #include "QueryContainerWindow.h" #include "QueryPoseView.h" +#include "Shortcuts.h" // #pragma mark - BQueryContainerWindow @@ -93,28 +94,23 @@ BQueryContainerWindow::AddWindowMenu(BMenu* menu) { BMenuItem* item; - item = new BMenuItem(B_TRANSLATE("Resize to fit"), - new BMessage(kResizeToFit), 'Y'); + item = Shortcuts()->ResizeToFitItem(); item->SetTarget(this); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY); + item = Shortcuts()->SelectItem(); item->SetTarget(PoseView()); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A'); + item = Shortcuts()->SelectAllItem(); item->SetTarget(PoseView()); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Invert selection"), - new BMessage(kInvertSelection), 'S'); + item = Shortcuts()->InvertSelectionItem(); item->SetTarget(PoseView()); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Close"), - new BMessage(B_QUIT_REQUESTED), 'W'); + item = Shortcuts()->CloseItem(); item->SetTarget(this); menu->AddItem(item); } @@ -123,15 +119,11 @@ BQueryContainerWindow::AddWindowMenu(BMenu* menu) void BQueryContainerWindow::AddWindowContextMenus(BMenu* menu) { - BMenuItem* resizeItem = new BMenuItem(B_TRANSLATE("Resize to fit"), - new BMessage(kResizeToFit), 'Y'); + BMenuItem* resizeItem = Shortcuts()->ResizeToFitItem(); menu->AddItem(resizeItem); - menu->AddItem(new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A')); - BMenuItem* closeItem = new BMenuItem(B_TRANSLATE("Close"), - new BMessage(B_QUIT_REQUESTED), 'W'); + menu->AddItem(Shortcuts()->SelectItem()); + menu->AddItem(Shortcuts()->SelectAllItem()); + BMenuItem* closeItem = Shortcuts()->CloseItem(); menu->AddItem(closeItem); // target items as needed diff --git a/src/kits/tracker/Shortcuts.cpp b/src/kits/tracker/Shortcuts.cpp new file mode 100644 index 0000000000..b349faee3c --- /dev/null +++ b/src/kits/tracker/Shortcuts.cpp @@ -0,0 +1,1488 @@ +/* + * Copyright 2020-2024 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ + + +#include "Shortcuts.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Commands.h" +#include "FSClipboard.h" +#include "FSUtils.h" +#include "Model.h" +#include "Pose.h" +#include "Tracker.h" +#include "TrackerSettings.h" +#include "Utilities.h" + + +#undef B_TRANSLATION_CONTEXT +#define B_TRANSLATION_CONTEXT "ContainerWindow" + + +TShortcuts::TShortcuts() + : + fContainerWindow(NULL), + fInWindow(false) +{ + // the dumb version: for adding and limited updates +} + + +TShortcuts::TShortcuts(BContainerWindow* window) + : + fContainerWindow(window), + fInWindow(window != NULL) +{ + // the smart version: update methods work +} + + +// #pragma mark - Shortcuts build methods + + +BMenuItem* +TShortcuts::AddOnsItem() +{ + return new BMenuItem(AddOnsLabel(), NULL); +} + + +const char* +TShortcuts::AddOnsLabel() +{ + return B_TRANSLATE("Add-ons"); +} + + +BMenuItem* +TShortcuts::AddPrinterItem() +{ + return new BMenuItem(AddPrinterLabel(), new BMessage(kAddPrinter)); +} + + +const char* +TShortcuts::AddPrinterLabel() +{ + return B_TRANSLATE("Add printer" B_UTF8_ELLIPSIS); +} + + +BMenuItem* +TShortcuts::ArrangeByItem() +{ + return new BMenuItem(ArrangeByLabel(), NULL); +} + + +const char* +TShortcuts::ArrangeByLabel() +{ + return B_TRANSLATE("Arrange by"); +} + + +BMenuItem* +TShortcuts::CleanupItem() +{ + return new BMenuItem(CleanupLabel(), new BMessage(kCleanup), 'K'); +} + + +const char* +TShortcuts::CleanupLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Clean up all"); + else + return B_TRANSLATE("Clean up"); +} + + +int32 +TShortcuts::CleanupCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kCleanupAll; + else + return kCleanup; +} + + +BMenuItem* +TShortcuts::CloseItem() +{ + return new BMenuItem(CloseLabel(), new BMessage(B_QUIT_REQUESTED), 'W'); +} + + +const char* +TShortcuts::CloseLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Close all"); + else + return B_TRANSLATE("Close"); +} + + +int32 +TShortcuts::CloseCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kCloseAllWindows; + else + return B_QUIT_REQUESTED; +} + + +BMenuItem* +TShortcuts::CloseAllInWorkspaceItem() +{ + return new BMenuItem(CloseAllInWorkspaceLabel(), new BMessage(kCloseAllInWorkspace), 'Q'); +} + + +const char* +TShortcuts::CloseAllInWorkspaceLabel() +{ + return B_TRANSLATE("Close all in workspace"); +} + + +BMenuItem* +TShortcuts::CopyItem() +{ + return new BMenuItem(CopyLabel(), new BMessage(B_COPY), 'C'); +} + + +const char* +TShortcuts::CopyLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Copy more"); + else + return B_TRANSLATE("Copy"); +} + + +int32 +TShortcuts::CopyCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kCopyMoreSelectionToClipboard; + else + return B_COPY; +} + + +BMenuItem* +TShortcuts::CopyToItem() +{ + return new BMenuItem(CopyToLabel(), new BMessage(kCopySelectionTo)); +} + + +BMenuItem* +TShortcuts::CopyToItem(BMenu* menu) +{ + return new BMenuItem(menu, new BMessage(kCopySelectionTo)); +} + + +const char* +TShortcuts::CopyToLabel() +{ + return B_TRANSLATE("Copy to"); +} + + +BMenuItem* +TShortcuts::CreateLinkItem() +{ + return new BMenuItem(CreateLinkLabel(), new BMessage(kCreateLink)); +} + + +BMenuItem* +TShortcuts::CreateLinkItem(BMenu* menu) +{ + return new BMenuItem(menu, new BMessage(kCreateLink)); +} + + +const char* +TShortcuts::CreateLinkLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Create relative link"); + else + return B_TRANSLATE("Create link"); +} + + +int32 +TShortcuts::CreateLinkCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kCreateRelativeLink; + else + return kCreateLink; +} + + +BMenuItem* +TShortcuts::CreateLinkHereItem() +{ + return new BMenuItem(CreateLinkHereLabel(), new BMessage(kCreateLink)); +} + + +const char* +TShortcuts::CreateLinkHereLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Create relative link here"); + else + return B_TRANSLATE("Create link here"); +} + + +int32 +TShortcuts::CreateLinkHereCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kCreateRelativeLink; + else + return kCreateLink; +} + + +BMenuItem* +TShortcuts::CutItem() +{ + return new BMenuItem(CutLabel(), new BMessage(B_CUT), 'X'); +} + + +const char* +TShortcuts::CutLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Cut more"); + else + return B_TRANSLATE("Cut"); +} + + +int32 +TShortcuts::CutCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kCutMoreSelectionToClipboard; + else + return B_CUT; +} + + +BMenuItem* +TShortcuts::DeleteItem() +{ + return new BMenuItem(DeleteLabel(), new BMessage(kDeleteSelection)); +} + + +const char* +TShortcuts::DeleteLabel() +{ + return B_TRANSLATE("Delete"); +} + + +BMenuItem* +TShortcuts::DuplicateItem() +{ + return new BMenuItem(DuplicateLabel(), new BMessage(kDuplicateSelection), 'D'); +} + + +const char* +TShortcuts::DuplicateLabel() +{ + return B_TRANSLATE("Duplicate"); +} + + +BMenuItem* +TShortcuts::EditNameItem() +{ + return new BMenuItem(EditNameLabel(), new BMessage(kEditName), 'E'); +} + + +const char* +TShortcuts::EditNameLabel() +{ + return B_TRANSLATE("Edit name"); +} + + +BMenuItem* +TShortcuts::EditQueryItem() +{ + return new BMenuItem(EditQueryLabel(), new BMessage(kEditQuery), 'G'); +} + + +const char* +TShortcuts::EditQueryLabel() +{ + return B_TRANSLATE("Edit query"); +} + + +BMenuItem* +TShortcuts::EmptyTrashItem() +{ + return new BMenuItem(EmptyTrashLabel(), new BMessage(kEmptyTrash)); +} + + +const char* +TShortcuts::EmptyTrashLabel() +{ + return B_TRANSLATE("Empty Trash"); +} + + +BMenuItem* +TShortcuts::FindItem() +{ + return new BMenuItem(FindLabel(), new BMessage(kFindButton), 'F'); +} + + +const char* +TShortcuts::FindLabel() +{ + return B_TRANSLATE("Find" B_UTF8_ELLIPSIS); +} + + +BMenuItem* +TShortcuts::GetInfoItem() +{ + return new BMenuItem(GetInfoLabel(), new BMessage(kGetInfo), 'I'); +} + + +const char* +TShortcuts::GetInfoLabel() +{ + return B_TRANSLATE("Get info"); +} + + +BMenuItem* +TShortcuts::IdentifyItem() +{ + BMessage* message = new BMessage(kIdentifyEntry); + BMenuItem* item = new BMenuItem(IdentifyLabel(), message); + message->AddBool("force", (modifiers() & B_SHIFT_KEY) != 0); + + if (fInWindow) + item->SetTarget(PoseView()); + + return item; +} + + +const char* +TShortcuts::IdentifyLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Force identify"); + else + return B_TRANSLATE("Identify"); +} + + +BMenuItem* +TShortcuts::InvertSelectionItem() +{ + return new BMenuItem(InvertSelectionLabel(), new BMessage(kInvertSelection), 'S'); +} + + +const char* +TShortcuts::InvertSelectionLabel() +{ + return B_TRANSLATE("Invert selection"); +} + + +BMenuItem* +TShortcuts::MakeActivePrinterItem() +{ + return new BMenuItem(MakeActivePrinterLabel(), new BMessage(kMakeActivePrinter)); +} + + +const char* +TShortcuts::MakeActivePrinterLabel() +{ + return B_TRANSLATE("Make active printer"); +} + + +BMenuItem* +TShortcuts::MountItem() +{ + return new BMenuItem(MountLabel(), new BMessage(kMountVolume)); +} + + +BMenuItem* +TShortcuts::MountItem(BMenu* menu) +{ + return new BMenuItem(menu, new BMessage(kMountVolume)); +} + + +const char* +TShortcuts::MountLabel() +{ + return B_TRANSLATE("Mount"); +} + + +BMenuItem* +TShortcuts::MoveToItem() +{ + return new BMenuItem(MoveToLabel(), new BMessage(kMoveSelectionTo)); +} + + +BMenuItem* +TShortcuts::MoveToItem(BMenu* menu) +{ + return new BMenuItem(menu, new BMessage(kMoveSelectionTo)); +} + + +const char* +TShortcuts::MoveToLabel() +{ + return B_TRANSLATE("Move to"); +} + + +BMenuItem* +TShortcuts::MoveToTrashItem() +{ + return new BMenuItem(MoveToTrashLabel(), new BMessage(kMoveSelectionToTrash), 'T'); +} + + +const char* +TShortcuts::MoveToTrashLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Delete"); + else + return B_TRANSLATE("Move to Trash"); +} + + +int32 +TShortcuts::MoveToTrashCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kDeleteSelection; + else + return kMoveSelectionToTrash; +} + + +BMenuItem* +TShortcuts::NewFolderItem() +{ + return new BMenuItem(NewFolderLabel(), new BMessage(kNewFolder), 'N'); +} + + +const char* +TShortcuts::NewFolderLabel() +{ + return B_TRANSLATE("New folder"); +} + + +BMenuItem* +TShortcuts::NewTemplatesItem() +{ + return new BMenuItem(B_TRANSLATE("New"), new BMessage(kNewEntryFromTemplate)); +} + + +BMenuItem* +TShortcuts::NewTemplatesItem(BMenu* menu) +{ + return new BMenuItem(menu, new BMessage(kNewEntryFromTemplate)); +} + + +const char* +TShortcuts::NewTemplatesLabel() +{ + return B_TRANSLATE("New"); +} + + +BMenuItem* +TShortcuts::OpenItem() +{ + return new BMenuItem(OpenLabel(), new BMessage(kOpenSelection), 'O'); +} + + +const char* +TShortcuts::OpenLabel() +{ + return B_TRANSLATE("Open"); +} + + +BMenuItem* +TShortcuts::OpenParentItem() +{ + return new BMenuItem(OpenParentLabel(), new BMessage(kOpenParentDir), B_UP_ARROW); +} + + +const char* +TShortcuts::OpenParentLabel() +{ + return B_TRANSLATE("Open parent"); +} + + +BMenuItem* +TShortcuts::OpenWithItem() +{ + return new BMenuItem(OpenWithLabel(), new BMessage(kOpenSelectionWith)); +} + + +BMenuItem* +TShortcuts::OpenWithItem(BMenu* menu) +{ + return new BMenuItem(menu, new BMessage(kOpenSelectionWith)); +} + + +const char* +TShortcuts::OpenWithLabel() +{ + return B_TRANSLATE("Open with" B_UTF8_ELLIPSIS); +} + + +BMenuItem* +TShortcuts::PasteItem() +{ + return new BMenuItem(PasteLabel(), new BMessage(B_PASTE), 'V'); +} + + +const char* +TShortcuts::PasteLabel() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return B_TRANSLATE("Paste links"); + else + return B_TRANSLATE("Paste"); +} + + +int32 +TShortcuts::PasteCommand() +{ + if ((modifiers() & B_SHIFT_KEY) != 0) + return kPasteLinksFromClipboard; + else + return B_PASTE; +} + + +BMenuItem* +TShortcuts::ResizeToFitItem() +{ + return new BMenuItem(ResizeToFitLabel(), new BMessage(kResizeToFit), 'Y'); +} + + +const char* +TShortcuts::ResizeToFitLabel() +{ + return B_TRANSLATE("Resize to fit"); +} + + +BMenuItem* +TShortcuts::RestoreItem() +{ + return new BMenuItem(RestoreLabel(), new BMessage(kRestoreSelectionFromTrash)); +} + + +const char* +TShortcuts::RestoreLabel() +{ + return B_TRANSLATE("Restore"); +} + + +BMenuItem* +TShortcuts::ReverseOrderItem() +{ + return new BMenuItem(ReverseOrderLabel(), new BMessage(kArrangeReverseOrder)); +} + + +const char* +TShortcuts::ReverseOrderLabel() +{ + return B_TRANSLATE("Reverse order"); +} + + +BMenuItem* +TShortcuts::SelectItem() +{ + return new BMenuItem(SelectLabel(), new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY); +} + + +const char* +TShortcuts::SelectLabel() +{ + return B_TRANSLATE("Select" B_UTF8_ELLIPSIS); +} + + +BMenuItem* +TShortcuts::SelectAllItem() +{ + return new BMenuItem(SelectAllLabel(), new BMessage(B_SELECT_ALL), 'A', B_SHIFT_KEY); +} + + +const char* +TShortcuts::SelectAllLabel() +{ + return B_TRANSLATE("Select all"); +} + + +BMenuItem* +TShortcuts::UnmountItem() +{ + return new BMenuItem(UnmountLabel(), new BMessage(kUnmountVolume), 'U'); +} + + +const char* +TShortcuts::UnmountLabel() +{ + return B_TRANSLATE("Unmount"); +} + + +// #pragma mark - Shortcuts update methods + + +void +TShortcuts::Update(BMenu* menu) +{ + if (menu == NULL) + return; + + int32 itemCount = menu->CountItems(); + for (int32 index = 0; index < itemCount; index++) { + BMenuItem* item = menu->ItemAt(index); + if (item == NULL || item->Message() == NULL) + continue; + + switch (item->Message()->what) { + case kAddPrinter: + UpdateAddPrinterItem(item); + break; + + case kCleanup: + case kCleanupAll: + UpdateCleanupItem(item); + break; + + case B_COPY: + case kCopyMoreSelectionToClipboard: + UpdateCopyItem(item); + break; + + case kCopySelectionTo: + UpdateCopyToItem(item); + break; + + case kCreateLink: + case kCreateRelativeLink: + UpdateCreateLinkItem(item); + break; + + case B_CUT: + case kCutMoreSelectionToClipboard: + UpdateCutItem(item); + break; + + case kDeleteSelection: + // delete command used by a different item in Trash + if (IsTrash() || InTrash()) + UpdateDeleteItem(item); + else + UpdateMoveToTrashItem(item); + break; + + case kDuplicateSelection: + UpdateDuplicateItem(item); + break; + + case kEditName: + UpdateEditNameItem(item); + break; + + case kEditQuery: + UpdateEditQueryItem(item); + break; + + case kEmptyTrash: + UpdateEmptyTrashItem(item); + break; + + case kFindButton: + UpdateFindItem(item); + break; + + case kGetInfo: + UpdateGetInfoItem(item); + break; + + case kIdentifyEntry: + UpdateIdentifyItem(item); + break; + + case kInvertSelection: + UpdateInvertSelectionItem(item); + break; + + case kMakeActivePrinter: + UpdateMakeActivePrinterItem(item); + break; + + case kMoveSelectionTo: + UpdateMoveToItem(item); + break; + + case kMoveSelectionToTrash: + UpdateMoveToTrashItem(item); + break; + + case kNewFolder: + UpdateNewFolderItem(item); + break; + + case kNewEntryFromTemplate: + UpdateNewTemplatesItem(item); + break; + + case kOpenSelection: + UpdateOpenItem(item); + break; + + case kOpenParentDir: + UpdateOpenParentItem(item); + break; + + case B_PASTE: + case kPasteLinksFromClipboard: + UpdatePasteItem(item); + break; + + case kResizeToFit: + UpdateResizeToFitItem(item); + break; + + case kRestoreSelectionFromTrash: + UpdateRestoreItem(item); + break; + + case kArrangeReverseOrder: + UpdateReverseOrderItem(item); + break; + + case B_SELECT_ALL: + UpdateSelectAllItem(item); + break; + + case kShowSelectionWindow: + UpdateSelectItem(item); + break; + + case B_QUIT_REQUESTED: + case kCloseAllWindows: + UpdateCloseItem(item); + break; + + case kCloseAllInWorkspace: + UpdateCloseAllInWorkspaceItem(item); + break; + + case kUnmountVolume: + UpdateUnmountItem(item); + break; + + default: + break; + } + } +} + + +void +TShortcuts::UpdateAddOnsItem(BMenuItem* item) +{ + if (item == NULL || item->Submenu() == NULL) + return; + + item->SetEnabled(item->Submenu()->CountItems() > 0); + + if (fInWindow) + item->Submenu()->SetTargetForItems(fContainerWindow); +} + + +void +TShortcuts::UpdateAddPrinterItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetEnabled(true); + item->SetTarget(be_app); +} + + +void +TShortcuts::UpdateArrangeByItem(BMenuItem* item) +{ + if (item == NULL || item->Submenu() == NULL) + return; + + if (fInWindow) { + item->SetEnabled(PoseView()->ViewMode() != kListMode); + item->Submenu()->SetTargetForItems(PoseView()); + } +} + + +void +TShortcuts::UpdateCleanupItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(CleanupLabel()); + item->Message()->what = CleanupCommand(); + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY | (modifiers() & B_SHIFT_KEY)); + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateCloseAllInWorkspaceItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetEnabled(true); + item->SetTarget(be_app); +} + + +void +TShortcuts::UpdateCloseItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(CloseLabel()); + item->Message()->what = CloseCommand(); + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY | (modifiers() & B_SHIFT_KEY)); + + if (fInWindow) { + if ((modifiers() & B_SHIFT_KEY) != 0) + item->SetTarget(be_app); + else + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateCopyItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(CopyLabel()); + item->Message()->what = CopyCommand(); + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY | (modifiers() & B_SHIFT_KEY)); + + if (fInWindow) { + item->SetEnabled(IsCurrentFocusOnTextView() || HasSelection()); + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateCopyToItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateCreateLinkItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(CreateLinkLabel()); + item->Message()->what = CreateLinkCommand(); + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateCreateLinkHereItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(CreateLinkHereLabel()); + item->Message()->what = CreateLinkHereCommand(); + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateCutItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(CutLabel()); + item->Message()->what = CutCommand(); + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY | (modifiers() & B_SHIFT_KEY)); + + if (fInWindow) { + if (IsCurrentFocusOnTextView()) + item->SetEnabled(true); + else if (IsRoot() || IsTrash() || IsVirtualDirectory()) + item->SetEnabled(false); + else + item->SetEnabled(HasSelection() && TargetIsReadOnly() == false); + + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateDeleteItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(B_TRANSLATE("Delete")); + item->Message()->what = kDeleteSelection; + if (item->Shortcut() != 0) + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY); + + if (fInWindow) { + item->SetEnabled(HasSelection() && !SelectionIsReadOnly()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateDuplicateItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(PoseView()->CanMoveToTrashOrDuplicate()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateEditNameItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(PoseView()->CanEditName()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateEditQueryItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateEmptyTrashItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(static_cast(be_app)->TrashFull()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateFindItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateGetInfoItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateIdentifyItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(IdentifyLabel()); + item->Message()->ReplaceBool("force", (modifiers() & B_SHIFT_KEY) != 0); + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateInvertSelectionItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateMakeActivePrinterItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(PoseView()->CountSelected() == 1); + item->SetTarget(be_app); + } +} + + +void +TShortcuts::UpdateMoveToItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(HasSelection() && !SelectionIsReadOnly()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateMoveToTrashItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (item->Shortcut() == 0) { + // make sure this is the real Move to Trash item, not the Delete item in Trash + item->SetLabel(B_TRANSLATE("Delete")); + item->Message()->what = kDeleteSelection; + } else { + item->SetLabel(MoveToTrashLabel()); + item->Message()->what = MoveToTrashCommand(); + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY | (modifiers() & B_SHIFT_KEY)); + } + + if (fInWindow) { + item->SetEnabled(HasSelection() && !SelectionIsReadOnly()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateNewFolderItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(!(IsRoot() || IsTrash() || InTrash()) && TargetIsReadOnly() == false); + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateNewTemplatesItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(TargetIsReadOnly() == false); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateOpenItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateOpenParentItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(PoseView()->CanOpenParent()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateOpenWithItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetShortcut('O', B_COMMAND_KEY | B_CONTROL_KEY); + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdatePasteItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(PasteLabel()); + item->Message()->what = PasteCommand(); + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY | (modifiers() & B_SHIFT_KEY)); + + if (fInWindow) { + bool isPastable = FSClipboardHasRefs() && !SelectionIsReadOnly() && !IsTrash(); + item->SetEnabled(IsCurrentFocusOnTextView() || isPastable); + + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateResizeToFitItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateRestoreItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(HasSelection()); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateReverseOrderItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateSelectItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(PoseView()); + } +} + + +void +TShortcuts::UpdateSelectAllItem(BMenuItem* item) +{ + if (item == NULL) + return; + + if (fInWindow) { + item->SetEnabled(true); + item->SetTarget(fContainerWindow); + } +} + + +void +TShortcuts::UpdateUnmountItem(BMenuItem* item) +{ + if (item == NULL) + return; + + item->SetLabel(UnmountLabel()); + item->Message()->what = kUnmountVolume; + item->SetShortcut(item->Shortcut(), B_COMMAND_KEY); + + if (fInWindow) { + item->SetEnabled(PoseView()->CanUnmountSelection()); + item->SetTarget(PoseView()); + } +} + + +// #pragma mark - Shortcuts convenience methods + + +BMenuItem* +TShortcuts::FindItem(BMenu* menu, int32 command1, int32 command2) +{ + // find menu item by either of a pair of commands + BMenuItem* item1 = menu->FindItem(command1); + BMenuItem* item2 = menu->FindItem(command2); + if (item1 == NULL && item2 == NULL) + return NULL; + + return item1 != NULL ? item1 : item2; +} + + +bool +TShortcuts::IsCurrentFocusOnTextView() const +{ + // used to redirect cut/copy/paste and other text-based shortcuts + if (!fInWindow) + return false; + + BWindow* window = fContainerWindow; + return dynamic_cast(window->CurrentFocus()) != NULL; +} + + +bool +TShortcuts::IsDesktop() const +{ + return fInWindow && PoseView()->TargetModel()->IsDesktop(); +} + + +bool +TShortcuts::IsQuery() const +{ + return fInWindow && PoseView()->TargetModel()->IsQuery(); +} + + +bool +TShortcuts::IsQueryTemplate() const +{ + return fInWindow && PoseView()->TargetModel()->IsQueryTemplate(); +} + + +bool +TShortcuts::IsRoot() const +{ + return fInWindow && PoseView()->TargetModel()->IsRoot(); +} + + +bool +TShortcuts::InTrash() const +{ + return fInWindow && PoseView()->TargetModel()->InTrash(); +} + + +bool +TShortcuts::IsTrash() const +{ + return fInWindow && PoseView()->TargetModel()->IsTrash(); +} + + +bool +TShortcuts::IsVirtualDirectory() const +{ + return PoseView()->TargetModel()->IsVirtualDirectory(); +} + + +bool +TShortcuts::IsVolume() const +{ + return fInWindow && PoseView()->TargetModel()->IsVolume(); +} + + +bool +TShortcuts::HasSelection() const +{ + return fInWindow && PoseView()->CountSelected() > 0; +} + + +bool +TShortcuts::SelectionIsReadOnly() const +{ + return fInWindow && PoseView()->SelectedVolumeIsReadOnly(); +} + + +bool +TShortcuts::TargetIsReadOnly() const +{ + return fInWindow && PoseView()->TargetVolumeIsReadOnly(); +} diff --git a/src/kits/tracker/Shortcuts.h b/src/kits/tracker/Shortcuts.h new file mode 100644 index 0000000000..581566070f --- /dev/null +++ b/src/kits/tracker/Shortcuts.h @@ -0,0 +1,230 @@ +/* + * Copyright 2020-2024 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * John Scipione, jscipione@gmail.com + */ +#ifndef _SHORTCUTS_H +#define _SHORTCUTS_H + + +#include + +#include "ContainerWindow.h" + + +class BMenu; +class BMenuItem; + + +namespace BPrivate { + +class BPoseView; + + +class TShortcuts { +public: + TShortcuts(); + TShortcuts(BContainerWindow* window); + + // build item + + BMenuItem* AddOnsItem(); + const char* AddOnsLabel(); + + BMenuItem* ArrangeByItem(); + const char* ArrangeByLabel(); + + BMenuItem* AddPrinterItem(); + const char* AddPrinterLabel(); + + BMenuItem* CleanupItem(); + const char* CleanupLabel(); + int32 CleanupCommand(); + + BMenuItem* CloseItem(); + const char* CloseLabel(); + int32 CloseCommand(); + + BMenuItem* CloseAllInWorkspaceItem(); + const char* CloseAllInWorkspaceLabel(); + + BMenuItem* CopyItem(); + const char* CopyLabel(); + int32 CopyCommand(); + + BMenuItem* CopyToItem(); + BMenuItem* CopyToItem(BMenu*); + const char* CopyToLabel(); + + BMenuItem* CreateLinkItem(); + BMenuItem* CreateLinkItem(BMenu*); + const char* CreateLinkLabel(); + int32 CreateLinkCommand(); + + BMenuItem* CreateLinkHereItem(); + const char* CreateLinkHereLabel(); + int32 CreateLinkHereCommand(); + + BMenuItem* CutItem(); + const char* CutLabel(); + int32 CutCommand(); + + BMenuItem* DeleteItem(); + const char* DeleteLabel(); + + BMenuItem* DuplicateItem(); + const char* DuplicateLabel(); + + BMenuItem* EditNameItem(); + const char* EditNameLabel(); + + BMenuItem* EditQueryItem(); + const char* EditQueryLabel(); + + BMenuItem* EmptyTrashItem(); + const char* EmptyTrashLabel(); + + BMenuItem* FindItem(); + const char* FindLabel(); + + BMenuItem* GetInfoItem(); + const char* GetInfoLabel(); + + BMenuItem* IdentifyItem(); + const char* IdentifyLabel(); + + BMenuItem* InvertSelectionItem(); + const char* InvertSelectionLabel(); + + BMenuItem* MakeActivePrinterItem(); + const char* MakeActivePrinterLabel(); + + BMenuItem* MountItem(); + BMenuItem* MountItem(BMenu*); + const char* MountLabel(); + + BMenuItem* MoveToItem(); + BMenuItem* MoveToItem(BMenu*); + const char* MoveToLabel(); + + BMenuItem* MoveToTrashItem(); + const char* MoveToTrashLabel(); + int32 MoveToTrashCommand(); + + BMenuItem* NewFolderItem(); + const char* NewFolderLabel(); + + BMenuItem* NewTemplatesItem(); + BMenuItem* NewTemplatesItem(BMenu*); + const char* NewTemplatesLabel(); + + BMenuItem* OpenItem(); + const char* OpenLabel(); + + BMenuItem* OpenParentItem(); + const char* OpenParentLabel(); + + BMenuItem* OpenWithItem(); + BMenuItem* OpenWithItem(BMenu*); + const char* OpenWithLabel(); + + BMenuItem* PasteItem(); + const char* PasteLabel(); + int32 PasteCommand(); + + BMenuItem* RestoreItem(); + const char* RestoreLabel(); + + BMenuItem* ReverseOrderItem(); + const char* ReverseOrderLabel(); + + BMenuItem* ResizeToFitItem(); + const char* ResizeToFitLabel(); + + BMenuItem* SelectItem(); + const char* SelectLabel(); + + BMenuItem* SelectAllItem(); + const char* SelectAllLabel(); + + BMenuItem* UnmountItem(); + const char* UnmountLabel(); + + // update item + + void Update(BMenu*); + + void UpdateAddOnsItem(BMenuItem*); + void UpdateAddPrinterItem(BMenuItem*); + void UpdateArrangeByItem(BMenuItem*); + void UpdateCleanupItem(BMenuItem*); + void UpdateCloseAllInWorkspaceItem(BMenuItem*); + void UpdateCloseItem(BMenuItem*); + void UpdateCopyItem(BMenuItem*); + void UpdateCopyToItem(BMenuItem*); + void UpdateCreateLinkItem(BMenuItem*); + void UpdateCreateLinkHereItem(BMenuItem*); + void UpdateCutItem(BMenuItem*); + void UpdateDeleteItem(BMenuItem*); + void UpdateDuplicateItem(BMenuItem*); + void UpdateEditNameItem(BMenuItem*); + void UpdateEditQueryItem(BMenuItem*); + void UpdateEmptyTrashItem(BMenuItem*); + void UpdateFindItem(BMenuItem*); + void UpdateGetInfoItem(BMenuItem*); + void UpdateIdentifyItem(BMenuItem*); + void UpdateInvertSelectionItem(BMenuItem*); + void UpdateMakeActivePrinterItem(BMenuItem*); + void UpdateMoveToItem(BMenuItem*); + void UpdateMoveToTrashItem(BMenuItem*); + void UpdateNewFolderItem(BMenuItem*); + void UpdateNewTemplatesItem(BMenuItem*); + void UpdateOpenItem(BMenuItem*); + void UpdateOpenParentItem(BMenuItem*); + void UpdateOpenWithItem(BMenuItem*); + void UpdatePasteItem(BMenuItem*); + void UpdateResizeToFitItem(BMenuItem*); + void UpdateRestoreItem(BMenuItem*); + void UpdateReverseOrderItem(BMenuItem*); + void UpdateSelectItem(BMenuItem*); + void UpdateSelectAllItem(BMenuItem*); + void UpdateUnmountItem(BMenuItem*); + + // convenience methods + + BMenuItem* FindItem(BMenu* menu, int32 command1, int32 command2); + BPoseView* PoseView() const; + + bool IsCurrentFocusOnTextView() const; + bool IsDesktop() const; + bool IsQuery() const; + bool IsQueryTemplate() const; + bool IsRoot() const; + bool InTrash() const; + bool IsTrash() const; + bool IsVirtualDirectory() const; + bool IsVolume() const; + bool HasSelection() const; + bool SelectionIsReadOnly() const; + bool TargetIsReadOnly() const; + +private: + BContainerWindow* fContainerWindow; + bool fInWindow; +}; + + +inline BPoseView* +TShortcuts::PoseView() const +{ + return fInWindow ? fContainerWindow->PoseView() : NULL; +} + +} // namespace BPrivate + +using namespace BPrivate; + + +#endif // _SHORTCUTS_H diff --git a/src/kits/tracker/Tracker.cpp b/src/kits/tracker/Tracker.cpp index 91dd2cce0f..c7c63b5e94 100644 --- a/src/kits/tracker/Tracker.cpp +++ b/src/kits/tracker/Tracker.cpp @@ -289,41 +289,13 @@ TTracker::TTracker() gLaunchLooper = new LaunchLooper(); gLaunchLooper->Run(); - // open desktop window - BContainerWindow* deskWindow = NULL; - BDirectory deskDir; - if (FSGetDeskDir(&deskDir) == B_OK) { - // create desktop - BEntry entry; - deskDir.GetEntry(&entry); - Model* model = new Model(&entry, true); - if (model->InitCheck() == B_OK) { - AutoLock lock(&fWindowList); - deskWindow = new BDeskWindow(&fWindowList); - AutoLock windowLock(deskWindow); - deskWindow->CreatePoseView(model); - deskWindow->Init(); + // create Desktop window and lock it + AutoLock lock(&fWindowList); + BContainerWindow* deskWindow = new BDeskWindow(&fWindowList); + AutoLock windowLock(deskWindow); - if (TrackerSettings().ShowDisksIcon()) { - // create model for root of everything - BEntry entry("/"); - Model model(&entry); - if (model.InitCheck() == B_OK) { - // add the root icon to desktop window - BMessage message; - message.what = B_NODE_MONITOR; - message.AddInt32("opcode", B_ENTRY_CREATED); - message.AddInt32("device", model.NodeRef()->device); - message.AddInt64("node", model.NodeRef()->node); - message.AddInt64("directory", - model.EntryRef()->directory); - message.AddString("name", model.EntryRef()->name); - deskWindow->PostMessage(&message, deskWindow->PoseView()); - } - } - } else - delete model; - } + // init Desktop now that pose view is created and window is locked + deskWindow->Init(); } diff --git a/src/kits/tracker/VirtualDirectoryWindow.cpp b/src/kits/tracker/VirtualDirectoryWindow.cpp index ae960377f2..4b3b4cec8f 100644 --- a/src/kits/tracker/VirtualDirectoryWindow.cpp +++ b/src/kits/tracker/VirtualDirectoryWindow.cpp @@ -49,6 +49,7 @@ All rights reserved. #include #include "Commands.h" +#include "Shortcuts.h" #include "VirtualDirectoryManager.h" #include "VirtualDirectoryPoseView.h" @@ -134,33 +135,27 @@ VirtualDirectoryWindow::AddWindowMenu(BMenu* menu) { BMenuItem* item; - item = new BMenuItem(B_TRANSLATE("Resize to fit"), - new BMessage(kResizeToFit), 'Y'); + item = Shortcuts()->ResizeToFitItem(); item->SetTarget(this); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY); + item = Shortcuts()->SelectItem(); item->SetTarget(PoseView()); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A'); + item = Shortcuts()->SelectAllItem(); item->SetTarget(this); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Invert selection"), - new BMessage(kInvertSelection), 'S'); + item = Shortcuts()->InvertSelectionItem(); item->SetTarget(PoseView()); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Open parent"), - new BMessage(kOpenParentDir), B_UP_ARROW); + item = Shortcuts()->OpenParentItem(); item->SetTarget(PoseView()); menu->AddItem(item); - item = new BMenuItem(B_TRANSLATE("Close"), - new BMessage(B_QUIT_REQUESTED), 'W'); + item = Shortcuts()->CloseItem(); item->SetTarget(this); menu->AddItem(item); } @@ -169,15 +164,11 @@ VirtualDirectoryWindow::AddWindowMenu(BMenu* menu) void VirtualDirectoryWindow::AddWindowContextMenus(BMenu* menu) { - BMenuItem* resizeItem = new BMenuItem(B_TRANSLATE("Resize to fit"), - new BMessage(kResizeToFit), 'Y'); + BMenuItem* resizeItem = Shortcuts()->ResizeToFitItem(); menu->AddItem(resizeItem); - menu->AddItem(new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), - new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY)); - menu->AddItem(new BMenuItem(B_TRANSLATE("Select all"), - new BMessage(B_SELECT_ALL), 'A')); - BMenuItem* closeItem = new BMenuItem(B_TRANSLATE("Close"), - new BMessage(B_QUIT_REQUESTED), 'W'); + menu->AddItem(Shortcuts()->SelectItem()); + menu->AddItem(Shortcuts()->SelectAllItem()); + BMenuItem* closeItem = Shortcuts()->CloseItem(); menu->AddItem(closeItem); // target items as needed menu->SetTargetForItems(PoseView()); diff --git a/src/kits/tracker/infowindow/HeaderView.cpp b/src/kits/tracker/infowindow/HeaderView.cpp index 70933cd545..430a5e1b67 100644 --- a/src/kits/tracker/infowindow/HeaderView.cpp +++ b/src/kits/tracker/infowindow/HeaderView.cpp @@ -55,6 +55,7 @@ All rights reserved. #include "Model.h" #include "NavMenu.h" #include "PoseView.h" +#include "Shortcuts.h" #include "Tracker.h" @@ -333,7 +334,7 @@ HeaderView::MouseDown(BPoint where) Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); if (SecondaryMouseButtonDown(modifiers(), buttons)) { // Show contextual menu - BPopUpMenu* contextMenu = new BPopUpMenu("FileContext", false, false); + BPopUpMenu* contextMenu = new BPopUpMenu("PoseContext", false, false); if (contextMenu != NULL) { BuildContextMenu(contextMenu); contextMenu->SetAsyncAutoDestruct(true); @@ -581,17 +582,14 @@ HeaderView::BuildContextMenu(BMenu* parent) navigationItem->SetTarget(be_app); } - parent->AddItem(new BMenuItem(B_TRANSLATE("Open"), - new BMessage(kOpenSelection), 'O')); + parent->AddItem(TShortcuts().OpenItem()); if (!model.IsDesktop() && !model.IsRoot() && !model.IsTrash()) { - parent->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), - new BMessage(kEditItem), 'E')); + parent->AddItem(TShortcuts().EditNameItem()); parent->AddSeparatorItem(); if (fModel->IsVolume()) { - BMenuItem* item = new BMenuItem(B_TRANSLATE("Unmount"), - new BMessage(kUnmountVolume), 'U'); + BMenuItem* item = TShortcuts().UnmountItem(); parent->AddItem(item); // volume model, enable/disable the Unmount item BVolume boot; @@ -604,12 +602,10 @@ HeaderView::BuildContextMenu(BMenu* parent) } if (!model.IsRoot() && !model.IsVolume() && !model.IsTrash()) - parent->AddItem(new BMenuItem(B_TRANSLATE("Identify"), - new BMessage(kIdentifyEntry))); + parent->AddItem(TShortcuts().IdentifyItem()); if (model.IsTrash()) - parent->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), - new BMessage(kEmptyTrash))); + parent->AddItem(TShortcuts().EmptyTrashItem()); BMenuItem* sizeItem = NULL; if (model.IsDirectory() && !model.IsVolume() && !model.IsRoot()) { diff --git a/src/kits/tracker/infowindow/InfoWindow.cpp b/src/kits/tracker/infowindow/InfoWindow.cpp index 8b80ac441f..72c3020b6f 100644 --- a/src/kits/tracker/infowindow/InfoWindow.cpp +++ b/src/kits/tracker/infowindow/InfoWindow.cpp @@ -113,7 +113,7 @@ BInfoWindow::BInfoWindow(Model* model, int32 group_index, if (list != NULL) list->AddItem(this); - AddShortcut('E', 0, new BMessage(kEditItem)); + AddShortcut('E', 0, new BMessage(kEditName)); AddShortcut('O', 0, new BMessage(kOpenSelection)); AddShortcut('U', 0, new BMessage(kUnmountVolume)); AddShortcut('P', 0, new BMessage(kPermissionsSelected)); @@ -266,7 +266,7 @@ BInfoWindow::MessageReceived(BMessage* message) break; } - case kEditItem: + case kEditName: { BEntry entry(fModel->EntryRef()); fHeaderView->BeginEditingTitle();