Files
haiku-beta6/src/apps/drivesetup/MainWindow.cpp
T
Bryce Groff 2f3ce2bf7e DriveSetup:
- File system is now only displayed when the partition actually has a filesystem.
- Now checks if the DiskSystem supports initializing.
- Updated the *ParamsPanels, as well as, the Disk System add-ons to use the new storage api changes (see below).

Storage Kit:
- Simplified the parameters editor system. Now all parameter editor requests go through a single function, GetParameterEditor, and pass a B_PARAMETER_EDITOR_TYPE to request a particular parameter editor.
- Moved DiskDeviceAddOnManager.h to the headers directory, as it is now required by InitParamsPanel.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@39115 a95241bf-73f2-0310-859d-f6bbb57e9c96
2010-10-24 03:39:19 +00:00

1116 lines
28 KiB
C++

/*
* Copyright 2002-2010 Haiku Inc. All rights reserved.
* Distributed under the terms of the MIT license.
*
* Authors:
* Erik Jaesler <[email protected]>
* Ithamar R. Adema <[email protected]>
* Ingo Weinhold <[email protected]>
* Stephan Aßmus <[email protected]>
*/
#include "MainWindow.h"
#include <stdio.h>
#include <string.h>
#include <Alert.h>
#include <Application.h>
#include <Catalog.h>
#include <ColumnListView.h>
#include <ColumnTypes.h>
#include <Debug.h>
#include <DiskDevice.h>
#include <DiskDeviceVisitor.h>
#include <DiskDeviceTypes.h>
#include <DiskSystem.h>
#include <Locale.h>
#include <MenuItem.h>
#include <MenuBar.h>
#include <Menu.h>
#include <Path.h>
#include <Partition.h>
#include <PartitioningInfo.h>
#include <Roster.h>
#include <Screen.h>
#include <Volume.h>
#include <VolumeRoster.h>
#include "CreateParamsPanel.h"
#include "DiskView.h"
#include "InitParamsPanel.h"
#include "PartitionList.h"
#include "Support.h"
#include "tracker_private.h"
#undef B_TRANSLATE_CONTEXT
#define B_TRANSLATE_CONTEXT "MainWindow"
class ListPopulatorVisitor : public BDiskDeviceVisitor {
public:
ListPopulatorVisitor(PartitionListView* list, int32& diskCount,
SpaceIDMap& spaceIDMap)
:
fPartitionList(list),
fDiskCount(diskCount),
fSpaceIDMap(spaceIDMap)
{
fDiskCount = 0;
fSpaceIDMap.Clear();
// start with an empty list
int32 rows = fPartitionList->CountRows();
for (int32 i = rows - 1; i >= 0; i--) {
BRow* row = fPartitionList->RowAt(i);
fPartitionList->RemoveRow(row);
delete row;
}
}
virtual bool Visit(BDiskDevice* device)
{
fDiskCount++;
// if we don't prepare the device for modifications,
// we cannot get information about available empty
// regions on the device or child partitions
device->PrepareModifications();
_AddPartition(device);
return false; // Don't stop yet!
}
virtual bool Visit(BPartition* partition, int32 level)
{
_AddPartition(partition);
return false; // Don't stop yet!
}
private:
void _AddPartition(BPartition* partition) const
{
// add the partition itself
fPartitionList->AddPartition(partition);
// add any available space on it
BPartitioningInfo info;
status_t ret = partition->GetPartitioningInfo(&info);
if (ret >= B_OK) {
partition_id parentID = partition->ID();
off_t offset;
off_t size;
for (int32 i = 0;
info.GetPartitionableSpaceAt(i, &offset, &size) >= B_OK;
i++) {
// TODO: remove again once Disk Device API is fixed
if (!is_valid_partitionable_space(size))
continue;
//
partition_id id = fSpaceIDMap.SpaceIDFor(parentID, offset);
fPartitionList->AddSpace(parentID, id, offset, size);
}
}
}
PartitionListView* fPartitionList;
int32& fDiskCount;
SpaceIDMap& fSpaceIDMap;
BDiskDevice* fLastPreparedDevice;
};
class MountAllVisitor : public BDiskDeviceVisitor {
public:
MountAllVisitor()
{
}
virtual bool Visit(BDiskDevice* device)
{
return false; // Don't stop yet!
}
virtual bool Visit(BPartition* partition, int32 level)
{
partition->Mount();
return false; // Don't stop yet!
}
private:
PartitionListView* fPartitionList;
};
enum {
MSG_MOUNT_ALL = 'mnta',
MSG_MOUNT = 'mnts',
MSG_UNMOUNT = 'unmt',
MSG_FORMAT = 'frmt',
MSG_CREATE = 'crtp',
MSG_INITIALIZE = 'init',
MSG_DELETE = 'delt',
MSG_EJECT = 'ejct',
MSG_SURFACE_TEST = 'sfct',
MSG_RESCAN = 'rscn',
MSG_PARTITION_ROW_SELECTED = 'prsl',
};
// #pragma mark -
MainWindow::MainWindow(BRect frame)
: BWindow(frame, B_TRANSLATE("DriveSetup"), B_DOCUMENT_WINDOW,
B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE),
fCurrentDisk(NULL),
fCurrentPartitionID(-1),
fSpaceIDMap()
{
BMenuBar* menuBar = new BMenuBar(Bounds(), "root menu");
// create all the menu items
fFormatMI = new BMenuItem(B_TRANSLATE("Format (not implemented)"),
new BMessage(MSG_FORMAT));
fEjectMI = new BMenuItem(B_TRANSLATE("Eject"),
new BMessage(MSG_EJECT), 'E');
fSurfaceTestMI = new BMenuItem(
B_TRANSLATE("Surface test (not implemented)"),
new BMessage(MSG_SURFACE_TEST));
fRescanMI = new BMenuItem(B_TRANSLATE("Rescan"), new BMessage(MSG_RESCAN));
fCreateMI = new BMenuItem(B_TRANSLATE("Create" B_UTF8_ELLIPSIS),
new BMessage(MSG_CREATE), 'C');
fDeleteMI = new BMenuItem(B_TRANSLATE("Delete"),
new BMessage(MSG_DELETE), 'D');
fMountMI = new BMenuItem(B_TRANSLATE("Mount"),
new BMessage(MSG_MOUNT), 'M');
fUnmountMI = new BMenuItem(B_TRANSLATE("Unmount"),
new BMessage(MSG_UNMOUNT), 'U');
fMountAllMI = new BMenuItem(B_TRANSLATE("Mount all"),
new BMessage(MSG_MOUNT_ALL), 'M', B_SHIFT_KEY);
// Disk menu
fDiskMenu = new BMenu(B_TRANSLATE("Disk"));
fDiskMenu->AddItem(fFormatMI);
fDiskMenu->AddItem(fEjectMI);
fDiskMenu->AddItem(fSurfaceTestMI);
fDiskMenu->AddSeparatorItem();
fDiskMenu->AddItem(fRescanMI);
menuBar->AddItem(fDiskMenu);
// Parition menu
fPartitionMenu = new BMenu(B_TRANSLATE("Partition"));
fPartitionMenu->AddItem(fCreateMI);
fInitMenu = new BMenu(B_TRANSLATE("Initialize"));
fPartitionMenu->AddItem(fInitMenu);
fPartitionMenu->AddItem(fDeleteMI);
fPartitionMenu->AddSeparatorItem();
fPartitionMenu->AddItem(fMountMI);
fPartitionMenu->AddItem(fUnmountMI);
fPartitionMenu->AddSeparatorItem();
fPartitionMenu->AddItem(fMountAllMI);
menuBar->AddItem(fPartitionMenu);
AddChild(menuBar);
// add DiskView
BRect r(Bounds());
r.top = menuBar->Frame().bottom + 1;
r.bottom = floorf(r.top + r.Height() * 0.33);
fDiskView = new DiskView(r, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP,
fSpaceIDMap);
AddChild(fDiskView);
// add PartitionListView
r.top = r.bottom + 2;
r.bottom = Bounds().bottom;
r.InsetBy(-1, -1);
fListView = new PartitionListView(r, B_FOLLOW_ALL);
AddChild(fListView);
// configure PartitionListView
fListView->SetSelectionMode(B_SINGLE_SELECTION_LIST);
fListView->SetSelectionMessage(new BMessage(MSG_PARTITION_ROW_SELECTED));
fListView->SetTarget(this);
status_t ret = fDDRoster.StartWatching(BMessenger(this));
if (ret != B_OK) {
fprintf(stderr, "Failed to start watching for device changes: %s\n",
strerror(ret));
}
// visit all disks in the system and show their contents
_ScanDrives();
if (!be_roster->IsRunning(kDeskbarSignature))
SetFlags(Flags() | B_NOT_MINIMIZABLE);
}
MainWindow::~MainWindow()
{
BDiskDeviceRoster().StopWatching(this);
delete fCurrentDisk;
}
void
MainWindow::MessageReceived(BMessage* message)
{
switch (message->what) {
case MSG_MOUNT_ALL:
_MountAll();
break;
case MSG_MOUNT:
_Mount(fCurrentDisk, fCurrentPartitionID);
break;
case MSG_UNMOUNT:
_Unmount(fCurrentDisk, fCurrentPartitionID);
break;
case MSG_FORMAT:
printf("MSG_FORMAT\n");
break;
case MSG_CREATE: {
_Create(fCurrentDisk, fCurrentPartitionID);
break;
}
case MSG_INITIALIZE: {
BString diskSystemName;
if (message->FindString("disk system", &diskSystemName) != B_OK)
break;
_Initialize(fCurrentDisk, fCurrentPartitionID, diskSystemName);
break;
}
case MSG_DELETE:
_Delete(fCurrentDisk, fCurrentPartitionID);
break;
case MSG_EJECT:
// TODO: completely untested, especially interesting
// if partition list behaves when partitions disappear
if (fCurrentDisk) {
// TODO: only if no partitions are mounted anymore?
fCurrentDisk->Eject(true);
_ScanDrives();
}
break;
case MSG_SURFACE_TEST:
printf("MSG_SURFACE_TEST\n");
break;
// TODO: this could probably be done better!
case B_DEVICE_UPDATE:
printf("B_DEVICE_UPDATE\n");
case MSG_RESCAN:
_ScanDrives();
break;
case MSG_PARTITION_ROW_SELECTED:
// selection of partitions via list view
_AdaptToSelectedPartition();
break;
case MSG_SELECTED_PARTITION_ID: {
// selection of partitions via disk view
partition_id id;
if (message->FindInt32("partition_id", &id) == B_OK) {
if (BRow* row = fListView->FindRow(id)) {
fListView->DeselectAll();
fListView->AddToSelection(row);
_AdaptToSelectedPartition();
}
}
break;
}
default:
BWindow::MessageReceived(message);
break;
}
}
bool
MainWindow::QuitRequested()
{
// TODO: ask about any unsaved changes
be_app->PostMessage(B_QUIT_REQUESTED);
Hide();
return false;
}
// #pragma mark -
status_t
MainWindow::StoreSettings(BMessage* archive) const
{
if (archive->ReplaceRect("window frame", Frame()) < B_OK)
archive->AddRect("window frame", Frame());
BMessage columnSettings;
fListView->SaveState(&columnSettings);
if (archive->ReplaceMessage("column settings", &columnSettings) < B_OK)
archive->AddMessage("column settings", &columnSettings);
return B_OK;
}
status_t
MainWindow::RestoreSettings(BMessage* archive)
{
BRect frame;
if (archive->FindRect("window frame", &frame) == B_OK) {
BScreen screen(this);
if (frame.Intersects(screen.Frame())) {
MoveTo(frame.LeftTop());
ResizeTo(frame.Width(), frame.Height());
}
}
BMessage columnSettings;
if (archive->FindMessage("column settings", &columnSettings) == B_OK)
fListView->LoadState(&columnSettings);
return B_OK;
}
void
MainWindow::ApplyDefaultSettings()
{
if (!Lock())
return;
fListView->ResizeAllColumnsToPreferred();
// Adjust window size for convenience
float enlargeBy = fListView->PreferredSize().width
- fListView->Bounds().Width();
if (enlargeBy > 0.0f) {
BScreen screen(this);
float windowWidth = Frame().Width() + enlargeBy;
if (windowWidth > screen.Frame().Width() - 20.0f)
windowWidth = screen.Frame().Width() - 20.0f;
ResizeTo(windowWidth, Frame().Height());
}
CenterOnScreen();
Unlock();
}
// #pragma mark -
void
MainWindow::_ScanDrives()
{
fSpaceIDMap.Clear();
int32 diskCount = 0;
ListPopulatorVisitor driveVisitor(fListView, diskCount, fSpaceIDMap);
fDDRoster.VisitEachPartition(&driveVisitor);
fDiskView->SetDiskCount(diskCount);
// restore selection
PartitionListRow* previousSelection
= fListView->FindRow(fCurrentPartitionID);
if (previousSelection) {
fListView->AddToSelection(previousSelection);
_UpdateMenus(fCurrentDisk, fCurrentPartitionID,
previousSelection->ParentID());
fDiskView->ForceUpdate();
} else {
_UpdateMenus(NULL, -1, -1);
}
}
// #pragma mark -
void
MainWindow::_AdaptToSelectedPartition()
{
partition_id diskID = -1;
partition_id partitionID = -1;
partition_id parentID = -1;
BRow* _selectedRow = fListView->CurrentSelection();
if (_selectedRow) {
// go up to top level row
BRow* _topLevelRow = _selectedRow;
BRow* parent = NULL;
while (fListView->FindParent(_topLevelRow, &parent, NULL))
_topLevelRow = parent;
PartitionListRow* topLevelRow
= dynamic_cast<PartitionListRow*>(_topLevelRow);
PartitionListRow* selectedRow
= dynamic_cast<PartitionListRow*>(_selectedRow);
if (topLevelRow)
diskID = topLevelRow->ID();
if (selectedRow) {
partitionID = selectedRow->ID();
parentID = selectedRow->ParentID();
}
}
_SetToDiskAndPartition(diskID, partitionID, parentID);
}
void
MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition,
partition_id parent)
{
//printf("MainWindow::_SetToDiskAndPartition(disk: %ld, partition: %ld, "
// "parent: %ld)\n", disk, partition, parent);
BDiskDevice* oldDisk = NULL;
if (!fCurrentDisk || fCurrentDisk->ID() != disk) {
oldDisk = fCurrentDisk;
fCurrentDisk = NULL;
if (disk >= 0) {
BDiskDevice* newDisk = new BDiskDevice();
status_t ret = newDisk->SetTo(disk);
if (ret < B_OK) {
printf("error switching disks: %s\n", strerror(ret));
delete newDisk;
} else
fCurrentDisk = newDisk;
}
}
fCurrentPartitionID = partition;
fDiskView->SetDisk(fCurrentDisk, fCurrentPartitionID);
_UpdateMenus(fCurrentDisk, fCurrentPartitionID, parent);
delete oldDisk;
}
void
MainWindow::_UpdateMenus(BDiskDevice* disk,
partition_id selectedPartition, partition_id parentID)
{
while (BMenuItem* item = fInitMenu->RemoveItem(0L))
delete item;
if (!disk) {
fFormatMI->SetEnabled(false);
fEjectMI->SetEnabled(false);
fSurfaceTestMI->SetEnabled(false);
fPartitionMenu->SetEnabled(false);
} else {
// fFormatMI->SetEnabled(true);
fFormatMI->SetEnabled(false);
fEjectMI->SetEnabled(disk->IsRemovableMedia());
// fSurfaceTestMI->SetEnabled(true);
fSurfaceTestMI->SetEnabled(false);
fCreateMI->SetEnabled(false);
// Create menu and items
fPartitionMenu->SetEnabled(true);
BPartition* parentPartition = NULL;
if (selectedPartition <= -2)
parentPartition = disk->FindDescendant(parentID);
if (parentPartition && parentPartition->ContainsPartitioningSystem())
fCreateMI->SetEnabled(true);
bool prepared = disk->PrepareModifications() == B_OK;
fInitMenu->SetEnabled(prepared);
fDeleteMI->SetEnabled(prepared);
BPartition* partition = disk->FindDescendant(selectedPartition);
if (partition == NULL)
partition = disk;
BDiskSystem diskSystem;
fDDRoster.RewindDiskSystems();
while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) {
if (!diskSystem.SupportsInitializing())
continue;
if (disk->ID() != selectedPartition
&& disk->ContainsPartitioningSystem()
&& !diskSystem.IsFileSystem()) {
// Do not confuse the user with nested partition maps?
continue;
}
BMessage* message = new BMessage(MSG_INITIALIZE);
message->AddInt32("parent id", parentID);
message->AddString("disk system", diskSystem.PrettyName());
BString label = diskSystem.PrettyName();
label << B_UTF8_ELLIPSIS;
BMenuItem* item = new BMenuItem(label.String(), message);
// TODO: Very unintuitive that we have to use the pretty name here!
// item->SetEnabled(partition->CanInitialize(diskSystem.Name()));
item->SetEnabled(partition->CanInitialize(diskSystem.PrettyName()));
fInitMenu->AddItem(item);
}
// Mount items
if (partition) {
BDiskSystem partitionDiskSystem;
partition->GetDiskSystem(&partitionDiskSystem);
fInitMenu->SetEnabled(!partition->IsMounted()
&& !partition->IsReadOnly()
&& partition->Device()->HasMedia()
// Check if the current disk system allows initialzation.
&& partition->CanInitialize(partitionDiskSystem.PrettyName()));
fDeleteMI->SetEnabled(!partition->IsMounted()
&& !partition->IsDevice());
fMountMI->SetEnabled(!partition->IsMounted());
bool unMountable = false;
if (partition->IsMounted()) {
// see if this partition is the boot volume
BVolume volume;
BVolume bootVolume;
if (BVolumeRoster().GetBootVolume(&bootVolume) == B_OK
&& partition->GetVolume(&volume) == B_OK) {
unMountable = volume != bootVolume;
} else
unMountable = true;
}
fUnmountMI->SetEnabled(unMountable);
} else {
fInitMenu->SetEnabled(false);
fDeleteMI->SetEnabled(false);
fMountMI->SetEnabled(false);
fUnmountMI->SetEnabled(false);
}
if (prepared)
disk->CancelModifications();
fMountAllMI->SetEnabled(true);
}
if (selectedPartition < 0) {
fDeleteMI->SetEnabled(false);
fMountMI->SetEnabled(false);
}
}
void
MainWindow::_DisplayPartitionError(BString _message,
const BPartition* partition, status_t error) const
{
char message[1024];
if (partition && _message.FindFirst("%s") >= 0) {
BString name;
name << "\"" << partition->ContentName() << "\"";
snprintf(message, sizeof(message), _message.String(), name.String());
} else {
_message.ReplaceAll("%s", "");
snprintf(message, sizeof(message), _message.String());
}
if (error < B_OK) {
BString helper = message;
const char* errorString =
B_TRANSLATE_COMMENT("Error: ", "in any error alert");
snprintf(message, sizeof(message), "%s\n\n%s%s", helper.String(),
errorString, strerror(error));
}
BAlert* alert = new BAlert("error", message, B_TRANSLATE("OK"), NULL, NULL,
B_WIDTH_FROM_WIDEST, error < B_OK ? B_STOP_ALERT : B_INFO_ALERT);
alert->Go(NULL);
}
// #pragma mark -
void
MainWindow::_Mount(BDiskDevice* disk, partition_id selectedPartition)
{
if (!disk || selectedPartition < 0) {
_DisplayPartitionError(B_TRANSLATE("You need to select a partition "
"entry from the list."));
return;
}
BPartition* partition = disk->FindDescendant(selectedPartition);
if (!partition) {
_DisplayPartitionError(B_TRANSLATE("Unable to find the selected "
"partition by ID."));
return;
}
if (!partition->IsMounted()) {
status_t ret = partition->Mount();
if (ret < B_OK) {
_DisplayPartitionError(
B_TRANSLATE("Could not mount partition %s."), partition, ret);
} else {
// successful mount, adapt to the changes
_ScanDrives();
}
} else {
_DisplayPartitionError(
B_TRANSLATE("The partition %s is already mounted."), partition);
}
}
void
MainWindow::_Unmount(BDiskDevice* disk, partition_id selectedPartition)
{
if (!disk || selectedPartition < 0) {
_DisplayPartitionError(B_TRANSLATE("You need to select a partition "
"entry from the list."));
return;
}
BPartition* partition = disk->FindDescendant(selectedPartition);
if (!partition) {
_DisplayPartitionError(B_TRANSLATE("Unable to find the selected "
"partition by ID."));
return;
}
if (partition->IsMounted()) {
BPath path;
partition->GetMountPoint(&path);
status_t ret = partition->Unmount();
if (ret < B_OK) {
_DisplayPartitionError(
B_TRANSLATE("Could not unmount partition %s."),
partition, ret);
} else {
if (dev_for_path(path.Path()) == dev_for_path("/"))
rmdir(path.Path());
// successful unmount, adapt to the changes
_ScanDrives();
}
} else {
_DisplayPartitionError(
B_TRANSLATE("The partition %s is already unmounted."),
partition);
}
}
void
MainWindow::_MountAll()
{
MountAllVisitor visitor;
fDDRoster.VisitEachPartition(&visitor);
}
// #pragma mark -
class ModificationPreparer {
public:
ModificationPreparer(BDiskDevice* disk)
:
fDisk(disk),
fModificationStatus(fDisk->PrepareModifications())
{
}
~ModificationPreparer()
{
if (fModificationStatus == B_OK)
fDisk->CancelModifications();
}
status_t ModificationStatus() const
{
return fModificationStatus;
}
status_t CommitModifications()
{
status_t ret = fDisk->CommitModifications();
if (ret == B_OK)
fModificationStatus = B_ERROR;
return ret;
}
private:
BDiskDevice* fDisk;
status_t fModificationStatus;
};
void
MainWindow::_Initialize(BDiskDevice* disk, partition_id selectedPartition,
const BString& diskSystemName)
{
if (!disk || selectedPartition < 0) {
_DisplayPartitionError(B_TRANSLATE("You need to select a partition "
"entry from the list."));
return;
}
if (disk->IsReadOnly()) {
_DisplayPartitionError(B_TRANSLATE("The selected disk is read-only."));
return;
}
BPartition* partition = disk->FindDescendant(selectedPartition);
if (!partition) {
_DisplayPartitionError(B_TRANSLATE("Unable to find the selected "
"partition by ID."));
return;
}
if (partition->IsMounted()) {
_DisplayPartitionError(
B_TRANSLATE("The partition %s is currently mounted."));
// TODO: option to unmount and continue on success to unmount
return;
}
char message[512];
if (partition->ContentName() && strlen(partition->ContentName()) > 0) {
snprintf(message, sizeof(message), B_TRANSLATE("Are you sure you want "
"to initialize the partition \"%s\"? You will be asked again "
"before changes are written to the disk."),
partition->ContentName());
} else {
snprintf(message, sizeof(message), B_TRANSLATE("Are you sure you want "
"to initialize the partition? You will be asked again "
"before changes are written to the disk."));
}
BAlert* alert = new BAlert("first notice", message,
B_TRANSLATE("Continue"), B_TRANSLATE("Cancel"), NULL,
B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
int32 choice = alert->Go();
if (choice == 1)
return;
BDiskSystem diskSystem;
fDDRoster.RewindDiskSystems();
bool found = false;
while (fDDRoster.GetNextDiskSystem(&diskSystem) == B_OK) {
if (diskSystem.SupportsInitializing()) {
if (diskSystemName == diskSystem.PrettyName()) {
found = true;
break;
}
}
}
if (!found) {
snprintf(message, sizeof(message), B_TRANSLATE("Disk system \"%s\"\" "
"not found!"));
_DisplayPartitionError(message);
return;
}
ModificationPreparer modificationPreparer(disk);
status_t ret = modificationPreparer.ModificationStatus();
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("There was an error preparing the "
"disk for modifications."), NULL, ret);
return;
}
BString name;
BString parameters;
if (diskSystemName == "Be File System") {
InitParamsPanel* panel = new InitParamsPanel(this, diskSystemName,
partition);
if (panel->Go(name, parameters) == GO_CANCELED)
return;
} else if (diskSystemName == "Intel Partition Map") {
// TODO: parameters?
} else if (diskSystemName == "Intel Extended Partition") {
// TODO: parameters?
}
bool supportsName = diskSystem.SupportsContentName();
BString validatedName(name);
ret = partition->ValidateInitialize(diskSystem.PrettyName(),
supportsName ? &validatedName : NULL, parameters.String());
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("Validation of the given "
"initialization parameters failed."), partition, ret);
return;
}
BString previousName = partition->ContentName();
ret = partition->Initialize(diskSystem.PrettyName(),
supportsName ? validatedName.String() : NULL, parameters.String());
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("Initialization of the partition "
"%s failed. (Nothing has been written to disk.)"), partition, ret);
return;
}
// everything looks fine, we are ready to actually write the changes
// to disk
// Warn the user one more time...
if (previousName.Length() > 0) {
if (partition->IsDevice()) {
snprintf(message, sizeof(message), B_TRANSLATE("Are you sure you "
"want to write the changes back to disk now?\n\n"
"All data on the disk %s will be irretrievably lost if you "
"do so!"), previousName.String());
} else {
snprintf(message, sizeof(message), B_TRANSLATE("Are you sure you "
"want to write the changes back to disk now?\n\n"
"All data on the partition %s will be irretrievably lost if you "
"do so!"), previousName.String());
}
} else {
if (partition->IsDevice()) {
snprintf(message, sizeof(message), B_TRANSLATE("Are you sure you "
"want to write the changes back to disk now?\n\n"
"All data on the selected disk will be irretrievably lost if "
"you do so!"));
} else {
snprintf(message, sizeof(message), B_TRANSLATE("Are you sure you "
"want to write the changes back to disk now?\n\n"
"All data on the selected partition will be irretrievably lost "
"if you do so!"));
}
}
alert = new BAlert("final notice", message,
B_TRANSLATE("Write changes"), B_TRANSLATE("Cancel"), NULL,
B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
choice = alert->Go();
if (choice == 1)
return;
// commit
ret = modificationPreparer.CommitModifications();
// The partition pointer is toast now! Use the partition ID to
// retrieve it again.
partition = disk->FindDescendant(selectedPartition);
if (ret == B_OK) {
_DisplayPartitionError(B_TRANSLATE("The partition %s has been "
"successfully initialized.\n"), partition);
} else {
_DisplayPartitionError(B_TRANSLATE("Failed to initialize the "
"partition %s!\n"), partition, ret);
}
_ScanDrives();
}
void
MainWindow::_Create(BDiskDevice* disk, partition_id selectedPartition)
{
if (!disk || selectedPartition > -2) {
_DisplayPartitionError(B_TRANSLATE("The currently selected partition "
"is not empty."));
return;
}
if (disk->IsReadOnly()) {
_DisplayPartitionError(B_TRANSLATE("The selected disk is read-only."));
return;
}
PartitionListRow* currentSelection = dynamic_cast<PartitionListRow*>(
fListView->CurrentSelection());
if (!currentSelection) {
_DisplayPartitionError(B_TRANSLATE("There was an error acquiring the "
"partition row."));
return;
}
BPartition* parent = disk->FindDescendant(currentSelection->ParentID());
if (!parent) {
_DisplayPartitionError(B_TRANSLATE("The currently selected partition "
"does not have a parent partition."));
return;
}
if (!parent->ContainsPartitioningSystem()) {
_DisplayPartitionError(B_TRANSLATE("The selected partition does not "
"contain a partitioning system."));
return;
}
ModificationPreparer modificationPreparer(disk);
status_t ret = modificationPreparer.ModificationStatus();
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("There was an error preparing the "
"disk for modifications."), NULL, ret);
return;
}
// get partitioning info
BPartitioningInfo partitioningInfo;
status_t error = parent->GetPartitioningInfo(&partitioningInfo);
if (error != B_OK) {
_DisplayPartitionError(B_TRANSLATE("Could not aquire partitioning "
"information."));
return;
}
int32 spacesCount = partitioningInfo.CountPartitionableSpaces();
if (spacesCount == 0) {
_DisplayPartitionError(B_TRANSLATE("There's no space on the partition "
"where a child partition could be created."));
return;
}
BString name, type, parameters;
off_t offset = currentSelection->Offset();
off_t size = currentSelection->Size();
CreateParamsPanel* panel = new CreateParamsPanel(this, parent, offset,
size);
if (panel->Go(offset, size, name, type, parameters) == GO_CANCELED)
return;
ret = parent->ValidateCreateChild(&offset, &size, type.String(),
&name, parameters.String());
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("Validation of the given creation "
"parameters failed."));
return;
}
// Warn the user one more time...
BAlert* alert = new BAlert("final notice", B_TRANSLATE("Are you sure you "
"want to write the changes back to disk now?\n\n"
"All data on the partition will be irretrievably lost if you do "
"so!"), B_TRANSLATE("Write changes"), B_TRANSLATE("Cancel"), NULL,
B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
int32 choice = alert->Go();
if (choice == 1)
return;
ret = parent->CreateChild(offset, size, type.String(),
name.String(), parameters.String());
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("Creation of the partition has "
"failed."));
return;
}
// commit
ret = modificationPreparer.CommitModifications();
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("Failed to initialize the "
"partition. No changes have been written to disk."));
return;
}
// The disk layout has changed, update disk information
bool updated;
ret = disk->Update(&updated);
_ScanDrives();
fDiskView->ForceUpdate();
}
void
MainWindow::_Delete(BDiskDevice* disk, partition_id selectedPartition)
{
if (!disk || selectedPartition < 0) {
_DisplayPartitionError(B_TRANSLATE("You need to select a partition "
"entry from the list."));
return;
}
if (disk->IsReadOnly()) {
_DisplayPartitionError(B_TRANSLATE("The selected disk is read-only."));
return;
}
BPartition* partition = disk->FindDescendant(selectedPartition);
if (!partition) {
_DisplayPartitionError(B_TRANSLATE("Unable to find the selected "
"partition by ID."));
return;
}
BPartition* parent = partition->Parent();
if (!parent) {
_DisplayPartitionError(B_TRANSLATE("The currently selected partition "
"does not have a parent partition."));
return;
}
ModificationPreparer modificationPreparer(disk);
status_t ret = modificationPreparer.ModificationStatus();
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("There was an error preparing the "
"disk for modifications."), NULL, ret);
return;
}
if (!parent->CanDeleteChild(partition->Index())) {
_DisplayPartitionError(
B_TRANSLATE("Cannot delete the selected partition."));
return;
}
// Warn the user one more time...
BAlert* alert = new BAlert("final notice", B_TRANSLATE("Are you sure you "
"want to delete the selected partition?\n\n"
"All data on the partition will be irretrievably lost if you "
"do so!"), B_TRANSLATE("Delete partition"), B_TRANSLATE("Cancel"), NULL,
B_WIDTH_FROM_WIDEST, B_WARNING_ALERT);
int32 choice = alert->Go();
if (choice == 1)
return;
ret = parent->DeleteChild(partition->Index());
if (ret != B_OK) {
_DisplayPartitionError(
B_TRANSLATE("Could not delete the selected partition."));
return;
}
ret = modificationPreparer.CommitModifications();
if (ret != B_OK) {
_DisplayPartitionError(B_TRANSLATE("Failed to delete the partition. "
"No changes have been written to disk."));
return;
}
_ScanDrives();
fDiskView->ForceUpdate();
}