More Tracker refactoring:
* relocated Trash dirs to volume roots by modifying find_directory() to report the trash location as volume/Trash. * FSUtils no longer creates /home/Desktop on every volume. * TrashWatcher now keeps icons in sync on all volumes. * Simplified FSGetDeskDir since it no longer has to worry about getting the desk directory on any volume other than the root. * Relocated trash context menu logic to BContainerWindow so it can also be used at the volume roots. * DesktopPoseView now creates a virtual Trash pose representing the trash contents as before. * Corrected typo: Model::WriteAttrKillForegin() -> Model::WriteAttrKillForeign(). Closes ticket #5245. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35085 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
bb7cffd0d1
commit
01dffd8edd
@ -94,6 +94,8 @@ namespace BPrivate {
|
||||
#define kAttrPoseInfo_le "_trk/pinfo_le"
|
||||
#define kAttrDisksPoseInfo_be "_trk/d_pinfo"
|
||||
#define kAttrDisksPoseInfo_le "_trk/d_pinfo_le"
|
||||
#define kAttrTrashPoseInfo_be "_trk/t_pinfo"
|
||||
#define kAttrTrashPoseInfo_le "_trk/t_pinfo_le"
|
||||
#define kAttrColumns_be "_trk/columns"
|
||||
#define kAttrColumns_le "_trk/columns_le"
|
||||
#define kAttrViewState_be "_trk/viewstate"
|
||||
@ -117,6 +119,9 @@ namespace BPrivate {
|
||||
#define kAttrDisksPoseInfo kAttrDisksPoseInfo_le
|
||||
#define kAttrDisksPoseInfoForeign kAttrDisksPoseInfo_be
|
||||
|
||||
#define kAttrTrashPoseInfo kAttrTrashPoseInfo_le
|
||||
#define kAttrTrashPoseInfoForeign kAttrTrashPoseInfo_be
|
||||
|
||||
#define kAttrPoseInfo kAttrPoseInfo_le
|
||||
#define kAttrPoseInfoForeign kAttrPoseInfo_be
|
||||
|
||||
@ -149,6 +154,9 @@ namespace BPrivate {
|
||||
#define kAttrDisksPoseInfo kAttrDisksPoseInfo_be
|
||||
#define kAttrDisksPoseInfoForeign kAttrDisksPoseInfo_le
|
||||
|
||||
#define kAttrTrashPoseInfo kAttrTrashPoseInfo_be
|
||||
#define kAttrTrashPoseInfoForeign kAttrTrashPoseInfo_le
|
||||
|
||||
#define kAttrPoseInfo kAttrPoseInfo_be
|
||||
#define kAttrPoseInfoForeign kAttrPoseInfo_le
|
||||
|
||||
|
@ -804,7 +804,11 @@ BContainerWindow::AddContextMenus()
|
||||
AddDropContextMenus(fDropContextMenu);
|
||||
|
||||
fDragContextMenu = new BSlowContextMenu("DragContext");
|
||||
// will get added and built dynamically in ShowContextMenu
|
||||
// will get added and built dynamically in ShowContextMenu
|
||||
|
||||
fTrashContextMenu = new BPopUpMenu("TrashContext", false, false);
|
||||
fTrashContextMenu->SetFont(be_plain_font);
|
||||
AddTrashContextMenus(fTrashContextMenu);
|
||||
}
|
||||
|
||||
|
||||
@ -2482,101 +2486,124 @@ BContainerWindow::ShowContextMenu(BPoint loc, const entry_ref *ref, BView *)
|
||||
if (ref) {
|
||||
// clicked on a pose, show file or volume context menu
|
||||
Model model(ref);
|
||||
|
||||
BEntry entry;
|
||||
if (entry.SetTo(ref) == B_OK && FSIsTrashDir(&entry)) {
|
||||
|
||||
bool showAsVolume = false;
|
||||
bool filePanel = PoseView()->IsFilePanel();
|
||||
|
||||
if (Dragging()) {
|
||||
fContextMenu = NULL;
|
||||
|
||||
BEntry entry;
|
||||
model.GetEntry(&entry);
|
||||
|
||||
// only show for directories (directory, volume, root)
|
||||
//
|
||||
// don't show a popup for the trash or printers
|
||||
// trash is handled in DeskWindow
|
||||
//
|
||||
// since this menu is opened asynchronously
|
||||
// we need to make sure we don't open it more
|
||||
// than once, the IsShowing flag is set in
|
||||
// SlowContextPopup::AttachedToWindow and
|
||||
// reset in DetachedFromWindow
|
||||
// see the notes in SlowContextPopup::AttachedToWindow
|
||||
|
||||
if (!FSIsPrintersDir(&entry) && !fDragContextMenu->IsShowing()) {
|
||||
// printf("ShowContextMenu - target is %s %i\n", ref->name, IsShowing(ref));
|
||||
fDragContextMenu->ClearMenu();
|
||||
|
||||
// in case the ref is a symlink, resolve it
|
||||
// only pop open for directories
|
||||
BEntry resolvedEntry(ref, true);
|
||||
if (!resolvedEntry.IsDirectory())
|
||||
return;
|
||||
|
||||
entry_ref resolvedRef;
|
||||
resolvedEntry.GetRef(&resolvedRef);
|
||||
|
||||
// use the resolved ref for the menu
|
||||
fDragContextMenu->SetNavDir(&resolvedRef);
|
||||
fDragContextMenu->SetTypesList(fCachedTypesList);
|
||||
fDragContextMenu->SetTarget(BMessenger(this));
|
||||
BPoseView *poseView = PoseView();
|
||||
if (poseView) {
|
||||
BMessenger tmpTarget(poseView);
|
||||
fDragContextMenu->InitTrackingHook(
|
||||
&BPoseView::MenuTrackingHook, &tmpTarget, fDragMessage);
|
||||
}
|
||||
|
||||
// this is now asynchronous so that we don't
|
||||
// deadlock in Window::Quit,
|
||||
fDragContextMenu->Go(global, true, false, true);
|
||||
}
|
||||
return;
|
||||
} else if (TargetModel()->IsRoot() || model.IsVolume()) {
|
||||
fContextMenu = fVolumeContextMenu;
|
||||
showAsVolume = true;
|
||||
} else
|
||||
fContextMenu = fFileContextMenu;
|
||||
|
||||
// clean up items from last context menu
|
||||
|
||||
if (fContextMenu) {
|
||||
if (fContextMenu->Window())
|
||||
if (fTrashContextMenu->Window() || Dragging())
|
||||
return;
|
||||
else
|
||||
MenusEnded();
|
||||
|
||||
if (model.InitCheck() == B_OK) { // ??? Do I need this ???
|
||||
if (showAsVolume) {
|
||||
// non-volume enable/disable copy, move, identify
|
||||
EnableNamedMenuItem(fContextMenu, kDuplicateSelection, false);
|
||||
EnableNamedMenuItem(fContextMenu, kMoveToTrash, false);
|
||||
EnableNamedMenuItem(fContextMenu, kIdentifyEntry, false);
|
||||
|
||||
// volume model, enable/disable the Unmount item
|
||||
bool ejectableVolumeSelected = false;
|
||||
|
||||
BVolume boot;
|
||||
BVolumeRoster().GetBootVolume(&boot);
|
||||
BVolume volume;
|
||||
volume.SetTo(model.NodeRef()->device);
|
||||
if (volume != boot)
|
||||
ejectableVolumeSelected = true;
|
||||
|
||||
EnableNamedMenuItem(fContextMenu, "Unmount", ejectableVolumeSelected);
|
||||
|
||||
DeleteSubmenu(fNavigationItem);
|
||||
|
||||
// selected item was trash, show the trash context menu instead
|
||||
BPoint global(loc);
|
||||
PoseView()->ConvertToScreen(&global);
|
||||
PoseView()->CommitActivePose();
|
||||
BRect mouse_rect(global.x, global.y, global.x, global.y);
|
||||
mouse_rect.InsetBy(-5, -5);
|
||||
|
||||
EnableNamedMenuItem(fTrashContextMenu, kEmptyTrash,
|
||||
static_cast<TTracker *>(be_app)->TrashFull());
|
||||
|
||||
SetupNavigationMenu(ref, fTrashContextMenu);
|
||||
fTrashContextMenu->Go(global, true, false, mouse_rect, true);
|
||||
} else {
|
||||
|
||||
bool showAsVolume = false;
|
||||
bool filePanel = PoseView()->IsFilePanel();
|
||||
|
||||
if (Dragging()) {
|
||||
fContextMenu = NULL;
|
||||
|
||||
BEntry entry;
|
||||
model.GetEntry(&entry);
|
||||
|
||||
// only show for directories (directory, volume, root)
|
||||
//
|
||||
// don't show a popup for the trash or printers
|
||||
// trash is handled in DeskWindow
|
||||
//
|
||||
// since this menu is opened asynchronously
|
||||
// we need to make sure we don't open it more
|
||||
// than once, the IsShowing flag is set in
|
||||
// SlowContextPopup::AttachedToWindow and
|
||||
// reset in DetachedFromWindow
|
||||
// see the notes in SlowContextPopup::AttachedToWindow
|
||||
|
||||
if (!FSIsPrintersDir(&entry) && !fDragContextMenu->IsShowing()) {
|
||||
// printf("ShowContextMenu - target is %s %i\n", ref->name, IsShowing(ref));
|
||||
fDragContextMenu->ClearMenu();
|
||||
|
||||
// in case the ref is a symlink, resolve it
|
||||
// only pop open for directories
|
||||
BEntry resolvedEntry(ref, true);
|
||||
if (!resolvedEntry.IsDirectory())
|
||||
return;
|
||||
|
||||
entry_ref resolvedRef;
|
||||
resolvedEntry.GetRef(&resolvedRef);
|
||||
|
||||
// use the resolved ref for the menu
|
||||
fDragContextMenu->SetNavDir(&resolvedRef);
|
||||
fDragContextMenu->SetTypesList(fCachedTypesList);
|
||||
fDragContextMenu->SetTarget(BMessenger(this));
|
||||
BPoseView *poseView = PoseView();
|
||||
if (poseView) {
|
||||
BMessenger tmpTarget(poseView);
|
||||
fDragContextMenu->InitTrackingHook(
|
||||
&BPoseView::MenuTrackingHook, &tmpTarget, fDragMessage);
|
||||
}
|
||||
|
||||
// this is now asynchronous so that we don't
|
||||
// deadlock in Window::Quit,
|
||||
fDragContextMenu->Go(global, true, false, true);
|
||||
}
|
||||
return;
|
||||
} else if (TargetModel()->IsRoot() || model.IsVolume()) {
|
||||
fContextMenu = fVolumeContextMenu;
|
||||
showAsVolume = true;
|
||||
} else
|
||||
fContextMenu = fFileContextMenu;
|
||||
|
||||
// clean up items from last context menu
|
||||
|
||||
if (fContextMenu) {
|
||||
if (fContextMenu->Window())
|
||||
return;
|
||||
else
|
||||
MenusEnded();
|
||||
|
||||
if (model.InitCheck() == B_OK) { // ??? Do I need this ???
|
||||
if (showAsVolume) {
|
||||
// non-volume enable/disable copy, move, identify
|
||||
EnableNamedMenuItem(fContextMenu, kDuplicateSelection, false);
|
||||
EnableNamedMenuItem(fContextMenu, kMoveToTrash, false);
|
||||
EnableNamedMenuItem(fContextMenu, kIdentifyEntry, false);
|
||||
|
||||
// volume model, enable/disable the Unmount item
|
||||
bool ejectableVolumeSelected = false;
|
||||
|
||||
BVolume boot;
|
||||
BVolumeRoster().GetBootVolume(&boot);
|
||||
BVolume volume;
|
||||
volume.SetTo(model.NodeRef()->device);
|
||||
if (volume != boot)
|
||||
ejectableVolumeSelected = true;
|
||||
|
||||
EnableNamedMenuItem(fContextMenu, "Unmount", ejectableVolumeSelected);
|
||||
}
|
||||
}
|
||||
|
||||
SetupNavigationMenu(ref, fContextMenu);
|
||||
if (!showAsVolume && !filePanel) {
|
||||
SetupMoveCopyMenus(ref, fContextMenu);
|
||||
SetupOpenWithMenu(fContextMenu);
|
||||
}
|
||||
|
||||
UpdateMenu(fContextMenu, kPosePopUpContext);
|
||||
|
||||
fContextMenu->Go(global, true, false, mouseRect, true);
|
||||
}
|
||||
|
||||
SetupNavigationMenu(ref, fContextMenu);
|
||||
if (!showAsVolume && !filePanel) {
|
||||
SetupMoveCopyMenus(ref, fContextMenu);
|
||||
SetupOpenWithMenu(fContextMenu);
|
||||
}
|
||||
|
||||
UpdateMenu(fContextMenu, kPosePopUpContext);
|
||||
|
||||
fContextMenu->Go(global, true, false, mouseRect, true);
|
||||
}
|
||||
} else if (fWindowContextMenu) {
|
||||
if (fWindowContextMenu->Window())
|
||||
@ -2728,6 +2755,20 @@ BContainerWindow::AddDropContextMenus(BMenu *menu)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BContainerWindow::AddTrashContextMenus(BMenu *menu)
|
||||
{
|
||||
// setup special trash context menu
|
||||
menu->AddItem(new BMenuItem("Empty Trash",
|
||||
new BMessage(kEmptyTrash)));
|
||||
menu->AddItem(new BMenuItem("Open",
|
||||
new BMessage(kOpenSelection), 'O'));
|
||||
menu->AddItem(new BMenuItem("Get info",
|
||||
new BMessage(kGetInfo), 'I'));
|
||||
menu->SetTargetForItems(PoseView());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BContainerWindow::EachAddon(bool (*eachAddon)(const Model *, const char *,
|
||||
uint32 shortcut, bool primary, void *context), void *passThru)
|
||||
@ -3475,7 +3516,7 @@ BContainerWindow::SetUpDefaultState()
|
||||
|
||||
if (!TargetModel()->IsRoot()) {
|
||||
BDirectory desktop;
|
||||
FSGetDeskDir(&desktop, TargetModel()->EntryRef()->device);
|
||||
FSGetDeskDir(&desktop);
|
||||
|
||||
// try copying state from our parent directory, unless it is the desktop folder
|
||||
BEntry entry(TargetModel()->EntryRef());
|
||||
@ -3902,10 +3943,8 @@ WindowStateNodeOpener::WindowStateNodeOpener(BContainerWindow *window, bool forW
|
||||
fStreamNode(NULL)
|
||||
{
|
||||
if (window->TargetModel() && window->TargetModel()->IsRoot()) {
|
||||
BVolume bootVol;
|
||||
BVolumeRoster().GetBootVolume(&bootVol);
|
||||
BDirectory dir;
|
||||
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
|
||||
if (FSGetDeskDir(&dir) == B_OK) {
|
||||
fNode = new BDirectory(dir);
|
||||
fStreamNode = new AttributeStreamFileNode(fNode);
|
||||
}
|
||||
|
@ -213,6 +213,7 @@ class BContainerWindow : public BWindow {
|
||||
virtual void AddWindowContextMenus(BMenu *);
|
||||
virtual void AddVolumeContextMenus(BMenu *);
|
||||
virtual void AddDropContextMenus(BMenu *);
|
||||
virtual void AddTrashContextMenus(BMenu *);
|
||||
|
||||
virtual void RepopulateMenus();
|
||||
|
||||
@ -253,6 +254,7 @@ class BContainerWindow : public BWindow {
|
||||
BPopUpMenu *fWindowContextMenu;
|
||||
BPopUpMenu *fDropContextMenu;
|
||||
BPopUpMenu *fVolumeContextMenu;
|
||||
BPopUpMenu *fTrashContextMenu;
|
||||
BSlowContextMenu *fDragContextMenu;
|
||||
BMenuItem *fMoveToItem;
|
||||
BMenuItem *fCopyToItem;
|
||||
|
@ -147,7 +147,6 @@ BDeskWindow::~BDeskWindow()
|
||||
void
|
||||
BDeskWindow::Init(const BMessage *)
|
||||
{
|
||||
AddTrashContextMenu();
|
||||
//
|
||||
// Set the size of the screen before calling the container window's
|
||||
// Init() because it will add volume poses to this window and
|
||||
@ -356,52 +355,6 @@ BDeskWindow::AddWindowContextMenus(BMenu *menu)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BDeskWindow::AddTrashContextMenu()
|
||||
{
|
||||
// setup special trash context menu
|
||||
fTrashContextMenu = new BPopUpMenu("TrashContext", false, false);
|
||||
fTrashContextMenu->SetFont(be_plain_font);
|
||||
fTrashContextMenu->AddItem(new BMenuItem("Empty Trash",
|
||||
new BMessage(kEmptyTrash)));
|
||||
fTrashContextMenu->AddItem(new BMenuItem("Open",
|
||||
new BMessage(kOpenSelection), 'O'));
|
||||
fTrashContextMenu->AddItem(new BMenuItem("Get info",
|
||||
new BMessage(kGetInfo), 'I'));
|
||||
fTrashContextMenu->SetTargetForItems(PoseView());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BDeskWindow::ShowContextMenu(BPoint loc, const entry_ref *ref, BView *view)
|
||||
{
|
||||
BEntry entry;
|
||||
|
||||
// cleanup previous entries
|
||||
DeleteSubmenu(fNavigationItem);
|
||||
|
||||
if (ref && entry.SetTo(ref) == B_OK && FSIsTrashDir(&entry)) {
|
||||
|
||||
if (fTrashContextMenu->Window() || Dragging())
|
||||
return;
|
||||
|
||||
// selected item was trash, show the trash context menu instead
|
||||
BPoint global(loc);
|
||||
PoseView()->ConvertToScreen(&global);
|
||||
PoseView()->CommitActivePose();
|
||||
BRect mouse_rect(global.x, global.y, global.x, global.y);
|
||||
mouse_rect.InsetBy(-5, -5);
|
||||
|
||||
EnableNamedMenuItem(fTrashContextMenu, kEmptyTrash,
|
||||
static_cast<TTracker *>(be_app)->TrashFull());
|
||||
|
||||
SetupNavigationMenu(ref, fTrashContextMenu);
|
||||
fTrashContextMenu->Go(global, true, false, mouse_rect, true);
|
||||
} else
|
||||
_inherited::ShowContextMenu(loc, ref, view);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
BDeskWindow::WorkspaceActivated(int32 workspace, bool state)
|
||||
{
|
||||
|
@ -56,7 +56,6 @@ public:
|
||||
virtual void Quit();
|
||||
virtual void ScreenChanged(BRect, color_space);
|
||||
|
||||
virtual void ShowContextMenu(BPoint, const entry_ref *, BView *);
|
||||
virtual void CreatePoseView(Model *);
|
||||
|
||||
virtual bool ShouldAddMenus() const;
|
||||
@ -72,7 +71,6 @@ public:
|
||||
|
||||
protected:
|
||||
virtual void AddWindowContextMenus(BMenu *);
|
||||
void AddTrashContextMenu();
|
||||
virtual BPoseView *NewPoseView(Model *, BRect, uint32);
|
||||
|
||||
virtual void WorkspaceActivated(int32, bool);
|
||||
|
@ -73,11 +73,6 @@ ShouldShowDesktopPose(dev_t device, const Model *model, const PoseInfo *)
|
||||
} // namespace BPrivate
|
||||
|
||||
|
||||
DesktopEntryListCollection::DesktopEntryListCollection()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
|
||||
@ -101,7 +96,7 @@ DesktopPoseView::InitDesktopDirentIterator(BPoseView *nodeMonitoringTarget,
|
||||
if (sourceModel.InitCheck() != B_OK)
|
||||
return NULL;
|
||||
|
||||
CachedEntryIteratorList *result = new DesktopEntryListCollection();
|
||||
CachedEntryIteratorList *result = new CachedEntryIteratorList();
|
||||
|
||||
ASSERT(!sourceModel.IsQuery());
|
||||
ASSERT(sourceModel.Node());
|
||||
@ -176,6 +171,13 @@ DesktopPoseView::AddPosesThreadValid(const entry_ref *) const
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DesktopPoseView::AddPosesCompleted()
|
||||
{
|
||||
_inherited::AddPosesCompleted();
|
||||
AddTrashPose();
|
||||
}
|
||||
|
||||
bool
|
||||
DesktopPoseView::ShouldShowPose(const Model *model, const PoseInfo *poseInfo)
|
||||
{
|
||||
@ -212,7 +214,7 @@ DesktopPoseView::ShowVolumes(bool visible, bool showShared)
|
||||
{
|
||||
if (LockLooper()) {
|
||||
SavePoseLocations();
|
||||
if (!visible)
|
||||
if (!visible)
|
||||
RemoveRootPoses();
|
||||
else
|
||||
AddRootPoses(true, showShared);
|
||||
@ -221,6 +223,26 @@ DesktopPoseView::ShowVolumes(bool visible, bool showShared)
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DesktopPoseView::AddTrashPose()
|
||||
{
|
||||
BVolume volume;
|
||||
if (BVolumeRoster().GetBootVolume(&volume) == B_OK) {
|
||||
BDirectory trash;
|
||||
BEntry entry;
|
||||
node_ref ref;
|
||||
if (FSGetTrashDir(&trash, volume.Device()) == B_OK
|
||||
&& trash.GetEntry(&entry) == B_OK && entry.GetNodeRef(&ref) == B_OK) {
|
||||
WatchNewNode(&ref);
|
||||
Model *model = new Model(&entry);
|
||||
PoseInfo info;
|
||||
ReadPoseInfo(model, &info);
|
||||
CreatePose(model, &info, false, NULL, NULL, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
DesktopPoseView::StartSettingsWatch()
|
||||
{
|
||||
|
@ -58,6 +58,7 @@ public:
|
||||
void StopSettingsWatch();
|
||||
|
||||
virtual bool AddPosesThreadValid(const entry_ref *) const;
|
||||
virtual void AddPosesCompleted();
|
||||
|
||||
protected:
|
||||
virtual EntryListBase *InitDirentIterator(const entry_ref *);
|
||||
@ -77,11 +78,8 @@ private:
|
||||
|
||||
friend bool ShouldShowDesktopPose(dev_t device, const Model *,
|
||||
const PoseInfo *);
|
||||
};
|
||||
|
||||
class DesktopEntryListCollection : public CachedEntryIteratorList {
|
||||
public:
|
||||
DesktopEntryListCollection();
|
||||
|
||||
void AddTrashPose();
|
||||
};
|
||||
|
||||
|
||||
|
@ -109,10 +109,8 @@ BDirMenu::Populate(const BEntry *startEntry, BWindow *originatingWindow,
|
||||
parent.GetEntry(&entry);
|
||||
}
|
||||
|
||||
BVolume bootVol;
|
||||
BVolumeRoster().GetBootVolume(&bootVol);
|
||||
BDirectory desktopDir;
|
||||
FSGetDeskDir(&desktopDir, bootVol.Device());
|
||||
FSGetDeskDir(&desktopDir);
|
||||
BEntry desktopEntry;
|
||||
desktopDir.GetEntry(&desktopEntry);
|
||||
|
||||
|
@ -1881,7 +1881,8 @@ CheckName(uint32 moveMode, const BEntry *sourceEntry, const BDirectory *destDir,
|
||||
}
|
||||
}
|
||||
|
||||
if (FSIsTrashDir(sourceEntry)) {
|
||||
if (FSIsTrashDir(sourceEntry) && moveMode != kCreateLink
|
||||
&& moveMode != kCreateRelativeLink) {
|
||||
(new BAlert("", "You can't move or copy the trash.",
|
||||
"OK", 0, 0, B_WIDTH_AS_USUAL, B_WARNING_ALERT))->Go();
|
||||
return B_ERROR;
|
||||
@ -2291,15 +2292,10 @@ FSGetTrashDir(BDirectory *trash_dir, dev_t dev)
|
||||
|
||||
|
||||
status_t
|
||||
FSGetDeskDir(BDirectory *deskDir, dev_t dev)
|
||||
FSGetDeskDir(BDirectory *deskDir)
|
||||
{
|
||||
BVolume volume(dev);
|
||||
status_t result = volume.InitCheck();
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
BPath path;
|
||||
result = find_directory(B_DESKTOP_DIRECTORY, &path, true, &volume);
|
||||
status_t result = find_directory(B_DESKTOP_DIRECTORY, &path, true);
|
||||
if (result != B_OK)
|
||||
return result;
|
||||
|
||||
@ -2383,7 +2379,7 @@ FSIsTrashDir(const BEntry *entry)
|
||||
|
||||
|
||||
bool
|
||||
FSIsDeskDir(const BEntry *entry, dev_t device)
|
||||
FSIsDeskDir(const BEntry *entry)
|
||||
{
|
||||
BPath path;
|
||||
status_t result = find_directory(B_DESKTOP_DIRECTORY, &path, true);
|
||||
@ -2395,17 +2391,6 @@ FSIsDeskDir(const BEntry *entry, dev_t device)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FSIsDeskDir(const BEntry *entry)
|
||||
{
|
||||
entry_ref ref;
|
||||
if (entry->GetRef(&ref) != B_OK)
|
||||
return false;
|
||||
|
||||
return FSIsDeskDir(entry, ref.device);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
FSIsHomeDir(const BEntry *entry)
|
||||
{
|
||||
@ -2778,9 +2763,6 @@ FSCreateTrashDirs()
|
||||
continue;
|
||||
|
||||
BPath path;
|
||||
// TODO: relocate Trash directory such that a Desktop dir on
|
||||
// every volume is no longer needed
|
||||
find_directory(B_DESKTOP_DIRECTORY, &path, true, &volume);
|
||||
find_directory(B_TRASH_DIRECTORY, &path, true, &volume);
|
||||
|
||||
BDirectory trashDir;
|
||||
|
@ -190,7 +190,7 @@ _IMPEXP_TRACKER status_t FSCreateNewFolderIn(const node_ref *destDir, entry_ref
|
||||
node_ref *new_node);
|
||||
_IMPEXP_TRACKER void FSCreateTrashDirs();
|
||||
_IMPEXP_TRACKER status_t FSGetTrashDir(BDirectory *trashDir, dev_t volume);
|
||||
_IMPEXP_TRACKER status_t FSGetDeskDir(BDirectory *deskDir, dev_t volume);
|
||||
_IMPEXP_TRACKER status_t FSGetDeskDir(BDirectory *deskDir);
|
||||
_IMPEXP_TRACKER status_t FSRecursiveCalcSize(BInfoWindow *, BDirectory *,
|
||||
off_t *runningSize, int32 *fileCount, int32 *dirCount);
|
||||
|
||||
@ -233,7 +233,7 @@ status_t LaunchBrokenLink(const char *, const BMessage *);
|
||||
|
||||
status_t FSFindTrackerSettingsDir(BPath *, bool autoCreate = true);
|
||||
|
||||
bool FSIsDeskDir(const BEntry *, dev_t);
|
||||
bool FSIsDeskDir(const BEntry *);
|
||||
|
||||
bool ConfirmChangeIfWellKnownDirectory(const BEntry *entry, const char *action,
|
||||
bool dontAsk = false, int32 *confirmedAlready = NULL);
|
||||
|
@ -1252,7 +1252,7 @@ TFilePanel::CanOpenParent() const
|
||||
if (TrackerSettings().DesktopFilePanelRoot()) {
|
||||
// don't allow opening Desktop folder's parent
|
||||
BEntry entry(TargetModel()->EntryRef());
|
||||
if (FSIsDeskDir(&entry, TargetModel()->NodeRef()->device))
|
||||
if (FSIsDeskDir(&entry))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1280,11 +1280,8 @@ TFilePanel::SwitchDirToDesktopIfNeeded(entry_ref &ref)
|
||||
BEntry root("/");
|
||||
|
||||
BDirectory desktopDir;
|
||||
BVolume bootVol;
|
||||
BVolumeRoster().GetBootVolume(&bootVol);
|
||||
FSGetDeskDir(&desktopDir, bootVol.Device());
|
||||
|
||||
if ((bootVol.Device() != ref.device && FSIsDeskDir(&entry, ref.device))
|
||||
FSGetDeskDir(&desktopDir);
|
||||
if (FSIsDeskDir(&entry)
|
||||
// navigated into non-boot desktop, switch to boot desktop
|
||||
|| (entry == root && !settings.ShowDisksIcon())) {
|
||||
// hit "/" level, map to desktop
|
||||
@ -1293,7 +1290,7 @@ TFilePanel::SwitchDirToDesktopIfNeeded(entry_ref &ref)
|
||||
entry.GetRef(&ref);
|
||||
return true;
|
||||
}
|
||||
return FSIsDeskDir(&entry, ref.device);
|
||||
return FSIsDeskDir(&entry);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1156,7 +1156,7 @@ Model::WriteAttr(const char *attr, type_code type, off_t offset,
|
||||
|
||||
|
||||
ssize_t
|
||||
Model::WriteAttrKillForegin(const char *attr, const char *foreignAttr,
|
||||
Model::WriteAttrKillForeign(const char *attr, const char *foreignAttr,
|
||||
type_code type, off_t offset, const void *buffer, size_t length)
|
||||
{
|
||||
BModelWriteOpener opener(this);
|
||||
|
@ -196,7 +196,7 @@ class Model {
|
||||
const void *buffer, size_t );
|
||||
// cover call, creates a writable node and writes out attributes
|
||||
// into it; work around for file nodes not being writeable
|
||||
ssize_t WriteAttrKillForegin(const char *attr, const char *foreignAttr,
|
||||
ssize_t WriteAttrKillForeign(const char *attr, const char *foreignAttr,
|
||||
type_code type, off_t, const void *buffer, size_t);
|
||||
|
||||
bool Mimeset(bool force);
|
||||
|
@ -757,17 +757,24 @@ BPoseView::SavePoseLocations(BRect *frameIfDesktop)
|
||||
ASSERT(model);
|
||||
ASSERT(model->InitCheck() == B_OK);
|
||||
// special handling for "root" disks icon
|
||||
if (model->IsRoot()) {
|
||||
BVolume bootVol;
|
||||
// and trash pose on desktop dir
|
||||
BEntry entry;
|
||||
model->GetEntry(&entry);
|
||||
bool isTrash = FSIsTrashDir(&entry) && IsDesktopView();
|
||||
if (model->IsRoot() || isTrash) {
|
||||
BDirectory dir;
|
||||
BVolumeRoster().GetBootVolume(&bootVol);
|
||||
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
|
||||
if (dir.WriteAttr(kAttrDisksPoseInfo, B_RAW_TYPE, 0,
|
||||
if (FSGetDeskDir(&dir) == B_OK) {
|
||||
const char *poseInfoAttr = (isTrash) ? kAttrTrashPoseInfo
|
||||
: kAttrDisksPoseInfo;
|
||||
const char *poseInfoAttrForeign = (isTrash)
|
||||
? kAttrTrashPoseInfoForeign
|
||||
: kAttrDisksPoseInfoForeign;
|
||||
if (dir.WriteAttr(poseInfoAttr, B_RAW_TYPE, 0,
|
||||
&poseInfo, sizeof(poseInfo)) == sizeof(poseInfo))
|
||||
// nuke opposite endianness
|
||||
dir.RemoveAttr(kAttrDisksPoseInfoForeign);
|
||||
dir.RemoveAttr(poseInfoAttrForeign);
|
||||
|
||||
if (desktop && dir.WriteAttr(kAttrExtendedDisksPoseInfo,
|
||||
if (!isTrash && desktop && dir.WriteAttr(kAttrExtendedDisksPoseInfo,
|
||||
B_RAW_TYPE, 0,
|
||||
extendedPoseInfo, extendedPoseInfoSize)
|
||||
== (ssize_t)extendedPoseInfoSize)
|
||||
@ -775,11 +782,11 @@ BPoseView::SavePoseLocations(BRect *frameIfDesktop)
|
||||
dir.RemoveAttr(kAttrExtendedDisksPoseInfoForegin);
|
||||
}
|
||||
} else {
|
||||
model->WriteAttrKillForegin(kAttrPoseInfo, kAttrPoseInfoForeign,
|
||||
model->WriteAttrKillForeign(kAttrPoseInfo, kAttrPoseInfoForeign,
|
||||
B_RAW_TYPE, 0, &poseInfo, sizeof(poseInfo));
|
||||
|
||||
if (desktop) {
|
||||
model->WriteAttrKillForegin(kAttrExtendedPoseInfo,
|
||||
model->WriteAttrKillForeign(kAttrExtendedPoseInfo,
|
||||
kAttrExtendedPoseInfoForegin,
|
||||
B_RAW_TYPE, 0, extendedPoseInfo, extendedPoseInfoSize);
|
||||
}
|
||||
@ -2634,17 +2641,22 @@ BPoseView::ReadPoseInfo(Model *model, PoseInfo *poseInfo)
|
||||
BModelOpener opener(model);
|
||||
if (!model->Node())
|
||||
return;
|
||||
|
||||
|
||||
ReadAttrResult result = kReadAttrFailed;
|
||||
BEntry entry;
|
||||
model->GetEntry(&entry);
|
||||
bool isTrash = FSIsTrashDir(&entry) && IsDesktopView();
|
||||
|
||||
// special case the "root" disks icon
|
||||
if (model->IsRoot()) {
|
||||
BVolume bootVol;
|
||||
// as well as the trash on desktop
|
||||
if (model->IsRoot() || isTrash) {
|
||||
BDirectory dir;
|
||||
|
||||
BVolumeRoster().GetBootVolume(&bootVol);
|
||||
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
|
||||
result = ReadAttr(&dir, kAttrDisksPoseInfo, kAttrDisksPoseInfoForeign,
|
||||
if (FSGetDeskDir(&dir) == B_OK) {
|
||||
const char *poseInfoAttr = (isTrash) ? kAttrTrashPoseInfo
|
||||
: kAttrDisksPoseInfo;
|
||||
const char *poseInfoAttrForeign = (isTrash) ? kAttrTrashPoseInfoForeign
|
||||
: kAttrDisksPoseInfoForeign;
|
||||
result = ReadAttr(&dir, poseInfoAttr, poseInfoAttrForeign,
|
||||
B_RAW_TYPE, 0, poseInfo, sizeof(*poseInfo), &PoseInfo::EndianSwap);
|
||||
}
|
||||
} else {
|
||||
@ -2710,11 +2722,8 @@ BPoseView::ReadExtendedPoseInfo(Model *model)
|
||||
|
||||
// special case the "root" disks icon
|
||||
if (model->IsRoot()) {
|
||||
BVolume bootVol;
|
||||
BDirectory dir;
|
||||
|
||||
BVolumeRoster().GetBootVolume(&bootVol);
|
||||
if (FSGetDeskDir(&dir, bootVol.Device()) == B_OK) {
|
||||
if (FSGetDeskDir(&dir) == B_OK) {
|
||||
extendedPoseInfoAttrName = kAttrExtendedDisksPoseInfo;
|
||||
extendedPoseInfoAttrForeignName = kAttrExtendedDisksPoseInfoForegin;
|
||||
} else
|
||||
|
@ -459,7 +459,8 @@ class BPoseView : public BView {
|
||||
|
||||
virtual void AddPoses(Model *model = NULL);
|
||||
// if <model> is zero, PoseView has other means of iterating through all
|
||||
// the entries that it adds
|
||||
// the entries thaat it adds
|
||||
|
||||
virtual void AddRootPoses(bool watchIndividually, bool mountShared);
|
||||
// watchIndividually is used when placing a volume pose onto the Desktop
|
||||
// where unlike in the Root window it will not be watched by the folder
|
||||
|
@ -237,9 +237,6 @@ TTracker::QuitRequested()
|
||||
gStatusWindow->AttemptToQuit();
|
||||
// try quitting the copy/move/empty trash threads
|
||||
|
||||
BVolume bootVolume;
|
||||
DEBUG_ONLY(status_t err =) BVolumeRoster().GetBootVolume(&bootVolume);
|
||||
ASSERT(err == B_OK);
|
||||
BMessage message;
|
||||
AutoLock<WindowList> lock(&fWindowList);
|
||||
// save open windows in a message inside an attribute of the desktop
|
||||
@ -294,7 +291,7 @@ TTracker::QuitRequested()
|
||||
|
||||
// write windows to open on disk
|
||||
BDirectory deskDir;
|
||||
if (!BootedInSafeMode() && FSGetDeskDir(&deskDir, bootVolume.Device()) == B_OK) {
|
||||
if (!BootedInSafeMode() && FSGetDeskDir(&deskDir) == B_OK) {
|
||||
// if message is empty, delete the corresponding attribute
|
||||
if (message.CountNames(B_ANY_TYPE)) {
|
||||
size_t size = (size_t)message.FlattenedSize();
|
||||
@ -1189,11 +1186,9 @@ TTracker::_OpenPreviouslyOpenedWindows(const char* pathFilter)
|
||||
if (pathFilter != NULL)
|
||||
filterLength = strlen(pathFilter);
|
||||
|
||||
BVolume bootVolume;
|
||||
BVolumeRoster().GetBootVolume(&bootVolume);
|
||||
BDirectory deskDir;
|
||||
attr_info attrInfo;
|
||||
if (FSGetDeskDir(&deskDir, bootVolume.Device()) != B_OK
|
||||
if (FSGetDeskDir(&deskDir) != B_OK
|
||||
|| deskDir.GetAttrInfo(kAttrOpenWindows, &attrInfo) != B_OK)
|
||||
return;
|
||||
|
||||
@ -1279,10 +1274,8 @@ TTracker::ReadyToRun()
|
||||
|
||||
// open desktop window
|
||||
BContainerWindow *deskWindow = NULL;
|
||||
BVolume bootVolume;
|
||||
BVolumeRoster().GetBootVolume(&bootVolume);
|
||||
BDirectory deskDir;
|
||||
if (FSGetDeskDir(&deskDir, bootVolume.Device()) == B_OK) {
|
||||
if (FSGetDeskDir(&deskDir) == B_OK) {
|
||||
// create desktop
|
||||
BEntry entry;
|
||||
deskDir.GetEntry(&entry);
|
||||
|
@ -152,46 +152,48 @@ BTrashWatcher::MessageReceived(BMessage *message)
|
||||
void
|
||||
BTrashWatcher::UpdateTrashIcons()
|
||||
{
|
||||
BVolume boot;
|
||||
if (BVolumeRoster().GetBootVolume(&boot) != B_OK)
|
||||
return;
|
||||
BVolumeRoster roster;
|
||||
BVolume volume;
|
||||
roster.Rewind();
|
||||
|
||||
BDirectory trashDir;
|
||||
if (FSGetTrashDir(&trashDir, boot.Device()) == B_OK) {
|
||||
// pull out the icons for the current trash state from resources and
|
||||
// apply them onto the trash directory node
|
||||
size_t largeSize = 0;
|
||||
size_t smallSize = 0;
|
||||
const void *largeData = GetTrackerResources()->LoadResource('ICON',
|
||||
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &largeSize);
|
||||
|
||||
const void *smallData = GetTrackerResources()->LoadResource('MICN',
|
||||
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &smallSize);
|
||||
|
||||
while (roster.GetNextVolume(&volume) == B_OK) {
|
||||
if (FSGetTrashDir(&trashDir, volume.Device()) == B_OK) {
|
||||
// pull out the icons for the current trash state from resources and
|
||||
// apply them onto the trash directory node
|
||||
size_t largeSize = 0;
|
||||
size_t smallSize = 0;
|
||||
const void *largeData = GetTrackerResources()->LoadResource('ICON',
|
||||
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &largeSize);
|
||||
|
||||
const void *smallData = GetTrackerResources()->LoadResource('MICN',
|
||||
fTrashFull ? kResTrashFullIcon : kResTrashIcon, &smallSize);
|
||||
|
||||
#ifdef HAIKU_TARGET_PLATFORM_HAIKU
|
||||
size_t vectorSize = 0;
|
||||
const void *vectorData = GetTrackerResources()->LoadResource(
|
||||
B_VECTOR_ICON_TYPE, fTrashFull ? kResTrashFullIcon : kResTrashIcon,
|
||||
&vectorSize);
|
||||
|
||||
if (vectorData)
|
||||
trashDir.WriteAttr(kAttrIcon, B_VECTOR_ICON_TYPE, 0,
|
||||
vectorData, vectorSize);
|
||||
else
|
||||
TRESPASS();
|
||||
size_t vectorSize = 0;
|
||||
const void *vectorData = GetTrackerResources()->LoadResource(
|
||||
B_VECTOR_ICON_TYPE, fTrashFull ? kResTrashFullIcon : kResTrashIcon,
|
||||
&vectorSize);
|
||||
|
||||
if (vectorData)
|
||||
trashDir.WriteAttr(kAttrIcon, B_VECTOR_ICON_TYPE, 0,
|
||||
vectorData, vectorSize);
|
||||
else
|
||||
TRESPASS();
|
||||
#endif
|
||||
|
||||
if (largeData)
|
||||
trashDir.WriteAttr(kAttrLargeIcon, 'ICON', 0,
|
||||
largeData, largeSize);
|
||||
else
|
||||
TRESPASS();
|
||||
|
||||
if (smallData)
|
||||
trashDir.WriteAttr(kAttrMiniIcon, 'MICN', 0,
|
||||
smallData, smallSize);
|
||||
else
|
||||
TRESPASS();
|
||||
|
||||
if (largeData)
|
||||
trashDir.WriteAttr(kAttrLargeIcon, 'ICON', 0,
|
||||
largeData, largeSize);
|
||||
else
|
||||
TRESPASS();
|
||||
|
||||
if (smallData)
|
||||
trashDir.WriteAttr(kAttrMiniIcon, 'MICN', 0,
|
||||
smallData, smallSize);
|
||||
else
|
||||
TRESPASS();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,7 +201,7 @@ find_directory(directory_which which, dev_t device, bool createIt,
|
||||
case B_TRASH_DIRECTORY:
|
||||
// TODO: eventually put that into the file system API?
|
||||
if (device == bootDevice || !strcmp(fsInfo.fsh_name, "bfs"))
|
||||
template = "$h/Desktop/Trash";
|
||||
template = "Trash"; // TODO: add suffix for current user
|
||||
else if (!strcmp(fsInfo.fsh_name, "dos"))
|
||||
template = "RECYCLED/_BEOS_";
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user