1/*
2Open Tracker License
3
4Terms and Conditions
5
6Copyright (c) 1991-2000, Be Incorporated. All rights reserved.
7
8Permission is hereby granted, free of charge, to any person obtaining a copy of
9this software and associated documentation files (the "Software"), to deal in
10the Software without restriction, including without limitation the rights to
11use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
12of the Software, and to permit persons to whom the Software is furnished to do
13so, subject to the following conditions:
14
15The above copyright notice and this permission notice applies to all licensees
16and shall be included in all copies or substantial portions of the Software.
17
18THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF TITLE, MERCHANTABILITY,
20FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
21BE INCORPORATED BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
22AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF, OR IN CONNECTION
23WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25Except as contained in this notice, the name of Be Incorporated shall not be
26used in advertising or otherwise to promote the sale, use or other dealings in
27this Software without prior written authorization from Be Incorporated.
28
29Tracker(TM), Be(R), BeOS(R), and BeIA(TM) are trademarks or registered trademarks
30of Be Incorporated in the United States and other countries. Other brand product
31names are registered trademarks or trademarks of their respective holders.
32All rights reserved.
33*/
34
35// MountMenu implements a context menu used for mounting/unmounting volumes
36
37
38#include "MountMenu.h"
39
40#include <Catalog.h>
41#include <ControlLook.h>
42#include <Debug.h>
43#include <Locale.h>
44#include <MenuItem.h>
45#include <Mime.h>
46#include <InterfaceDefs.h>
47#include <VolumeRoster.h>
48#include <Volume.h>
49
50#include <fs_info.h>
51
52#include "Commands.h"
53#include "IconMenuItem.h"
54#include "Tracker.h"
55#include "Bitmaps.h"
56
57#include <DiskDevice.h>
58#include <DiskDeviceList.h>
59
60#define SHOW_NETWORK_VOLUMES
61
62#undef B_TRANSLATION_CONTEXT
63#define B_TRANSLATION_CONTEXT "MountMenu"
64
65
66class AddMenuItemVisitor : public BDiskDeviceVisitor {
67public:
68	AddMenuItemVisitor(BMenu* menu);
69	virtual ~AddMenuItemVisitor();
70
71	virtual bool Visit(BDiskDevice* device);
72	virtual bool Visit(BPartition* partition, int32 level);
73
74private:
75	BMenu* fMenu;
76};
77
78
79//	#pragma mark - AddMenuItemVisitor
80
81
82AddMenuItemVisitor::AddMenuItemVisitor(BMenu* menu)
83	:
84	fMenu(menu)
85{
86}
87
88
89AddMenuItemVisitor::~AddMenuItemVisitor()
90{
91}
92
93
94bool
95AddMenuItemVisitor::Visit(BDiskDevice* device)
96{
97	return Visit(device, 0);
98}
99
100
101bool
102AddMenuItemVisitor::Visit(BPartition* partition, int32 level)
103{
104	if (!partition->ContainsFileSystem())
105		return false;
106
107	// get name (and eventually the type)
108	BString name = partition->ContentName();
109	if (name.Length() == 0) {
110		name = partition->Name();
111		if (name.Length() == 0) {
112			const char* type = partition->ContentType();
113			if (type == NULL)
114				return false;
115
116			uint32 divisor = 1UL << 30;
117			char unit = 'G';
118			if (partition->Size() < divisor) {
119				divisor = 1UL << 20;
120				unit = 'M';
121			}
122
123			name.SetToFormat("(%.1f %cB %s)",
124				1.0 * partition->Size() / divisor, unit, type);
125		}
126	}
127
128	// get icon
129	BBitmap* icon = new BBitmap(BRect(BPoint(0, 0), be_control_look->ComposeIconSize(B_MINI_ICON)),
130		B_RGBA32);
131	if (partition->GetIcon(icon, B_MINI_ICON) != B_OK) {
132		delete icon;
133		icon = NULL;
134	}
135
136	BMessage* message = new BMessage(partition->IsMounted() ?
137		kUnmountVolume : kMountVolume);
138	message->AddInt32("id", partition->ID());
139
140	// TODO: for now, until we actually have disk device icons
141	BMenuItem* item;
142	if (icon != NULL)
143		item = new IconMenuItem(name.String(), message, icon);
144	else
145		item = new BMenuItem(name.String(), message);
146	if (partition->IsMounted()) {
147		item->SetMarked(true);
148
149		BVolume volume;
150		if (partition->GetVolume(&volume) == B_OK) {
151			BVolume bootVolume;
152			BVolumeRoster().GetBootVolume(&bootVolume);
153			if (volume == bootVolume)
154				item->SetEnabled(false);
155		}
156	}
157
158	fMenu->AddItem(item);
159	return false;
160}
161
162
163//	#pragma mark - MountMenu
164
165
166MountMenu::MountMenu(const char* name)
167	: BMenu(name)
168{
169}
170
171
172bool
173MountMenu::AddDynamicItem(add_state)
174{
175	// remove old items
176	for (;;) {
177		BMenuItem* item = RemoveItem((int32)0);
178		if (item == NULL)
179			break;
180		delete item;
181	}
182
183	BDiskDeviceList devices;
184	status_t status = devices.Fetch();
185	if (status == B_OK) {
186		AddMenuItemVisitor visitor(this);
187		devices.VisitEachPartition(&visitor);
188	}
189
190#ifdef SHOW_NETWORK_VOLUMES
191	// iterate the volume roster and look for volumes with the
192	// 'shared' attributes -- these same volumes will not be returned
193	// by the autoMounter because they do not show up in the /dev tree
194	BVolumeRoster volumeRoster;
195	BVolume volume;
196	while (volumeRoster.GetNextVolume(&volume) == B_OK) {
197		if (volume.IsShared()) {
198			BBitmap* icon = new BBitmap(BRect(0, 0, 15, 15), B_CMAP8);
199			fs_info info;
200			if (fs_stat_dev(volume.Device(), &info) != B_OK) {
201				PRINT(("Cannot get mount menu item icon; bad device ID\n"));
202				delete icon;
203				continue;
204			}
205			// Use the shared icon instead of the device icon
206			if (get_device_icon(info.device_name, icon, B_MINI_ICON)
207					!= B_OK) {
208				GetTrackerResources()->GetIconResource(R_ShareIcon,
209					B_MINI_ICON, icon);
210			}
211
212			BMessage* message = new BMessage(kUnmountVolume);
213			message->AddInt32("device_id", volume.Device());
214			char volumeName[B_FILE_NAME_LENGTH];
215			volume.GetName(volumeName);
216
217			BMenuItem* item = new IconMenuItem(volumeName, message, icon);
218			item->SetMarked(true);
219			AddItem(item);
220		}
221	}
222#endif	// SHOW_NETWORK_VOLUMES
223
224	AddSeparatorItem();
225
226	BMenuItem* mountAll = new BMenuItem(B_TRANSLATE("Mount all"),
227		new BMessage(kMountAllNow));
228	AddItem(mountAll);
229	BMenuItem* mountSettings = new BMenuItem(
230		B_TRANSLATE("Settings" B_UTF8_ELLIPSIS),
231		new BMessage(kRunAutomounterSettings));
232	AddItem(mountSettings);
233
234	SetTargetForItems(be_app);
235
236	return false;
237}
238