libroot/posix/stdio: Remove unused portions.
[haiku.git] / src / apps / drivesetup / PartitionList.cpp
blob1fd294685ea4fd0fd20aeebd39c174c5c0bc0440
1 /*
2 * Copyright 2006-2013, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT license.
5 * Authors:
6 * Ithamar R. Adema <ithamar@unet.nl>
7 * James Urquhart
8 * Stephan Aßmus <superstippi@gmx.de>
9 * Axel Dörfler, axeld@pinc-software.de
13 #include "PartitionList.h"
15 #include <Catalog.h>
16 #include <ColumnTypes.h>
17 #include <Locale.h>
18 #include <Path.h>
20 #include <driver_settings.h>
22 #include "Support.h"
23 #include "MainWindow.h"
26 #undef B_TRANSLATION_CONTEXT
27 #define B_TRANSLATION_CONTEXT "PartitionList"
30 static const char* kUnavailableString = "";
32 enum {
33 kDeviceColumn,
34 kFilesystemColumn,
35 kVolumeNameColumn,
36 kMountedAtColumn,
37 kSizeColumn,
38 kParametersColumn,
39 kPartitionTypeColumn,
43 // #pragma mark - BBitmapStringField
46 BBitmapStringField::BBitmapStringField(BBitmap* bitmap, const char* string)
48 Inherited(string),
49 fBitmap(bitmap)
54 BBitmapStringField::~BBitmapStringField()
56 delete fBitmap;
60 void
61 BBitmapStringField::SetBitmap(BBitmap* bitmap)
63 delete fBitmap;
64 fBitmap = 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)
81 SetWantsEvents(true);
85 void
86 PartitionColumn::DrawField(BField* field, BRect rect, BView* parent)
88 BBitmapStringField* bitmapField
89 = dynamic_cast<BBitmapStringField*>(field);
90 BStringField* stringField = dynamic_cast<BStringField*>(field);
92 if (bitmapField) {
93 const BBitmap* bitmap = bitmapField->Bitmap();
95 // figure out the placement
96 float x = 0.0;
97 BRect r = bitmap ? bitmap->Bounds() : BRect(0, 0, 15, 15);
98 float y = rect.top + ((rect.Height() - r.Height()) / 2);
99 float width = 0.0;
101 switch (Alignment()) {
102 default:
103 case B_ALIGN_LEFT:
104 case B_ALIGN_CENTER:
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);
108 break;
110 case B_ALIGN_RIGHT:
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);
114 break;
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);
124 // draw the bitmap
125 if (bitmap) {
126 parent->SetDrawingMode(B_OP_ALPHA);
127 parent->DrawBitmap(bitmap, BPoint(x, y));
128 parent->SetDrawingMode(B_OP_OVER);
131 // draw the string
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);
151 float
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);
159 float width = 0.0;
161 if (bitmapField) {
162 const BBitmap* bitmap = bitmapField->Bitmap();
163 BFont font;
164 parent->GetFont(&font);
165 width = font.StringWidth(bitmapField->String()) + 3 * sTextMargin;
166 if (bitmap)
167 width += bitmap->Bounds().Width();
168 else
169 width += 16;
170 } else if (stringField) {
171 BFont font;
172 parent->GetFont(&font);
173 width = font.StringWidth(stringField->String()) + 2 * sTextMargin;
175 return max_c(width, parentWidth);
179 bool
180 PartitionColumn::AcceptsField(const BField* field) const
182 return dynamic_cast<const BStringField*>(field) != NULL;
186 void
187 PartitionColumn::InitTextMargin(BView* parent)
189 BFont font;
190 parent->GetFont(&font);
191 sTextMargin = ceilf(font.Size() * 0.8);
195 // #pragma mark - PartitionListRow
198 PartitionListRow::PartitionListRow(BPartition* partition)
200 Inherited(),
201 fPartitionID(partition->ID()),
202 fParentID(partition->Parent() ? partition->Parent()->ID() : -1),
203 fOffset(partition->Offset()),
204 fSize(partition->Size())
206 BPath path;
207 partition->GetPath(&path);
209 // Device icon
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) {
216 delete icon;
217 icon = NULL;
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);
234 else
235 SetField(new BStringField(kUnavailableString), kVolumeNameColumn);
236 } else if (partition->CountChildren() > 0) {
237 SetField(new BStringField(kUnavailableString), kFilesystemColumn);
238 SetField(new BStringField(kUnavailableString), kVolumeNameColumn);
239 } else {
240 if (!partitionType.IsEmpty()) {
241 partitionType.Prepend("(");
242 partitionType.Append(")");
243 SetField(new BStringField(partitionType), kFilesystemColumn);
244 } else
245 SetField(new BStringField(kUnavailableString), kFilesystemColumn);
247 SetField(new BStringField(kUnavailableString), kVolumeNameColumn);
250 // Mounted at
252 if (partition->IsMounted() && partition->GetMountPoint(&path) == B_OK)
253 SetField(new BStringField(path.Path()), kMountedAtColumn);
254 else
255 SetField(new BStringField(kUnavailableString), kMountedAtColumn);
257 // Size
259 if (fSize > 0) {
260 char size[1024];
261 SetField(new BStringField(string_for_size(partition->Size(), size,
262 sizeof(size))), kSizeColumn);
263 } else {
264 SetField(new BStringField(kUnavailableString), kSizeColumn);
267 // Additional parameters
269 if (partition->Parameters() != NULL) {
270 BString parameters;
272 // check parameters
273 void* handle = parse_driver_settings_string(partition->Parameters());
274 if (handle != NULL) {
275 bool active = get_driver_boolean_parameter(handle, "active", false, true);
276 if (active)
277 parameters += B_TRANSLATE("Active");
279 delete_driver_settings(handle);
282 SetField(new BStringField(parameters), kParametersColumn);
283 } else {
284 SetField(new BStringField(kUnavailableString), kParametersColumn);
287 // Partition type
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)
298 Inherited(),
299 fPartitionID(id),
300 fParentID(parentID),
301 fOffset(offset),
302 fSize(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);
318 const char*
319 PartitionListRow::DevicePath()
321 BBitmapStringField* stringField
322 = dynamic_cast<BBitmapStringField*>(GetField(kDeviceColumn));
324 if (stringField == NULL)
325 return 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);
356 void
357 PartitionListView::AttachedToWindow()
359 Inherited::AttachedToWindow();
360 PartitionColumn::InitTextMargin(ScrollView());
364 bool
365 PartitionListView::InitiateDrag(BPoint rowPoint, bool wasSelected)
367 PartitionListRow* draggedRow
368 = dynamic_cast<PartitionListRow*>(RowAt(rowPoint));
369 if (draggedRow == NULL)
370 return false;
372 const char* draggedPath = draggedRow->DevicePath();
373 if (draggedPath == NULL)
374 return false;
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);
384 return true;
388 void
389 PartitionListView::ExpandOrCollapse(BRow* row, bool expand)
391 BColumnListView::ExpandOrCollapse(row, expand);
392 Window()->PostMessage(MSG_UPDATE_ZOOM_LIMITS);
396 PartitionListRow*
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)
403 return item;
404 if (CountRows(item) > 0) {
405 // recurse into child rows
406 item = FindRow(id, item);
407 if (item)
408 return item;
412 return NULL;
416 PartitionListRow*
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)
423 return partitionrow;
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) {
436 // add it
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);
450 return partitionrow;
454 PartitionListRow*
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);
460 if (!parent)
461 return NULL;
463 // create the row for this partition
464 PartitionListRow* partitionrow = new PartitionListRow(parentID,
465 id, offset, size);
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);
476 return partitionrow;
480 BSize
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();
487 return size;
491 int32
492 PartitionListView::_InsertIndexForOffset(PartitionListRow* parent,
493 off_t offset) const
495 int32 index = 0;
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)
501 break;
503 return index;