xref: /haiku/src/kits/tracker/MountMenu.cpp (revision 1e36cfc2721ef13a187c6f7354dc9cbc485e89d3)
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 // MountMenu implements a context menu used for mounting/unmounting volumes
36 
37 #include <MenuItem.h>
38 #include <Mime.h>
39 #include <InterfaceDefs.h>
40 #include <VolumeRoster.h>
41 #include <Volume.h>
42 #include <fs_info.h>
43 
44 #include "AutoMounter.h"
45 #include "Commands.h"
46 #include "MountMenu.h"
47 #include "IconMenuItem.h"
48 #include "Tracker.h"
49 #include "Bitmaps.h"
50 
51 #ifdef __HAIKU__
52 #	include <DiskDevice.h>
53 #	include <DiskDeviceList.h>
54 #else
55 #	include "DeviceMap.h"
56 #endif
57 
58 #define SHOW_NETWORK_VOLUMES
59 
60 
61 #ifdef __HAIKU__
62 //	#pragma mark - Haiku Disk Device API
63 
64 
65 class AddMenuItemVisitor : public BDiskDeviceVisitor {
66 	public:
67 		AddMenuItemVisitor(BMenu* menu);
68 		virtual ~AddMenuItemVisitor();
69 
70 		virtual bool Visit(BDiskDevice *device);
71 		virtual bool Visit(BPartition *partition, int32 level);
72 
73 	private:
74 		BMenu* fMenu;
75 };
76 
77 
78 AddMenuItemVisitor::AddMenuItemVisitor(BMenu* menu)
79 	:
80 	fMenu(menu)
81 {
82 }
83 
84 
85 AddMenuItemVisitor::~AddMenuItemVisitor()
86 {
87 }
88 
89 
90 bool
91 AddMenuItemVisitor::Visit(BDiskDevice *device)
92 {
93 	return Visit(device, 0);
94 }
95 
96 
97 bool
98 AddMenuItemVisitor::Visit(BPartition *partition, int32 level)
99 {
100 	if (!partition->ContainsFileSystem())
101 		return NULL;
102 
103 	// get name (and eventually the type)
104 	BString name = partition->ContentName();
105 	if (name.Length() == 0) {
106 		name = partition->Name();
107 		if (name.Length() == 0) {
108 			const char *type = partition->ContentType();
109 			if (type == NULL)
110 				return NULL;
111 
112 			name = "(unnamed ";
113 			name << type;
114 			name << ")";
115 		}
116 	}
117 
118 	// get icon
119 	BBitmap *icon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1),
120 		B_CMAP8);
121 	if (partition->GetIcon(icon, B_MINI_ICON) != B_OK) {
122 		delete icon;
123 		icon = NULL;
124 	}
125 
126 	BMessage *message = new BMessage(partition->IsMounted() ?
127 		kUnmountVolume : kMountVolume);
128 	message->AddInt32("id", partition->ID());
129 
130 	// TODO: for now, until we actually have disk device icons
131 	BMenuItem *item;
132 	if (icon != NULL)
133 		item = new IconMenuItem(name.String(), message, icon);
134 	else
135 		item = new BMenuItem(name.String(), message);
136 	if (partition->IsMounted()) {
137 		item->SetMarked(true);
138 
139 		BVolume volume;
140 		if (partition->GetVolume(&volume) == B_OK) {
141 			BVolume bootVolume;
142 			BVolumeRoster().GetBootVolume(&bootVolume);
143 			if (volume == bootVolume)
144 				item->SetEnabled(false);
145 		}
146 	}
147 
148 	fMenu->AddItem(item);
149 	return false;
150 }
151 
152 #else	// !__HAIKU__
153 //	#pragma mark - R5 DeviceMap API
154 
155 
156 struct AddOneAsMenuItemParams {
157 	BMenu *mountMenu;
158 };
159 
160 
161 static Partition *
162 AddOnePartitionAsMenuItem(Partition *partition, void *castToParams)
163 {
164 	if (partition->Hidden())
165 		return NULL;
166 
167 	AddOneAsMenuItemParams *params = (AddOneAsMenuItemParams *)castToParams;
168 	BBitmap *icon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1),
169 		B_CMAP8);
170 	get_device_icon(partition->GetDevice()->Name(), icon->Bits(), B_MINI_ICON);
171 
172 
173 	const char *name = partition->GetDevice()->DisplayName();
174 
175 	if (!partition->GetDevice()->IsFloppy() ||
176 		partition->Mounted() == kMounted) {
177 		if (*partition->VolumeName())
178 			name = partition->VolumeName();
179 		else if (*partition->Type())
180 			name = partition->Type();
181 	}
182 
183 	BMessage *message = new BMessage;
184 
185 	if (partition->Mounted() == kMounted) {
186 		message->what = kUnmountVolume;
187 		message->AddInt32("device_id", partition->VolumeDeviceID());
188 	} else {
189 		message->what = kMountVolume;
190 
191 		//
192 		//	Floppies have an ID of -1, because they don't have
193 		//	partition (and hence no parititon ID).
194 		//
195 		if (partition->GetDevice()->IsFloppy())
196 			message->AddInt32("id", kFloppyID);
197 		else
198 			message->AddInt32("id", partition->UniqueID());
199 	}
200 
201 	BMenuItem *item = new IconMenuItem(name, message, icon);
202 	if (partition->Mounted() == kMounted)
203 		item->SetMarked(true);
204 
205 	if (partition->Mounted() == kMounted) {
206 		BVolume partVolume(partition->VolumeDeviceID());
207 
208 		BVolume bootVolume;
209 		BVolumeRoster().GetBootVolume(&bootVolume);
210 		if (partVolume == bootVolume)
211 			item->SetEnabled(false);
212 	}
213 
214 	params->mountMenu->AddItem(item);
215 
216 	return NULL;
217 }
218 #endif	// !__HAIKU__
219 
220 
221 //	#pragma mark -
222 
223 
224 MountMenu::MountMenu(const char *name)
225 	: BMenu(name)
226 {
227 	SetFont(be_plain_font);
228 }
229 
230 
231 bool
232 MountMenu::AddDynamicItem(add_state)
233 {
234 	// remove old items
235 	for (;;) {
236 		BMenuItem *item = RemoveItem(0L);
237 		if (item == NULL)
238 			break;
239 		delete item;
240 	}
241 
242 #ifdef __HAIKU__
243 	BDiskDeviceList devices;
244 	status_t status = devices.Fetch();
245 	if (status == B_OK) {
246 		AddMenuItemVisitor visitor(this);
247 		devices.VisitEachPartition(&visitor);
248 	}
249 #else
250 	AddOneAsMenuItemParams params;
251 	params.mountMenu = this;
252 
253 	AutoMounter *autoMounter = dynamic_cast<TTracker *>(be_app)->
254 		AutoMounterLoop();
255 
256 	autoMounter->CheckVolumesNow();
257 	autoMounter->EachPartition(&AddOnePartitionAsMenuItem, &params);
258 #endif
259 
260 #ifdef SHOW_NETWORK_VOLUMES
261 	// iterate the volume roster and look for volumes with the
262 	// 'shared' attributes -- these same volumes will not be returned
263 	// by the autoMounter because they do not show up in the /dev tree
264 	BVolumeRoster volumeRoster;
265 	BVolume volume;
266 	bool needSeparator = false;
267 	while (volumeRoster.GetNextVolume(&volume) == B_OK) {
268 		if (volume.IsShared()) {
269 			needSeparator = true;
270 			BBitmap *icon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8);
271 			fs_info info;
272 			if (fs_stat_dev(volume.Device(), &info) != B_OK) {
273 				PRINT(("Cannot get mount menu item icon; bad device ID\n"));
274 				delete icon;
275 				continue;
276 			}
277 			// Use the shared icon instead of the device icon
278 			if (get_device_icon(info.device_name, icon->Bits(), B_MINI_ICON) != B_OK)
279 				GetTrackerResources()->GetIconResource(kResShareIcon, B_MINI_ICON, icon);
280 
281 			BMessage *message = new BMessage(kUnmountVolume);
282 			message->AddInt32("device_id", volume.Device());
283 			char volumeName[B_FILE_NAME_LENGTH];
284 			volume.GetName(volumeName);
285 
286 			BMenuItem *item = new IconMenuItem(volumeName, message, icon);
287 			item->SetMarked(true);
288 			AddItem(item);
289 		}
290 	}
291 #endif	// SHOW_NETWORK_VOLUMES
292 
293 	AddSeparatorItem();
294 
295 #ifndef __HAIKU__
296 	// add an option to rescan the scsii bus, etc.
297 	BMenuItem *rescanItem = NULL;
298 	if (modifiers() & B_SHIFT_KEY) {
299 		rescanItem = new BMenuItem("Rescan Devices", new BMessage(kAutomounterRescan));
300 		AddItem(rescanItem);
301 	}
302 #endif
303 
304 	BMenuItem *mountAll = new BMenuItem("Mount All", new BMessage(kMountAllNow));
305 	AddItem(mountAll);
306 	BMenuItem *mountSettings = new BMenuItem("Settings"B_UTF8_ELLIPSIS,
307 		new BMessage(kRunAutomounterSettings));
308 	AddItem(mountSettings);
309 
310 	SetTargetForItems(be_app);
311 
312 #ifndef __HAIKU__
313 	if (rescanItem)
314 		rescanItem->SetTarget(autoMounter);
315 #endif
316 
317 	return false;
318 }
319