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 <no-reply+haikuformatbot@haiku-os.org>
Reviewed-by: John Scipione <jscipione@gmail.com>
This commit is contained in:
John Scipione 2023-12-01 21:18:18 -05:00
parent e46d9f45b8
commit 9df392ba32
4 changed files with 134 additions and 36 deletions

View File

@ -397,6 +397,7 @@ BContainerWindow::BContainerWindow(LockingList<BWindow>* 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<BSeparatorItem*>(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<BSeparatorItem*>(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);
}

View File

@ -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;

View File

@ -930,7 +930,11 @@ IconCache::Preload(AutoLock<SimpleIconCache>* 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<SimpleIconCache>* 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

View File

@ -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))