Merge branch 'partition-flags'

Extensive go-over on the partitioning code. #622 is maybe "possibly fixed",
but there's no real indication of what constitutes an invalid combination
of flags.

FIXES #884 FIXES #951 FIXES #953 FIXES #622
This commit is contained in:
Adriaan de Groot 2018-05-16 11:37:27 -04:00
commit 65d00ccc37
13 changed files with 278 additions and 95 deletions

View File

@ -40,6 +40,7 @@ if ( KPMcore_FOUND )
gui/EncryptWidget.cpp gui/EncryptWidget.cpp
gui/PartitionPage.cpp gui/PartitionPage.cpp
gui/PartitionBarsView.cpp gui/PartitionBarsView.cpp
gui/PartitionDialogHelpers.cpp
gui/PartitionLabelsView.cpp gui/PartitionLabelsView.cpp
gui/PartitionSizeController.cpp gui/PartitionSizeController.cpp
gui/PartitionSplitterWidget.cpp gui/PartitionSplitterWidget.cpp

View File

@ -22,6 +22,7 @@
#include "core/DeviceModel.h" #include "core/DeviceModel.h"
#include "core/KPMHelpers.h" #include "core/KPMHelpers.h"
#include "core/PartitionInfo.h"
#include "core/PartitionIterator.h" #include "core/PartitionIterator.h"
#include <kpmcore/backend/corebackend.h> #include <kpmcore/backend/corebackend.h>
@ -343,8 +344,10 @@ isEfiSystem()
bool bool
isEfiBootable( const Partition* candidate ) isEfiBootable( const Partition* candidate )
{ {
auto flags = PartitionInfo::flags( candidate );
/* If bit 17 is set, old-style Esp flag, it's OK */ /* If bit 17 is set, old-style Esp flag, it's OK */
if ( candidate->activeFlags().testFlag( PartitionTable::FlagEsp ) ) if ( flags.testFlag( PartitionTable::FlagEsp ) )
return true; return true;
@ -359,7 +362,7 @@ isEfiBootable( const Partition* candidate )
const PartitionTable* table = dynamic_cast<const PartitionTable*>( root ); const PartitionTable* table = dynamic_cast<const PartitionTable*>( root );
return table && ( table->type() == PartitionTable::TableType::gpt ) && return table && ( table->type() == PartitionTable::TableType::gpt ) &&
candidate->activeFlags().testFlag( PartitionTable::FlagBoot ); flags.testFlag( PartitionTable::FlagBoot );
} }
} // nmamespace PartUtils } // nmamespace PartUtils

View File

@ -258,6 +258,7 @@ PartitionCoreModule::createPartition( Device* device,
{ {
SetPartFlagsJob* fJob = new SetPartFlagsJob( device, partition, flags ); SetPartFlagsJob* fJob = new SetPartFlagsJob( device, partition, flags );
deviceInfo->jobs << Calamares::job_ptr( fJob ); deviceInfo->jobs << Calamares::job_ptr( fJob );
PartitionInfo::setFlags( partition, flags );
} }
refresh(); refresh();
@ -381,8 +382,8 @@ PartitionCoreModule::setPartitionFlags( Device* device,
PartitionModel::ResetHelper( partitionModelForDevice( device ) ); PartitionModel::ResetHelper( partitionModelForDevice( device ) );
SetPartFlagsJob* job = new SetPartFlagsJob( device, partition, flags ); SetPartFlagsJob* job = new SetPartFlagsJob( device, partition, flags );
deviceInfo->jobs << Calamares::job_ptr( job ); deviceInfo->jobs << Calamares::job_ptr( job );
PartitionInfo::setFlags( partition, flags );
refresh(); refresh();
} }

View File

