1 /*
2 Open Tracker License
3
4 Terms and Conditions
5
6 Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8 Permission is hereby granted, free of charge, to any person obtaining a copy of
9 this software and associated documentation files (the "Software"), to deal in
10 the Software without restriction, including without limitation the rights to
11 use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12 of the Software, and to permit persons to whom the Software is furnished to do
13 so, subject to the following conditions:
14
15 The above copyright notice and this permission notice applies to all licensees
16 and shall be included in all copies or substantial portions of the Software.
17
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21 BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 Except as contained in this notice, the name of Be Incorporated shall not be
26 used in advertising or otherwise to promote the sale, use or other dealings in
27 this Software without prior written authorization from Be Incorporated.
28
29 Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30 of Be Incorporated in the United States and other countries. Other brand product
31 names are registered trademarks or trademarks of their respective holders.
32 All rights reserved.
33 */
34
35 // ToDo:
36 // get rid of fMenuBar, SetMenuBar and related mess
37
38
39 #include <Catalog.h>
40 #include <Debug.h>
41 #include <Directory.h>
42 #include <Locale.h>
43 #include <MenuBar.h>
44 #include <Path.h>
45 #include <Volume.h>
46 #include <VolumeRoster.h>
47
48 #include "Attributes.h"
49 #include "ContainerWindow.h"
50 #include "DirMenu.h"
51 #include "FSUtils.h"
52 #include "IconMenuItem.h"
53 #include "NavMenu.h"
54 #include "TrackerSettings.h"
55 #include "Utilities.h"
56
57
58 #undef B_TRANSLATION_CONTEXT
59 #define B_TRANSLATION_CONTEXT "DirMenu"
60
61
62 // #pragma mark - BDirMenu
63
64
BDirMenu(BMenuBar * bar,BMessenger target,uint32 command,const char * entryName)65 BDirMenu::BDirMenu(BMenuBar* bar, BMessenger target, uint32 command,
66 const char* entryName)
67 :
68 BPopUpMenu("directories"),
69 fTarget(target),
70 fMenuBar(bar),
71 fCommand(command)
72 {
73 if (entryName)
74 fEntryName = entryName;
75 else
76 fEntryName = "refs";
77 }
78
79
~BDirMenu()80 BDirMenu::~BDirMenu()
81 {
82 }
83
84
85 void
Populate(const BEntry * startEntry,BWindow * originatingWindow,bool includeStartEntry,bool select,bool reverse,bool addShortcuts,bool navMenuEntries)86 BDirMenu::Populate(const BEntry* startEntry, BWindow* originatingWindow,
87 bool includeStartEntry, bool select, bool reverse, bool addShortcuts,
88 bool navMenuEntries)
89 {
90 try {
91 if (!startEntry)
92 throw (status_t)B_ERROR;
93
94 Model model(startEntry);
95 ThrowOnInitCheckError(&model);
96
97 ModelMenuItem* menu = NULL;
98
99 if (fMenuBar) {
100 menu = new ModelMenuItem(&model, this, true, true);
101 fMenuBar->AddItem(menu);
102 }
103
104 BEntry entry(*startEntry);
105
106 bool showDesktop, showDisksIcon;
107 {
108 TrackerSettings settings;
109 showDesktop = settings.DesktopFilePanelRoot();
110 showDisksIcon = settings.ShowDisksIcon();
111 }
112
113 // might start one level above startEntry
114 if (!includeStartEntry) {
115 BDirectory parent;
116 BDirectory dir(&entry);
117
118 if (!showDesktop && dir.InitCheck() == B_OK
119 && dir.IsRootDirectory()) {
120 // if we're at the root directory skip "mnt" and
121 // go straight to "/"
122 parent.SetTo("/");
123 parent.GetEntry(&entry);
124 } else
125 FSGetParentVirtualDirectoryAware(entry, entry);
126 }
127
128 BDirectory desktopDir;
129 FSGetDeskDir(&desktopDir);
130 BEntry desktopEntry;
131 desktopDir.GetEntry(&desktopEntry);
132
133 for (;;) {
134 BNode node(&entry);
135 ThrowOnInitCheckError(&node);
136
137 PoseInfo info;
138 ReadAttrResult result = ReadAttr(&node, kAttrPoseInfo,
139 kAttrPoseInfoForeign, B_RAW_TYPE, 0, &info, sizeof(PoseInfo),
140 &PoseInfo::EndianSwap);
141
142 BEntry parentEntry;
143 bool hitRoot = false;
144
145 BDirectory dir(&entry);
146 if (!showDesktop && dir.InitCheck() == B_OK
147 && dir.IsRootDirectory()) {
148 // if we're at the root directory skip "mnt" and
149 // go straight to "/"
150 hitRoot = true;
151 parentEntry.SetTo("/");
152 } else
153 FSGetParentVirtualDirectoryAware(entry, parentEntry);
154
155 if (showDesktop) {
156 BEntry root("/");
157 // warp from "/" to Desktop properly
158 if (entry == root) {
159 if (showDisksIcon)
160 AddDisksIconToMenu(reverse);
161 entry = desktopEntry;
162 }
163
164 if (entry == desktopEntry)
165 hitRoot = true;
166 }
167
168 if (result == kReadAttrFailed || !info.fInvisible
169 || (showDesktop && desktopEntry == entry)) {
170 AddItemToDirMenu(&entry, originatingWindow, reverse,
171 addShortcuts, navMenuEntries);
172 }
173
174 if (hitRoot) {
175 if (!showDesktop && showDisksIcon && *startEntry != "/")
176 AddDisksIconToMenu(reverse);
177 break;
178 }
179
180 entry = parentEntry;
181 if (entry.InitCheck() != B_OK)
182 break;
183 }
184
185 // select last item in menu
186 if (!select)
187 return;
188
189 ModelMenuItem* item
190 = dynamic_cast<ModelMenuItem*>(ItemAt(CountItems() - 1));
191 if (item != NULL) {
192 item->SetMarked(true);
193 if (menu) {
194 entry.SetTo(item->TargetModel()->EntryRef());
195 ThrowOnError(menu->SetEntry(&entry));
196 }
197 }
198 } catch (status_t err) {
199 PRINT(("BDirMenu::Populate: caught error %s\n", strerror(err)));
200 if (!CountItems()) {
201 BString error;
202 error << "Error [" << strerror(err) << "] populating menu";
203 AddItem(new BMenuItem(error.String(), 0));
204 }
205 }
206 }
207
208
209 void
AddItemToDirMenu(const BEntry * entry,BWindow * originatingWindow,bool atEnd,bool addShortcuts,bool navMenuEntries)210 BDirMenu::AddItemToDirMenu(const BEntry* entry, BWindow* originatingWindow,
211 bool atEnd, bool addShortcuts, bool navMenuEntries)
212 {
213 Model model(entry);
214 if (model.InitCheck() != B_OK)
215 return;
216
217 BMessage* message = new BMessage(fCommand);
218 message->AddRef(fEntryName.String(), model.EntryRef());
219
220 // add reference to the container windows model so that we can
221 // close the window if
222 BContainerWindow* window = originatingWindow ?
223 dynamic_cast<BContainerWindow*>(originatingWindow) : 0;
224 if (window != NULL) {
225 message->AddData("nodeRefsToClose", B_RAW_TYPE,
226 window->TargetModel()->NodeRef(), sizeof (node_ref));
227 }
228 ModelMenuItem* item;
229 if (navMenuEntries) {
230 BNavMenu* subMenu = new BNavMenu(model.Name(), B_REFS_RECEIVED,
231 fTarget, window);
232 entry_ref ref;
233 entry->GetRef(&ref);
234 subMenu->SetNavDir(&ref);
235 item = new ModelMenuItem(&model, subMenu);
236 item->SetLabel(model.Name());
237 item->SetMessage(message);
238 } else {
239 item = new ModelMenuItem(&model, model.Name(), message);
240 }
241
242 if (addShortcuts) {
243 if (model.IsDesktop())
244 item->SetShortcut('D', B_COMMAND_KEY);
245 else if (FSIsHomeDir(entry))
246 item->SetShortcut('H', B_COMMAND_KEY);
247 }
248
249 if (atEnd)
250 AddItem(item);
251 else
252 AddItem(item, 0);
253
254 item->SetTarget(fTarget);
255
256 if (fMenuBar != NULL) {
257 ModelMenuItem* menu
258 = dynamic_cast<ModelMenuItem*>(fMenuBar->ItemAt(0));
259 if (menu != NULL) {
260 ThrowOnError(menu->SetEntry(entry));
261 item->SetMarked(true);
262 }
263 }
264 }
265
266
267 void
AddDisksIconToMenu(bool atEnd)268 BDirMenu::AddDisksIconToMenu(bool atEnd)
269 {
270 BEntry entry("/");
271 Model model(&entry);
272 if (model.InitCheck() != B_OK)
273 return;
274
275 BMessage* message = new BMessage(fCommand);
276 message->AddRef(fEntryName.String(), model.EntryRef());
277
278 ModelMenuItem* item = new ModelMenuItem(&model,
279 B_TRANSLATE(B_DISKS_DIR_NAME), message);
280 if (atEnd)
281 AddItem(item);
282 else
283 AddItem(item, 0);
284 }
285