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