xref: /haiku/src/apps/drivesetup/MainWindow.cpp (revision cda5b8808fd0262f0fac472f6cfa809f846a83cf)
1 /*
2  * Copyright 2002-2008 Haiku Inc. All rights reserved.
3  * Distributed under the terms of the MIT license.
4  *
5  * Authors:
6  *		Erik Jaesler <ejakowatz@users.sourceforge.net>
7  *		Ithamar R. Adema <ithamar@unet.nl>
8  *		Stephan Aßmus <superstippi@gmx.de>
9  */
10 #include "MainWindow.h"
11 #include "DiskView.h"
12 #include "InitParamsPanel.h"
13 #include "PartitionList.h"
14 #include "Support.h"
15 
16 #include <Alert.h>
17 #include <Application.h>
18 
19 #include <DiskDeviceVisitor.h>
20 #include <DiskSystem.h>
21 #include <DiskDevice.h>
22 #include <Partition.h>
23 #include <PartitioningInfo.h>
24 #include <Path.h>
25 
26 #include <ColumnListView.h>
27 #include <ColumnTypes.h>
28 #include <MenuItem.h>
29 #include <MenuBar.h>
30 #include <Menu.h>
31 #include <Screen.h>
32 #include <Volume.h>
33 #include <VolumeRoster.h>
34 
35 
36 class ListPopulatorVisitor : public BDiskDeviceVisitor {
37 public:
38 	ListPopulatorVisitor(PartitionListView* list, int32& diskCount,
39 			SpaceIDMap& spaceIDMap)
40 		: fPartitionList(list)
41 		, fDiskCount(diskCount)
42 		, fSpaceIDMap(spaceIDMap)
43 	{
44 		fDiskCount = 0;
45 		fSpaceIDMap.Clear();
46 		// start with an empty list
47 		int32 rows = fPartitionList->CountRows();
48 		for (int32 i = rows - 1; i >= 0; i--) {
49 			BRow* row = fPartitionList->RowAt(i);
50 			fPartitionList->RemoveRow(row);
51 			delete row;
52 		}
53 	}
54 
55 	virtual bool Visit(BDiskDevice* device)
56 	{
57 		fDiskCount++;
58 		// if we don't prepare the device for modifications,
59 		// we cannot get information about available empty
60 		// regions on the device or child partitions
61 device->PrepareModifications();
62 		_AddPartition(device);
63 		return false; // Don't stop yet!
64 	}
65 
66 	virtual bool Visit(BPartition* partition, int32 level)
67 	{
68 		_AddPartition(partition);
69 		return false; // Don't stop yet!
70 	}
71 
72 private:
73 	void _AddPartition(BPartition* partition) const
74 	{
75 		// add the partition itself
76 		fPartitionList->AddPartition(partition);
77 
78 		// add any available space on it
79 		BPartitioningInfo info;
80 		status_t ret = partition->GetPartitioningInfo(&info);
81 		if (ret >= B_OK) {
82 			partition_id parentID = partition->ID();
83 			off_t offset;
84 			off_t size;
85 			for (int32 i = 0;
86 				info.GetPartitionableSpaceAt(i, &offset, &size) >= B_OK;
87 				i++) {
88 				// TODO: remove again once Disk Device API is fixed
89 				if (!is_valid_partitionable_space(size))
90 					continue;
91 				//
92 				partition_id id = fSpaceIDMap.SpaceIDFor(parentID, offset);
93 				fPartitionList->AddSpace(parentID, id, offset, size);
94 			}
95 		}
96 	}
97 
98 	PartitionListView*	fPartitionList;
99 	int32&				fDiskCount;
100 	SpaceIDMap&			fSpaceIDMap;
101 };
102 
103 
104 class MountAllVisitor : public BDiskDeviceVisitor {
105 public:
106 	MountAllVisitor()
107 	{
108 	}
109 
110 	virtual bool Visit(BDiskDevice* device)
111 	{
112 		return false; // Don't stop yet!
113 	}
114 
115 	virtual bool Visit(BPartition* partition, int32 level)
116 	{
117 		partition->Mount();
118 		return false; // Don't stop yet!
119 	}
120 
121 private:
122 	PartitionListView* fPartitionList;
123 };
124 
125 
126 enum {
127 	MSG_MOUNT_ALL				= 'mnta',
128 	MSG_MOUNT					= 'mnts',
129 	MSG_UNMOUNT					= 'unmt',
130 	MSG_FORMAT					= 'frmt',
131 	MSG_CREATE					= 'crtp',
132 	MSG_INITIALIZE				= 'init',
133 	MSG_DELETE					= 'delt',
134 	MSG_EJECT					= 'ejct',
135 	MSG_SURFACE_TEST			= 'sfct',
136 	MSG_RESCAN					= 'rscn',
137 
138 	MSG_PARTITION_ROW_SELECTED	= 'prsl',
139 };
140 
141 
142 // #pragma mark -
143 
144 
145 MainWindow::MainWindow(BRect frame)
146 	: BWindow(frame, "DriveSetup", B_DOCUMENT_WINDOW,
147 		B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE)
148 	, fCurrentDisk(NULL)
149 	, fCurrentPartitionID(-1)
150 	, fSpaceIDMap()
151 {
152 	BMenuBar* menuBar = new BMenuBar(Bounds(), "root menu");
153 
154 	// create all the menu items
155 	fFormatMI = new BMenuItem("Format (not implemented)", new BMessage(MSG_FORMAT));
156 	fEjectMI = new BMenuItem("Eject", new BMessage(MSG_EJECT), 'E');
157 	fSurfaceTestMI = new BMenuItem("Surface Test (not implemented)",
158 		new BMessage(MSG_SURFACE_TEST));
159 	fRescanMI = new BMenuItem("Rescan", new BMessage(MSG_RESCAN));
160 
161 	fDeleteMI = new BMenuItem("Delete (not implemented)",
162 		new BMessage(MSG_DELETE));
163 fDeleteMI->SetEnabled(false);
164 
165 	fMountMI = new BMenuItem("Mount", new BMessage(MSG_MOUNT), 'M');
166 	fUnmountMI = new BMenuItem("Unmount", new BMessage(MSG_UNMOUNT), 'U');
167 	fMountAllMI = new BMenuItem("Mount All",
168 		new BMessage(MSG_MOUNT_ALL), 'M', B_SHIFT_KEY);
169 
170 	// Disk menu
171 	fDiskMenu = new BMenu("Disk");
172 		fDiskMenu->AddItem(fFormatMI);
173 		fDiskMenu->AddItem(fEjectMI);
174 		fDiskMenu->AddItem(fSurfaceTestMI);
175 
176 		fDiskMenu->AddSeparatorItem();
177 
178 		fDiskMenu->AddItem(fRescanMI);
179 	menuBar->AddItem(fDiskMenu);
180 
181 	// Parition menu
182 	fPartitionMenu = new BMenu("Partition");
183 		fCreateMenu = new BMenu("Create (not implemented)");
184 		fPartitionMenu->AddItem(fCreateMenu);
185 
186 		fInitMenu = new BMenu("Initialize");
187 		fPartitionMenu->AddItem(fInitMenu);
188 
189 		fPartitionMenu->AddItem(fDeleteMI);
190 
191 		fPartitionMenu->AddSeparatorItem();
192 
193 		fPartitionMenu->AddItem(fMountMI);
194 		fPartitionMenu->AddItem(fUnmountMI);
195 
196 		fPartitionMenu->AddSeparatorItem();
197 
198 		fPartitionMenu->AddItem(fMountAllMI);
199 	menuBar->AddItem(fPartitionMenu);
200 
201 	AddChild(menuBar);
202 
203 
204 	// add DiskView
205 	BRect r(Bounds());
206 	r.top = menuBar->Frame().bottom + 1;
207 	r.bottom = floorf(r.top + r.Height() * 0.33);
208 	fDiskView = new DiskView(r, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
209 		fSpaceIDMap);
210 	AddChild(fDiskView);
211 
212 	// add PartitionListView
213 	r.top = r.bottom + 2;
214 	r.bottom = Bounds().bottom;
215 	r.InsetBy(-1, -1);
216 	fListView = new PartitionListView(r, B_FOLLOW_ALL);
217 	AddChild(fListView);
218 
219 	// configure PartitionListView
220 	fListView->SetSelectionMessage(new BMessage(MSG_PARTITION_ROW_SELECTED));
221 	fListView->SetTarget(this);
222 
223 	// populate the Initialiaze menu with the available file systems
224 	_ScanFileSystems();
225 
226 	// visit all disks in the system and show their contents
227 	_ScanDrives();
228 }
229 
230 
231 MainWindow::~MainWindow()
232 {
233 	delete fCurrentDisk;
234 }
235 
236 
237 void
238 MainWindow::MessageReceived(BMessage* message)
239 {
240 	switch (message->what) {
241 		case MSG_MOUNT_ALL:
242 			_MountAll();
243 			break;
244 		case MSG_MOUNT:
245 			_Mount(fCurrentDisk, fCurrentPartitionID);
246 			break;
247 		case MSG_UNMOUNT:
248 			_Unmount(fCurrentDisk, fCurrentPartitionID);
249 			break;
250 
251 		case MSG_FORMAT:
252 			printf("MSG_FORMAT\n");
253 			break;
254 
255 		case MSG_CREATE:
256 			printf("MSG_CREATE\n");
257 			break;
258 
259 		case MSG_INITIALIZE: {
260 			BString diskSystemName;
261 			if (message->FindString("format", &diskSystemName) != B_OK)
262 				break;
263 			_Initialize(fCurrentDisk, fCurrentPartitionID, diskSystemName);
264 			break;
265 		}
266 
267 		case MSG_DELETE:
268 			printf("MSG_DELETE\n");
269 			break;
270 
271 		case MSG_EJECT:
272 			// TODO: completely untested, especially interesting
273 			// if partition list behaves when partitions disappear
274 			if (fCurrentDisk) {
275 				// TODO: only if no partitions are mounted anymore?
276 				fCurrentDisk->Eject(true);
277 				_ScanDrives();
278 			}
279 			break;
280 		case MSG_SURFACE_TEST:
281 			printf("MSG_SURFACE_TEST\n");
282 			break;
283 		case MSG_RESCAN:
284 			_ScanDrives();
285 			break;
286 
287 		case MSG_PARTITION_ROW_SELECTED:
288 			// selection of partitions via list view
289 			_AdaptToSelectedPartition();
290 			break;
291 		case MSG_SELECTED_PARTITION_ID: {
292 			// selection of partitions via disk view
293 			partition_id id;
294 			if (message->FindInt32("partition_id", &id) == B_OK) {
295 				if (BRow* row = fListView->FindRow(id)) {
296 					fListView->DeselectAll();
297 					fListView->AddToSelection(row);
298 					_AdaptToSelectedPartition();
299 				}
300 			}
301 			break;
302 		}
303 
304 		default:
305 			BWindow::MessageReceived(message);
306 			break;
307 	}
308 }
309 
310 
311 bool
312 MainWindow::QuitRequested()
313 {
314 	// TODO: ask about any unsaved changes
315 	be_app->PostMessage(B_QUIT_REQUESTED);
316 	Hide();
317 	return false;
318 }
319 
320 
321 // #pragma mark -
322 
323 
324 status_t
325 MainWindow::StoreSettings(BMessage* archive) const
326 {
327 	if (archive->ReplaceRect("window frame", Frame()) < B_OK)
328 		archive->AddRect("window frame", Frame());
329 
330 	BMessage columnSettings;
331 	fListView->SaveState(&columnSettings);
332 	if (archive->ReplaceMessage("column settings", &columnSettings) < B_OK)
333 		archive->AddMessage("column settings", &columnSettings);
334 
335 	return B_OK;
336 }
337 
338 
339 status_t
340 MainWindow::RestoreSettings(BMessage* archive)
341 {
342 	BRect frame;
343 	if (archive->FindRect("window frame", &frame) == B_OK) {
344 		BScreen screen(this);
345 		if (frame.Intersects(screen.Frame())) {
346 			MoveTo(frame.LeftTop());
347 			ResizeTo(frame.Width(), frame.Height());
348 		}
349 	}
350 
351 	BMessage columnSettings;
352 	if (archive->FindMessage("column settings", &columnSettings) == B_OK)
353 		fListView->LoadState(&columnSettings);
354 
355 	return B_OK;
356 }
357 
358 
359 // #pragma mark -
360 
361 
362 void
363 MainWindow::_ScanDrives()
364 {
365 	fSpaceIDMap.Clear();
366 	int32 diskCount = 0;
367 	ListPopulatorVisitor driveVisitor(fListView, diskCount, fSpaceIDMap);
368 	fDDRoster.VisitEachPartition(&driveVisitor);
369 	fDiskView->SetDiskCount(diskCount);
370 
371 	// restore selection
372 	PartitionListRow* previousSelection
373 		= fListView->FindRow(fCurrentPartitionID);
374 	if (previousSelection) {
375 		fListView->AddToSelection(previousSelection);
376 		_EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID,
377 			previousSelection->ParentID());
378 	} else {
379 		_EnabledDisableMenuItems(NULL, -1, -1);
380 	}
381 }
382 
383 
384 void
385 MainWindow::_ScanFileSystems()
386 {
387 	while (BMenuItem* item = fInitMenu->RemoveItem(0L))
388 		delete item;
389 
390 	BDiskSystem diskSystem;
391 	fDDRoster.RewindDiskSystems();
392 	while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) {
393 		if (diskSystem.IsFileSystem() && diskSystem.SupportsInitializing()) {
394 			BMessage* message = new BMessage(MSG_INITIALIZE);
395 			message->AddString("format", diskSystem.PrettyName());
396 			BString label = diskSystem.PrettyName();
397 			label << B_UTF8_ELLIPSIS;
398 			fInitMenu->AddItem(new BMenuItem(label.String(), message));
399 		}
400 	}
401 }
402 
403 
404 // #pragma mark -
405 
406 
407 void
408 MainWindow::_AdaptToSelectedPartition()
409 {
410 	partition_id diskID = -1;
411 	partition_id partitionID = -1;
412 	partition_id parentID = -1;
413 
414 	BRow* _selectedRow = fListView->CurrentSelection();
415 	if (_selectedRow) {
416 		// go up to top level row
417 		BRow* _topLevelRow = _selectedRow;
418 		BRow* parent = NULL;
419 		while (fListView->FindParent(_topLevelRow, &parent, NULL))
420 			_topLevelRow = parent;
421 
422 		PartitionListRow* topLevelRow
423 			= dynamic_cast<PartitionListRow*>(_topLevelRow);
424 		PartitionListRow* selectedRow
425 			= dynamic_cast<PartitionListRow*>(_selectedRow);
426 
427 		if (topLevelRow)
428 			diskID = topLevelRow->ID();
429 		if (selectedRow) {
430 			partitionID = selectedRow->ID();
431 			parentID = selectedRow->ParentID();
432 		}
433 	}
434 
435 	_SetToDiskAndPartition(diskID, partitionID, parentID);
436 }
437 
438 
439 void
440 MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition,
441 	partition_id parent)
442 {
443 	BDiskDevice* oldDisk = NULL;
444 	if (!fCurrentDisk || fCurrentDisk->ID() != disk) {
445 		oldDisk = fCurrentDisk;
446 		fCurrentDisk = NULL;
447 		if (disk >= 0) {
448 			BDiskDevice* newDisk = new BDiskDevice();
449 			status_t ret = newDisk->SetTo(disk);
450 			if (ret < B_OK) {
451 				printf("error switching disks: %s\n", strerror(ret));
452 				delete newDisk;
453 			} else
454 				fCurrentDisk = newDisk;
455 		}
456 	}
457 
458 	fCurrentPartitionID = partition;
459 
460 	fDiskView->SetDisk(fCurrentDisk, fCurrentPartitionID);
461 	_EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID, parent);
462 
463 	delete oldDisk;
464 }
465 
466 
467 void
468 MainWindow::_EnabledDisableMenuItems(BDiskDevice* disk,
469 	partition_id selectedPartition, partition_id parentID)
470 {
471 	// clean out Create menu
472 	while (BMenuItem* item = fCreateMenu->RemoveItem(0L))
473 		delete item;
474 
475 	if (!disk) {
476 		fFormatMI->SetEnabled(false);
477 		fEjectMI->SetEnabled(false);
478 		fSurfaceTestMI->SetEnabled(false);
479 
480 		fPartitionMenu->SetEnabled(false);
481 	} else {
482 //		fFormatMI->SetEnabled(true);
483 fFormatMI->SetEnabled(false);
484 		fEjectMI->SetEnabled(disk->IsRemovableMedia());
485 //		fSurfaceTestMI->SetEnabled(true);
486 fSurfaceTestMI->SetEnabled(false);
487 
488 		// Create menu and items
489 		fPartitionMenu->SetEnabled(true);
490 
491 		BPartition* parentPartition = NULL;
492 		if (selectedPartition <= -2)
493 			parentPartition = disk->FindDescendant(parentID);
494 
495 		if (parentPartition) {
496 disk->PrepareModifications();
497 			fCreateMenu->SetEnabled(true);
498 			BString supportedChildType;
499 			int32 cookie = 0;
500 			status_t ret;
501 			while ((ret = parentPartition->GetNextSupportedChildType(&cookie,
502 				&supportedChildType)) == B_OK) {
503 				BMessage* message = new BMessage(MSG_CREATE);
504 				message->AddInt32("parent id", parentID);
505 				message->AddInt32("space id", selectedPartition);
506 				message->AddString("type", supportedChildType);
507 				BMenuItem* item = new BMenuItem(supportedChildType.String(),
508 					message);
509 				fCreateMenu->AddItem(item);
510 			}
511 			if (fCreateMenu->CountItems() == 0)
512 				fprintf(stderr, "Failed to get supported child types: %s\n",
513 					strerror(ret));
514 disk->CancelModifications();
515 		} else {
516 			fCreateMenu->SetEnabled(false);
517 		}
518 
519 		// Mount items
520 		BPartition* partition = disk->FindDescendant(selectedPartition);
521 		if (partition) {
522 			fInitMenu->SetEnabled(!partition->IsMounted());
523 //			fDeleteMI->SetEnabled(!partition->IsMounted());
524 fDeleteMI->SetEnabled(false);
525 			fMountMI->SetEnabled(!partition->IsMounted());
526 
527 			bool unMountable = false;
528 			if (partition->IsMounted()) {
529 				// see if this partition is the boot volume
530 				BVolume volume;
531 				BVolume bootVolume;
532 				if (BVolumeRoster().GetBootVolume(&bootVolume) == B_OK
533 					&& partition->GetVolume(&volume) == B_OK) {
534 					unMountable = volume != bootVolume;
535 				} else
536 					unMountable = true;
537 			}
538 			fUnmountMI->SetEnabled(unMountable);
539 		} else {
540 			fInitMenu->SetEnabled(false);
541 			fDeleteMI->SetEnabled(false);
542 			fMountMI->SetEnabled(false);
543 			fUnmountMI->SetEnabled(false);
544 		}
545 		fMountAllMI->SetEnabled(true);
546 	}
547 }
548 
549 
550 void
551 MainWindow::_DisplayPartitionError(BString _message,
552 	const BPartition* partition, status_t error) const
553 {
554 	char message[1024];
555 
556 	if (partition && _message.FindFirst("%s") >= 0) {
557 		BString name;
558 		name << " \"" << partition->ContentName() << "\"";
559 		sprintf(message, _message.String(), name.String());
560 	} else {
561 		_message.ReplaceAll("%s", "");
562 		sprintf(message, _message.String());
563 	}
564 
565 	if (error < B_OK) {
566 		BString helper = message;
567 		sprintf(message, "%s\n\nError: %s", helper.String(), strerror(error));
568 	}
569 
570 	BAlert* alert = new BAlert("error", message, "Ok", NULL, NULL,
571 		B_WIDTH_FROM_WIDEST, error < B_OK ? B_STOP_ALERT : B_INFO_ALERT);
572 	alert->Go(NULL);
573 }
574 
575 
576 // #pragma mark -
577 
578 
579 void
580 MainWindow::_Mount(BDiskDevice* disk, partition_id selectedPartition)
581 {
582 	if (!disk || selectedPartition < 0) {
583 		_DisplayPartitionError("You need to select a partition "
584 			"entry from the list.");
585 		return;
586 	}
587 
588 	BPartition* partition = disk->FindDescendant(selectedPartition);
589 	if (!partition) {
590 		_DisplayPartitionError("Unable to find the selected partition by id.");
591 		return;
592 	}
593 
594 	if (!partition->IsMounted()) {
595 		status_t ret = partition->Mount();
596 		if (ret < B_OK) {
597 			_DisplayPartitionError("Could not mount partition %s.",
598 				partition, ret);
599 		} else {
600 			// successful mount, adapt to the changes
601 			_ScanDrives();
602 		}
603 	} else {
604 		_DisplayPartitionError("The partition %s is already mounted.",
605 			partition);
606 	}
607 }
608 
609 
610 void
611 MainWindow::_Unmount(BDiskDevice* disk, partition_id selectedPartition)
612 {
613 	if (!disk || selectedPartition < 0) {
614 		_DisplayPartitionError("You need to select a partition "
615 			"entry from the list.");
616 		return;
617 	}
618 
619 	BPartition* partition = disk->FindDescendant(selectedPartition);
620 	if (!partition) {
621 		_DisplayPartitionError("Unable to find the selected partition by id.");
622 		return;
623 	}
624 
625 	if (partition->IsMounted()) {
626 		status_t ret = partition->Unmount();
627 		if (ret < B_OK) {
628 			_DisplayPartitionError("Could not unmount partition %s.",
629 				partition, ret);
630 		} else {
631 			// successful unmount, adapt to the changes
632 			_ScanDrives();
633 		}
634 	} else {
635 		_DisplayPartitionError("The partition %s is already unmounted.",
636 			partition);
637 	}
638 }
639 
640 
641 void
642 MainWindow::_MountAll()
643 {
644 	MountAllVisitor visitor;
645 	fDDRoster.VisitEachPartition(&visitor);
646 }
647 
648 
649 // #pragma mark -
650 
651 
652 void
653 MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition,
654 	const BString& diskSystemName)
655 {
656 	if (!disk || selectedPartition < 0) {
657 		_DisplayPartitionError("You need to select a partition "
658 			"entry from the list.");
659 		return;
660 	}
661 
662 	if (disk->IsReadOnly()) {
663 		_DisplayPartitionError("The selected disk is read-only.");
664 		return;
665 	}
666 
667 	BPartition* partition = disk->FindDescendant(selectedPartition);
668 	if (!partition) {
669 		_DisplayPartitionError("Unable to find the selected partition by id.");
670 		return;
671 	}
672 
673 	if (partition->IsMounted()) {
674 		_DisplayPartitionError("The partition %s is currently mounted.");
675 		// TODO: option to unmount and continue on success to unmount
676 		return;
677 	}
678 
679 	BString message("Are you sure you want to initialize the partition ");
680 	message << "\"" << partition->ContentName();
681 	message << "\"? After entering the initialization parameters, ";
682 	message << "you can abort this operation right before writing ";
683 	message << "changes back to the disk.";
684 	BAlert* alert = new BAlert("first notice", message.String(),
685 		"Continue", "Cancel", NULL, B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
686 	int32 choice = alert->Go();
687 
688 	if (choice == 1)
689 		return;
690 
691 	BDiskSystem diskSystem;
692 	fDDRoster.RewindDiskSystems();
693 	bool found = false;
694 	while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) {
695 		if (diskSystem.IsFileSystem() && diskSystem.SupportsInitializing()) {
696 			if (diskSystemName == diskSystem.PrettyName()) {
697 				found = true;
698 				break;
699 			}
700 		}
701 	}
702 
703 	if (!found) {
704 		BString message("Disk system \"");
705 		message << diskSystemName << "\" not found!";
706 		_DisplayPartitionError(message);
707 		return;
708 	}
709 
710 
711 	// allow BFS only, since our parameter string
712 	// construction only handles BFS at the moment
713 	if (diskSystemName != "Be File System") {
714 		_DisplayPartitionError("Don't know how to construct parameters "
715 			"for this file system.");
716 		return;
717 	}
718 
719 	status_t ret = disk->PrepareModifications();
720 	if (ret != B_OK) {
721 		_DisplayPartitionError("There was an error preparing the "
722 			"disk for modifications.", NULL, ret);
723 		return;
724 	}
725 
726 	// TODO: use partition initialization editor
727 	// (partition->GetInitializationParameterEditor())
728 
729 	BString name = "Haiku";
730 	BString parameters;
731 	InitParamsPanel* panel = new InitParamsPanel(this);
732 	panel->Go(name, parameters);
733 
734 	bool supportsName = diskSystem.SupportsContentName();
735 	BString validatedName(name);
736 	ret = partition->ValidateInitialize(diskSystem.PrettyName(),
737 		supportsName ? &validatedName : NULL, parameters.String());
738 	if (ret != B_OK) {
739 		_DisplayPartitionError("Validation of the given initialization "
740 			"parameters failed.", partition, ret);
741 		return;
742 	}
743 
744 	BString previousName = partition->ContentName();
745 
746 	ret = partition->Initialize(diskSystem.PrettyName(),
747 		supportsName ? name.String() : NULL, parameters.String());
748 	if (ret != B_OK) {
749 		_DisplayPartitionError("Initialization of the partition %s "
750 			"failed. (Nothing has been written to disk.)", partition, ret);
751 		return;
752 	}
753 
754 	// everything looks fine, we are ready to actually write the changes
755 	// to disk
756 
757 	message = "Are you sure you want to write the changes back to "
758 		"disk now?\n\n";
759 	message << "All data on the partition \"" << previousName;
760 	message << "\" will be irrevertably lost if you do so!";
761 	alert = new BAlert("final notice", message.String(),
762 		"Write Changes", "Cancel", NULL, B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
763 	choice = alert->Go();
764 
765 	if (choice == 1)
766 		return;
767 
768 	// commit
769 	ret = disk->CommitModifications();
770 	if (ret == B_OK) {
771 		_DisplayPartitionError("The partition %s has been successfully "
772 			"initialized.\n", partition);
773 	} else {
774 		_DisplayPartitionError("Failed to initialize the partition "
775 			"%s!\n", partition, ret);
776 	}
777 
778 	_ScanDrives();
779 }
780 
781