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 <[email protected]>
Tested-by: Commit checker robot <[email protected]>
This commit is contained in:
John Scipione
2025-01-26 18:29:22 +00:00
parent e17a9b1ee0
commit e46d9f45b8
18 changed files with 3259 additions and 1825 deletions
+1 -1
View File
@@ -68,7 +68,7 @@ const uint32 kPasteLinksFromClipboard = 'Tplc';
const uint32 kCancelSelectionToClipboard = 'Tesc'; const uint32 kCancelSelectionToClipboard = 'Tesc';
const uint32 kClipboardPosesChanged = 'Tcpc'; const uint32 kClipboardPosesChanged = 'Tcpc';
const uint32 kEditItem = 'Tedt'; const uint32 kEditName = 'Tedt';
const uint32 kEditQuery = 'Qedt'; const uint32 kEditQuery = 'Qedt';
const uint32 kNewFolder = 'Tnwf'; const uint32 kNewFolder = 'Tnwf';
const uint32 kNewEntryFromTemplate = 'Tnwe'; const uint32 kNewEntryFromTemplate = 'Tnwe';
File diff suppressed because it is too large Load Diff
+62 -27
View File
@@ -63,6 +63,8 @@ class Model;
class ModelNodeLazyOpener; class ModelNodeLazyOpener;
class BorderedView; class BorderedView;
class SelectionWindow; class SelectionWindow;
class TShortcuts;
class TemplatesMenu;
#define kDefaultFolderTemplate "DefaultFolderTemplate" #define kDefaultFolderTemplate "DefaultFolderTemplate"
@@ -132,6 +134,7 @@ public:
Model* TargetModel() const; Model* TargetModel() const;
BPoseView* PoseView() const; BPoseView* PoseView() const;
TShortcuts* Shortcuts() const;
BNavigator* Navigator() const; BNavigator* Navigator() const;
virtual void SelectionChanged(); virtual void SelectionChanged();
@@ -142,6 +145,8 @@ public:
void RestoreStateCommon(); void RestoreStateCommon();
virtual void SaveState(bool hide = true); virtual void SaveState(bool hide = true);
virtual void SaveState(BMessage &) const; virtual void SaveState(BMessage &) const;
virtual void SwitchDirectory(const entry_ref* ref);
virtual void OpenParent();
void UpdateTitle(); void UpdateTitle();
bool StateNeedsSaving() const; bool StateNeedsSaving() const;
@@ -155,21 +160,27 @@ public:
// calls for inheriting window size, attribute layout, etc. // calls for inheriting window size, attribute layout, etc.
// deprecated // deprecated
virtual void AddMimeTypesToMenu(BMenu*);
void AddMimeTypesToMenu(); void AddMimeTypesToMenu();
virtual void MarkAttributesMenu(BMenu*); void AddMimeTypesToMenu(BMenu*);
void MarkAttributesMenu();
BMenuItem* NewArrangeByMenu();
virtual void SetupArrangeByMenu(BMenu*);
void MarkArrangeByMenu(BMenu*); void MarkArrangeByMenu(BMenu*);
BMenuItem* NewAttributeMenuItem(const char* label, const char* name, BMenuItem* NewAttributeMenuItem(const char* label, const char* name,
int32 type, float width, int32 align, bool editable, int32 type, float width, int32 align, bool editable,
bool statField); bool statField);
BMenuItem* NewAttributeMenuItem(const char* label, const char* name, BMenuItem* NewAttributeMenuItem(const char* label, const char* name,
int32 type, const char* displayAs, float width, int32 align, int32 type, const char* displayAs, float width, int32 align,
bool editable, bool statField); bool editable, bool statField);
virtual void NewAttributesMenu(BMenu*);
void NewAttributesMenu();
virtual void NewAttributesMenu(BMenu*);
void MarkAttributesMenu();
virtual void MarkAttributesMenu(BMenu*);
void HideAttributesMenu(); void HideAttributesMenu();
void ShowAttributesMenu(); void ShowAttributesMenu();
PiggybackTaskLoop* DelayedTaskLoop(); PiggybackTaskLoop* DelayedTaskLoop();
// use for RunLater queueing // use for RunLater queueing
void PulseTaskLoop(); void PulseTaskLoop();
@@ -196,6 +207,14 @@ public:
void SetPathWatchingEnabled(bool); void SetPathWatchingEnabled(bool);
bool IsPathWatchingEnabled(void) const; bool IsPathWatchingEnabled(void) const;
protected:
enum MenuContext {
kFileMenuContext,
kWindowMenuContext,
kPosePopUpContext,
kWindowPopUpContext
};
protected: protected:
virtual BPoseView* NewPoseView(Model*, uint32); virtual BPoseView* NewPoseView(Model*, uint32);
// instantiate a different flavor of BPoseView for different // instantiate a different flavor of BPoseView for different
@@ -217,42 +236,42 @@ protected:
// desktop window // desktop window
virtual void AddFileMenu(BMenu* menu); virtual void AddFileMenu(BMenu* menu);
virtual void AddWindowMenu(BMenu* menu); virtual void AddWindowMenu(BMenu* menu);
virtual void AddIconSizeMenu(BMenu* menu);
virtual void AddContextMenus(); 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 DetachSubmenus();
virtual void AddWindowContextMenus(BMenu*);
virtual void AddVolumeContextMenus(BMenu*);
virtual void AddDropContextMenus(BMenu*);
virtual void AddTrashContextMenus(BMenu*);
virtual void RepopulateMenus(); virtual void RepopulateMenus();
void PopulateArrangeByMenu(BMenu*);
virtual void SetCutItem(BMenu*); virtual void SetupNavigationMenu(BMenu*, const entry_ref*);
virtual void SetCopyItem(BMenu*); virtual void SetupMoveCopyMenus(BMenu*, const entry_ref*);
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 PopulateMoveCopyNavMenu(BNavMenu*, uint32, virtual void PopulateMoveCopyNavMenu(BNavMenu*, uint32,
const entry_ref*, bool); const entry_ref*, bool);
virtual void SetupOpenWithMenu(BMenu*); 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*);
virtual void SetupEditQueryItem(BMenu*, const entry_ref* ref);
virtual void SetupDiskMenu(BMenu*); virtual void SetupDiskMenu(BMenu*);
virtual void BuildAddOnsMenu(BMenu*); virtual void BuildAddOnsMenu(BMenu*);
void BuildMimeTypeList(BStringList& mimeTypes); void BuildMimeTypeList(BStringList& mimeTypes);
enum UpdateMenuContext { virtual void UpdateMenu(BMenu* menu, MenuContext context,
kMenuBarContext, const entry_ref* ref = NULL);
kPosePopUpContext, virtual void UpdateFileMenu(BMenu* menu);
kWindowPopUpContext virtual void UpdatePoseContextMenu(BMenu* menu, const entry_ref* ref);
}; virtual void UpdateFileMenuOrPoseContextMenu(BMenu* menu, MenuContext context,
const entry_ref* ref = NULL);
virtual void UpdateMenu(BMenu* menu, UpdateMenuContext context); 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* AddMimeMenu(const BMimeType& mimeType, bool isSuperType,
BMenu* menu, int32 start); BMenu* menu, int32 start);
@@ -270,6 +289,12 @@ protected:
uint32 fOpenFlags; uint32 fOpenFlags;
bool fUsesLayout; 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; BGroupLayout* fRootLayout;
BGroupView* fMenuContainer; BGroupView* fMenuContainer;
BGridView* fPoseContainer; BGridView* fPoseContainer;
@@ -277,8 +302,9 @@ protected:
BGroupView* fVScrollBarContainer; BGroupView* fVScrollBarContainer;
BGroupView* fCountContainer; BGroupView* fCountContainer;
TShortcuts* fShortcuts;
BPopUpMenu* fContextMenu; BPopUpMenu* fContextMenu;
BPopUpMenu* fFileContextMenu; BPopUpMenu* fPoseContextMenu;
BPopUpMenu* fWindowContextMenu; BPopUpMenu* fWindowContextMenu;
BPopUpMenu* fDropContextMenu; BPopUpMenu* fDropContextMenu;
BPopUpMenu* fVolumeContextMenu; BPopUpMenu* fVolumeContextMenu;
@@ -288,7 +314,9 @@ protected:
BMenuItem* fCopyToItem; BMenuItem* fCopyToItem;
BMenuItem* fCreateLinkItem; BMenuItem* fCreateLinkItem;
BMenuItem* fOpenWithItem; BMenuItem* fOpenWithItem;
BMenuItem* fEditQueryItem;
ModelMenuItem* fNavigationItem; ModelMenuItem* fNavigationItem;
BMenuItem* fNewTemplatesItem;
BMenuBar* fMenuBar; BMenuBar* fMenuBar;
DraggableContainerIcon* fDraggableIcon; DraggableContainerIcon* fDraggableIcon;
BNavigator* fNavigator; BNavigator* fNavigator;
@@ -296,7 +324,7 @@ protected:
BMenu* fAttrMenu; BMenu* fAttrMenu;
BMenu* fWindowMenu; BMenu* fWindowMenu;
BMenu* fFileMenu; BMenu* fFileMenu;
BMenu* fArrangeByMenu; BMenuItem* fArrangeByItem;
SelectionWindow* fSelectionWindow; SelectionWindow* fSelectionWindow;
@@ -391,6 +419,13 @@ BContainerWindow::PoseView() const
} }
inline TShortcuts*
BContainerWindow::Shortcuts() const
{
return fShortcuts;
}
inline void inline void
BContainerWindow::SetupDiskMenu(BMenu*) BContainerWindow::SetupDiskMenu(BMenu*)
{ {
+46 -101
View File
@@ -64,6 +64,7 @@ All rights reserved.
#include "KeyInfos.h" #include "KeyInfos.h"
#include "MountMenu.h" #include "MountMenu.h"
#include "PoseView.h" #include "PoseView.h"
#include "Shortcuts.h"
#include "TemplatesMenu.h" #include "TemplatesMenu.h"
#include "Tracker.h" #include "Tracker.h"
@@ -194,21 +195,17 @@ BDeskWindow::BDeskWindow(LockingList<BWindow>* windowList, uint32 openFlags)
fNodeRef(NULL), fNodeRef(NULL),
fShortcutsSettings(NULL) fShortcutsSettings(NULL)
{ {
// Add icon view switching shortcuts. These are displayed in the context // create pose view
// menu, although they obviously don't work from those menu items. BDirectory deskDir;
BMessage* message = new BMessage(kIconMode); if (FSGetDeskDir(&deskDir) == B_OK) {
AddShortcut('1', B_COMMAND_KEY, message, PoseView()); BEntry entry;
deskDir.GetEntry(&entry);
message = new BMessage(kMiniIconMode); Model* model = new Model(&entry, true);
AddShortcut('2', B_COMMAND_KEY, message, PoseView()); if (model->InitCheck() == B_OK)
CreatePoseView(model);
message = new BMessage(kIconMode); else
message->AddInt32("scale", 1); delete model;
AddShortcut('+', B_COMMAND_KEY, message, PoseView()); }
message = new BMessage(kIconMode);
message->AddInt32("scale", 0);
AddShortcut('-', B_COMMAND_KEY, message, PoseView());
} }
@@ -254,6 +251,40 @@ BDeskWindow::Init(const BMessage*)
if (fDeskShelf != NULL) if (fDeskShelf != NULL)
fDeskShelf->SetDisplaysZombies(true); 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 void
BDeskWindow::WorkspaceActivated(int32 workspace, bool state) BDeskWindow::WorkspaceActivated(int32 workspace, bool state)
{ {
-1
View File
@@ -71,7 +71,6 @@ public:
void SaveDesktopPoseLocations(); void SaveDesktopPoseLocations();
protected: protected:
virtual void AddWindowContextMenus(BMenu*);
virtual BPoseView* NewPoseView(Model*, uint32); virtual BPoseView* NewPoseView(Model*, uint32);
virtual void WorkspaceActivated(int32, bool); virtual void WorkspaceActivated(int32, bool);
+2 -2
View File
@@ -296,7 +296,7 @@ BFilePanel::SetPanelDirectory(const entry_ref* ref)
if (!lock) if (!lock)
return; return;
static_cast<TFilePanel*>(fWindow)->SetTo(ref); static_cast<TFilePanel*>(fWindow)->SwitchDirectory(ref);
} }
@@ -312,7 +312,7 @@ BFilePanel::SetPanelDirectory(const char* path)
if (!lock) if (!lock)
return; return;
static_cast<TFilePanel*>(fWindow)->SetTo(&ref); static_cast<TFilePanel*>(fWindow)->SwitchDirectory(&ref);
} }
+309 -374
View File
@@ -77,6 +77,7 @@ All rights reserved.
#include "IconMenuItem.h" #include "IconMenuItem.h"
#include "MimeTypes.h" #include "MimeTypes.h"
#include "NavMenu.h" #include "NavMenu.h"
#include "Shortcuts.h"
#include "Tracker.h" #include "Tracker.h"
#include "Utilities.h" #include "Utilities.h"
@@ -114,11 +115,7 @@ key_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter)
if (filter == NULL) if (filter == NULL)
return B_DISPATCH_MESSAGE; return B_DISPATCH_MESSAGE;
BLooper* looper = filter->Looper(); TFilePanel* panel = dynamic_cast<TFilePanel*>(filter->Looper());
if (looper == NULL)
return B_DISPATCH_MESSAGE;
TFilePanel* panel = dynamic_cast<TFilePanel*>(looper);
if (panel == NULL || panel->TrackingMenu()) if (panel == NULL || panel->TrackingMenu())
return B_DISPATCH_MESSAGE; return B_DISPATCH_MESSAGE;
@@ -135,11 +132,11 @@ key_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter)
if ((modifiers & B_COMMAND_KEY) != 0) { if ((modifiers & B_COMMAND_KEY) != 0) {
switch (key) { switch (key) {
case B_UP_ARROW: case B_UP_ARROW:
looper->PostMessage(kOpenParentDir); BMessenger(panel).SendMessage(kOpenParentDir);
return B_SKIP_MESSAGE; return B_SKIP_MESSAGE;
case 'w': case 'w':
looper->PostMessage(kCancelButton); BMessenger(panel).SendMessage(kCancelButton);
return B_SKIP_MESSAGE; return B_SKIP_MESSAGE;
default: default:
@@ -151,9 +148,9 @@ key_down_filter(BMessage* message, BHandler** handler, BMessageFilter* filter)
if (view->ActivePose() != NULL) if (view->ActivePose() != NULL)
view->CommitActivePose(false); view->CommitActivePose(false);
else if (view->IsTypeAheadFiltering()) else if (view->IsTypeAheadFiltering())
looper->PostMessage(B_CANCEL, *handler); BMessenger(panel).SendMessage(B_CANCEL, *handler);
else else
looper->PostMessage(kCancelButton); BMessenger(panel).SendMessage(kCancelButton);
return B_SKIP_MESSAGE; return B_SKIP_MESSAGE;
} }
@@ -183,6 +180,7 @@ TFilePanel::TFilePanel(file_panel_mode mode, BMessenger* target, const BEntry* s
fClientObject(NULL), fClientObject(NULL),
fSelectionIterator(0), fSelectionIterator(0),
fMessage(NULL), fMessage(NULL),
fFavoritesMenu(NULL),
fHideWhenDone(hideWhenDone), fHideWhenDone(hideWhenDone),
fIsTrackingMenu(false), fIsTrackingMenu(false),
fDefaultStateRestored(false) fDefaultStateRestored(false)
@@ -212,8 +210,10 @@ TFilePanel::TFilePanel(file_panel_mode mode, BMessenger* target, const BEntry* s
else else
fMessage = new BMessage(B_REFS_RECEIVED); fMessage = new BMessage(B_REFS_RECEIVED);
gLocalizedNamePreferred // no new template menu in file panel
= BLocaleRoster::Default()->IsFilesystemTranslationPreferred(); fNewTemplatesItem = NULL;
gLocalizedNamePreferred = BLocaleRoster::Default()->IsFilesystemTranslationPreferred();
// check for legal starting directory // check for legal starting directory
Model* model = new Model(); Model* model = new Model();
@@ -357,21 +357,18 @@ TFilePanel::MessageDropFilter(BMessage* message, BHandler**, BMessageFilter* fil
entry.GetRef(&ref); entry.GetRef(&ref);
panel->fTaskLoop->RunLater(NewMemberFunctionObjectWithResult // don't delay the initial selection try if the target directory is already current
(&TFilePanel::SelectChildInParent, panel, panel->fTaskLoop->RunLater(
const_cast<const entry_ref*>(&ref), NewMemberFunctionObjectWithResult(&TFilePanel::SelectChildInParent, panel,
const_cast<const node_ref*>(&child)), const_cast<const entry_ref*>(&ref), const_cast<const node_ref*>(&child)),
ref == *panel->TargetModel()->EntryRef() ? 0 : 100000, 200000, ref == *panel->TargetModel()->EntryRef() ? 0 : 100000, 200000, 5000000);
5000000);
// if the target directory is already current, we won't
// delay the initial selection try
// also set the save name to the dragged in entry // also set the save name to the dragged in entry
if (panel->IsSavePanel()) if (panel->IsSavePanel())
panel->SetSaveText(path.Leaf()); panel->SetSaveText(path.Leaf());
} }
panel->SetTo(&ref); panel->SwitchDirectory(&ref);
return B_SKIP_MESSAGE; return B_SKIP_MESSAGE;
} }
@@ -412,7 +409,7 @@ TFilePanel::FSFilter(BMessage* message, BHandler**, BMessageFilter* filter)
// but not wind title // but not wind title
if (*(panel->TargetModel()->NodeRef()) == itemNode) { if (*(panel->TargetModel()->NodeRef()) == itemNode) {
panel->TargetModel()->UpdateEntryRef(&dirNode, name); panel->TargetModel()->UpdateEntryRef(&dirNode, name);
panel->SetTo(panel->TargetModel()->EntryRef()); panel->SwitchDirectory(panel->TargetModel()->EntryRef());
return B_SKIP_MESSAGE; return B_SKIP_MESSAGE;
} }
break; break;
@@ -439,9 +436,7 @@ TFilePanel::FSFilter(BMessage* message, BHandler**, BMessageFilter* filter)
root.GetEntry(&entry); root.GetEntry(&entry);
entry.GetRef(&ref); entry.GetRef(&ref);
panel->SwitchDirToDesktopIfNeeded(ref); panel->SwitchDirectory(&ref);
panel->SetTo(&ref);
return B_SKIP_MESSAGE; return B_SKIP_MESSAGE;
} }
break; break;
@@ -544,25 +539,37 @@ TFilePanel::SetRefFilter(BRefFilter* filter)
void void
TFilePanel::SetTo(const entry_ref* ref) TFilePanel::SwitchDirectory(const entry_ref* ref)
{ {
if (ref == NULL) if (ref == NULL)
return; return;
entry_ref setToRef(*ref); entry_ref setToRef(*ref);
bool isDesktop = SwitchDirToDesktopIfNeeded(setToRef); bool isDesktop = SwitchDirToDesktopIfNeeded(setToRef);
BEntry entry(&setToRef); BEntry entry(&setToRef, true);
if (entry.InitCheck() != B_OK || !entry.IsDirectory()) if (entry.InitCheck() != B_OK)
return; return;
PoseView()->SetIsDesktop(isDesktop); PoseView()->SetIsDesktop(isDesktop);
PoseView()->SwitchDir(&setToRef); _inherited::SwitchDirectory(&setToRef);
SwitchDirMenuTo(&setToRef);
AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome)); AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome));
// our shortcut got possibly removed because the home // our shortcut got possibly removed because the home
// menu item got removed - we shouldn't really have to do // menu item got removed - we shouldn't really have to do
// this - this is a workaround for a kit bug. // 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<ModelMenuItem*>(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); fDirMenuField->MenuBar()->SetMaxContentWidth(rect.Width() - 26.0f);
// Make room for the icon // Make room for the icon
fDirMenu = new BDirMenu(fDirMenuField->MenuBar(), fDirMenu = new BDirMenu(fDirMenuField->MenuBar(), this, kSwitchDirectory, "refs");
this, kSwitchDirectory, "refs");
BEntry entry(TargetModel()->EntryRef()); BEntry entry(TargetModel()->EntryRef());
if (entry.InitCheck() == B_OK) if (entry.InitCheck() == B_OK)
@@ -786,20 +792,18 @@ TFilePanel::Init(const BMessage*)
else else
fBackView->AddChild(fPoseContainer); fBackView->AddChild(fPoseContainer);
fShortcuts = new TShortcuts(this);
AddShortcut('W', B_COMMAND_KEY, new BMessage(kCancelButton)); AddShortcut('W', B_COMMAND_KEY, new BMessage(kCancelButton));
AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome)); AddShortcut('H', B_COMMAND_KEY, new BMessage(kSwitchToHome));
AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY, AddShortcut('A', B_COMMAND_KEY | B_SHIFT_KEY, new BMessage(kShowSelectionWindow));
new BMessage(kShowSelectionWindow));
AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), this); AddShortcut('A', B_COMMAND_KEY, new BMessage(B_SELECT_ALL), this);
AddShortcut('S', B_COMMAND_KEY, new BMessage(kInvertSelection), AddShortcut('S', B_COMMAND_KEY, new BMessage(kInvertSelection), PoseView());
PoseView());
AddShortcut('Y', B_COMMAND_KEY, new BMessage(kResizeToFit), 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, new BMessage(kOpenDir));
AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY | B_OPTION_KEY, AddShortcut(B_DOWN_ARROW, B_COMMAND_KEY | B_OPTION_KEY, new BMessage(kOpenDir));
new BMessage(kOpenDir));
AddShortcut(B_UP_ARROW, B_COMMAND_KEY, new BMessage(kOpenParentDir)); AddShortcut(B_UP_ARROW, B_COMMAND_KEY, new BMessage(kOpenParentDir));
AddShortcut(B_UP_ARROW, B_COMMAND_KEY | B_OPTION_KEY, AddShortcut(B_UP_ARROW, B_COMMAND_KEY | B_OPTION_KEY, new BMessage(kOpenParentDir));
new BMessage(kOpenParentDir));
if (!fIsSavePanel && (fNodeFlavors & B_DIRECTORY_NODE) == 0) if (!fIsSavePanel && (fNodeFlavors & B_DIRECTORY_NODE) == 0)
default_button->SetEnabled(false); default_button->SetEnabled(false);
@@ -808,54 +812,10 @@ TFilePanel::Init(const BMessage*)
RestoreState(); RestoreState();
AddMenus(); if (ShouldAddMenus())
AddMenus();
AddContextMenus(); 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()->ScrollTo(B_ORIGIN);
PoseView()->UpdateScrollRange(); PoseView()->UpdateScrollRange();
PoseView()->ScrollTo(B_ORIGIN); 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 void
TFilePanel::RestoreState() TFilePanel::RestoreState()
{ {
@@ -961,103 +982,71 @@ TFilePanel::RestoreWindowState(const BMessage &message)
void void
TFilePanel::AddFileContextMenus(BMenu* menu) TFilePanel::AddPoseContextMenu(BMenu* menu)
{ {
menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), menu->AddItem(Shortcuts()->GetInfoItem());
new BMessage(kGetInfo), 'I')); menu->AddItem(Shortcuts()->EditNameItem());
menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), if (TargetModel()->InTrash()) {
new BMessage(kEditItem), 'E')); menu->AddItem(Shortcuts()->DeleteItem());
menu->AddItem(new BMenuItem(B_TRANSLATE("Duplicate"), menu->AddItem(Shortcuts()->RestoreItem());
new BMessage(kDuplicateSelection), 'D')); } else {
menu->AddItem(new BMenuItem(B_TRANSLATE("Move to Trash"), menu->AddItem(Shortcuts()->DuplicateItem());
new BMessage(kMoveSelectionToTrash), 'T')); menu->AddItem(Shortcuts()->MoveToTrashItem());
}
menu->AddSeparatorItem(); menu->AddSeparatorItem();
BMenuItem* cutItem = new BMenuItem(B_TRANSLATE("Cut"), menu->AddItem(Shortcuts()->CutItem());
new BMessage(B_CUT), 'X'); menu->AddItem(Shortcuts()->CopyItem());
menu->AddItem(cutItem); #ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU
BMenuItem* copyItem = new BMenuItem(B_TRANSLATE("Copy"), menu->AddItem(Shortcuts()->PasteItem());
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);
#endif #endif
} }
void void
TFilePanel::AddVolumeContextMenus(BMenu* menu) TFilePanel::AddVolumeContextMenu(BMenu* menu)
{ {
menu->AddItem(new BMenuItem(B_TRANSLATE("Open"), menu->AddItem(Shortcuts()->OpenItem());
new BMessage(kOpenSelection), 'O')); menu->AddItem(Shortcuts()->GetInfoItem());
menu->AddItem(new BMenuItem(B_TRANSLATE("Get info"), menu->AddItem(Shortcuts()->EditNameItem());
new BMessage(kGetInfo), 'I'));
menu->AddItem(new BMenuItem(B_TRANSLATE("Edit name"),
new BMessage(kEditItem), 'E'));
#if CUT_COPY_PASTE_IN_CONTEXT_MENU #ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU
menu->AddSeparatorItem(); menu->AddSeparatorItem();
BMenuItem* pasteItem = new BMenuItem(B_TRANSLATE("Paste"), menu->AddItem(Shortcuts()->PasteItem());
new BMessage(B_PASTE), 'V');
#endif
menu->SetTargetForItems(PoseView());
#if CUT_COPY_PASTE_IN_CONTEXT_MENU
pasteItem->SetTarget(this);
#endif #endif
} }
void void
TFilePanel::AddWindowContextMenus(BMenu* menu) TFilePanel::AddWindowContextMenu(BMenu* menu)
{ {
BMenuItem* item = new BMenuItem(B_TRANSLATE("New folder"), menu->AddItem(Shortcuts()->NewFolderItem());
new BMessage(kNewFolder), 'N'); menu->AddItem(new BSeparatorItem());
item->SetTarget(PoseView());
menu->AddItem(item);
menu->AddSeparatorItem();
#if CUT_COPY_PASTE_IN_CONTEXT_MENU #ifdef CUT_COPY_PASTE_IN_CONTEXT_MENU
item = new BMenuItem(B_TRANSLATE("Paste"), new BMessage(B_PASTE), 'V'); menu->AddItem(Shortcuts()->PasteItem());
item->SetTarget(this);
menu->AddItem(item);
menu->AddSeparatorItem(); menu->AddSeparatorItem();
#endif #endif
item = new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), menu->AddItem(Shortcuts()->SelectItem());
new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY); menu->AddItem(Shortcuts()->SelectAllItem());
item->SetTarget(PoseView()); menu->AddItem(Shortcuts()->InvertSelectionItem());
menu->AddItem(item); menu->AddItem(Shortcuts()->OpenParentItem());
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);
} }
void 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(); PoseView()->CommitActivePose();
} }
EnableNamedMenuItem(fMenuBar, kNewFolder, !TargetModel()->IsRoot() UpdateMenu(fFileMenu, kFileMenuContext);
&& !PoseView()->TargetVolumeIsReadOnly());
EnableNamedMenuItem(fMenuBar, kDuplicateSelection,
PoseView()->CanMoveToTrashOrDuplicate());
EnableNamedMenuItem(fMenuBar, kMoveSelectionToTrash,
PoseView()->CanMoveToTrashOrDuplicate());
EnableNamedMenuItem(fMenuBar, kEditItem, PoseView()->CanEditName());
SetCutItem(fMenuBar);
SetCopyItem(fMenuBar);
SetPasteItem(fMenuBar);
fIsTrackingMenu = true; fIsTrackingMenu = true;
} }
@@ -1097,64 +1076,74 @@ TFilePanel::MenusEnded()
void void
TFilePanel::ShowContextMenu(BPoint where, const entry_ref* ref) TFilePanel::DetachSubmenus()
{ {
ASSERT(IsLocked()); // no submenus to detatch in file panel
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;
} }
void 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 // do nothing here so nav menu doesn't get added
} }
@@ -1230,84 +1219,77 @@ TFilePanel::MessageReceived(BMessage* message)
switch (message->what) { switch (message->what) {
case B_REFS_RECEIVED: case B_REFS_RECEIVED:
{
// item was double clicked in file panel (PoseView) or from the favorites menu // item was double clicked in file panel (PoseView) or from the favorites menu
if (message->FindRef("refs", &ref) == B_OK) { if (message->FindRef("refs", &ref) != B_OK)
BEntry entry(&ref, true); break;
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);
PoseView()->SetIsDesktop(isDesktop); BEntry entry(&ref, true);
entry.SetTo(&ref); if (entry.InitCheck() != B_OK)
PoseView()->SwitchDir(&ref); break;
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<BButton*>(FindView("default button"));
if (button == NULL || !button->IsEnabled())
break;
}
if (IsSavePanel()) { // Double-click on dir or link-to-dir ALWAYS opens the dir.
int32 count = 0; // If more than one dir is selected the first one is opened.
type_code type; if (entry.IsDirectory()) {
message->GetInfo("refs", &type, &count); SwitchDirectory(&ref);
} else {
// Don't allow saves of multiple files // Otherwise, we have a file or a link to a file.
if (count > 1) { // AdjustButton has already tested the flavor if it comes from the file
ShowCenteredAlert( // panel; all we have to do is see if the button is enabled.
B_TRANSLATE( // In other cases, however, we can't rely on that. So first check for
"Sorry, saving more than one " // TrackerViewToken in the message to see if it's coming from the pose view
"item is not allowed."), if (message->HasMessenger("TrackerViewToken")) {
B_TRANSLATE("Cancel")); BButton* button = dynamic_cast<BButton*>(FindView("default button"));
} else { if (button == NULL || !button->IsEnabled())
// if we are a savepanel, set up the break;
// 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);
}
} }
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; break;
}
case kSwitchDirectory: case kSwitchDirectory:
{ {
entry_ref ref; entry_ref ref;
// this comes from dir menu or nav menu, so switch directories if (message->FindRef("refs", &ref) != B_OK)
if (message->FindRef("refs", &ref) == B_OK) { break;
BEntry entry(&ref, true);
if (entry.GetRef(&ref) == B_OK) SwitchDirectory(&ref);
SetTo(&ref);
}
break; break;
} }
@@ -1320,7 +1302,7 @@ TFilePanel::MessageReceived(BMessage* message)
break; break;
} }
SetTo(&ref); SwitchDirectory(&ref);
break; break;
} }
@@ -1387,8 +1369,7 @@ TFilePanel::MessageReceived(BMessage* message)
if (fIsSavePanel) { if (fIsSavePanel) {
if (PoseView()->IsFocus() if (PoseView()->IsFocus()
&& PoseView()->CountSelected() == 1) { && PoseView()->CountSelected() == 1) {
Model* model = (PoseView()->SelectionList()-> Model* model = (PoseView()->SelectionList()->FirstItem())->TargetModel();
FirstItem())->TargetModel();
if (model->ResolveIfLink()->IsDirectory()) { if (model->ResolveIfLink()->IsDirectory()) {
PoseView()->CommitActivePose(); PoseView()->CommitActivePose();
PoseView()->OpenSelection(); PoseView()->OpenSelection();
@@ -1404,20 +1385,21 @@ TFilePanel::MessageReceived(BMessage* message)
case B_OBSERVER_NOTICE_CHANGE: case B_OBSERVER_NOTICE_CHANGE:
{ {
int32 observerWhat; int32 observerWhat;
if (message->FindInt32("be:observe_change_what", &observerWhat) if (message->FindInt32("be:observe_change_what", &observerWhat) == B_OK) {
== B_OK) {
switch (observerWhat) { switch (observerWhat) {
case kDesktopFilePanelRootChanged: case kDesktopFilePanelRootChanged:
{ {
bool desktopIsRoot = true; bool desktopIsRoot;
if (message->FindBool("DesktopFilePanelRoot", if (message->FindBool("DesktopFilePanelRoot", &desktopIsRoot) == B_OK
&desktopIsRoot) == B_OK) { && TrackerSettings().DesktopFilePanelRoot() != desktopIsRoot) {
TrackerSettings(). TrackerSettings().SetDesktopFilePanelRoot(desktopIsRoot);
SetDesktopFilePanelRoot(desktopIsRoot); SwitchDirectory(TargetModel()->EntryRef());
} }
SetTo(TargetModel()->EntryRef());
break; break;
} }
default:
break;
} }
} }
break; break;
@@ -1441,7 +1423,7 @@ TFilePanel::OpenDirectory()
if (model->ResolveIfLink()->IsDirectory()) { if (model->ResolveIfLink()->IsDirectory()) {
BMessage message(B_REFS_RECEIVED); BMessage message(B_REFS_RECEIVED);
message.AddRef("refs", model->EntryRef()); message.AddRef("refs", model->EntryRef());
PostMessage(&message); BMessenger(this).SendMessage(&message);
} }
} }
@@ -1449,52 +1431,29 @@ TFilePanel::OpenDirectory()
void void
TFilePanel::OpenParent() TFilePanel::OpenParent()
{ {
if (!CanOpenParent()) BEntry entry(TargetModel()->EntryRef());
return; Model oldModel(*PoseView()->TargetModel());
const node_ref* oldNode = oldModel.NodeRef();
BEntry parentEntry; BEntry parentEntry;
BDirectory dir; if (TrackerSettings().DesktopFilePanelRoot() && FSIsRootDir(&entry)) {
// open parent on root, set to Desktop
Model oldModel(*PoseView()->TargetModel()); BDirectory desktopDir;
BEntry entry(oldModel.EntryRef()); if (FSGetDeskDir(&desktopDir) != B_OK || desktopDir.GetEntry(&parentEntry) != B_OK)
return;
if (entry.InitCheck() == B_OK } else if (FSGetParentVirtualDirectoryAware(entry, parentEntry) != B_OK) {
&& entry.GetParent(&dir) == B_OK return;
&& 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<const entry_ref*>(&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;
} }
// block on "/" entry_ref setToRef;
BEntry root("/"); parentEntry.GetRef(&setToRef);
node_ref rootRef; const entry_ref* parent = &setToRef;
root.GetNodeRef(&rootRef); 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; return false;
BEntry entry(&ref); BEntry entry(&ref);
BEntry root("/");
BDirectory desktopDir; BDirectory desktopDir;
FSGetDeskDir(&desktopDir); FSGetDeskDir(&desktopDir);
if (FSIsDeskDir(&entry) if (FSIsDeskDir(&entry) || (!settings.ShowDisksIcon() && FSIsRootDir(&entry))) {
// navigated into non-boot desktop, switch to boot desktop // navigated into desktop folder or hit "root" level, switch to Desktop
|| (entry == root && !settings.ShowDisksIcon())) {
// hit "/" level, map to desktop
desktopDir.GetEntry(&entry); desktopDir.GetEntry(&entry);
entry.GetRef(&ref); entry.GetRef(&ref);
return true; return true;
} }
return FSIsDeskDir(&entry); 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<ModelMenuItem*>(
fDirMenuField->MenuBar()->ItemAt(0));
ASSERT(item != NULL);
if (item != NULL)
item->SetEntry(&entry);
}
void void
TFilePanel::WindowActivated(bool active) TFilePanel::WindowActivated(bool active)
{ {
@@ -1897,9 +1835,9 @@ BFilePanelPoseView::ShowVolumes(bool visible, bool showShared)
AddRootPoses(true, showShared); AddRootPoses(true, showShared);
} }
TFilePanel* filepanel = dynamic_cast<TFilePanel*>(Window()); TFilePanel* panel = dynamic_cast<TFilePanel*>(Window());
if (filepanel != NULL && TargetModel() != NULL) if (panel != NULL && TargetModel() != NULL)
filepanel->SetTo(TargetModel()->EntryRef()); panel->SwitchDirectory(TargetModel()->EntryRef());
} }
@@ -1912,8 +1850,7 @@ BFilePanelPoseView::AdaptToVolumeChange(BMessage* message)
message->FindBool("ShowDisksIcon", &showDisksIcon); message->FindBool("ShowDisksIcon", &showDisksIcon);
message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop); message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop);
message->FindBool("MountSharedVolumesOntoDesktop", message->FindBool("MountSharedVolumesOntoDesktop", &mountSharedVolumesOntoDesktop);
&mountSharedVolumesOntoDesktop);
BEntry entry("/"); BEntry entry("/");
Model model(&entry); Model model(&entry);
@@ -1931,8 +1868,7 @@ BFilePanelPoseView::AdaptToVolumeChange(BMessage* message)
monitorMsg.AddInt64("directory", model.EntryRef()->directory); monitorMsg.AddInt64("directory", model.EntryRef()->directory);
monitorMsg.AddString("name", model.EntryRef()->name); monitorMsg.AddString("name", model.EntryRef()->name);
TrackerSettings().SetShowDisksIcon(showDisksIcon); TrackerSettings().SetShowDisksIcon(showDisksIcon);
if (Window() != NULL) Window()->PostMessage(&monitorMsg, this);
Window()->PostMessage(&monitorMsg, this);
} }
ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop); ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop);
@@ -1946,8 +1882,7 @@ BFilePanelPoseView::AdaptToDesktopIntegrationChange(BMessage* message)
bool mountSharedVolumesOntoDesktop = true; bool mountSharedVolumesOntoDesktop = true;
message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop); message->FindBool("MountVolumesOntoDesktop", &mountVolumesOnDesktop);
message->FindBool("MountSharedVolumesOntoDesktop", message->FindBool("MountSharedVolumesOntoDesktop", &mountSharedVolumesOntoDesktop);
&mountSharedVolumesOntoDesktop);
ShowVolumes(false, mountSharedVolumesOntoDesktop); ShowVolumes(false, mountSharedVolumesOntoDesktop);
ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop); ShowVolumes(mountVolumesOnDesktop, mountSharedVolumesOntoDesktop);
+21 -9
View File
@@ -73,14 +73,13 @@ public:
virtual void MenusBeginning(); virtual void MenusBeginning();
virtual void MenusEnded(); virtual void MenusEnded();
virtual void DispatchMessage(BMessage* message, BHandler* handler); virtual void DispatchMessage(BMessage* message, BHandler* handler);
virtual void ShowContextMenu(BPoint, const entry_ref*);
void SetClientObject(BFilePanel*); void SetClientObject(BFilePanel*);
void SetRefFilter(BRefFilter*); void SetRefFilter(BRefFilter*);
void SetNodeFlavors(uint32 nodeFlavors) { fNodeFlavors = nodeFlavors; } void SetNodeFlavors(uint32 nodeFlavors) { fNodeFlavors = nodeFlavors; }
void SetSaveText(const char* text); void SetSaveText(const char* text);
void SetButtonLabel(file_panel_button, 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(); virtual void SelectionChanged();
void HandleOpenButton(); void HandleOpenButton();
void HandleSaveButton(); void HandleSaveButton();
@@ -115,12 +114,26 @@ protected:
virtual void RestoreWindowState(const BMessage&); virtual void RestoreWindowState(const BMessage&);
virtual void RestoreState(const BMessage&); virtual void RestoreState(const BMessage&);
virtual void AddFileContextMenus(BMenu*); virtual void AddMenus();
virtual void AddVolumeContextMenus(BMenu*); virtual void AddFileMenu(BMenu* menu);
virtual void AddWindowContextMenus(BMenu*); virtual void AddWindowMenu(BMenu* menu);
virtual void AddDropContextMenus(BMenu*); 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 OpenDirectory();
virtual void OpenParent(); virtual void OpenParent();
virtual void WindowActivated(bool state); virtual void WindowActivated(bool state);
@@ -134,8 +147,6 @@ protected:
private: private:
bool SwitchDirToDesktopIfNeeded(entry_ref &ref); bool SwitchDirToDesktopIfNeeded(entry_ref &ref);
bool CanOpenParent() const;
void SwitchDirMenuTo(const entry_ref* ref);
void AdjustButton(); void AdjustButton();
bool SelectChildInParent(const entry_ref* parent, const node_ref* child); bool SelectChildInParent(const entry_ref* parent, const node_ref* child);
void OpenSelectionCommon(BMessage*); void OpenSelectionCommon(BMessage*);
@@ -150,6 +161,7 @@ private:
BFilePanel* fClientObject; BFilePanel* fClientObject;
int32 fSelectionIterator; int32 fSelectionIterator;
BMessage* fMessage; BMessage* fMessage;
BMenu* fFavoritesMenu;
BString fButtonText; BString fButtonText;
bool fHideWhenDone; bool fHideWhenDone;
bool fIsTrackingMenu; bool fIsTrackingMenu;
+2
View File
@@ -74,6 +74,7 @@ for architectureObject in [ MultiArchSubDirSetup ] {
SelectionWindow.cpp SelectionWindow.cpp
Settings.cpp Settings.cpp
SettingsViews.cpp SettingsViews.cpp
Shortcuts.cpp
SlowMenu.cpp SlowMenu.cpp
StatusWindow.cpp StatusWindow.cpp
TaskLoop.cpp TaskLoop.cpp
@@ -138,6 +139,7 @@ DoCatalogs libtracker.so :
RegExp.cpp RegExp.cpp
SelectionWindow.cpp SelectionWindow.cpp
SettingsViews.cpp SettingsViews.cpp
Shortcuts.cpp
StatusWindow.cpp StatusWindow.cpp
TemplatesMenu.cpp TemplatesMenu.cpp
TextWidget.cpp TextWidget.cpp
+51 -62
View File
@@ -92,6 +92,7 @@ All rights reserved.
#include "MimeTypes.h" #include "MimeTypes.h"
#include "Navigator.h" #include "Navigator.h"
#include "Pose.h" #include "Pose.h"
#include "Shortcuts.h"
#include "Tests.h" #include "Tests.h"
#include "Thread.h" #include "Thread.h"
#include "Tracker.h" #include "Tracker.h"
@@ -1656,7 +1657,7 @@ void
BPoseView::AddPosesCompleted() BPoseView::AddPosesCompleted()
{ {
BContainerWindow* window = ContainerWindow(); BContainerWindow* window = ContainerWindow();
if (window != NULL) if (window != NULL && window->ShouldAddMenus())
window->AddMimeTypesToMenu(); window->AddMimeTypesToMenu();
// if we're not in icon mode then we need to check for poses that // 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)); IdentifySelection(message->GetBool("force", false));
break; break;
case kEditItem: case kEditName:
{ {
if (ActivePose()) if (ActivePose())
break; break;
@@ -6232,17 +6233,14 @@ BPoseView::DeleteSelection(bool selectNext, bool confirm)
if (selectCount <= 0) if (selectCount <= 0)
return; return;
if (!CheckVolumeReadOnly( if (!CheckVolumeReadOnly(fSelectionList->ItemAt(0)->TargetModel()->EntryRef()))
fSelectionList->ItemAt(0)->TargetModel()->EntryRef())) {
return; return;
}
BObjectList<entry_ref>* entriesToDelete BObjectList<entry_ref>* entriesToDelete = new BObjectList<entry_ref>(selectCount, true);
= new BObjectList<entry_ref>(selectCount, true);
for (int32 index = 0; index < selectCount; index++) { for (int32 index = 0; index < selectCount; index++) {
entriesToDelete->AddItem(new entry_ref( entry_ref* ref = new entry_ref(*fSelectionList->ItemAt(index)->TargetModel()->EntryRef());
*fSelectionList->ItemAt(index)->TargetModel()->EntryRef())); entriesToDelete->AddItem(ref);
} }
Delete(entriesToDelete, selectNext, confirm); Delete(entriesToDelete, selectNext, confirm);
@@ -6271,8 +6269,7 @@ BPoseView::RestoreSelectionFromTrash(bool selectNext)
void void
BPoseView::Delete(const entry_ref &ref, bool selectNext, bool confirm) BPoseView::Delete(const entry_ref &ref, bool selectNext, bool confirm)
{ {
BObjectList<entry_ref>* entriesToDelete BObjectList<entry_ref>* entriesToDelete = new BObjectList<entry_ref>(1, true);
= new BObjectList<entry_ref>(1, true);
entriesToDelete->AddItem(new entry_ref(ref)); entriesToDelete->AddItem(new entry_ref(ref));
Delete(entriesToDelete, selectNext, confirm); Delete(entriesToDelete, selectNext, confirm);
@@ -6287,8 +6284,7 @@ BPoseView::Delete(BObjectList<entry_ref>* list, bool selectNext, bool confirm)
return; return;
} }
BObjectList<FunctionObject>* taskList = BObjectList<FunctionObject>* taskList = new BObjectList<FunctionObject>(2, true);
new BObjectList<FunctionObject>(2, true);
// first move selection to trash, // first move selection to trash,
taskList->AddItem(NewFunctionObject(FSDeleteRefList, list, false, confirm)); taskList->AddItem(NewFunctionObject(FSDeleteRefList, list, false, confirm));
@@ -6311,8 +6307,7 @@ BPoseView::Delete(BObjectList<entry_ref>* list, bool selectNext, bool confirm)
// deleted // deleted
Model* targetModel = TargetModel(); Model* targetModel = TargetModel();
ASSERT(targetModel != NULL); ASSERT(targetModel != NULL);
taskList->AddItem(NewMemberFunctionObject( taskList->AddItem(NewMemberFunctionObject(&TTracker::SelectPoseAtLocationSoon, tracker,
&TTracker::SelectPoseAtLocationSoon, tracker,
*targetModel->NodeRef(), pointInPose)); *targetModel->NodeRef(), pointInPose));
} }
} }
@@ -6330,8 +6325,7 @@ BPoseView::RestoreItemsFromTrash(BObjectList<entry_ref>* list, bool selectNext)
return; return;
} }
BObjectList<FunctionObject>* taskList = BObjectList<FunctionObject>* taskList = new BObjectList<FunctionObject>(2, true);
new BObjectList<FunctionObject>(2, true);
// first restoree selection // first restoree selection
taskList->AddItem(NewFunctionObject(FSRestoreRefList, list, false)); taskList->AddItem(NewFunctionObject(FSRestoreRefList, list, false));
@@ -6354,8 +6348,7 @@ BPoseView::RestoreItemsFromTrash(BObjectList<entry_ref>* list, bool selectNext)
// restored // restored
Model* targetModel = TargetModel(); Model* targetModel = TargetModel();
ASSERT(targetModel != NULL); ASSERT(targetModel != NULL);
taskList->AddItem(NewMemberFunctionObject( taskList->AddItem(NewMemberFunctionObject(&TTracker::SelectPoseAtLocationSoon, tracker,
&TTracker::SelectPoseAtLocationSoon, tracker,
*targetModel->NodeRef(), pointInPose)); *targetModel->NodeRef(), pointInPose));
} }
} }
@@ -6391,8 +6384,7 @@ BPoseView::DoMoveToTrash()
if (TargetModel()->IsTrash()) if (TargetModel()->IsTrash())
return DeleteSelection(true, false); return DeleteSelection(true, false);
bool shiftDown = (Window()->CurrentMessage()->FindInt32("modifiers") bool shiftDown = (Window()->CurrentMessage()->FindInt32("modifiers") & B_SHIFT_KEY) != 0;
& B_SHIFT_KEY) != 0;
if (shiftDown) if (shiftDown)
DeleteSelection(); DeleteSelection();
else else
@@ -6751,7 +6743,7 @@ BPoseView::KeyDown(const char* bytes, int32 count)
if (message != NULL) { if (message != NULL) {
int32 key; int32 key;
if (message->FindInt32("key", &key) == B_OK && key == B_F2_KEY) if (message->FindInt32("key", &key) == B_OK && key == B_F2_KEY)
Window()->PostMessage(kEditItem, this); Window()->PostMessage(kEditName, this);
} }
break; break;
} }
@@ -7472,7 +7464,7 @@ BPoseView::WasClickInPath(const BPose* pose, int32 index,
if (entry.GetRef(&ref) == B_OK) { if (entry.GetRef(&ref) == B_OK) {
BMessage message(B_REFS_RECEIVED); BMessage message(B_REFS_RECEIVED);
message.AddRef("refs", &ref); message.AddRef("refs", &ref);
be_app->PostMessage(&message); Window()->PostMessage(&message);
return true; return true;
} }
@@ -8596,54 +8588,53 @@ BPoseView::SetDefaultPrinter()
void void
BPoseView::OpenParent() BPoseView::OpenParent()
{ {
if (ParentIsRoot()) if (!CanOpenParent())
return; return;
BEntry entry(TargetModel()->EntryRef()); BMessage message(kOpenParentDir);
entry_ref ref; message.AddRef("refs", TargetModel()->EntryRef());
if (FSGetParentVirtualDirectoryAware(entry, entry) != B_OK || entry.GetRef(&ref) != B_OK) Window()->PostMessage(&message);
return;
BMessage message(B_REFS_RECEIVED);
message.AddRef("refs", &ref);
if (dynamic_cast<TTracker*>(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);
}
} }
bool bool
BPoseView::ParentIsRoot() BPoseView::CanOpenParent()
{ {
if (IsDesktop() || TargetModel()->IsRoot()) TrackerSettings settings;
return true; 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 // override by holding control key
if ((modifiers() & B_CONTROL_KEY) != 0) 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; return false;
BEntry entry(TargetModel()->EntryRef()); // if show disks is on still one more level to go
bool isRoot = FSGetParentVirtualDirectoryAware(entry, entry) == B_OK && FSIsRootDir(&entry); bool parentIsRoot = FSIsRootDir(&parentEntry);
if (isRoot && (TrackerSettings().SingleWindowBrowse() || TrackerSettings().ShowDisksIcon())) if (parentIsRoot && settings.ShowDisksIcon())
return false; return true;
return isRoot; return !parentIsRoot;
} }
@@ -8692,8 +8683,7 @@ BPoseView::ClearSelection()
break; break;
} }
} else { } else {
int32 startIndex = FirstIndexAtOrBelow( int32 startIndex = FirstIndexAtOrBelow((int32)(bounds.top - IconPoseHeight()), true);
(int32)(bounds.top - IconPoseHeight()), true);
int32 poseCount = fVSPoseList->CountItems(); int32 poseCount = fVSPoseList->CountItems();
for (int32 index = startIndex; index < poseCount; index++) { for (int32 index = startIndex; index < poseCount; index++) {
BPose* pose = fVSPoseList->ItemAt(index); BPose* pose = fVSPoseList->ItemAt(index);
@@ -8758,8 +8748,7 @@ BPoseView::ShowSelection(bool show)
break; break;
} }
} else { } else {
int32 startIndex = FirstIndexAtOrBelow( int32 startIndex = FirstIndexAtOrBelow((int32)(bounds.top - IconPoseHeight()), true);
(int32)(bounds.top - IconPoseHeight()), true);
int32 poseCount = fVSPoseList->CountItems(); int32 poseCount = fVSPoseList->CountItems();
for (int32 index = startIndex; index < poseCount; index++) { for (int32 index = startIndex; index < poseCount; index++) {
BPose* pose = fVSPoseList->ItemAt(index); BPose* pose = fVSPoseList->ItemAt(index);
+1 -1
View File
@@ -276,7 +276,7 @@ public:
void UnmountSelectedVolumes(); void UnmountSelectedVolumes();
virtual void OpenParent(); virtual void OpenParent();
virtual bool ParentIsRoot(); virtual bool CanOpenParent();
virtual void OpenSelection(BPose* clicked_pose = NULL, virtual void OpenSelection(BPose* clicked_pose = NULL,
int32* index = NULL); int32* index = NULL);
+10 -18
View File
@@ -46,6 +46,7 @@ All rights reserved.
#include "Commands.h" #include "Commands.h"
#include "QueryContainerWindow.h" #include "QueryContainerWindow.h"
#include "QueryPoseView.h" #include "QueryPoseView.h"
#include "Shortcuts.h"
// #pragma mark - BQueryContainerWindow // #pragma mark - BQueryContainerWindow
@@ -93,28 +94,23 @@ BQueryContainerWindow::AddWindowMenu(BMenu* menu)
{ {
BMenuItem* item; BMenuItem* item;
item = new BMenuItem(B_TRANSLATE("Resize to fit"), item = Shortcuts()->ResizeToFitItem();
new BMessage(kResizeToFit), 'Y');
item->SetTarget(this); item->SetTarget(this);
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), item = Shortcuts()->SelectItem();
new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY);
item->SetTarget(PoseView()); item->SetTarget(PoseView());
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Select all"), item = Shortcuts()->SelectAllItem();
new BMessage(B_SELECT_ALL), 'A');
item->SetTarget(PoseView()); item->SetTarget(PoseView());
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Invert selection"), item = Shortcuts()->InvertSelectionItem();
new BMessage(kInvertSelection), 'S');
item->SetTarget(PoseView()); item->SetTarget(PoseView());
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Close"), item = Shortcuts()->CloseItem();
new BMessage(B_QUIT_REQUESTED), 'W');
item->SetTarget(this); item->SetTarget(this);
menu->AddItem(item); menu->AddItem(item);
} }
@@ -123,15 +119,11 @@ BQueryContainerWindow::AddWindowMenu(BMenu* menu)
void void
BQueryContainerWindow::AddWindowContextMenus(BMenu* menu) BQueryContainerWindow::AddWindowContextMenus(BMenu* menu)
{ {
BMenuItem* resizeItem = new BMenuItem(B_TRANSLATE("Resize to fit"), BMenuItem* resizeItem = Shortcuts()->ResizeToFitItem();
new BMessage(kResizeToFit), 'Y');
menu->AddItem(resizeItem); menu->AddItem(resizeItem);
menu->AddItem(new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), menu->AddItem(Shortcuts()->SelectItem());
new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY)); menu->AddItem(Shortcuts()->SelectAllItem());
menu->AddItem(new BMenuItem(B_TRANSLATE("Select all"), BMenuItem* closeItem = Shortcuts()->CloseItem();
new BMessage(B_SELECT_ALL), 'A'));
BMenuItem* closeItem = new BMenuItem(B_TRANSLATE("Close"),
new BMessage(B_QUIT_REQUESTED), 'W');
menu->AddItem(closeItem); menu->AddItem(closeItem);
// target items as needed // target items as needed
File diff suppressed because it is too large Load Diff
+230
View File
@@ -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 <SupportDefs.h>
#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
+6 -34
View File
@@ -289,41 +289,13 @@ TTracker::TTracker()
gLaunchLooper = new LaunchLooper(); gLaunchLooper = new LaunchLooper();
gLaunchLooper->Run(); gLaunchLooper->Run();
// open desktop window // create Desktop window and lock it
BContainerWindow* deskWindow = NULL; AutoLock<WindowList> lock(&fWindowList);
BDirectory deskDir; BContainerWindow* deskWindow = new BDeskWindow(&fWindowList);
if (FSGetDeskDir(&deskDir) == B_OK) { AutoLock<BWindow> windowLock(deskWindow);
// create desktop
BEntry entry;
deskDir.GetEntry(&entry);
Model* model = new Model(&entry, true);
if (model->InitCheck() == B_OK) {
AutoLock<WindowList> lock(&fWindowList);
deskWindow = new BDeskWindow(&fWindowList);
AutoLock<BWindow> windowLock(deskWindow);
deskWindow->CreatePoseView(model);
deskWindow->Init();
if (TrackerSettings().ShowDisksIcon()) { // init Desktop now that pose view is created and window is locked
// create model for root of everything deskWindow->Init();
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;
}
} }
+11 -20
View File
@@ -49,6 +49,7 @@ All rights reserved.
#include <AutoLocker.h> #include <AutoLocker.h>
#include "Commands.h" #include "Commands.h"
#include "Shortcuts.h"
#include "VirtualDirectoryManager.h" #include "VirtualDirectoryManager.h"
#include "VirtualDirectoryPoseView.h" #include "VirtualDirectoryPoseView.h"
@@ -134,33 +135,27 @@ VirtualDirectoryWindow::AddWindowMenu(BMenu* menu)
{ {
BMenuItem* item; BMenuItem* item;
item = new BMenuItem(B_TRANSLATE("Resize to fit"), item = Shortcuts()->ResizeToFitItem();
new BMessage(kResizeToFit), 'Y');
item->SetTarget(this); item->SetTarget(this);
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), item = Shortcuts()->SelectItem();
new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY);
item->SetTarget(PoseView()); item->SetTarget(PoseView());
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Select all"), item = Shortcuts()->SelectAllItem();
new BMessage(B_SELECT_ALL), 'A');
item->SetTarget(this); item->SetTarget(this);
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Invert selection"), item = Shortcuts()->InvertSelectionItem();
new BMessage(kInvertSelection), 'S');
item->SetTarget(PoseView()); item->SetTarget(PoseView());
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Open parent"), item = Shortcuts()->OpenParentItem();
new BMessage(kOpenParentDir), B_UP_ARROW);
item->SetTarget(PoseView()); item->SetTarget(PoseView());
menu->AddItem(item); menu->AddItem(item);
item = new BMenuItem(B_TRANSLATE("Close"), item = Shortcuts()->CloseItem();
new BMessage(B_QUIT_REQUESTED), 'W');
item->SetTarget(this); item->SetTarget(this);
menu->AddItem(item); menu->AddItem(item);
} }
@@ -169,15 +164,11 @@ VirtualDirectoryWindow::AddWindowMenu(BMenu* menu)
void void
VirtualDirectoryWindow::AddWindowContextMenus(BMenu* menu) VirtualDirectoryWindow::AddWindowContextMenus(BMenu* menu)
{ {
BMenuItem* resizeItem = new BMenuItem(B_TRANSLATE("Resize to fit"), BMenuItem* resizeItem = Shortcuts()->ResizeToFitItem();
new BMessage(kResizeToFit), 'Y');
menu->AddItem(resizeItem); menu->AddItem(resizeItem);
menu->AddItem(new BMenuItem(B_TRANSLATE("Select" B_UTF8_ELLIPSIS), menu->AddItem(Shortcuts()->SelectItem());
new BMessage(kShowSelectionWindow), 'A', B_SHIFT_KEY)); menu->AddItem(Shortcuts()->SelectAllItem());
menu->AddItem(new BMenuItem(B_TRANSLATE("Select all"), BMenuItem* closeItem = Shortcuts()->CloseItem();
new BMessage(B_SELECT_ALL), 'A'));
BMenuItem* closeItem = new BMenuItem(B_TRANSLATE("Close"),
new BMessage(B_QUIT_REQUESTED), 'W');
menu->AddItem(closeItem); menu->AddItem(closeItem);
// target items as needed // target items as needed
menu->SetTargetForItems(PoseView()); menu->SetTargetForItems(PoseView());
+7 -11
View File
@@ -55,6 +55,7 @@ All rights reserved.
#include "Model.h" #include "Model.h"
#include "NavMenu.h" #include "NavMenu.h"
#include "PoseView.h" #include "PoseView.h"
#include "Shortcuts.h"
#include "Tracker.h" #include "Tracker.h"
@@ -333,7 +334,7 @@ HeaderView::MouseDown(BPoint where)
Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons); Window()->CurrentMessage()->FindInt32("buttons", (int32*)&buttons);
if (SecondaryMouseButtonDown(modifiers(), buttons)) { if (SecondaryMouseButtonDown(modifiers(), buttons)) {
// Show contextual menu // Show contextual menu
BPopUpMenu* contextMenu = new BPopUpMenu("FileContext", false, false); BPopUpMenu* contextMenu = new BPopUpMenu("PoseContext", false, false);
if (contextMenu != NULL) { if (contextMenu != NULL) {
BuildContextMenu(contextMenu); BuildContextMenu(contextMenu);
contextMenu->SetAsyncAutoDestruct(true); contextMenu->SetAsyncAutoDestruct(true);
@@ -581,17 +582,14 @@ HeaderView::BuildContextMenu(BMenu* parent)
navigationItem->SetTarget(be_app); navigationItem->SetTarget(be_app);
} }
parent->AddItem(new BMenuItem(B_TRANSLATE("Open"), parent->AddItem(TShortcuts().OpenItem());
new BMessage(kOpenSelection), 'O'));
if (!model.IsDesktop() && !model.IsRoot() && !model.IsTrash()) { if (!model.IsDesktop() && !model.IsRoot() && !model.IsTrash()) {
parent->AddItem(new BMenuItem(B_TRANSLATE("Edit name"), parent->AddItem(TShortcuts().EditNameItem());
new BMessage(kEditItem), 'E'));
parent->AddSeparatorItem(); parent->AddSeparatorItem();
if (fModel->IsVolume()) { if (fModel->IsVolume()) {
BMenuItem* item = new BMenuItem(B_TRANSLATE("Unmount"), BMenuItem* item = TShortcuts().UnmountItem();
new BMessage(kUnmountVolume), 'U');
parent->AddItem(item); parent->AddItem(item);
// volume model, enable/disable the Unmount item // volume model, enable/disable the Unmount item
BVolume boot; BVolume boot;
@@ -604,12 +602,10 @@ HeaderView::BuildContextMenu(BMenu* parent)
} }
if (!model.IsRoot() && !model.IsVolume() && !model.IsTrash()) if (!model.IsRoot() && !model.IsVolume() && !model.IsTrash())
parent->AddItem(new BMenuItem(B_TRANSLATE("Identify"), parent->AddItem(TShortcuts().IdentifyItem());
new BMessage(kIdentifyEntry)));
if (model.IsTrash()) if (model.IsTrash())
parent->AddItem(new BMenuItem(B_TRANSLATE("Empty Trash"), parent->AddItem(TShortcuts().EmptyTrashItem());
new BMessage(kEmptyTrash)));
BMenuItem* sizeItem = NULL; BMenuItem* sizeItem = NULL;
if (model.IsDirectory() && !model.IsVolume() && !model.IsRoot()) { if (model.IsDirectory() && !model.IsVolume() && !model.IsRoot()) {
+2 -2
View File
@@ -113,7 +113,7 @@ BInfoWindow::BInfoWindow(Model* model, int32 group_index,
if (list != NULL) if (list != NULL)
list->AddItem(this); list->AddItem(this);
AddShortcut('E', 0, new BMessage(kEditItem)); AddShortcut('E', 0, new BMessage(kEditName));
AddShortcut('O', 0, new BMessage(kOpenSelection)); AddShortcut('O', 0, new BMessage(kOpenSelection));
AddShortcut('U', 0, new BMessage(kUnmountVolume)); AddShortcut('U', 0, new BMessage(kUnmountVolume));
AddShortcut('P', 0, new BMessage(kPermissionsSelected)); AddShortcut('P', 0, new BMessage(kPermissionsSelected));
@@ -266,7 +266,7 @@ BInfoWindow::MessageReceived(BMessage* message)
break; break;
} }
case kEditItem: case kEditName:
{ {
BEntry entry(fModel->EntryRef()); BEntry entry(fModel->EntryRef());
fHeaderView->BeginEditingTitle(); fHeaderView->BeginEditingTitle();