* Implemented support for generating global partition_ids for partitionable
spaces. This way we can use all the existing logic to select them in either list view or the disk layout view. IAW, selecting empty spaces now works. * Changed the way the Create menu works. It is now only enabled if a space item is selected and then the sub items are filled with the types that the parent partition says it supports for child creation. (Does not yet seem to work.) * PartitionViews for spaces were not put into the partition_id -> view map. * Fixed focus indication when switching the disk for the disk layout view, previously, the correct view was only selected when the disk did not change. * Added a temporary work around to avoid showing bogus space items at all (those smaller than a "cylinder size"). Currently hard coded to 8 MB size. But I already have an idea how we could fix this in the Disk Device API implementation. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23854 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
fb3fcd8754
commit
967d72041f
@ -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("<empty>", 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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -9,12 +9,15 @@
|
||||
#include <DiskDevice.h>
|
||||
#include <View.h>
|
||||
|
||||
#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;
|
||||
|
@ -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 ) {
|
||||
|
@ -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<PartitionListRow*>(_topLevelRow);
|
||||
PartitionListRow* selectedRow
|
||||
= dynamic_cast<PartitionListRow*>(_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());
|
||||
|
@ -13,6 +13,8 @@
|
||||
#include <DiskDeviceRoster.h>
|
||||
#include <Window.h>
|
||||
|
||||
#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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Support.h"
|
||||
|
||||
#include <Partition.h>
|
||||
#include <String.h>
|
||||
|
||||
|
||||
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<HashString, partition_id>()
|
||||
, 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;
|
||||
}
|
||||
|
||||
|
||||
|
@ -6,7 +6,9 @@
|
||||
#define SUPPORT_H
|
||||
|
||||
|
||||
#include <SupportDefs.h>
|
||||
#include <DiskDeviceDefs.h>
|
||||
#include <HashMap.h>
|
||||
#include <HashString.h>
|
||||
|
||||
|
||||
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<HashString, partition_id> {
|
||||
public:
|
||||
SpaceIDMap();
|
||||
virtual ~SpaceIDMap();
|
||||
|
||||
partition_id SpaceIDFor(partition_id parentID,
|
||||
off_t spaceOffset);
|
||||
|
||||
private:
|
||||
partition_id fNextSpaceID;
|
||||
};
|
||||
|
||||
|
||||
#endif // SUPPORT_H
|
||||
|
Loading…
x
Reference in New Issue
Block a user