@ -27,8 +27,9 @@
namespace PartitionInfo namespace PartitionInfo
{ {
static const char* MOUNT_POINT_PROPERTY = "_calamares_mountPoint"; static const char MOUNT_POINT_PROPERTY[] = "_calamares_mountPoint";
static const char* FORMAT_PROPERTY = "_calamares_format"; static const char FORMAT_PROPERTY[] = "_calamares_format";
static const char FLAGS_PROPERTY[] = "_calamares_flags";
QString QString
mountPoint( Partition* partition ) mountPoint( Partition* partition )
@ -54,18 +55,33 @@ setFormat( Partition* partition, bool value )
partition->setProperty( FORMAT_PROPERTY, value ); partition->setProperty( FORMAT_PROPERTY, value );
} }
PartitionTable::Flags flags(const Partition* partition)
{
auto v = partition->property( FLAGS_PROPERTY );
if (v.type() == QVariant::Int )
return static_cast<PartitionTable::Flags>( v.toInt() );
return partition->activeFlags();
}
void setFlags(Partition* partition, PartitionTable::Flags f)
{
partition->setProperty( FLAGS_PROPERTY, PartitionTable::Flags::Int( f ) );
}
void void
reset( Partition* partition ) reset( Partition* partition )
{ {
partition->setProperty( MOUNT_POINT_PROPERTY, QVariant() ); partition->setProperty( MOUNT_POINT_PROPERTY, QVariant() );
partition->setProperty( FORMAT_PROPERTY, QVariant() ); partition->setProperty( FORMAT_PROPERTY, QVariant() );
partition->setProperty( FLAGS_PROPERTY, QVariant() );
} }
bool bool
isDirty( Partition* partition ) isDirty( Partition* partition )
{ {
return !mountPoint( partition ).isEmpty() return !mountPoint( partition ).isEmpty()
|| format( partition ); || format( partition )
|| flags( partition ) != partition->activeFlags();
} }
} // namespace } // namespace

View File

