2 * Copyright 2006-2013, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT license.
6 * Ithamar R. Adema <ithamar@unet.nl>
8 * Stephan Aßmus <superstippi@gmx.de>
9 * Axel Dörfler, axeld@pinc-software.de
13 #include "PartitionList.h"
16 #include <ColumnTypes.h>
20 #include <driver_settings.h>
23 #include "MainWindow.h"
26 #undef B_TRANSLATION_CONTEXT
27 #define B_TRANSLATION_CONTEXT "PartitionList"
30 static const char* kUnavailableString
= "";
43 // #pragma mark - BBitmapStringField
46 BBitmapStringField::BBitmapStringField(BBitmap
* bitmap
, const char* string
)
54 BBitmapStringField::~BBitmapStringField()
61 BBitmapStringField::SetBitmap(BBitmap
* bitmap
)
65 // TODO: cause a redraw?
69 // #pragma mark - PartitionColumn
72 float PartitionColumn::sTextMargin
= 0.0;
75 PartitionColumn::PartitionColumn(const char* title
, float width
, float minWidth
,
76 float maxWidth
, uint32 truncateMode
, alignment align
)
78 Inherited(title
, width
, minWidth
, maxWidth
, align
),
79 fTruncateMode(truncateMode
)
86 PartitionColumn::DrawField(BField
* field
, BRect rect
, BView
* parent
)
88 BBitmapStringField
* bitmapField
89 = dynamic_cast<BBitmapStringField
*>(field
);
90 BStringField
* stringField
= dynamic_cast<BStringField
*>(field
);
93 const BBitmap
* bitmap
= bitmapField
->Bitmap();
95 // figure out the placement
97 BRect r
= bitmap
? bitmap
->Bounds() : BRect(0, 0, 15, 15);
98 float y
= rect
.top
+ ((rect
.Height() - r
.Height()) / 2);
101 switch (Alignment()) {
105 x
= rect
.left
+ sTextMargin
;
106 width
= rect
.right
- (x
+ r
.Width()) - (2 * sTextMargin
);
107 r
.Set(x
+ r
.Width(), rect
.top
, rect
.right
- width
, rect
.bottom
);
111 x
= rect
.right
- sTextMargin
- r
.Width();
112 width
= (x
- rect
.left
- (2 * sTextMargin
));
113 r
.Set(rect
.left
, rect
.top
, rect
.left
+ width
, rect
.bottom
);
117 if (width
!= bitmapField
->Width()) {
118 BString
truncatedString(bitmapField
->String());
119 parent
->TruncateString(&truncatedString
, fTruncateMode
, width
+ 2);
120 bitmapField
->SetClippedString(truncatedString
.String());
121 bitmapField
->SetWidth(width
);
126 parent
->SetDrawingMode(B_OP_ALPHA
);
127 parent
->DrawBitmap(bitmap
, BPoint(x
, y
));
128 parent
->SetDrawingMode(B_OP_OVER
);
132 DrawString(bitmapField
->ClippedString(), parent
, r
);
134 } else if (stringField
) {
136 float width
= rect
.Width() - (2 * sTextMargin
);
138 if (width
!= stringField
->Width()) {
139 BString
truncatedString(stringField
->String());
141 parent
->TruncateString(&truncatedString
, fTruncateMode
, width
+ 2);
142 stringField
->SetClippedString(truncatedString
.String());
143 stringField
->SetWidth(width
);
146 DrawString(stringField
->ClippedString(), parent
, rect
);
152 PartitionColumn::GetPreferredWidth(BField
*_field
, BView
* parent
) const
154 BBitmapStringField
* bitmapField
155 = dynamic_cast<BBitmapStringField
*>(_field
);
156 BStringField
* stringField
= dynamic_cast<BStringField
*>(_field
);
158 float parentWidth
= Inherited::GetPreferredWidth(_field
, parent
);
162 const BBitmap
* bitmap
= bitmapField
->Bitmap();
164 parent
->GetFont(&font
);
165 width
= font
.StringWidth(bitmapField
->String()) + 3 * sTextMargin
;
167 width
+= bitmap
->Bounds().Width();
170 } else if (stringField
) {
172 parent
->GetFont(&font
);
173 width
= font
.StringWidth(stringField
->String()) + 2 * sTextMargin
;
175 return max_c(width
, parentWidth
);
180 PartitionColumn::AcceptsField(const BField
* field
) const
182 return dynamic_cast<const BStringField
*>(field
) != NULL
;
187 PartitionColumn::InitTextMargin(BView
* parent
)
190 parent
->GetFont(&font
);
191 sTextMargin
= ceilf(font
.Size() * 0.8);
195 // #pragma mark - PartitionListRow
198 PartitionListRow::PartitionListRow(BPartition
* partition
)
201 fPartitionID(partition
->ID()),
202 fParentID(partition
->Parent() ? partition
->Parent()->ID() : -1),
203 fOffset(partition
->Offset()),
204 fSize(partition
->Size())
207 partition
->GetPath(&path
);
211 BBitmap
* icon
= NULL
;
212 if (partition
->IsDevice()) {
213 icon_size size
= B_MINI_ICON
;
214 icon
= new BBitmap(BRect(0, 0, size
- 1, size
- 1), B_RGBA32
);
215 if (partition
->GetIcon(icon
, size
) != B_OK
) {
221 SetField(new BBitmapStringField(icon
, path
.Path()), kDeviceColumn
);
223 // File system & volume name
225 BString
partitionType(partition
->Type());
227 if (partition
->ContainsFileSystem()) {
228 SetField(new BStringField(partition
->ContentType()), kFilesystemColumn
);
229 SetField(new BStringField(partition
->ContentName()), kVolumeNameColumn
);
230 } else if (partition
->IsDevice()) {
231 SetField(new BStringField(kUnavailableString
), kFilesystemColumn
);
232 if (partition
->Name() != NULL
&& partition
->Name()[0])
233 SetField(new BStringField(partition
->Name()), kVolumeNameColumn
);
235 SetField(new BStringField(kUnavailableString
), kVolumeNameColumn
);
236 } else if (partition
->CountChildren() > 0) {
237 SetField(new BStringField(kUnavailableString
), kFilesystemColumn
);
238 SetField(new BStringField(kUnavailableString
), kVolumeNameColumn
);
240 if (!partitionType
.IsEmpty()) {
241 partitionType
.Prepend("(");
242 partitionType
.Append(")");
243 SetField(new BStringField(partitionType
), kFilesystemColumn
);
245 SetField(new BStringField(kUnavailableString
), kFilesystemColumn
);
247 SetField(new BStringField(kUnavailableString
), kVolumeNameColumn
);
252 if (partition
->IsMounted() && partition
->GetMountPoint(&path
) == B_OK
)
253 SetField(new BStringField(path
.Path()), kMountedAtColumn
);
255 SetField(new BStringField(kUnavailableString
), kMountedAtColumn
);
261 SetField(new BStringField(string_for_size(partition
->Size(), size
,
262 sizeof(size
))), kSizeColumn
);
264 SetField(new BStringField(kUnavailableString
), kSizeColumn
);
267 // Additional parameters
269 if (partition
->Parameters() != NULL
) {
273 void* handle
= parse_driver_settings_string(partition
->Parameters());
274 if (handle
!= NULL
) {
275 bool active
= get_driver_boolean_parameter(handle
, "active", false, true);
277 parameters
+= B_TRANSLATE("Active");
279 delete_driver_settings(handle
);
282 SetField(new BStringField(parameters
), kParametersColumn
);
284 SetField(new BStringField(kUnavailableString
), kParametersColumn
);
289 if (partitionType
.IsEmpty())
290 partitionType
= partition
->ContentType();
291 SetField(new BStringField(partitionType
), kPartitionTypeColumn
);
295 PartitionListRow::PartitionListRow(partition_id parentID
, partition_id id
,
296 off_t offset
, off_t size
)
304 // TODO: design icon for spaces on partitions
305 SetField(new BBitmapStringField(NULL
, "-"), kDeviceColumn
);
307 SetField(new BStringField(B_TRANSLATE("<empty>")), kFilesystemColumn
);
308 SetField(new BStringField(kUnavailableString
), kVolumeNameColumn
);
310 SetField(new BStringField(kUnavailableString
), kMountedAtColumn
);
312 char sizeString
[1024];
313 SetField(new BStringField(string_for_size(size
, sizeString
,
314 sizeof(sizeString
))), kSizeColumn
);
319 PartitionListRow::DevicePath()
321 BBitmapStringField
* stringField
322 = dynamic_cast<BBitmapStringField
*>(GetField(kDeviceColumn
));
324 if (stringField
== NULL
)
327 return stringField
->String();
331 // #pragma mark - PartitionListView
334 PartitionListView::PartitionListView(const BRect
& frame
, uint32 resizeMode
)
335 : Inherited(frame
, "storagelist", resizeMode
, 0, B_NO_BORDER
, true)
337 AddColumn(new PartitionColumn(B_TRANSLATE("Device"), 150, 50, 500,
338 B_TRUNCATE_MIDDLE
), kDeviceColumn
);
339 AddColumn(new PartitionColumn(B_TRANSLATE("File system"), 100, 50, 500,
340 B_TRUNCATE_MIDDLE
), kFilesystemColumn
);
341 AddColumn(new PartitionColumn(B_TRANSLATE("Volume name"), 130, 50, 500,
342 B_TRUNCATE_MIDDLE
), kVolumeNameColumn
);
343 AddColumn(new PartitionColumn(B_TRANSLATE("Mounted at"), 100, 50, 500,
344 B_TRUNCATE_MIDDLE
), kMountedAtColumn
);
345 AddColumn(new PartitionColumn(B_TRANSLATE("Size"), 100, 50, 500,
346 B_TRUNCATE_END
, B_ALIGN_RIGHT
), kSizeColumn
);
347 AddColumn(new PartitionColumn(B_TRANSLATE("Parameters"), 100, 50, 500,
348 B_TRUNCATE_END
), kParametersColumn
);
349 AddColumn(new PartitionColumn(B_TRANSLATE("Partition type"), 200, 50, 500,
350 B_TRUNCATE_END
), kPartitionTypeColumn
);
352 SetSortingEnabled(false);
357 PartitionListView::AttachedToWindow()
359 Inherited::AttachedToWindow();
360 PartitionColumn::InitTextMargin(ScrollView());
365 PartitionListView::InitiateDrag(BPoint rowPoint
, bool wasSelected
)
367 PartitionListRow
* draggedRow
368 = dynamic_cast<PartitionListRow
*>(RowAt(rowPoint
));
369 if (draggedRow
== NULL
)
372 const char* draggedPath
= draggedRow
->DevicePath();
373 if (draggedPath
== NULL
)
376 BRect draggedRowRect
;
377 GetRowRect(draggedRow
, &draggedRowRect
);
379 BMessage
dragMessage(B_MIME_DATA
);
380 dragMessage
.AddData("text/plain", B_MIME_TYPE
, draggedPath
,
381 strlen(draggedPath
));
383 DragMessage(&dragMessage
, draggedRowRect
, NULL
);
389 PartitionListView::ExpandOrCollapse(BRow
* row
, bool expand
)
391 BColumnListView::ExpandOrCollapse(row
, expand
);
392 Window()->PostMessage(MSG_UPDATE_ZOOM_LIMITS
);
397 PartitionListView::FindRow(partition_id id
, PartitionListRow
* parent
)
399 for (int32 i
= 0; i
< CountRows(parent
); i
++) {
400 PartitionListRow
* item
401 = dynamic_cast<PartitionListRow
*>(RowAt(i
, parent
));
402 if (item
!= NULL
&& item
->ID() == id
)
404 if (CountRows(item
) > 0) {
405 // recurse into child rows
406 item
= FindRow(id
, item
);
417 PartitionListView::AddPartition(BPartition
* partition
)
419 PartitionListRow
* partitionrow
= FindRow(partition
->ID());
421 // forget about it if this partition is already in the listview
422 if (partitionrow
!= NULL
)
425 // create the row for this partition
426 partitionrow
= new PartitionListRow(partition
);
428 // see if this partition has a parent, or should have
429 // a parent (add it in this case)
430 PartitionListRow
* parent
= NULL
;
431 if (partition
->Parent() != NULL
) {
432 // check if it is in the listview
433 parent
= FindRow(partition
->Parent()->ID());
434 // If parent of this partition is not yet in the list
435 if (parent
== NULL
) {
437 parent
= AddPartition(partition
->Parent());
441 // find a proper insertion index based on the on-disk offset
442 int32 index
= _InsertIndexForOffset(parent
, partition
->Offset());
444 // add the row, parent may be NULL (add at top level)
445 AddRow(partitionrow
, index
, parent
);
447 // make sure the row is initially expanded
448 ExpandOrCollapse(partitionrow
, true);
455 PartitionListView::AddSpace(partition_id parentID
, partition_id id
,
456 off_t offset
, off_t size
)
458 // the parent should already be in the listview
459 PartitionListRow
* parent
= FindRow(parentID
);
463 // create the row for this partition
464 PartitionListRow
* partitionrow
= new PartitionListRow(parentID
,
467 // find a proper insertion index based on the on-disk offset
468 int32 index
= _InsertIndexForOffset(parent
, offset
);
470 // add the row, parent may be NULL (add at top level)
471 AddRow(partitionrow
, index
, parent
);
473 // make sure the row is initially expanded
474 ExpandOrCollapse(partitionrow
, true);
481 PartitionListView::PreferredSize()
483 // Remove default size for parameters + partition type column
484 BSize size
= BColumnListView::PreferredSize();
485 size
.width
-= ColumnAt(kParametersColumn
)->Width()
486 + ColumnAt(kPartitionTypeColumn
)->Width();
492 PartitionListView::_InsertIndexForOffset(PartitionListRow
* parent
,
496 int32 count
= CountRows(parent
);
497 for (; index
< count
; index
++) {
498 const PartitionListRow
* item
499 = dynamic_cast<const PartitionListRow
*>(RowAt(index
, parent
));
500 if (item
&& item
->Offset() > offset
)