diff --git a/src/apps/drivesetup/DiskView.cpp b/src/apps/drivesetup/DiskView.cpp index f9807bcf6e..4d38a4b3d6 100644 --- a/src/apps/drivesetup/DiskView.cpp +++ b/src/apps/drivesetup/DiskView.cpp @@ -183,10 +183,11 @@ private: class DiskView::PartitionLayout : public BDiskDeviceVisitor { public: - PartitionLayout(BView* view) + PartitionLayout(BView* view, SpaceIDMap& spaceIDMap) : fView(view) , fViewMap() , fSelectedPartition(-1) + , fSpaceIDMap(spaceIDMap) { } @@ -258,7 +259,7 @@ public: } private: - void _AddSpaces(BPartition* partition, PartitionView* parentView) const + void _AddSpaces(BPartition* partition, PartitionView* parentView) { // add any available space on the partition BPartitioningInfo info; @@ -269,10 +270,17 @@ public: 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; + // double scale = (double)size / parentSize; + partition_id id + = fSpaceIDMap.SpaceIDFor(partition->ID(), offset); PartitionView* view = new PartitionView("", scale, - offset, parentView->Level() + 1, -2); + offset, parentView->Level() + 1, id); + fViewMap.Put(id, view); BGroupLayout* layout = parentView->GroupLayout(); layout->AddView(_FindInsertIndex(view, layout), view, scale); } @@ -301,18 +309,21 @@ public: BView* fView; PartitionViewMap fViewMap; partition_id fSelectedPartition; + SpaceIDMap& fSpaceIDMap; }; // #pragma mark - -DiskView::DiskView(const BRect& frame, uint32 resizeMode) +DiskView::DiskView(const BRect& frame, uint32 resizeMode, + SpaceIDMap& spaceIDMap) : Inherited(frame, "diskview", resizeMode, B_WILL_DRAW | B_FULL_UPDATE_ON_RESIZE) , fDiskCount(0) , fDisk(NULL) - , fPartitionLayout(new PartitionLayout(this)) + , fSpaceIDMap(spaceIDMap) + , fPartitionLayout(new PartitionLayout(this, fSpaceIDMap)) { BGroupLayout* layout = new BGroupLayout(B_HORIZONTAL, kLayoutInset); SetLayout(layout); @@ -407,12 +418,12 @@ DiskView::SetDiskCount(int32 count) void DiskView::SetDisk(BDiskDevice* disk, partition_id selectedPartition) { - fPartitionLayout->SetSelectedPartition(selectedPartition); - if (fDisk != disk) { fDisk = disk; _UpdateLayout(); } + + fPartitionLayout->SetSelectedPartition(selectedPartition); } diff --git a/src/apps/drivesetup/DiskView.h b/src/apps/drivesetup/DiskView.h index ff1d596853..1670ee58e1 100644 --- a/src/apps/drivesetup/DiskView.h +++ b/src/apps/drivesetup/DiskView.h @@ -9,12 +9,15 @@ #include #include +#include "Support.h" + class DiskView : public BView { typedef BView Inherited; public: DiskView(const BRect& frame, - uint32 resizeMode); + uint32 resizeMode, + SpaceIDMap& spaceIDMap); virtual ~DiskView(); // BView interface @@ -28,6 +31,7 @@ private: int32 fDiskCount; BDiskDevice* fDisk; + SpaceIDMap& fSpaceIDMap; class PartitionLayout; PartitionLayout* fPartitionLayout; diff --git a/src/apps/drivesetup/Jamfile b/src/apps/drivesetup/Jamfile index 3927ad613f..bd85b21ee7 100644 --- a/src/apps/drivesetup/Jamfile +++ b/src/apps/drivesetup/Jamfile @@ -12,9 +12,8 @@ Preference DriveSetup : PartitionList.cpp Support.cpp - : be libcolumnlistview.a - : - DriveSetup.rdef + : be libcolumnlistview.a libshared.a + : DriveSetup.rdef ; if ( $(TARGET_PLATFORM) = libbe_test ) { diff --git a/src/apps/drivesetup/MainWindow.cpp b/src/apps/drivesetup/MainWindow.cpp index 38b0995b14..acd72c6daa 100644 --- a/src/apps/drivesetup/MainWindow.cpp +++ b/src/apps/drivesetup/MainWindow.cpp @@ -35,11 +35,14 @@ class ListPopulatorVisitor : public BDiskDeviceVisitor { public: - ListPopulatorVisitor(PartitionListView* list, int32& diskCount) + 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--) { @@ -76,18 +79,25 @@ private: 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++) { - fPartitionList->AddSpace(partition->ID(), offset, size); + // 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; }; @@ -118,9 +128,7 @@ enum { MSG_MOUNT = 'mnts', MSG_UNMOUNT = 'unmt', MSG_FORMAT = 'frmt', - MSG_CREATE_PRIMARY = 'crpr', - MSG_CREATE_EXTENDED = 'crex', - MSG_CREATE_LOGICAL = 'crlg', + MSG_CREATE = 'crtp', MSG_INITIALIZE = 'init', MSG_DELETE = 'delt', MSG_EJECT = 'ejct', @@ -131,10 +139,14 @@ enum { }; +// #pragma mark - + + MainWindow::MainWindow(BRect frame) : BWindow(frame, "DriveSetup", B_DOCUMENT_WINDOW, B_ASYNCHRONOUS_CONTROLS | B_NOT_ZOOMABLE) , fCurrentDisk(NULL) + , fSpaceIDMap() { BMenuBar* menuBar = new BMenuBar(Bounds(), "root menu"); @@ -145,13 +157,6 @@ MainWindow::MainWindow(BRect frame) new BMessage(MSG_SURFACE_TEST)); fRescanMI = new BMenuItem("Rescan", new BMessage(MSG_RESCAN)); - fCreatePrimaryMI = new BMenuItem("Primary", - new BMessage(MSG_CREATE_PRIMARY)); - fCreateExtendedMI = new BMenuItem("Extended", - new BMessage(MSG_CREATE_EXTENDED)); - fCreateLogicalMI = new BMenuItem("Logical", - new BMessage(MSG_CREATE_LOGICAL)); - fDeleteMI = new BMenuItem("Delete (not implemented)", new BMessage(MSG_DELETE)); fDeleteMI->SetEnabled(false); @@ -174,10 +179,7 @@ fDeleteMI->SetEnabled(false); // Parition menu fPartitionMenu = new BMenu("Partition"); - fCreateMenu = new BMenu("Create (not implemented)"); - fCreateMenu->AddItem(fCreatePrimaryMI); - fCreateMenu->AddItem(fCreateExtendedMI); - fCreateMenu->AddItem(fCreateLogicalMI); + fCreateMenu = new BMenu("Create"); fPartitionMenu->AddItem(fCreateMenu); fInitMenu = new BMenu("Initialize"); @@ -202,7 +204,8 @@ fDeleteMI->SetEnabled(false); 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); + fDiskView = new DiskView(r, B_FOLLOW_LEFT_RIGHT | B_FOLLOW_TOP, + fSpaceIDMap); AddChild(fDiskView); // add PartitionListView @@ -222,7 +225,7 @@ fDeleteMI->SetEnabled(false); // visit all disks in the system and show their contents _ScanDrives(); - _EnabledDisableMenuItems(NULL, -1); + _EnabledDisableMenuItems(NULL, -1, -1); } @@ -250,14 +253,8 @@ MainWindow::MessageReceived(BMessage* message) printf("MSG_FORMAT\n"); break; - case MSG_CREATE_PRIMARY: - printf("MSG_CREATE_PRIMARY\n"); - break; - case MSG_CREATE_EXTENDED: - printf("MSG_CREATE_EXTENDED\n"); - break; - case MSG_CREATE_LOGICAL: - printf("MSG_CREATE_LOGICAL\n"); + case MSG_CREATE: + printf("MSG_CREATE\n"); break; case MSG_INITIALIZE: { @@ -366,8 +363,9 @@ MainWindow::RestoreSettings(BMessage* archive) void MainWindow::_ScanDrives() { + fSpaceIDMap.Clear(); int32 diskCount = 0; - ListPopulatorVisitor driveVisitor(fListView, diskCount); + ListPopulatorVisitor driveVisitor(fListView, diskCount, fSpaceIDMap); fDDRoster.VisitEachPartition(&driveVisitor); fDiskView->SetDiskCount(diskCount); } @@ -399,8 +397,9 @@ MainWindow::_ScanFileSystems() void MainWindow::_AdaptToSelectedPartition() { - partition_id disk = -1; - partition_id partition = -1; + partition_id diskID = -1; + partition_id partitionID = -1; + partition_id parentID = -1; BRow* _selectedRow = fListView->CurrentSelection(); if (_selectedRow) { @@ -409,24 +408,27 @@ MainWindow::_AdaptToSelectedPartition() BRow* parent = NULL; while (fListView->FindParent(_topLevelRow, &parent, NULL)) _topLevelRow = parent; - + PartitionListRow* topLevelRow = dynamic_cast(_topLevelRow); PartitionListRow* selectedRow = dynamic_cast(_selectedRow); if (topLevelRow) - disk = topLevelRow->ID(); - if (selectedRow) - partition = selectedRow->ID(); + diskID = topLevelRow->ID(); + if (selectedRow) { + partitionID = selectedRow->ID(); + parentID = selectedRow->ParentID(); + } } - _SetToDiskAndPartition(disk, partition); + _SetToDiskAndPartition(diskID, partitionID, parentID); } void -MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition) +MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition, + partition_id parent) { BDiskDevice* oldDisk = NULL; if (!fCurrentDisk || fCurrentDisk->ID() != disk) { @@ -446,7 +448,7 @@ MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition) fCurrentPartitionID = partition; fDiskView->SetDisk(fCurrentDisk, fCurrentPartitionID); - _EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID); + _EnabledDisableMenuItems(fCurrentDisk, fCurrentPartitionID, parent); delete oldDisk; } @@ -454,8 +456,12 @@ MainWindow::_SetToDiskAndPartition(partition_id disk, partition_id partition) void MainWindow::_EnabledDisableMenuItems(BDiskDevice* disk, - partition_id selectedPartition) + partition_id selectedPartition, partition_id parentID) { + // clean out Create menu + while (BMenuItem* item = fCreateMenu->RemoveItem(0L)) + delete item; + if (!disk) { fFormatMI->SetEnabled(false); fEjectMI->SetEnabled(false); @@ -469,10 +475,36 @@ fFormatMI->SetEnabled(false); // fSurfaceTestMI->SetEnabled(true); fSurfaceTestMI->SetEnabled(false); + // Create menu and items fPartitionMenu->SetEnabled(true); - // fCreateMenu->SetEnabled(/*empty space selected*/); -fCreateMenu->SetEnabled(false); + BPartition* parentPartition = NULL; + if (selectedPartition <= -2) + parentPartition = disk->FindDescendant(parentID); + + if (parentPartition) { + fCreateMenu->SetEnabled(true); + BString supportedChildType; + int32 cookie = 0; + status_t ret; + while ((ret = parentPartition->GetNextSupportedChildType(&cookie, + &supportedChildType)) == B_OK) { + BMessage* message = new BMessage(MSG_CREATE); + message->AddInt32("parent id", parentID); + message->AddInt32("space id", selectedPartition); + message->AddString("type", supportedChildType); + BMenuItem* item = new BMenuItem(supportedChildType.String(), + message); + fCreateMenu->AddItem(item); + } + if (fCreateMenu->CountItems() == 0) + fprintf(stderr, "Failed to get supported child types: %s\n", + strerror(ret)); + } else { + fCreateMenu->SetEnabled(false); + } + + // Mount items BPartition* partition = disk->FindDescendant(selectedPartition); if (partition) { fInitMenu->SetEnabled(!partition->IsMounted()); diff --git a/src/apps/drivesetup/MainWindow.h b/src/apps/drivesetup/MainWindow.h index 910f189e19..691dd63fc5 100644 --- a/src/apps/drivesetup/MainWindow.h +++ b/src/apps/drivesetup/MainWindow.h @@ -13,6 +13,8 @@ #include #include +#include "Support.h" + class BDiskDevice; class BPartition; @@ -45,10 +47,12 @@ private: void _ScanFileSystems(); void _AdaptToSelectedPartition(); - void _SetToDiskAndPartition(partition_id disk, - partition_id partition); + void _SetToDiskAndPartition(partition_id diskID, + partition_id partitionID, + partition_id parentID); void _EnabledDisableMenuItems(BDiskDevice* disk, - partition_id selectedPartition); + partition_id selectedPartition, + partition_id parentID); void _DisplayPartitionError(BString message, const BPartition* partition = NULL, @@ -72,6 +76,8 @@ private: PartitionListView* fListView; DiskView* fDiskView; + SpaceIDMap fSpaceIDMap; + BMenu* fDiskMenu; BMenu* fPartitionMenu; BMenu* fInitMenu; @@ -82,9 +88,6 @@ private: BMenuItem* fSurfaceTestMI; BMenuItem* fRescanMI; - BMenuItem* fCreatePrimaryMI; - BMenuItem* fCreateExtendedMI; - BMenuItem* fCreateLogicalMI; BMenuItem* fDeleteMI; BMenuItem* fMountMI; BMenuItem* fUnmountMI; diff --git a/src/apps/drivesetup/PartitionList.cpp b/src/apps/drivesetup/PartitionList.cpp index 36335f5027..b0699d06d5 100644 --- a/src/apps/drivesetup/PartitionList.cpp +++ b/src/apps/drivesetup/PartitionList.cpp @@ -190,10 +190,10 @@ PartitionListRow::PartitionListRow(BPartition* partition) } -PartitionListRow::PartitionListRow(partition_id parentID, off_t offset, - off_t size) +PartitionListRow::PartitionListRow(partition_id parentID, partition_id id, + off_t offset, off_t size) : Inherited() - , fPartitionID(-2) + , fPartitionID(id) , fParentID(parentID) , fOffset(offset) , fSize(size) @@ -288,7 +288,8 @@ PartitionListView::AddPartition(BPartition* partition) PartitionListRow* -PartitionListView::AddSpace(partition_id parentID, off_t offset, off_t size) +PartitionListView::AddSpace(partition_id parentID, partition_id id, + off_t offset, off_t size) { // the parent should already be in the listview PartitionListRow* parent = FindRow(parentID); @@ -297,7 +298,7 @@ PartitionListView::AddSpace(partition_id parentID, off_t offset, off_t size) // create the row for this partition PartitionListRow* partitionrow = new PartitionListRow(parentID, - offset, size); + id, offset, size); // find a proper insertion index based on the on-disk offset int32 index = _InsertIndexForOffset(parent, offset); diff --git a/src/apps/drivesetup/PartitionList.h b/src/apps/drivesetup/PartitionList.h index 9e53296252..c180b042ae 100644 --- a/src/apps/drivesetup/PartitionList.h +++ b/src/apps/drivesetup/PartitionList.h @@ -64,7 +64,7 @@ class PartitionListRow : public BRow { public: PartitionListRow(BPartition* partition); PartitionListRow(partition_id parentID, - off_t offset, off_t size); + partition_id id, off_t offset, off_t size); partition_id ID() const { return fPartitionID; } @@ -92,7 +92,7 @@ public: PartitionListRow* parent = NULL); PartitionListRow* AddPartition(BPartition* partition); PartitionListRow* AddSpace(partition_id parent, - off_t offset, off_t size); + partition_id id, off_t offset, off_t size); private: int32 _InsertIndexForOffset(PartitionListRow* parent, diff --git a/src/apps/drivesetup/Support.cpp b/src/apps/drivesetup/Support.cpp index 597c895d2f..3702d6efdd 100644 --- a/src/apps/drivesetup/Support.cpp +++ b/src/apps/drivesetup/Support.cpp @@ -10,6 +10,7 @@ #include "Support.h" #include +#include const char* @@ -67,3 +68,43 @@ dump_partition_info(const BPartition* partition) printf("\tID(): %lx\n\n", partition->ID()); } + +bool +is_valid_partitionable_space(size_t size) +{ + // TODO: remove this again, the DiskDeviceAPI should + // not even show these spaces to begin with + return size >= 8 * 1024 * 1024; +} + + +// #pragma mark -SpaceIDMap + +SpaceIDMap::SpaceIDMap() + : HashMap() + , fNextSpaceID(-2) +{ +} + + +SpaceIDMap::~SpaceIDMap() +{ +} + + +partition_id +SpaceIDMap::SpaceIDFor(partition_id parentID, off_t spaceOffset) +{ + BString key; + key << parentID << ':' << (uint64)spaceOffset; + + if (ContainsKey(key.String())) + return Get(key.String()); + + partition_id newID = fNextSpaceID--; + Put(key.String(), newID); + + return newID; +} + + diff --git a/src/apps/drivesetup/Support.h b/src/apps/drivesetup/Support.h index 82d0f37624..42a118b316 100644 --- a/src/apps/drivesetup/Support.h +++ b/src/apps/drivesetup/Support.h @@ -6,7 +6,9 @@ #define SUPPORT_H -#include +#include +#include +#include class BPartition; @@ -16,5 +18,20 @@ const char* string_for_size(off_t size, char *string); void dump_partition_info(const BPartition* partition); +bool is_valid_partitionable_space(size_t size); + + +class SpaceIDMap : public HashMap { +public: + SpaceIDMap(); + virtual ~SpaceIDMap(); + + partition_id SpaceIDFor(partition_id parentID, + off_t spaceOffset); + +private: + partition_id fNextSpaceID; +}; + #endif // SUPPORT_H