@ -21,6 +21,8 @@
#include <QHash> #include <QHash>
#include <QString> #include <QString>
#include <kpmcore/core/partitiontable.h>
class Partition; class Partition;
/** /**
@ -45,6 +47,9 @@ void setMountPoint( Partition* partition, const QString& value );
bool format( Partition* partition ); bool format( Partition* partition );
void setFormat( Partition* partition, bool value ); void setFormat( Partition* partition, bool value );
PartitionTable::Flags flags( const Partition* partition );
void setFlags( Partition* partition, PartitionTable::Flags f );
void reset( Partition* partition ); void reset( Partition* partition );
/** /**

View File

@ -23,6 +23,7 @@
#include "core/PartitionInfo.h" #include "core/PartitionInfo.h"
#include "core/PartUtils.h" #include "core/PartUtils.h"
#include "core/KPMHelpers.h" #include "core/KPMHelpers.h"
#include "gui/PartitionDialogHelpers.h"
#include "gui/PartitionSizeController.h" #include "gui/PartitionSizeController.h"
#include "ui_CreatePartitionDialog.h" #include "ui_CreatePartitionDialog.h"
@ -56,7 +57,7 @@ static QSet< FileSystem::Type > s_unmountableFS(
FileSystem::Lvm2_PV FileSystem::Lvm2_PV
} ); } );
CreatePartitionDialog::CreatePartitionDialog( Device* device, PartitionNode* parentPartition, const QStringList& usedMountPoints, QWidget* parentWidget ) CreatePartitionDialog::CreatePartitionDialog( Device* device, PartitionNode* parentPartition, Partition* partition, const QStringList& usedMountPoints, QWidget* parentWidget )
: QDialog( parentWidget ) : QDialog( parentWidget )
, m_ui( new Ui_CreatePartitionDialog ) , m_ui( new Ui_CreatePartitionDialog )
, m_partitionSizeController( new PartitionSizeController( this ) ) , m_partitionSizeController( new PartitionSizeController( this ) )
@ -81,12 +82,7 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device, PartitionNode* par
m_ui->lvNameLineEdit->setValidator(validator); m_ui->lvNameLineEdit->setValidator(validator);
} }
QStringList mountPoints = { "/", "/boot", "/home", "/opt", "/usr", "/var" }; standardMountPoints( *(m_ui->mountPointComboBox), partition ? PartitionInfo::mountPoint( partition ) : QString() );
if ( PartUtils::isEfiSystem() )
mountPoints << Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString();
mountPoints.removeDuplicates();
mountPoints.sort();
m_ui->mountPointComboBox->addItems( mountPoints );
if ( device->partitionTable()->type() == PartitionTable::msdos || if ( device->partitionTable()->type() == PartitionTable::msdos ||
device->partitionTable()->type() == PartitionTable::msdos_sectorbased ) device->partitionTable()->type() == PartitionTable::msdos_sectorbased )
@ -125,7 +121,8 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device, PartitionNode* par
m_ui->fsComboBox->setCurrentIndex( defaultFsIndex ); m_ui->fsComboBox->setCurrentIndex( defaultFsIndex );
updateMountPointUi(); updateMountPointUi();
setupFlagsList(); setFlagList( *(m_ui->m_listFlags), static_cast< PartitionTable::Flags >( ~PartitionTable::Flags::Int(0) ), partition ? PartitionInfo::flags( partition ) : PartitionTable::Flags() );
// Checks the initial selection. // Checks the initial selection.
checkMountPointSelection(); checkMountPointSelection();
} }
@ -137,35 +134,9 @@ CreatePartitionDialog::~CreatePartitionDialog()
PartitionTable::Flags PartitionTable::Flags
CreatePartitionDialog::newFlags() const CreatePartitionDialog::newFlags() const
{ {
PartitionTable::Flags flags; return flagsFromList( *(m_ui->m_listFlags) );
for ( int i = 0; i < m_ui->m_listFlags->count(); i++ )
if ( m_ui->m_listFlags->item( i )->checkState() == Qt::Checked )
flags |= static_cast< PartitionTable::Flag >(
m_ui->m_listFlags->item( i )->data( Qt::UserRole ).toInt() );
return flags;
} }
void
CreatePartitionDialog::setupFlagsList()
{
int f = 1;
QString s;
while ( !( s = PartitionTable::flagName( static_cast< PartitionTable::Flag >( f ) ) ).isEmpty() )
{
QListWidgetItem* item = new QListWidgetItem( s );
m_ui->m_listFlags->addItem( item );
item->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
item->setData( Qt::UserRole, f );
item->setCheckState( Qt::Unchecked );
f <<= 1;
}
}
void void
CreatePartitionDialog::initMbrPartitionTypeUi() CreatePartitionDialog::initMbrPartitionTypeUi()
{ {
@ -246,7 +217,7 @@ CreatePartitionDialog::createPartition()
partition->setPartitionPath(m_device->deviceNode() + QStringLiteral("/") + m_ui->lvNameLineEdit->text().trimmed()); partition->setPartitionPath(m_device->deviceNode() + QStringLiteral("/") + m_ui->lvNameLineEdit->text().trimmed());
} }
PartitionInfo::setMountPoint( partition, m_ui->mountPointComboBox->currentText() ); PartitionInfo::setMountPoint( partition, selectedMountPoint( m_ui->mountPointComboBox ) );
PartitionInfo::setFormat( partition, true ); PartitionInfo::setFormat( partition, true );
return partition; return partition;
@ -283,9 +254,7 @@ CreatePartitionDialog::updateMountPointUi()
void void
CreatePartitionDialog::checkMountPointSelection() CreatePartitionDialog::checkMountPointSelection()
{ {
const QString& selection = m_ui->mountPointComboBox->currentText(); if ( m_usedMountPoints.contains( selectedMountPoint( m_ui->mountPointComboBox ) ) )
if ( m_usedMountPoints.contains( selection ) )
{ {
m_ui->labelMountPoint->setText( tr( "Mountpoint already in use. Please select another one." ) ); m_ui->labelMountPoint->setText( tr( "Mountpoint already in use. Please select another one." ) );
m_ui->buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false ); m_ui->buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );
@ -334,7 +303,7 @@ CreatePartitionDialog::initFromPartitionToCreate( Partition* partition )
m_ui->fsComboBox->setCurrentText( FileSystem::nameForType( fsType ) ); m_ui->fsComboBox->setCurrentText( FileSystem::nameForType( fsType ) );
// Mount point // Mount point
m_ui->mountPointComboBox->setCurrentText( PartitionInfo::mountPoint( partition ) ); setSelectedMountPoint( m_ui->mountPointComboBox, PartitionInfo::mountPoint( partition ) );
updateMountPointUi(); updateMountPointUi();
} }

View File

@ -42,7 +42,13 @@ class CreatePartitionDialog : public QDialog
{ {
Q_OBJECT Q_OBJECT
public: public:
CreatePartitionDialog( Device* device, PartitionNode* parentPartition, const QStringList& usedMountPoints, QWidget* parentWidget = nullptr ); /**
* @brief Dialog for editing a new partition.
*
* For the (unlikely) case that a newly created partition is being re-edited,
* pass a pointer to that @p partition, otherwise pass nullptr.
*/
CreatePartitionDialog( Device* device, PartitionNode* parentPartition, Partition* partition, const QStringList& usedMountPoints, QWidget* parentWidget = nullptr );
~CreatePartitionDialog(); ~CreatePartitionDialog();
/** /**
@ -64,7 +70,6 @@ private Q_SLOTS:
void checkMountPointSelection(); void checkMountPointSelection();
private: private:
void setupFlagsList();
QScopedPointer< Ui_CreatePartitionDialog > m_ui; QScopedPointer< Ui_CreatePartitionDialog > m_ui;
PartitionSizeController* m_partitionSizeController; PartitionSizeController* m_partitionSizeController;
Device* m_device; Device* m_device;

View File

@ -28,6 +28,7 @@
#include <core/PartitionInfo.h> #include <core/PartitionInfo.h>
#include "core/PartUtils.h" #include "core/PartUtils.h"
#include <core/KPMHelpers.h> #include <core/KPMHelpers.h>
#include "gui/PartitionDialogHelpers.h"
#include <gui/PartitionSizeController.h> #include <gui/PartitionSizeController.h>
#include <ui_EditExistingPartitionDialog.h> #include <ui_EditExistingPartitionDialog.h>
@ -55,19 +56,12 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit
, m_usedMountPoints( usedMountPoints ) , m_usedMountPoints( usedMountPoints )
{ {
m_ui->setupUi( this ); m_ui->setupUi( this );
standardMountPoints( *(m_ui->mountPointComboBox), PartitionInfo::mountPoint( partition ) );
QStringList mountPoints = { "/", "/boot", "/home", "/opt", "/usr", "/var" };
if ( PartUtils::isEfiSystem() )
mountPoints << Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString();
mountPoints.removeDuplicates();
mountPoints.sort();
m_ui->mountPointComboBox->addItems( mountPoints );
QColor color = ColorUtils::colorForPartition( m_partition ); QColor color = ColorUtils::colorForPartition( m_partition );
m_partitionSizeController->init( m_device, m_partition, color ); m_partitionSizeController->init( m_device, m_partition, color );
m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox ); m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox );
m_ui->mountPointComboBox->setCurrentText( PartitionInfo::mountPoint( partition ) );
connect( m_ui->mountPointComboBox, &QComboBox::currentTextChanged, connect( m_ui->mountPointComboBox, &QComboBox::currentTextChanged,
this, &EditExistingPartitionDialog::checkMountPointSelection ); this, &EditExistingPartitionDialog::checkMountPointSelection );
@ -112,7 +106,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit
m_ui->fileSystemLabel->setEnabled( m_ui->formatRadioButton->isChecked() ); m_ui->fileSystemLabel->setEnabled( m_ui->formatRadioButton->isChecked() );
m_ui->fileSystemComboBox->setEnabled( m_ui->formatRadioButton->isChecked() ); m_ui->fileSystemComboBox->setEnabled( m_ui->formatRadioButton->isChecked() );
setupFlagsList(); setFlagList( *(m_ui->m_listFlags), m_partition->availableFlags(), PartitionInfo::flags( m_partition ) );
} }
@ -123,44 +117,13 @@ EditExistingPartitionDialog::~EditExistingPartitionDialog()
PartitionTable::Flags PartitionTable::Flags
EditExistingPartitionDialog::newFlags() const EditExistingPartitionDialog::newFlags() const
{ {
PartitionTable::Flags flags; return flagsFromList( *(m_ui->m_listFlags) );
for ( int i = 0; i < m_ui->m_listFlags->count(); i++ )
if ( m_ui->m_listFlags->item( i )->checkState() == Qt::Checked )
flags |= static_cast< PartitionTable::Flag >(
m_ui->m_listFlags->item( i )->data( Qt::UserRole ).toInt() );
return flags;
} }
void
EditExistingPartitionDialog::setupFlagsList()
{
int f = 1;
QString s;
while ( !( s = PartitionTable::flagName( static_cast< PartitionTable::Flag >( f ) ) ).isEmpty() )
{
if ( m_partition->availableFlags() & f )
{
QListWidgetItem* item = new QListWidgetItem( s );
m_ui->m_listFlags->addItem( item );
item->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
item->setData( Qt::UserRole, f );
item->setCheckState( ( m_partition->activeFlags() & f ) ?
Qt::Checked :
Qt::Unchecked );
}
f <<= 1;
}
}
void void
EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core )
{ {
PartitionInfo::setMountPoint( m_partition, m_ui->mountPointComboBox->currentText() ); PartitionInfo::setMountPoint( m_partition, selectedMountPoint(m_ui->mountPointComboBox) );
qint64 newFirstSector = m_partitionSizeController->firstSector(); qint64 newFirstSector = m_partitionSizeController->firstSector();
qint64 newLastSector = m_partitionSizeController->lastSector(); qint64 newLastSector = m_partitionSizeController->lastSector();
@ -294,15 +257,13 @@ EditExistingPartitionDialog::updateMountPointPicker()
m_ui->mountPointLabel->setEnabled( canMount ); m_ui->mountPointLabel->setEnabled( canMount );
m_ui->mountPointComboBox->setEnabled( canMount ); m_ui->mountPointComboBox->setEnabled( canMount );
if ( !canMount ) if ( !canMount )
m_ui->mountPointComboBox->setCurrentText( QString() ); setSelectedMountPoint( m_ui->mountPointComboBox, QString() );
} }
void void
EditExistingPartitionDialog::checkMountPointSelection() EditExistingPartitionDialog::checkMountPointSelection()
{ {
const QString& selection = m_ui->mountPointComboBox->currentText(); if ( m_usedMountPoints.contains( selectedMountPoint( m_ui->mountPointComboBox ) ) )
if ( m_usedMountPoints.contains( selection ) )
{ {
m_ui->labelMountPoint->setText( tr( "Mountpoint already in use. Please select another one." ) ); m_ui->labelMountPoint->setText( tr( "Mountpoint already in use. Please select another one." ) );
m_ui->buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false ); m_ui->buttonBox->button( QDialogButtonBox::Ok )->setEnabled( false );

View File

@ -56,7 +56,6 @@ private:
QStringList m_usedMountPoints; QStringList m_usedMountPoints;
PartitionTable::Flags newFlags() const; PartitionTable::Flags newFlags() const;
void setupFlagsList();
void replacePartResizerWidget(); void replacePartResizerWidget();
void updateMountPointPicker(); void updateMountPointPicker();
}; };

View File

@ -0,0 +1,118 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2018, Adriaan de Groot <groot@kde.org>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Calamares is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#include "PartitionDialogHelpers.h"
#include "core/PartUtils.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "utils/Logger.h"
#include <QComboBox>
#include <QListWidget>
QStringList
standardMountPoints()
{
QStringList mountPoints{ "/", "/boot", "/home", "/opt", "/srv", "/usr", "/var" };
if ( PartUtils::isEfiSystem() )
mountPoints << Calamares::JobQueue::instance()->globalStorage()->value( "efiSystemPartition" ).toString();
mountPoints.removeDuplicates();
mountPoints.sort();
return mountPoints;
}
void
standardMountPoints(QComboBox& combo)
{
combo.clear();
combo.addItem( combo.tr( "(no mount point)" ) );
combo.addItems( standardMountPoints() );
}
void
standardMountPoints(QComboBox& combo, const QString& selected)
{
standardMountPoints( combo );
setSelectedMountPoint( combo, selected );
}
QString
selectedMountPoint(QComboBox& combo)
{
if ( combo.currentIndex() == 0 )
return QString();
return combo.currentText();
}
void
setSelectedMountPoint(QComboBox& combo, const QString& selected)
{
if ( selected.isEmpty() )
combo.setCurrentIndex( 0 ); // (no mount point)
else
{
for ( int i = 0; i < combo.count(); ++i )
if ( selected == combo.itemText( i ) )
{
combo.setCurrentIndex( i );
return;
}
combo.addItem( selected );
combo.setCurrentIndex( combo.count() - 1);
}
}
PartitionTable::Flags
flagsFromList( const QListWidget& list )
{
PartitionTable::Flags flags;
for ( int i = 0; i < list.count(); i++ )
if ( list.item( i )->checkState() == Qt::Checked )
flags |= static_cast< PartitionTable::Flag >(
list.item( i )->data( Qt::UserRole ).toInt() );
return flags;
}
void
setFlagList( QListWidget& list, PartitionTable::Flags available, PartitionTable::Flags checked )
{
int f = 1;
QString s;
while ( !( s = PartitionTable::flagName( static_cast< PartitionTable::Flag >( f ) ) ).isEmpty() )
{
if ( available & f )
{
QListWidgetItem* item = new QListWidgetItem( s );
list.addItem( item );
item->setFlags( Qt::ItemIsUserCheckable | Qt::ItemIsEnabled );
item->setData( Qt::UserRole, f );
item->setCheckState( ( checked & f ) ?
Qt::Checked :
Qt::Unchecked );
}
f <<= 1;
}
}

View File

@ -0,0 +1,68 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2014, Aurélien Gâteau <agateau@kde.org>
* Copyright 2016, Teo Mrnjavac <teo@kde.org>
* Copyright 2018, Adriaan de Groot <groot@kde.org>
*
* Calamares is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Calamares is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef PARTITION_GUI_PARTITIONDIALOGHELPERS
#define PARTITION_GUI_PARTITIONDIALOGHELPERS
#include <kpmcore/core/partitiontable.h>
#include <QStringList>
class QComboBox;
class QListWidget;
/**
* Returns a list of standard mount points (e.g. /, /usr, ...).
* This also includes the EFI mount point if that is necessary
* on the target system.
*/
QStringList standardMountPoints();
/**
* Clears the combobox and fills it with "(no mount point)"
* and the elements of standardMountPoints(), above.
*/
void standardMountPoints( QComboBox& );
/**
* As above, but also sets the displayed mount point to @p selected,
* unless it is empty, in which case "(no mount point)" is chosen.
*/
void standardMountPoints( QComboBox&, const QString& selected );
/**
* Get the mount point selected in the combo box (which should
* have been set up with standardMountPoints(), above); this
* will map the topmost item (i.e. "(no mount point)") back
* to blank, to allow easy detection of no-mount-selected.
*/
QString selectedMountPoint( QComboBox& combo );
static inline QString selectedMountPoint(QComboBox* combo) { return selectedMountPoint(*combo); }
void setSelectedMountPoint( QComboBox& combo, const QString& selected );
static inline void setSelectedMountPoint(QComboBox* combo, const QString& selected) { setSelectedMountPoint( *combo, selected); }
/**
* Get the flags that have been checked in the list widget.
*/
PartitionTable::Flags flagsFromList( const QListWidget& list );
void setFlagList( QListWidget& list, PartitionTable::Flags available, PartitionTable::Flags checked );
#endif

