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, ¶ms); 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