diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index 08278a3b6..a135b758f 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -26,6 +26,8 @@ #include "utils/CalamaresUtilsSystem.h" #include "utils/Units.h" +#include "utils/NamedEnum.h" + #include "JobQueue.h" #include "utils/Logger.h" @@ -248,4 +250,35 @@ doReplacePartition( PartitionCoreModule* core, core->dumpQueue(); } +namespace Choices +{ +static const NamedEnumTable& +nameTable() +{ + static const NamedEnumTable names{ + { QStringLiteral( "none" ), SwapChoice::NoSwap }, + { QStringLiteral( "small" ), SwapChoice::SmallSwap }, + { QStringLiteral( "suspend" ), SwapChoice::FullSwap }, + { QStringLiteral( "reuse" ), SwapChoice::ReuseSwap }, + { QStringLiteral( "file" ), SwapChoice::SwapFile } + }; + + return names; } + +SwapChoice +nameToChoice( QString name, bool& ok ) +{ + return nameTable().find( name, ok ); +} + +QString +choiceToName( SwapChoice c ) +{ + bool ok = false; + return nameTable().find( c, ok ); +} + +} // namespace Choices + +} // namespace PartitionActions diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index 1c543854b..179b835ab 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -43,6 +43,9 @@ namespace Choices SwapFile // use a file (if supported) }; + SwapChoice nameToChoice( QString name, bool& ok ); + QString choiceToName( SwapChoice ); + struct ReplacePartitionOptions { QString defaultFsType; // e.g. "ext4" or "btrfs" diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 2fd932e0c..1ef1a00e5 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -66,14 +66,30 @@ using PartitionActions::Choices::SwapChoice; +/** @brief Given a set of swap choices, return a sensible value from it. + * + * "Sensible" here means: if there is one value, use it; otherwise, use + * NoSwap if there are no choices, or if NoSwap is one of the choices, in the set. + * If that's not possible, any value from the set. + */ +SwapChoice pickOne( const SwapChoiceSet& s ) +{ + if ( s.count() == 0 ) + return SwapChoice::NoSwap; + if ( s.count() == 1 ) + return *( s.begin() ); + if ( s.contains( SwapChoice::NoSwap ) ) + return SwapChoice::NoSwap; + // Here, count > 1 but NoSwap is not a member. + return *( s.begin() ); +} + /** * @brief ChoicePage::ChoicePage is the default constructor. Called on startup as part of * the module loading code path. - * @param compactMode if true, the drive selector will be a combo box on top, otherwise it - * will show up as a list view. * @param parent the QWidget parent. */ -ChoicePage::ChoicePage( QWidget* parent ) +ChoicePage::ChoicePage( const SwapChoiceSet& swapChoices, QWidget* parent ) : QWidget( parent ) , m_nextEnabled( false ) , m_core( nullptr ) @@ -85,8 +101,6 @@ ChoicePage::ChoicePage( QWidget* parent ) , m_replaceButton( nullptr ) , m_somethingElseButton( nullptr ) , m_eraseSwapChoices( nullptr ) - , m_replaceSwapChoices( nullptr ) - , m_alongsideSwapChoices( nullptr ) , m_deviceInfoWidget( nullptr ) , m_beforePartitionBarsView( nullptr ) , m_beforePartitionLabelsView( nullptr ) @@ -94,18 +108,17 @@ ChoicePage::ChoicePage( QWidget* parent ) , m_lastSelectedDeviceIndex( -1 ) , m_enableEncryptionWidget( true ) , m_allowManualPartitioning( true ) + , m_availableSwapChoices( swapChoices ) + , m_eraseSwapChoice( pickOne( swapChoices ) ) { setupUi( this ); - m_defaultFsType = Calamares::JobQueue::instance()-> - globalStorage()-> - value( "defaultFileSystemType" ).toString(); - m_enableEncryptionWidget = Calamares::JobQueue::instance()-> - globalStorage()-> - value( "enableLuksAutomatedPartitioning" ).toBool(); - m_allowManualPartitioning = Calamares::JobQueue::instance()-> - globalStorage()-> - value( "allowManualPartitioning" ).toBool(); + auto gs = Calamares::JobQueue::instance()->globalStorage(); + + m_defaultFsType = gs->value( "defaultFileSystemType" ).toString(); + m_enableEncryptionWidget = gs->value( "enableLuksAutomatedPartitioning" ).toBool(); + m_allowManualPartitioning = gs->value( "allowManualPartitioning" ).toBool(); + if ( FileSystem::typeForName( m_defaultFsType ) == FileSystem::Unknown ) m_defaultFsType = "ext4"; @@ -147,7 +160,7 @@ ChoicePage::ChoicePage( QWidget* parent ) m_previewAfterFrame->hide(); m_encryptWidget->hide(); m_reuseHomeCheckBox->hide(); - Calamares::JobQueue::instance()->globalStorage()->insert( "reuseHome", false ); + gs->insert( "reuseHome", false ); } @@ -191,11 +204,12 @@ ChoicePage::init( PartitionCoreModule* core ) * No texts are set -- that happens later by the translator functions. */ static inline QComboBox* -createCombo( std::initializer_list< SwapChoice > l ) +createCombo( const QSet< SwapChoice >& s ) { QComboBox* box = new QComboBox; - for ( SwapChoice c : l ) - box->addItem( QString(), c ); + for ( SwapChoice c : { SwapChoice::NoSwap, SwapChoice::SmallSwap, SwapChoice::FullSwap, SwapChoice::ReuseSwap, SwapChoice::SwapFile } ) + if ( s.contains( c ) ) + box->addItem( QString(), c ); return box; } @@ -254,26 +268,17 @@ ChoicePage::setupChoices() // Fill up swap options // .. TODO: only if enabled in the config - m_eraseSwapChoices = createCombo( { SwapChoice::NoSwap, SwapChoice::SmallSwap, SwapChoice::FullSwap } ); - m_eraseButton->addOptionsComboBox( m_eraseSwapChoices ); - -#if 0 - m_replaceSwapChoices = createCombo( { SwapChoice::NoSwap, SwapChoice::ReuseSwap, SwapChoice::SmallSwap, SwapChoice::FullSwap } ); - m_replaceButton->addOptionsComboBox( m_replaceSwapChoices ); - - m_alongsideSwapChoices = createCombo( { SwapChoice::NoSwap, SwapChoice::ReuseSwap, SwapChoice::SmallSwap, SwapChoice::FullSwap } ); - m_alongsideButton->addOptionsComboBox( m_alongsideSwapChoices ); -#endif + if ( m_availableSwapChoices.count() > 1 ) + { + m_eraseSwapChoices = createCombo( m_availableSwapChoices ); + m_eraseButton->addOptionsComboBox( m_eraseSwapChoices ); + } m_itemsLayout->addWidget( m_alongsideButton ); m_itemsLayout->addWidget( m_replaceButton ); m_itemsLayout->addWidget( m_eraseButton ); m_somethingElseButton = new PrettyRadioButton; - CALAMARES_RETRANSLATE( - m_somethingElseButton->setText( tr( "Manual partitioning
" - "You can create or resize partitions yourself." ) ); - ) m_somethingElseButton->setIconSize( iconSize ); m_somethingElseButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionManual, CalamaresUtils::Original, @@ -283,7 +288,7 @@ ChoicePage::setupChoices() m_itemsLayout->addStretch(); - connect( m_grp, static_cast< void( QButtonGroup::* )( int, bool ) >( &QButtonGroup::buttonToggled ), + connect( m_grp, QOverload::of( &QButtonGroup::buttonToggled ), this, [ this ]( int id, bool checked ) { if ( checked ) // An action was picked. @@ -310,19 +315,15 @@ ChoicePage::setupChoices() m_rightLayout->setStretchFactor( m_previewAfterFrame, 0 ); connect( this, &ChoicePage::actionChosen, - this, [=] - { - Device* currd = selectedDevice(); - if ( currd ) - { - applyActionChoice( currentChoice() ); - } - } ); + this, &ChoicePage::onActionChanged ); + if ( m_eraseSwapChoices ) + connect( m_eraseSwapChoices, QOverload::of(&QComboBox::currentIndexChanged), + this, &ChoicePage::onActionChanged ); CALAMARES_RETRANSLATE( + m_somethingElseButton->setText( tr( "Manual partitioning
" + "You can create or resize partitions yourself." ) ); updateSwapChoicesTr( m_eraseSwapChoices ); - updateSwapChoicesTr( m_alongsideSwapChoices ); - updateSwapChoicesTr( m_replaceSwapChoices ); ) } @@ -417,6 +418,17 @@ ChoicePage::continueApplyDeviceChoice() } +void +ChoicePage::onActionChanged() +{ + Device* currd = selectedDevice(); + if ( currd ) + { + applyActionChoice( currentChoice() ); + } +} + + void ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice ) { @@ -505,7 +517,7 @@ ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice ) case Manual: break; } - updateActionChoicePreview( currentChoice() ); + updateActionChoicePreview( choice ); } @@ -1138,7 +1150,7 @@ ChoicePage::createBootloaderComboBox( QWidget* parent ) bcb->setModel( m_core->bootLoaderModel() ); // When the chosen bootloader device changes, we update the choice in the PCM - connect( bcb, static_cast< void (QComboBox::*)(int) >( &QComboBox::currentIndexChanged ), + connect( bcb, QOverload::of( &QComboBox::currentIndexChanged ), this, [this]( int newIndex ) { QComboBox* bcb = qobject_cast< QComboBox* >( sender() ); diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index 34154d7d5..0d25c61ee 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -26,9 +26,11 @@ #include #include "core/OsproberEntry.h" +#include "core/PartitionActions.h" #include #include +#include class QBoxLayout; class QComboBox; @@ -44,6 +46,7 @@ class DeviceInfoWidget; class Device; +using SwapChoiceSet = QSet< PartitionActions::Choices::SwapChoice >; /** * @brief The ChoicePage class is the first page of the partitioning interface. @@ -63,7 +66,7 @@ public: Manual }; - explicit ChoicePage( QWidget* parent = nullptr ); + explicit ChoicePage( const SwapChoiceSet& swapChoices, QWidget* parent = nullptr ); virtual ~ChoicePage(); /** @@ -113,6 +116,9 @@ private slots: void onEncryptWidgetStateChanged(); void onHomeCheckBoxStateChanged(); + /** @brief Calls applyActionChoice() as needed. */ + void onActionChanged(); + private: void updateNextEnabled(); void setupChoices(); @@ -149,9 +155,7 @@ private: PrettyRadioButton* m_eraseButton; PrettyRadioButton* m_replaceButton; PrettyRadioButton* m_somethingElseButton; - QComboBox* m_eraseSwapChoices; - QComboBox* m_replaceSwapChoices; - QComboBox* m_alongsideSwapChoices; + QComboBox* m_eraseSwapChoices; // UI, see also m_swapChoices DeviceInfoWidget* m_deviceInfoWidget; @@ -168,6 +172,8 @@ private: QString m_defaultFsType; bool m_enableEncryptionWidget; + SwapChoiceSet m_availableSwapChoices; // What is available + PartitionActions::Choices::SwapChoice m_eraseSwapChoice; // what is selected bool m_allowManualPartitioning; diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 759b686db..503924860 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -93,7 +93,7 @@ PartitionViewStep::continueLoading() Q_ASSERT( !m_manualPartitionPage ); m_manualPartitionPage = new PartitionPage( m_core ); - m_choicePage = new ChoicePage(); + m_choicePage = new ChoicePage( m_swapChoices ); m_choicePage->init( m_core ); @@ -586,7 +586,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) for ( const auto& item : l ) { bool ok = false; - auto v = nameToChoice( item, ok ); + auto v = PartitionActions::Choices::nameToChoice( item, ok ); if ( ok ) choices.insert( v ); } @@ -612,6 +612,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) else choices.insert( PartitionActions::Choices::SwapChoice::SmallSwap ); } + m_swapChoices = choices; // These gs settings seem to be unused (in upstream Calamares) outside of // the partition module itself. diff --git a/src/modules/partition/gui/PartitionViewStep.h b/src/modules/partition/gui/PartitionViewStep.h index dfd0310b3..f23108316 100644 --- a/src/modules/partition/gui/PartitionViewStep.h +++ b/src/modules/partition/gui/PartitionViewStep.h @@ -26,7 +26,10 @@ #include +#include "core/PartitionActions.h" + #include +#include class ChoicePage; class PartitionPage; @@ -76,6 +79,8 @@ private: PartitionPage* m_manualPartitionPage; QWidget* m_waitingWidget; + + QSet< PartitionActions::Choices::SwapChoice > m_swapChoices; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionViewStepFactory ) diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index a7483f36f..f812b67aa 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -26,10 +26,10 @@ efiSystemPartition: "/boot/efi" # 8.8GiB on disk in the end). userSwapChoices: - none # Create no swap, use no swap - # - reuse # Re-use existing swap, but don't create any + - reuse # Re-use existing swap, but don't create any - small # Up to 4GB - suspend # At least main memory size - # - file # To swap file instead of partition (unsupported right now) + - file # To swap file instead of partition (unsupported right now) # LEGACY SETTINGS (these will generate a warning) # ensureSuspendToDisk: true