From 9df392ba329eec188ebba7a7fca14c403529175b Mon Sep 17 00:00:00 2001 From: John Scipione Date: Fri, 1 Dec 2023 21:18:18 -0500 Subject: [PATCH] Tracker: Treat root (aka Disks) like a volume This yields the volume context menu on the Disks icon. Grab root (Disks) icon before getting volume icon so Disks doesn't get the generic volume icon. Don't add free space bar to Disks. Add Mount menu to the Disks File menu and context menu. Mount settings option has been removed as you can get to it from inside the Mount menu instead. SetupMountMenu() method is used to insert the Mount menu similar to SetupOpenWith() and SetupNavMenus(). Add DetachMountMenu() convenience method. Fixes #5584 Change-Id: Ic9e272807a0a36b89cba7258b9937b09b2da32dc Reviewed-on: https://review.haiku-os.org/c/haiku/+/7151 Haiku-Format: Haiku-format Bot Reviewed-by: John Scipione --- src/kits/tracker/ContainerWindow.cpp | 135 ++++++++++++++++++++++----- src/kits/tracker/ContainerWindow.h | 4 + src/kits/tracker/IconCache.cpp | 11 +-- src/kits/tracker/Pose.cpp | 20 ++-- 4 files changed, 134 insertions(+), 36 deletions(-) diff --git a/src/kits/tracker/ContainerWindow.cpp b/src/kits/tracker/ContainerWindow.cpp index 5ee876870b..dbaaa4f927 100644 --- a/src/kits/tracker/ContainerWindow.cpp +++ b/src/kits/tracker/ContainerWindow.cpp @@ -397,6 +397,7 @@ BContainerWindow::BContainerWindow(LockingList* list, uint32 openFlags, fCreateLinkItem(NULL), fOpenWithItem(NULL), fEditQueryItem(NULL), + fMountItem(NULL), fNavigationItem(NULL), fNewTemplatesItem(NULL), fMenuBar(NULL), @@ -552,6 +553,9 @@ BContainerWindow::Quit() if (fMoveToItem != NULL && fMoveToItem->Menu() == NULL) delete fMoveToItem; + if (fMountItem != NULL && fMountItem->Menu() == NULL) + delete fMountItem; + if (fOpenWithItem != NULL && fOpenWithItem->Menu() == NULL) delete fOpenWithItem; if (fEditQueryItem != NULL && fEditQueryItem->Menu() == NULL) @@ -661,6 +665,9 @@ BContainerWindow::DetachSubmenus() if (fMoveToItem != NULL && fMoveToItem->Menu() != NULL) fMoveToItem->Menu()->RemoveItem(fMoveToItem); + if (fMountItem != NULL && fMountItem->Menu() != NULL) + fMountItem = DetachMountMenu(); + if (fOpenWithItem != NULL && fOpenWithItem->Menu() != NULL) fOpenWithItem->Menu()->RemoveItem(fOpenWithItem); if (fEditQueryItem != NULL && fEditQueryItem->Menu() != NULL) @@ -1734,18 +1741,17 @@ BContainerWindow::AddFileMenu(BMenu* menu) 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))); - } + // "Mount >" menu and "Unmount" are inserted here, + // see UpdateMenu() and SetupMountMenu() - if (TargetModel()->IsTrash() || TargetModel()->InTrash()) { - menu->AddItem(Shortcuts()->DeleteItem()); - menu->AddItem(Shortcuts()->RestoreItem()); - } else { - menu->AddItem(Shortcuts()->DuplicateItem()); - menu->AddItem(Shortcuts()->MoveToTrashItem()); + if (!TargetModel()->IsRoot()) { + if (TargetModel()->IsTrash()) { + menu->AddItem(Shortcuts()->DeleteItem()); + menu->AddItem(Shortcuts()->RestoreItem()); + } else { + menu->AddItem(Shortcuts()->DuplicateItem()); + menu->AddItem(Shortcuts()->MoveToTrashItem()); + } } menu->AddSeparatorItem(); @@ -1922,6 +1928,7 @@ BContainerWindow::MenusEnded() DeleteSubmenu(fMoveToItem); DeleteSubmenu(fOpenWithItem); DeleteSubmenu(fNavigationItem); + DeleteSubmenu(fMountItem); } @@ -2141,6 +2148,83 @@ BContainerWindow::SetupNewTemplatesMenu(BMenu* parent, MenuContext context) } +void +BContainerWindow::SetupMountMenu(BMenu* parent, MenuContext context) +{ + SetupMountMenu(parent, context, TargetModel()->EntryRef()); +} + + +void +BContainerWindow::SetupMountMenu(BMenu* parent, MenuContext context, const entry_ref* ref) +{ + ASSERT(parent); + + // Remove "Mount", "Unmount" and separator item from the old menu + if (fMountItem != NULL && fMountItem->Menu() != NULL) + fMountItem = DetachMountMenu(); + + if (ref == NULL) + ref = TargetModel()->EntryRef(); + + Model model(ref); + + // bail out if not Desktop, root or volume + if (!(model.IsDesktop() || model.IsRoot() || model.IsVolume())) + return; + + // insert menu at the last position, add-ons gets added after + // (lower down on Desktop window context menu) + int32 mountIndex = parent->CountItems() - 1; + + delete fMountItem; + fMountItem = Shortcuts()->MountItem(new MountMenu(Shortcuts()->MountLabel())); + parent->AddItem(fMountItem, mountIndex); + + if (model.IsDesktop() + || (model.IsRoot() && (context == kWindowPopUpContext || context == kPosePopUpContext))) { + // No "Unmount", add separator item only + parent->AddItem(new BSeparatorItem(), mountIndex + 1); + } else { + // Add "Unmount" and separator + BMenuItem* unmountItem = Shortcuts()->UnmountItem(); + parent->AddItem(unmountItem, mountIndex + 1); + Shortcuts()->UpdateUnmountItem(unmountItem); + parent->AddItem(new BSeparatorItem(), mountIndex + 2); + } +} + + +BMenuItem* +BContainerWindow::DetachMountMenu() +{ + BMenu* menu = fMountItem->Menu(); + int32 mountIndex = menu->IndexOf(fMountItem); + if (mountIndex == B_ERROR) + return NULL; + + // remove items in reverse chronological order + + // we may not have "Unmount", look for item with U shortcut + if (menu->ItemAt(mountIndex + 1) != NULL && menu->ItemAt(mountIndex + 1)->Shortcut() == 'U') { + // remove and delete separator + BMenuItem* separator = menu->RemoveItem(mountIndex + 2); + if (dynamic_cast(separator) != NULL) + delete separator; + // remove and delete "Unmount" + delete menu->RemoveItem(mountIndex + 1); + } else { + // remove and delete separator + BMenuItem* separator = menu->RemoveItem(mountIndex + 1); + if (dynamic_cast(separator) != NULL) + delete separator; + } + + // remove "Mount >" menu item from parent and return it + return menu->RemoveItem(mountIndex); +} + + void BContainerWindow::PopulateMoveCopyNavMenu(BNavMenu* navMenu, uint32 what, const entry_ref* ref, bool addLocalOnly) @@ -2421,7 +2505,7 @@ BContainerWindow::ShowContextMenu(BPoint where, const entry_ref* ref) if (model.IsTrash()) fContextMenu = fTrashContextMenu; - else if (model.IsVolume()) + else if (model.IsVolume() || model.IsRoot()) fContextMenu = fVolumeContextMenu; else fContextMenu = fPoseContextMenu; @@ -2506,9 +2590,8 @@ BContainerWindow::AddVolumeContextMenu(BMenu* menu) menu->AddItem(Shortcuts()->EditNameItem()); menu->AddSeparatorItem(); - menu->AddItem(Shortcuts()->MountItem(new MountMenu(Shortcuts()->MountLabel()))); - menu->AddItem(Shortcuts()->UnmountItem()); - menu->AddSeparatorItem(); + // "Mount >", "Unmount" and a separator are inserted here, + // see UpdateMenu() and SetupMountMenu() menu->AddItem(new BMenuItem(new BMenu(Shortcuts()->AddOnsLabel()))); } @@ -2554,12 +2637,8 @@ BContainerWindow::AddWindowContextMenu(BMenu* menu) menu->AddItem(Shortcuts()->OpenParentItem()); menu->AddSeparatorItem(); - if (!PoseView()->IsFilePanel()) { - if (TargetModel()->IsRoot() || TargetModel()->IsDesktop()) { - menu->AddItem(Shortcuts()->MountItem(new MountMenu(Shortcuts()->MountLabel()))); - menu->AddSeparatorItem(); - } - } + // "Mount >" menu and "Unmount" are inserted here, + // see UpdateMenu() and SetupMountMenu(). menu->AddItem(new BMenuItem(new BMenu(Shortcuts()->AddOnsLabel()))); @@ -2801,6 +2880,16 @@ BContainerWindow::UpdateFileMenuOrPoseContextMenu(BMenu* menu, MenuContext conte SetupOpenWithMenu(menu); } + // "Mount >" menu and "Unmount" are inserted here + if (context == kPosePopUpContext) { + Model model(ref); + if (model.IsRoot() || model.IsVolume()) + SetupMountMenu(menu, kPosePopUpContext, ref); + } else if (context == kFileMenuContext) { + if (TargetModel()->IsRoot()) + SetupMountMenu(menu, kFileMenuContext); + } + // "Edit query" inserted before "Open with..." if (context == kPosePopUpContext) { if (ShouldHaveEditQueryItem(ref)) @@ -2832,6 +2921,10 @@ BContainerWindow::UpdateWindowContextMenu(BMenu* menu) UpdateWindowMenuOrWindowContextMenu(menu, kWindowPopUpContext); + // "Mount >" menu is inserted at the bottom + if (TargetModel()->IsDesktop() || TargetModel()->IsRoot()) + SetupMountMenu(menu, kWindowPopUpContext); + BuildAddOnsMenu(menu); } diff --git a/src/kits/tracker/ContainerWindow.h b/src/kits/tracker/ContainerWindow.h index c3c2e18d85..21ca813764 100644 --- a/src/kits/tracker/ContainerWindow.h +++ b/src/kits/tracker/ContainerWindow.h @@ -259,6 +259,9 @@ protected: virtual void SetupEditQueryItem(BMenu*); virtual void SetupEditQueryItem(BMenu*, const entry_ref* ref); virtual void SetupDiskMenu(BMenu*); + virtual void SetupMountMenu(BMenu*, MenuContext context); + virtual void SetupMountMenu(BMenu*, MenuContext context, const entry_ref* ref); + BMenuItem* DetachMountMenu(); virtual void BuildAddOnsMenu(BMenu*); void BuildMimeTypeList(BStringList& mimeTypes); @@ -315,6 +318,7 @@ protected: BMenuItem* fCreateLinkItem; BMenuItem* fOpenWithItem; BMenuItem* fEditQueryItem; + BMenuItem* fMountItem; ModelMenuItem* fNavigationItem; BMenuItem* fNewTemplatesItem; BMenuBar* fMenuBar; diff --git a/src/kits/tracker/IconCache.cpp b/src/kits/tracker/IconCache.cpp index b0ff82278a..b1d047ad14 100644 --- a/src/kits/tracker/IconCache.cpp +++ b/src/kits/tracker/IconCache.cpp @@ -930,7 +930,11 @@ IconCache::Preload(AutoLock* nodeCacheLocker, IconSource source = model->IconFrom(); if (source == kUnknownSource || source == kUnknownNotFromNode) { // fish for special first models and handle them appropriately - if (model->IsVolume()) { + if (model->IsRoot()) { + entry = GetRootIcon(nodeCacheLocker, sharedCacheLocker, &resultingOpenCache, model, + source, mode, size, &lazyBitmap); + ASSERT(entry != NULL); + } else if (model->IsVolume()) { // volume may use specialized icon in the volume node entry = GetNodeIcon(&modelOpener, nodeCacheLocker, &resultingOpenCache, model, source, mode, size, @@ -941,11 +945,6 @@ IconCache::Preload(AutoLock* nodeCacheLocker, &resultingOpenCache, model, source, mode, size, &lazyBitmap); } - } else if (model->IsRoot()) { - entry = GetRootIcon(nodeCacheLocker, sharedCacheLocker, - &resultingOpenCache, model, source, mode, size, - &lazyBitmap); - ASSERT(entry != NULL); } else { if (source == kUnknownSource) { // look for node icons first diff --git a/src/kits/tracker/Pose.cpp b/src/kits/tracker/Pose.cpp index b1123c2033..0beb99ec92 100644 --- a/src/kits/tracker/Pose.cpp +++ b/src/kits/tracker/Pose.cpp @@ -88,33 +88,35 @@ BPose::BPose(Model* model, BPoseView* view, uint32 clipboardMode, { CreateWidgets(view); - if (model->IsVolume()) { + if (model->IsVolume() && !model->IsRoot()) { fs_info info; dev_t device = model->NodeRef()->device; BVolume* volume = new BVolume(device); - if (volume->InitCheck() == B_OK - && fs_stat_dev(device, &info) == B_OK) { + if (volume->InitCheck() == B_OK && fs_stat_dev(device, &info) == B_OK) { // Philosophy here: // Bars go on all read/write volumes - // Exceptions: Not on CDDA - if (strcmp(info.fsh_name,"cdda") != 0 - && !volume->IsReadOnly()) { + // Exceptions: Not on CDDA or Disks + if (strcmp(info.fsh_name, "cdda") != 0 && !volume->IsReadOnly()) { // The volume is ok and we want space bars on it gPeriodicUpdatePoses.AddPose(this, view, _PeriodicUpdateCallback, volume); if (TrackerSettings().ShowVolumeSpaceBar()) fPercent = CalcFreeSpace(volume); - } else + } else { + // no space bars on volume delete volume; - } else + } + } else { + // bad volume delete volume; + } } } BPose::~BPose() { - if (fModel->IsVolume()) { + if (fModel->IsVolume() && !fModel->IsRoot()) { // we might be registered for periodic updates BVolume* volume = NULL; if (gPeriodicUpdatePoses.RemovePose(this, (void**)&volume))