View File

@ -34,6 +34,7 @@
#include "ui_PartitionPage.h" #include "ui_PartitionPage.h"
#include "ui_CreatePartitionTableDialog.h" #include "ui_CreatePartitionTableDialog.h"
#include "utils/Logger.h"
#include "utils/Retranslator.h" #include "utils/Retranslator.h"
#include "Branding.h" #include "Branding.h"
#include "JobQueue.h" #include "JobQueue.h"
@ -178,6 +179,29 @@ PartitionPage::onNewPartitionTableClicked()
updateBootLoaderIndex(); updateBootLoaderIndex();
} }
bool
PartitionPage::checkCanCreate( Device* device )
{
auto table = device->partitionTable();
if ( table->type() == PartitionTable::msdos ||table->type() == PartitionTable::msdos_sectorbased )
{
cDebug() << "Checking MSDOS partition" << table->numPrimaries() << "primaries, max" << table->maxPrimaries();
if ( ( table->numPrimaries() >= table->maxPrimaries() ) && !table->hasExtended() )
{
QMessageBox::warning( this, tr( "Can not create new partition" ),
tr( "The partition table on %1 already has %2 primary partitions, and no more can be added. "
"Please remove one primary partition and add an extended partition, instead." ).arg( device->name() ).arg( table->numPrimaries() )
);
return false;
}
return true;
}
else
return true; // GPT is fine
}
void void
PartitionPage::onCreateClicked() PartitionPage::onCreateClicked()
{ {
@ -188,8 +212,12 @@ PartitionPage::onCreateClicked()
Partition* partition = model->partitionForIndex( index ); Partition* partition = model->partitionForIndex( index );
Q_ASSERT( partition ); Q_ASSERT( partition );
if ( !checkCanCreate( model->device() ) )
return;
QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( model->device(), QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( model->device(),
partition->parent(), partition->parent(),
nullptr,
getCurrentUsedMountpoints(), getCurrentUsedMountpoints(),
this ); this );
dlg->initFromFreeSpace( partition ); dlg->initFromFreeSpace( partition );
@ -285,6 +313,7 @@ PartitionPage::updatePartitionToCreate( Device* device, Partition* partition )
QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( device, QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( device,
partition->parent(), partition->parent(),
partition,
mountPoints, mountPoints,
this ); this );
dlg->initFromPartitionToCreate( partition ); dlg->initFromPartitionToCreate( partition );

View File

@ -62,6 +62,14 @@ private:
void updateFromCurrentDevice(); void updateFromCurrentDevice();
void updateBootLoaderIndex(); void updateBootLoaderIndex();
/**
* @brief Check if a new partition can be created (as primary) on the device.
*
* Returns true if a new partition can be created on the device. Provides
* a warning popup and returns false if it cannot.
*/
bool checkCanCreate( Device* );
QStringList getCurrentUsedMountpoints(); QStringList getCurrentUsedMountpoints();
QMutex m_revertMutex; QMutex m_revertMutex;