xref: /haiku/src/kits/tracker/MountMenu.cpp (revision 746cac055adc6ac3308c7bc2d29040fb95689cc9)
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 false;
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 false;
111 
112 			uint32 divisor = 1UL << 30;
113 			char unit = 'G';
114 			if (partition->Size() < divisor) {
115 				divisor = 1UL << 20;
116 				unit = 'M';
117 			}
118 
119 			char* buffer = name.LockBuffer(256);
120 			snprintf(buffer, 256, "(%.1f %cB %s)",
121 				1.0 * partition->Size() / divisor, unit, type);
122 
123 			name.UnlockBuffer();
124 		}
125 	}
126 
127 	// get icon
128 	BBitmap *icon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1),
129 		B_RGBA32);
130 	if (partition->GetIcon(icon, B_MINI_ICON) != B_OK) {
131 		delete icon;
132 		icon = NULL;
133 	}
134 
135 	BMessage *message = new BMessage(partition->IsMounted() ?
136 		kUnmountVolume : kMountVolume);
137 	message->AddInt32("id", partition->ID());
138 
139 	// TODO: for now, until we actually have disk device icons
140 	BMenuItem *item;
141 	if (icon != NULL)
142 		item = new IconMenuItem(name.String(), message, icon);
143 	else
144 		item = new BMenuItem(name.String(), message);
145 	if (partition->IsMounted()) {
146 		item->SetMarked(true);
147 
148 		BVolume volume;
149 		if (partition->GetVolume(&volume) == B_OK) {
150 			BVolume bootVolume;
151 			BVolumeRoster().GetBootVolume(&bootVolume);
152 			if (volume == bootVolume)
153 				item->SetEnabled(false);
154 		}
155 	}
156 
157 	fMenu->AddItem(item);
158 	return false;
159 }
160 
161 #else	// !__HAIKU__
162 //	#pragma mark - R5 DeviceMap API
163 
164 
165 struct AddOneAsMenuItemParams {
166 	BMenu *mountMenu;
167 };
168 
169 
170 static Partition *
171 AddOnePartitionAsMenuItem(Partition *partition, void *castToParams)
172 {
173 	if (partition->Hidden())
174 		return NULL;
175 
176 	AddOneAsMenuItemParams *params = (AddOneAsMenuItemParams *)castToParams;
177 	BBitmap *icon = new BBitmap(BRect(0, 0, B_MINI_ICON - 1, B_MINI_ICON - 1),
178 		B_CMAP8);
179 	get_device_icon(partition->GetDevice()->Name(), icon->Bits(), B_MINI_ICON);
180 
181 
182 	const char *name = partition->GetDevice()->DisplayName();
183 
184 	if (!partition->GetDevice()->IsFloppy() ||
185 		partition->Mounted() == kMounted) {
186 		if (*partition->VolumeName())
187 			name = partition->VolumeName();
188 		else if (*partition->Type())
189 			name = partition->Type();
190 	}
191 
192 	BMessage *message = new BMessage;
193 
194 	if (partition->Mounted() == kMounted) {
195 		message->what = kUnmountVolume;
196 		message->AddInt32("device_id", partition->VolumeDeviceID());
197 	} else {
198 		message->what = kMountVolume;
199 
200 		//
201 		//	Floppies have an ID of -1, because they don't have
202 		//	partition (and hence no parititon ID).
203 		//
204 		if (partition->GetDevice()->IsFloppy())
205 			message->AddInt32("id", kFloppyID);
206 		else
207 			message->AddInt32("id", partition->UniqueID());
208 	}
209 
210 	BMenuItem *item = new IconMenuItem(name, message, icon);
211 	if (partition->Mounted() == kMounted)
212 		item->SetMarked(true);
213 
214 	if (partition->Mounted() == kMounted) {
215 		BVolume partVolume(partition->VolumeDeviceID());
216 
217 		BVolume bootVolume;
218 		BVolumeRoster().GetBootVolume(&bootVolume);
219 		if (partVolume == bootVolume)
220 			item->SetEnabled(false);
221 	}
222 
223 	params->mountMenu->AddItem(item);
224 
225 	return NULL;
226 }
227 #endif	// !__HAIKU__
228 
229 
230 //	#pragma mark -
231 
232 
233 MountMenu::MountMenu(const char *name)
234 	: BMenu(name)
235 {
236 	SetFont(be_plain_font);
237 }
238 
239 
240 bool
241 MountMenu::AddDynamicItem(add_state)
242 {
243 	// remove old items
244 	for (;;) {
245 		BMenuItem *item = RemoveItem(0L);
246 		if (item == NULL)
247 			break;
248 		delete item;
249 	}
250 
251 #ifdef __HAIKU__
252 	BDiskDeviceList devices;
253 	status_t status = devices.Fetch();
254 	if (status == B_OK) {
255 		AddMenuItemVisitor visitor(this);
256 		devices.VisitEachPartition(&visitor);
257 	}
258 #else
259 	AddOneAsMenuItemParams params;
260 	params.mountMenu = this;
261 
262 	AutoMounter *autoMounter = dynamic_cast<TTracker *>(be_app)->
263 		AutoMounterLoop();
264 
265 	autoMounter->CheckVolumesNow();
266 	autoMounter->EachPartition(&AddOnePartitionAsMenuItem, &params);
267 #endif
268 
269 #ifdef SHOW_NETWORK_VOLUMES
270 	// iterate the volume roster and look for volumes with the
271 	// 'shared' attributes -- these same volumes will not be returned
272 	// by the autoMounter because they do not show up in the /dev tree
273 	BVolumeRoster volumeRoster;
274 	BVolume volume;
275 	bool needSeparator = false;
276 	while (volumeRoster.GetNextVolume(&volume) == B_OK) {
277 		if (volume.IsShared()) {
278 			needSeparator = true;
279 			BBitmap *icon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8);
280 			fs_info info;
281 			if (fs_stat_dev(volume.Device(), &info) != B_OK) {
282 				PRINT(("Cannot get mount menu item icon; bad device ID\n"));
283 				delete icon;
284 				continue;
285 			}
286 			// Use the shared icon instead of the device icon
287 			if (get_device_icon(info.device_name, icon->Bits(), B_MINI_ICON) != B_OK)
288 				GetTrackerResources()->GetIconResource(kResShareIcon, B_MINI_ICON, icon);
289 
290 			BMessage *message = new BMessage(kUnmountVolume);
291 			message->AddInt32("device_id", volume.Device());
292 			char volumeName[B_FILE_NAME_LENGTH];
293 			volume.GetName(volumeName);
294 
295 			BMenuItem *item = new IconMenuItem(volumeName, message, icon);
296 			item->SetMarked(true);
297 			AddItem(item);
298 		}
299 	}
300 #endif	// SHOW_NETWORK_VOLUMES
301 
302 	AddSeparatorItem();
303 
304 #ifndef __HAIKU__
305 	// add an option to rescan the scsii bus, etc.
306 	BMenuItem *rescanItem = NULL;
307 	if (modifiers() & B_SHIFT_KEY) {
308 		rescanItem = new BMenuItem("Rescan Devices", new BMessage(kAutomounterRescan));
309 		AddItem(rescanItem);
310 	}
311 #endif
312 
313 	BMenuItem *mountAll = new BMenuItem("Mount All", new BMessage(kMountAllNow));
314 	AddItem(mountAll);
315 	BMenuItem *mountSettings = new BMenuItem("Settings" B_UTF8_ELLIPSIS,
316 		new BMessage(kRunAutomounterSettings));
317 	AddItem(mountSettings);
318 
319 	SetTargetForItems(be_app);
320 
321 #ifndef __HAIKU__
322 	if (rescanItem)
323 		rescanItem->SetTarget(autoMounter);
324 #endif
325 
326 	return false;
327 }
328