From e0cd90cab1624796ed12abb424422e726113185c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 11 Sep 2018 10:05:37 -0400 Subject: [PATCH 02/22] Update the documentation and implementation of swap calculation. Make the ramps consistent between suspend-to-disk and not, and don't do the weird drop from 8GiB swap down to 4GiB for large-memory systems. --- .../partition/core/PartitionActions.cpp | 55 ++++++------------- src/modules/partition/partition.conf | 16 ++++-- 2 files changed, 28 insertions(+), 43 deletions(-) diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index d35345424..99c231b1b 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -45,17 +45,7 @@ using CalamaresUtils::operator""_MiB; qint64 swapSuggestion( const qint64 availableSpaceB ) { - /* If suspend-to-disk is demanded, then we always need enough - * swap to write the whole memory to disk -- between 2GB and 8GB - * RAM give proportionally more swap, and from 8GB RAM keep - * swap = RAM. - * - * If suspend-to-disk is not demanded, then ramp up more slowly, - * to 8GB swap at 16GB memory, and then drop to 4GB for "large - * memory" machines, on the assumption that those don't need swap - * because they have tons of memory (or whatever they are doing, - * had better not run into swap). - */ + // See partition.conf for explanation qint64 suggestedSwapSizeB = 0; auto memory = CalamaresUtils::System::instance()->getTotalMemoryB(); qint64 availableRamB = memory.first; @@ -65,36 +55,25 @@ swapSuggestion( const qint64 availableSpaceB ) Calamares::JobQueue::instance()->globalStorage()-> value( "ensureSuspendToDisk" ).toBool(); - if ( ensureSuspendToDisk ) - { - if ( availableRamB < 4_GiB ) - suggestedSwapSizeB = qMax( 2_GiB, availableRamB * 2 ); - else if ( availableRamB >= 4_GiB && availableRamB < 8_GiB ) - suggestedSwapSizeB = 8_GiB; - else - suggestedSwapSizeB = availableRamB; + // Ramp up quickly to 8GiB, then follow memory size + if ( availableRamB <= 4_GiB ) + suggestedSwapSizeB = availableRamB * 2; + else if ( availableRamB <= 8_GiB ) + suggestedSwapSizeB = 8_GiB; + else + suggestedSwapSizeB = availableRamB; - suggestedSwapSizeB *= overestimationFactor; - } - else //if we don't care about suspend to disk - { - if ( availableRamB < 2_GiB ) - suggestedSwapSizeB = qMax( 2_GiB, availableRamB * 2 ); - else if ( availableRamB >= 2_GiB && availableRamB < 8_GiB ) - suggestedSwapSizeB = availableRamB; - else if ( availableRamB >= 8_GiB && availableRamB < 16_GiB ) - suggestedSwapSizeB = 8_GiB; - else - suggestedSwapSizeB = 4_GiB; + // .. top out at 8GiB if we don't care about suspend + if ( !ensureSuspendToDisk ) + suggestedSwapSizeB = qMin( 8_GiB, suggestedSwapSizeB ); - suggestedSwapSizeB *= overestimationFactor; - // don't use more than 10% of available space - qreal maxSwapDiskRatio = 0.10; - qint64 maxSwapSizeB = availableSpaceB * maxSwapDiskRatio; - if ( suggestedSwapSizeB > maxSwapSizeB ) - suggestedSwapSizeB = maxSwapSizeB; - } + // Allow for a fudge factor + suggestedSwapSizeB *= overestimationFactor; + + // don't use more than 10% of available space + if ( !ensureSuspendToDisk ) + suggestedSwapSizeB = qMin( suggestedSwapSizeB, qint64( 0.10 * availableSpaceB ) ); cDebug() << "Suggested swap size:" << suggestedSwapSizeB / 1024. / 1024. / 1024. << "GiB"; diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index 78ad82f10..3e0ce5950 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -6,11 +6,17 @@ efiSystemPartition: "/boot/efi" # Make sure an autogenerated swap partition is big enough for hibernation in # automated partitioning modes. Swap can be disabled through *neverCreateSwap*. # -# When *ensureSuspendToDisk* is true, swap is never smaller than physical -# memory, follows the guideline 2 * memory until swap reaches 8GiB. -# When *ensureSuspendToDisk* is false, swap size scales up with memory -# size until 8GiB, then at roughly half of memory size. -# +# - *neverCreateSwap* is true: no swap is created +# - *neverCreateSwap* is false (the default): swap is created, as follows: +# - *ensureSuspendToDisk* is true (default): Swap is always at least total +# memory size, and up to 4GiB RAM follows the rule-of-thumb 2 * memory; +# from 4GiB to 8 GiB it stays steady at 8GiB, and over 8 GiB memory +# swap is the size of main memory. +# - *ensureSuspendToDisk* is false: Follows the rules above, but Swap is at +# most 8GiB, and no more than 10% of available disk. +# In both cases, a fudge factor (usually 10% extra) is applied so that there +# is some space for administrative overhead (e.g. 8 GiB swap will allocate +# 8.8GiB on disk in the end). # # Default is true. ensureSuspendToDisk: true From c8133759081ed4cf1e8e50eaa7d3de03a508620f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Sep 2018 08:09:01 -0400 Subject: [PATCH 03/22] [partition] Prepare for swap options - Extend PrettyRadioButton with options (combo-boxes which may be added later). --- .../partition/gui/PrettyRadioButton.cpp | 21 +++++++++++++------ src/modules/partition/gui/PrettyRadioButton.h | 13 ++++++++++++ 2 files changed, 28 insertions(+), 6 deletions(-) diff --git a/src/modules/partition/gui/PrettyRadioButton.cpp b/src/modules/partition/gui/PrettyRadioButton.cpp index a697ed270..be09f5753 100644 --- a/src/modules/partition/gui/PrettyRadioButton.cpp +++ b/src/modules/partition/gui/PrettyRadioButton.cpp @@ -21,15 +21,16 @@ #include "utils/CalamaresUtilsGui.h" #include "widgets/ClickableLabel.h" +#include +#include #include -#include PrettyRadioButton::PrettyRadioButton( QWidget* parent ) : QWidget( parent ) { - QHBoxLayout* mainLayout = new QHBoxLayout; - setLayout( mainLayout ); + m_mainLayout = new QGridLayout; + setLayout( m_mainLayout ); m_radio = new QRadioButton; m_label = new ClickableLabel; @@ -41,9 +42,9 @@ PrettyRadioButton::PrettyRadioButton( QWidget* parent ) m_label->setWordWrap( true ); m_label->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - mainLayout->addWidget( m_radio ); - mainLayout->addWidget( m_label ); - mainLayout->setContentsMargins( 0, 0, 0, 0 ); + m_mainLayout->addWidget( m_radio, 0, 0 ); + m_mainLayout->addWidget( m_label, 0, 1, -1, 1 ); // Row span to right edge + m_mainLayout->setContentsMargins( 0, 0, 0, 0 ); } @@ -80,3 +81,11 @@ PrettyRadioButton::buttonWidget() const { return m_radio; } + +void +PrettyRadioButton::addOptionsComboBox( const QString& label, QComboBox* box ) +{ + int row = m_mainLayout->rowCount(); // Rows index from 0, count from 1 + m_mainLayout->addWidget( new QLabel( label ), row, 1 ); + m_mainLayout->addWidget( box, row, 2 ); +} diff --git a/src/modules/partition/gui/PrettyRadioButton.h b/src/modules/partition/gui/PrettyRadioButton.h index f475ce528..c5ed6b336 100644 --- a/src/modules/partition/gui/PrettyRadioButton.h +++ b/src/modules/partition/gui/PrettyRadioButton.h @@ -22,7 +22,16 @@ #include class ClickableLabel; +class QComboBox; +class QGridLayout; +/** @brief A radio button with fancy label next to it. + * + * The radio button itself can be retrieved with buttonWidget(), + * and the whole behaves a lot like a label. Extra options can be + * added to the display (options are hidden when the button is + * not selected) with addOptionsComboBox(). + */ class PrettyRadioButton : public QWidget { Q_OBJECT @@ -40,9 +49,13 @@ public: virtual QRadioButton* buttonWidget() const; + /** @brief Add an options drop-down to this button. */ + void addOptionsComboBox( const QString& label, QComboBox* ); + protected: ClickableLabel* m_label; QRadioButton* m_radio; + QGridLayout* m_mainLayout; }; #endif // PRETTYRADIOBUTTON_H From a791818a65de0281b12aedbf9178933ad94d472c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Sep 2018 08:18:45 -0400 Subject: [PATCH 04/22] [partition] Add swap drop-down - This is WIP; the drop-down contents should be customised, depending on configuration and the state of the device being installed-to. --- src/modules/partition/gui/ChoicePage.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index bef6e4966..b921941c2 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -172,6 +172,18 @@ ChoicePage::init( PartitionCoreModule* core ) ChoicePage::applyDeviceChoice(); } +static QComboBox* +swapSelectionCombo() +{ + QComboBox* box = new QComboBox; + box->addItem( box->tr( "No swap" ), 0 ); + box->addItem( box->tr( "Re-use swap" ), 1 ); + box->addItem( box->tr( "Limited swap" ), 2 ); + box->addItem( box->tr( "Full swap" ), 3 ); + box->addItem( box->tr( "Swap file" ), 4 ); + + return box; +} /** * @brief ChoicePage::setupChoices creates PrettyRadioButton objects for the action @@ -216,6 +228,7 @@ ChoicePage::setupChoices() m_eraseButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionEraseAuto, CalamaresUtils::Original, iconSize ) ); + m_eraseButton->addOptionsComboBox( tr( "Swap" ), swapSelectionCombo() ); m_grp->addButton( m_eraseButton->buttonWidget(), Erase ); m_replaceButton = new PrettyRadioButton; From dc492b301ce48e7cf0d28073debce7bc3056a9f9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Sep 2018 08:42:21 -0400 Subject: [PATCH 05/22] [partition] Drop label on swap-options box --- src/modules/partition/gui/ChoicePage.cpp | 2 +- src/modules/partition/gui/PrettyRadioButton.cpp | 5 ++--- src/modules/partition/gui/PrettyRadioButton.h | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index b921941c2..4dd214382 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -228,7 +228,7 @@ ChoicePage::setupChoices() m_eraseButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionEraseAuto, CalamaresUtils::Original, iconSize ) ); - m_eraseButton->addOptionsComboBox( tr( "Swap" ), swapSelectionCombo() ); + m_eraseButton->addOptionsComboBox( swapSelectionCombo() ); m_grp->addButton( m_eraseButton->buttonWidget(), Erase ); m_replaceButton = new PrettyRadioButton; diff --git a/src/modules/partition/gui/PrettyRadioButton.cpp b/src/modules/partition/gui/PrettyRadioButton.cpp index be09f5753..9be49fb82 100644 --- a/src/modules/partition/gui/PrettyRadioButton.cpp +++ b/src/modules/partition/gui/PrettyRadioButton.cpp @@ -83,9 +83,8 @@ PrettyRadioButton::buttonWidget() const } void -PrettyRadioButton::addOptionsComboBox( const QString& label, QComboBox* box ) +PrettyRadioButton::addOptionsComboBox( QComboBox* box ) { int row = m_mainLayout->rowCount(); // Rows index from 0, count from 1 - m_mainLayout->addWidget( new QLabel( label ), row, 1 ); - m_mainLayout->addWidget( box, row, 2 ); + m_mainLayout->addWidget( box, row, 1 ); } diff --git a/src/modules/partition/gui/PrettyRadioButton.h b/src/modules/partition/gui/PrettyRadioButton.h index c5ed6b336..1cb94c1a0 100644 --- a/src/modules/partition/gui/PrettyRadioButton.h +++ b/src/modules/partition/gui/PrettyRadioButton.h @@ -50,7 +50,7 @@ public: virtual QRadioButton* buttonWidget() const; /** @brief Add an options drop-down to this button. */ - void addOptionsComboBox( const QString& label, QComboBox* ); + void addOptionsComboBox( QComboBox* ); protected: ClickableLabel* m_label; From c3f3276188978f25b1e63c32ca639bacc2586fbe Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Sep 2018 09:20:44 -0400 Subject: [PATCH 06/22] [partition] Improve presentation of swap options --- .../partition/gui/PrettyRadioButton.cpp | 44 +++++++++++++++---- src/modules/partition/gui/PrettyRadioButton.h | 6 +++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/src/modules/partition/gui/PrettyRadioButton.cpp b/src/modules/partition/gui/PrettyRadioButton.cpp index 9be49fb82..cd3c6dd3b 100644 --- a/src/modules/partition/gui/PrettyRadioButton.cpp +++ b/src/modules/partition/gui/PrettyRadioButton.cpp @@ -23,28 +23,32 @@ #include #include +#include #include PrettyRadioButton::PrettyRadioButton( QWidget* parent ) : QWidget( parent ) + , m_radio( new QRadioButton ) + , m_label( new ClickableLabel ) + , m_mainLayout( new QGridLayout ) + , m_optionsLayout( nullptr ) { - m_mainLayout = new QGridLayout; setLayout( m_mainLayout ); - m_radio = new QRadioButton; - m_label = new ClickableLabel; - - connect( m_label, &ClickableLabel::clicked, - m_radio, &QRadioButton::click ); m_label->setBuddy( m_radio ); m_label->setWordWrap( true ); m_label->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); m_mainLayout->addWidget( m_radio, 0, 0 ); - m_mainLayout->addWidget( m_label, 0, 1, -1, 1 ); // Row span to right edge + m_mainLayout->addWidget( m_label, 0, 1 ); m_mainLayout->setContentsMargins( 0, 0, 0, 0 ); + + connect( m_label, &ClickableLabel::clicked, + m_radio, &QRadioButton::click ); + connect( m_radio, &QRadioButton::toggled, + this, &PrettyRadioButton::toggleOptions ); } @@ -85,6 +89,28 @@ PrettyRadioButton::buttonWidget() const void PrettyRadioButton::addOptionsComboBox( QComboBox* box ) { - int row = m_mainLayout->rowCount(); // Rows index from 0, count from 1 - m_mainLayout->addWidget( box, row, 1 ); + if ( !box ) + return; + + if ( !m_optionsLayout ) + { + QWidget* w = new QWidget; + m_optionsLayout = new QHBoxLayout; + m_optionsLayout->setAlignment( Qt::AlignmentFlag::AlignLeft ); + m_optionsLayout->addStretch( 1 ); + + w->setLayout( m_optionsLayout ); + m_mainLayout->addWidget( w, 1, 1 ); + + toggleOptions( m_radio->isChecked() ); + } + + m_optionsLayout->insertWidget( m_optionsLayout->count()-1, box ); +} + +void +PrettyRadioButton::toggleOptions( bool toggle ) +{ + if ( m_optionsLayout ) + m_optionsLayout->parentWidget()->setVisible( toggle ); } diff --git a/src/modules/partition/gui/PrettyRadioButton.h b/src/modules/partition/gui/PrettyRadioButton.h index 1cb94c1a0..c88c00728 100644 --- a/src/modules/partition/gui/PrettyRadioButton.h +++ b/src/modules/partition/gui/PrettyRadioButton.h @@ -24,6 +24,7 @@ class ClickableLabel; class QComboBox; class QGridLayout; +class QHBoxLayout; /** @brief A radio button with fancy label next to it. * @@ -52,10 +53,15 @@ public: /** @brief Add an options drop-down to this button. */ void addOptionsComboBox( QComboBox* ); +protected slots: + /// Options are hidden when the radio button is off + void toggleOptions( bool checked ); + protected: ClickableLabel* m_label; QRadioButton* m_radio; QGridLayout* m_mainLayout; + QHBoxLayout* m_optionsLayout; }; #endif // PRETTYRADIOBUTTON_H From 10f7bac2df3e650d097b5701f07d93828db933f6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Sep 2018 10:05:14 -0400 Subject: [PATCH 07/22] [partition] Reorder initialization --- src/modules/partition/gui/PrettyRadioButton.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/gui/PrettyRadioButton.cpp b/src/modules/partition/gui/PrettyRadioButton.cpp index cd3c6dd3b..18627f41c 100644 --- a/src/modules/partition/gui/PrettyRadioButton.cpp +++ b/src/modules/partition/gui/PrettyRadioButton.cpp @@ -29,8 +29,8 @@ PrettyRadioButton::PrettyRadioButton( QWidget* parent ) : QWidget( parent ) - , m_radio( new QRadioButton ) , m_label( new ClickableLabel ) + , m_radio( new QRadioButton ) , m_mainLayout( new QGridLayout ) , m_optionsLayout( nullptr ) { From 7d0451fe6924affe41d371b20a21016d3b3aa992 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Sep 2018 10:16:48 -0400 Subject: [PATCH 08/22] [partition] Rename Choice -> InstallChoice - There are more choices to be made (or to come) when partitioning, so don't take the most generic term for one enum. --- src/modules/partition/gui/ChoicePage.cpp | 8 ++++---- src/modules/partition/gui/ChoicePage.h | 10 +++++----- src/modules/partition/gui/PartitionViewStep.cpp | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 4dd214382..62ee27a7e 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -262,7 +262,7 @@ ChoicePage::setupChoices() { if ( checked ) // An action was picked. { - m_choice = static_cast< Choice >( id ); + m_choice = static_cast< InstallChoice >( id ); updateNextEnabled(); emit actionChosen(); @@ -386,7 +386,7 @@ ChoicePage::continueApplyDeviceChoice() void -ChoicePage::applyActionChoice( ChoicePage::Choice choice ) +ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice ) { m_beforePartitionBarsView->selectionModel()-> disconnect( SIGNAL( currentRowChanged( QModelIndex, QModelIndex ) ) ); @@ -901,7 +901,7 @@ ChoicePage::updateDeviceStatePreview() * @param choice the chosen partitioning action. */ void -ChoicePage::updateActionChoicePreview( ChoicePage::Choice choice ) +ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice ) { Device* currentDevice = selectedDevice(); Q_ASSERT( currentDevice ); @@ -1356,7 +1356,7 @@ ChoicePage::isNextEnabled() const } -ChoicePage::Choice +ChoicePage::InstallChoice ChoicePage::currentChoice() const { return m_choice; diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index c36747e93..d991e513a 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -53,7 +53,7 @@ class ChoicePage : public QWidget, private Ui::ChoicePage { Q_OBJECT public: - enum Choice + enum InstallChoice { NoChoice, Alongside, @@ -84,7 +84,7 @@ public: * currently selected partitioning mode (with a PrettyRadioButton). * @return the enum Choice value. */ - Choice currentChoice() const; + InstallChoice currentChoice() const; /** * @brief onLeave runs when control passes from this page to another one. @@ -95,7 +95,7 @@ public: * @brief applyActionChoice reacts to a choice of partitioning mode. * @param choice the partitioning action choice. */ - void applyActionChoice( ChoicePage::Choice choice ); + void applyActionChoice( ChoicePage::InstallChoice choice ); signals: void nextStatusChanged( bool ); @@ -121,7 +121,7 @@ private: void continueApplyDeviceChoice(); // .. called after scan void updateDeviceStatePreview(); - void updateActionChoicePreview( ChoicePage::Choice choice ); + void updateActionChoicePreview( ChoicePage::InstallChoice choice ); void setupActions(); OsproberEntryList getOsproberEntriesForDevice( Device* device ) const; void doAlongsideApply(); @@ -132,7 +132,7 @@ private: QMutex m_previewsMutex; - Choice m_choice; + InstallChoice m_choice; bool m_isEfi; QComboBox* m_drivesCombo; diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index b49b6c93b..6ad1a6c77 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -138,7 +138,7 @@ PartitionViewStep::createSummaryWidget() const widget->setLayout( mainLayout ); mainLayout->setMargin( 0 ); - ChoicePage::Choice choice = m_choicePage->currentChoice(); + ChoicePage::InstallChoice choice = m_choicePage->currentChoice(); QFormLayout* formLayout = new QFormLayout( widget ); const int MARGIN = CalamaresUtils::defaultFontHeight() / 2; From cfa940b35c8b09d9f7c491418cda9b6330466496 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Sep 2018 11:18:17 -0400 Subject: [PATCH 09/22] [partition] Support translations of swap choices - Introduce enum to indicate what is selected - Support translations - Fill selections for erase --- src/modules/partition/gui/ChoicePage.cpp | 69 +++++++++++++++++++----- src/modules/partition/gui/ChoicePage.h | 15 ++++++ 2 files changed, 70 insertions(+), 14 deletions(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 62ee27a7e..ab5a9316a 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -78,6 +78,9 @@ ChoicePage::ChoicePage( QWidget* parent ) , m_eraseButton( nullptr ) , m_replaceButton( nullptr ) , m_somethingElseButton( nullptr ) + , m_eraseSwapChoices( nullptr ) + , m_replaceSwapChoices( nullptr ) + , m_alongsideSwapChoices( nullptr ) , m_deviceInfoWidget( nullptr ) , m_beforePartitionBarsView( nullptr ) , m_beforePartitionLabelsView( nullptr ) @@ -172,19 +175,6 @@ ChoicePage::init( PartitionCoreModule* core ) ChoicePage::applyDeviceChoice(); } -static QComboBox* -swapSelectionCombo() -{ - QComboBox* box = new QComboBox; - box->addItem( box->tr( "No swap" ), 0 ); - box->addItem( box->tr( "Re-use swap" ), 1 ); - box->addItem( box->tr( "Limited swap" ), 2 ); - box->addItem( box->tr( "Full swap" ), 3 ); - box->addItem( box->tr( "Swap file" ), 4 ); - - return box; -} - /** * @brief ChoicePage::setupChoices creates PrettyRadioButton objects for the action * choices. @@ -228,7 +218,6 @@ ChoicePage::setupChoices() m_eraseButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionEraseAuto, CalamaresUtils::Original, iconSize ) ); - m_eraseButton->addOptionsComboBox( swapSelectionCombo() ); m_grp->addButton( m_eraseButton->buttonWidget(), Erase ); m_replaceButton = new PrettyRadioButton; @@ -239,6 +228,13 @@ ChoicePage::setupChoices() iconSize ) ); m_grp->addButton( m_replaceButton->buttonWidget(), Replace ); + // Fill up swap options + // .. TODO: only if enabled in the config + m_eraseSwapChoices = new QComboBox; + for ( SwapChoice c : { NoSwap, SmallSwap, FullSwap } ) + m_eraseSwapChoices->addItem( QString(), c ); + m_eraseButton->addOptionsComboBox( m_eraseSwapChoices ); + m_itemsLayout->addWidget( m_alongsideButton ); m_itemsLayout->addWidget( m_replaceButton ); m_itemsLayout->addWidget( m_eraseButton ); @@ -292,6 +288,12 @@ ChoicePage::setupChoices() applyActionChoice( currentChoice() ); } } ); + + CALAMARES_RETRANSLATE( + updateSwapChoicesTr( m_eraseSwapChoices ); + updateSwapChoicesTr( m_alongsideSwapChoices ); + updateSwapChoicesTr( m_replaceSwapChoices ); + ) } @@ -1404,3 +1406,42 @@ ChoicePage::updateNextEnabled() emit nextStatusChanged( enabled ); } +void +ChoicePage::updateSwapChoicesTr(QComboBox* box) +{ + if ( !box ) + return; + + static_assert(NoSwap == 0, "Enum values out-of-sync"); + for ( int index = 0; index < box->count(); ++index ) + { + bool ok = false; + int value = 0; + + switch ( value = box->itemData( index ).toInt( &ok ) ) + { + // case 0: + case NoSwap: + // toInt() returns 0 on failure, so check for ok + if ( ok ) // It was explicitly set to 0 + box->setItemText( index, tr( "No Swap" ) ); + else + cWarning() << "Box item" << index << box->itemText( index ) << "has non-integer role."; + break; + case ReuseSwap: + box->setItemText( index, tr( "Reuse Swap" ) ); + break; + case SmallSwap: + box->setItemText( index, tr( "Swap (no Hibernate)" ) ); + break; + case FullSwap: + box->setItemText( index, tr( "Swap (with Hibernate)" ) ); + break; + case SwapFile: + box->setItemText( index, tr( "Swap to file" ) ); + break; + default: + cWarning() << "Box item" << index << box->itemText( index ) << "has role" << value; + } + } +} diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index d991e513a..a8ff3a330 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -62,6 +62,15 @@ public: Manual }; + enum SwapChoice + { + NoSwap, // don't create any swap, don't use any + ReuseSwap, // don't create, but do use existing + SmallSwap, // up to 8GiB of swap + FullSwap, // ensureSuspendToDisk -- at least RAM size + SwapFile // use a file (if supported) + }; + explicit ChoicePage( QWidget* parent = nullptr ); virtual ~ChoicePage(); @@ -127,6 +136,9 @@ private: void doAlongsideApply(); void setupEfiSystemPartitionSelector(); + // Translations support + void updateSwapChoicesTr( QComboBox* box ); + bool m_nextEnabled; PartitionCoreModule* m_core; @@ -142,6 +154,9 @@ private: PrettyRadioButton* m_eraseButton; PrettyRadioButton* m_replaceButton; PrettyRadioButton* m_somethingElseButton; + QComboBox* m_eraseSwapChoices; + QComboBox* m_replaceSwapChoices; + QComboBox* m_alongsideSwapChoices; DeviceInfoWidget* m_deviceInfoWidget; From 959cd7b224585d67b4506f6b210987ffdbf5ff84 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 13 Sep 2018 04:44:36 -0400 Subject: [PATCH 10/22] [partition] Simplify creation of comboboxes for swap choices --- src/modules/partition/gui/ChoicePage.cpp | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index ab5a9316a..ccdc6920e 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -175,6 +175,20 @@ ChoicePage::init( PartitionCoreModule* core ) ChoicePage::applyDeviceChoice(); } + +/** @brief Creates a combobox with the given choices in it. + * + * No texts are set -- that happens later by the translator functions. + */ +static inline QComboBox* +createCombo( std::initializer_list< ChoicePage::SwapChoice > l ) +{ + QComboBox* box = new QComboBox; + for ( ChoicePage::SwapChoice c : l ) + box->addItem( QString(), c ); + return box; +} + /** * @brief ChoicePage::setupChoices creates PrettyRadioButton objects for the action * choices. @@ -230,11 +244,15 @@ ChoicePage::setupChoices() // Fill up swap options // .. TODO: only if enabled in the config - m_eraseSwapChoices = new QComboBox; - for ( SwapChoice c : { NoSwap, SmallSwap, FullSwap } ) - m_eraseSwapChoices->addItem( QString(), c ); + m_eraseSwapChoices = createCombo( { NoSwap, SmallSwap, FullSwap } ); m_eraseButton->addOptionsComboBox( m_eraseSwapChoices ); + m_replaceSwapChoices = createCombo( { NoSwap, ReuseSwap, SmallSwap, FullSwap } ); + m_replaceButton->addOptionsComboBox( m_replaceSwapChoices ); + + m_alongsideSwapChoices = createCombo( { NoSwap, ReuseSwap, SmallSwap, FullSwap } ); + m_alongsideButton->addOptionsComboBox( m_alongsideSwapChoices ); + m_itemsLayout->addWidget( m_alongsideButton ); m_itemsLayout->addWidget( m_replaceButton ); m_itemsLayout->addWidget( m_eraseButton ); From 8c79c981b112a53b58775e92a2d79e6d0bfd5b9a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 13 Sep 2018 05:33:39 -0400 Subject: [PATCH 11/22] [partition] Simplify space calculations - Q_ASSERT doesn't work in constexpr functions because it's not - May as well calculate bytes at compile-time, no need to give the runaround via number-of-MiB --- src/modules/partition/core/PartitionActions.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index 99c231b1b..7e488367f 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -83,10 +83,7 @@ swapSuggestion( const qint64 availableSpaceB ) constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) { - Q_ASSERT( bytes >= 0 ); - Q_ASSERT( blocksize > 0 ); qint64 blocks = bytes / blocksize; - Q_ASSERT( blocks >= 0 ); if ( blocks * blocksize != bytes ) ++blocks; @@ -114,17 +111,17 @@ doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPass // the logical sector size (usually 512B). EFI starts with 2MiB // empty and a 300MiB EFI boot partition, while BIOS starts at // the 1MiB boundary (usually sector 2048). - int uefisys_part_size = isEfi ? 300 : 0; - int empty_space_size = isEfi ? 2 : 1; + int uefisys_part_sizeB = isEfi ? 300_MiB : 0_MiB; + int empty_space_sizeB = isEfi ? 2_MiB : 1_MiB; // Since sectors count from 0, if the space is 2048 sectors in size, // the first free sector has number 2048 (and there are 2048 sectors // before that one, numbered 0..2047). - qint64 firstFreeSector = bytesToSectors( MiBtoBytes(empty_space_size), dev->logicalSize() ); + qint64 firstFreeSector = bytesToSectors( empty_space_sizeB, dev->logicalSize() ); if ( isEfi ) { - qint64 efiSectorCount = bytesToSectors( MiBtoBytes(uefisys_part_size), dev->logicalSize() ); + qint64 efiSectorCount = bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); Q_ASSERT( efiSectorCount > 0 ); // Since sectors count from 0, and this partition is created starting From 846e496d7666682d40d102a064e0cc8d24cdcfcb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 13 Sep 2018 05:50:46 -0400 Subject: [PATCH 12/22] [partition] Tidy includes --- src/modules/partition/gui/ChoicePage.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index ccdc6920e..4c5f7ff65 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -20,31 +20,32 @@ #include "ChoicePage.h" #include "core/BootLoaderModel.h" -#include "core/PartitionActions.h" -#include "core/PartitionCoreModule.h" #include "core/DeviceModel.h" -#include "core/PartitionModel.h" +#include "core/KPMHelpers.h" #include "core/OsproberEntry.h" #include "core/PartUtils.h" +#include "core/PartitionActions.h" +#include "core/PartitionCoreModule.h" +#include "core/PartitionInfo.h" #include "core/PartitionIterator.h" +#include "core/PartitionModel.h" -#include "ReplaceWidget.h" -#include "PrettyRadioButton.h" +#include "BootInfoWidget.h" +#include "DeviceInfoWidget.h" #include "PartitionBarsView.h" #include "PartitionLabelsView.h" #include "PartitionSplitterWidget.h" -#include "BootInfoWidget.h" -#include "DeviceInfoWidget.h" +#include "PrettyRadioButton.h" +#include "ReplaceWidget.h" #include "ScanningDialog.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" #include "utils/Retranslator.h" + #include "Branding.h" -#include "core/KPMHelpers.h" -#include "JobQueue.h" #include "GlobalStorage.h" -#include "core/PartitionInfo.h" +#include "JobQueue.h" #include #include From 513602141660deab76b228e7d6a741461e9d920f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 13 Sep 2018 06:23:33 -0400 Subject: [PATCH 13/22] [partition] Move SwapChoice to another namespace - The choice of swap needs to be handled in more places, so make the enum available in the partition module core instead of just inside the choice page. --- src/modules/partition/core/PartitionActions.h | 19 ++++++++++++++- src/modules/partition/gui/ChoicePage.cpp | 24 +++++++++---------- src/modules/partition/gui/ChoicePage.h | 9 ------- 3 files changed, 30 insertions(+), 22 deletions(-) diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index bb624552f..8312d582b 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -50,6 +50,23 @@ void doReplacePartition( PartitionCoreModule* core, Device* dev, Partition* partition, const QString& luksPassphrase = QString() ); -} + +/** @brief Namespace for enums + * + * This namespace houses non-class enums..... + */ +namespace Choices +{ + /** @brief Ccchoice of swap (size and type) */ + enum SwapChoice + { + NoSwap, // don't create any swap, don't use any + ReuseSwap, // don't create, but do use existing + SmallSwap, // up to 8GiB of swap + FullSwap, // ensureSuspendToDisk -- at least RAM size + SwapFile // use a file (if supported) + }; +} // namespace Choices +} // namespace PartitionActions #endif // PARTITIONACTIONS_H diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 4c5f7ff65..82302ac4c 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -59,7 +59,7 @@ #include #include - +using PartitionActions::Choices::SwapChoice; /** * @brief ChoicePage::ChoicePage is the default constructor. Called on startup as part of @@ -182,10 +182,10 @@ ChoicePage::init( PartitionCoreModule* core ) * No texts are set -- that happens later by the translator functions. */ static inline QComboBox* -createCombo( std::initializer_list< ChoicePage::SwapChoice > l ) +createCombo( std::initializer_list< SwapChoice > l ) { QComboBox* box = new QComboBox; - for ( ChoicePage::SwapChoice c : l ) + for ( SwapChoice c : l ) box->addItem( QString(), c ); return box; } @@ -245,13 +245,13 @@ ChoicePage::setupChoices() // Fill up swap options // .. TODO: only if enabled in the config - m_eraseSwapChoices = createCombo( { NoSwap, SmallSwap, FullSwap } ); + m_eraseSwapChoices = createCombo( { SwapChoice::NoSwap, SwapChoice::SmallSwap, SwapChoice:: FullSwap } ); m_eraseButton->addOptionsComboBox( m_eraseSwapChoices ); - m_replaceSwapChoices = createCombo( { NoSwap, ReuseSwap, SmallSwap, FullSwap } ); + m_replaceSwapChoices = createCombo( { SwapChoice::NoSwap, SwapChoice::ReuseSwap, SwapChoice::SmallSwap, SwapChoice::FullSwap } ); m_replaceButton->addOptionsComboBox( m_replaceSwapChoices ); - m_alongsideSwapChoices = createCombo( { NoSwap, ReuseSwap, SmallSwap, FullSwap } ); + m_alongsideSwapChoices = createCombo( { SwapChoice::NoSwap, SwapChoice::ReuseSwap, SwapChoice::SmallSwap, SwapChoice::FullSwap } ); m_alongsideButton->addOptionsComboBox( m_alongsideSwapChoices ); m_itemsLayout->addWidget( m_alongsideButton ); @@ -1431,7 +1431,7 @@ ChoicePage::updateSwapChoicesTr(QComboBox* box) if ( !box ) return; - static_assert(NoSwap == 0, "Enum values out-of-sync"); + static_assert(SwapChoice::NoSwap == 0, "Enum values out-of-sync"); for ( int index = 0; index < box->count(); ++index ) { bool ok = false; @@ -1440,23 +1440,23 @@ ChoicePage::updateSwapChoicesTr(QComboBox* box) switch ( value = box->itemData( index ).toInt( &ok ) ) { // case 0: - case NoSwap: + case SwapChoice::NoSwap: // toInt() returns 0 on failure, so check for ok if ( ok ) // It was explicitly set to 0 box->setItemText( index, tr( "No Swap" ) ); else cWarning() << "Box item" << index << box->itemText( index ) << "has non-integer role."; break; - case ReuseSwap: + case SwapChoice::ReuseSwap: box->setItemText( index, tr( "Reuse Swap" ) ); break; - case SmallSwap: + case SwapChoice::SmallSwap: box->setItemText( index, tr( "Swap (no Hibernate)" ) ); break; - case FullSwap: + case SwapChoice::FullSwap: box->setItemText( index, tr( "Swap (with Hibernate)" ) ); break; - case SwapFile: + case SwapChoice::SwapFile: box->setItemText( index, tr( "Swap to file" ) ); break; default: diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index a8ff3a330..07d052c2d 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -62,15 +62,6 @@ public: Manual }; - enum SwapChoice - { - NoSwap, // don't create any swap, don't use any - ReuseSwap, // don't create, but do use existing - SmallSwap, // up to 8GiB of swap - FullSwap, // ensureSuspendToDisk -- at least RAM size - SwapFile // use a file (if supported) - }; - explicit ChoicePage( QWidget* parent = nullptr ); virtual ~ChoicePage(); From d2f4079a18476adcf82aff0c8055fb72c1fc206b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 17 Sep 2018 06:42:14 -0400 Subject: [PATCH 14/22] [partition] Move partitioning options into a class - As (auto) partitioning grows more options, the parameter list becomes more unwieldy. Add some structure to it. --- .../partition/core/PartitionActions.cpp | 49 +++++------- src/modules/partition/core/PartitionActions.h | 76 +++++++++++++------ src/modules/partition/gui/ChoicePage.cpp | 68 ++++++++++------- src/modules/partition/gui/ReplaceWidget.cpp | 14 ++-- 4 files changed, 121 insertions(+), 86 deletions(-) diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index 7e488367f..e06ff6c36 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -28,7 +28,6 @@ #include "utils/Units.h" #include "JobQueue.h" #include "utils/Logger.h" -#include "GlobalStorage.h" #include #include @@ -43,17 +42,18 @@ using CalamaresUtils::operator""_GiB; using CalamaresUtils::operator""_MiB; qint64 -swapSuggestion( const qint64 availableSpaceB ) +swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) { + if ( ( swap != Choices::SmallSwap ) && ( swap != Choices::FullSwap ) ) + return 0; + // See partition.conf for explanation qint64 suggestedSwapSizeB = 0; auto memory = CalamaresUtils::System::instance()->getTotalMemoryB(); qint64 availableRamB = memory.first; qreal overestimationFactor = memory.second; - bool ensureSuspendToDisk = - Calamares::JobQueue::instance()->globalStorage()-> - value( "ensureSuspendToDisk" ).toBool(); + bool ensureSuspendToDisk = swap == Choices::FullSwap; // Ramp up quickly to 8GiB, then follow memory size if ( availableRamB <= 4_GiB ) @@ -97,16 +97,14 @@ bytesToSectors( qint64 bytes, qint64 blocksize ) } void -doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPassphrase ) +doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions o ) { - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - - bool isEfi = PartUtils::isEfiSystem(); - - QString defaultFsType = gs->value( "defaultFileSystemType" ).toString(); + QString defaultFsType = o.defaultFsType; if ( FileSystem::typeForName( defaultFsType ) == FileSystem::Unknown ) defaultFsType = "ext4"; + bool isEfi = PartUtils::isEfiSystem(); + // Partition sizes are expressed in MiB, should be multiples of // the logical sector size (usually 512B). EFI starts with 2MiB // empty and a 300MiB EFI boot partition, while BIOS starts at @@ -139,8 +137,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPass PartitionTable::FlagNone ); PartitionInfo::setFormat( efiPartition, true ); - PartitionInfo::setMountPoint( efiPartition, gs->value( "efiSystemPartition" ) - .toString() ); + PartitionInfo::setMountPoint( efiPartition, o.efiPartitionMountPoint ); core->createPartition( dev, efiPartition, PartitionTable::FlagEsp ); firstFreeSector = lastSector + 1; } @@ -149,20 +146,18 @@ doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPass core->createPartitionTable( dev, PartitionTable::msdos ); } - const bool mayCreateSwap = !gs->value( "neverCreateSwap" ).toBool(); + const bool mayCreateSwap = ( o.swap == Choices::SmallSwap ) || ( o.swap == Choices::FullSwap ); bool shouldCreateSwap = false; qint64 suggestedSwapSizeB = 0; if ( mayCreateSwap ) { qint64 availableSpaceB = ( dev->totalLogical() - firstFreeSector ) * dev->logicalSize(); - suggestedSwapSizeB = swapSuggestion( availableSpaceB ); + suggestedSwapSizeB = swapSuggestion( availableSpaceB, o.swap ); // Space required by this installation is what the distro claims is needed // (via global configuration) plus the swap size plus a fudge factor of // 0.6GiB (this was 2.1GiB up to Calamares 3.2.2). - qint64 requiredSpaceB = - GiBtoBytes( gs->value( "requiredStorageGB" ).toDouble() + 0.6 ) + - suggestedSwapSizeB; + qint64 requiredSpaceB = o.requiredSpaceB + 600_MiB + suggestedSwapSizeB; // If there is enough room for ESP + root + swap, create swap, otherwise don't. shouldCreateSwap = availableSpaceB > requiredSpaceB; @@ -175,7 +170,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPass } Partition* rootPartition = nullptr; - if ( luksPassphrase.isEmpty() ) + if ( o.luksPassphrase.isEmpty() ) { rootPartition = KPMHelpers::createNewPartition( dev->partitionTable(), @@ -195,7 +190,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPass FileSystem::typeForName( defaultFsType ), firstFreeSector, lastSectorForRoot, - luksPassphrase + o.luksPassphrase ); } PartitionInfo::setFormat( rootPartition, true ); @@ -205,7 +200,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPass if ( shouldCreateSwap ) { Partition* swapPartition = nullptr; - if ( luksPassphrase.isEmpty() ) + if ( o.luksPassphrase.isEmpty() ) { swapPartition = KPMHelpers::createNewPartition( dev->partitionTable(), @@ -225,7 +220,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, const QString& luksPass FileSystem::LinuxSwap, lastSectorForRoot + 1, dev->totalLogical() - 1, - luksPassphrase + o.luksPassphrase ); } PartitionInfo::setFormat( swapPartition, true ); @@ -240,13 +235,11 @@ void doReplacePartition( PartitionCoreModule* core, Device* dev, Partition* partition, - const QString& luksPassphrase ) + Choices::ReplacePartitionOptions o ) { cDebug() << "doReplacePartition for device" << partition->partitionPath(); - QString defaultFsType = Calamares::JobQueue::instance()-> - globalStorage()-> - value( "defaultFileSystemType" ).toString(); + QString defaultFsType = o.defaultFsType; if ( FileSystem::typeForName( defaultFsType ) == FileSystem::Unknown ) defaultFsType = "ext4"; @@ -267,7 +260,7 @@ doReplacePartition( PartitionCoreModule* core, } Partition* newPartition = nullptr; - if ( luksPassphrase.isEmpty() ) + if ( o.luksPassphrase.isEmpty() ) { newPartition = KPMHelpers::createNewPartition( partition->parent(), @@ -287,7 +280,7 @@ doReplacePartition( PartitionCoreModule* core, FileSystem::typeForName( defaultFsType ), partition->firstSector(), partition->lastSector(), - luksPassphrase + o.luksPassphrase ); } PartitionInfo::setMountPoint( newPartition, "/" ); diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index 8312d582b..5acf444fa 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -27,30 +27,6 @@ class Partition; namespace PartitionActions { - -/** - * @brief doAutopartition sets up an autopartitioning operation on the given Device. - * @param core a pointer to the PartitionCoreModule instance. - * @param dev the device to wipe. - * @param luksPassphrase the passphrase for LUKS encryption (optional, default is empty). - */ -void doAutopartition( PartitionCoreModule* core, - Device* dev, - const QString& luksPassphrase = QString() ); - -/** - * @brief doReplacePartition sets up replace-partitioning with the given partition. - * @param core a pointer to the PartitionCoreModule instance. - * @param dev a pointer to the Device on which to replace a partition. - * @param partition a pointer to the Partition to be replaced. - * @param luksPassphrase the passphrase for LUKS encryption (optional, default is empty). - * @note this function also takes care of requesting PCM to delete the partition. - */ -void doReplacePartition( PartitionCoreModule* core, - Device* dev, - Partition* partition, - const QString& luksPassphrase = QString() ); - /** @brief Namespace for enums * * This namespace houses non-class enums..... @@ -66,7 +42,59 @@ namespace Choices FullSwap, // ensureSuspendToDisk -- at least RAM size SwapFile // use a file (if supported) }; + + struct ReplacePartitionOptions + { + QString defaultFsType; // e.g. "ext4" or "btrfs" + QString luksPassphrase; // optional + + ReplacePartitionOptions( const QString& fs, const QString& luks ) + : defaultFsType( fs ) + , luksPassphrase( luks ) + { + } + }; + + struct AutoPartitionOptions : ReplacePartitionOptions + { + QString efiPartitionMountPoint; // optional, e.g. "/boot" + quint64 requiredSpaceB; // estimated required space for root partition + SwapChoice swap; + + AutoPartitionOptions( const QString& fs, const QString& luks, const QString& efi, qint64 r, SwapChoice s ) + : ReplacePartitionOptions( fs, luks ) + , efiPartitionMountPoint( efi ) + , requiredSpaceB( r > 0 ? r : 0 ) + , swap( s ) + { + } + }; + } // namespace Choices + +/** + * @brief doAutopartition sets up an autopartitioning operation on the given Device. + * @param core a pointer to the PartitionCoreModule instance. + * @param dev the device to wipe. + * @param options settings for autopartitioning. + */ +void doAutopartition( PartitionCoreModule* core, + Device* dev, + Choices::AutoPartitionOptions options ); + +/** + * @brief doReplacePartition sets up replace-partitioning with the given partition. + * @param core a pointer to the PartitionCoreModule instance. + * @param dev a pointer to the Device on which to replace a partition. + * @param partition a pointer to the Partition to be replaced. + * @param options settings for partitioning (not all fields apply) + * + * @note this function also takes care of requesting PCM to delete the partition. + */ +void doReplacePartition( PartitionCoreModule* core, + Device* dev, + Partition* partition, + Choices::ReplacePartitionOptions options ); } // namespace PartitionActions #endif // PARTITIONACTIONS_H diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 82302ac4c..b5a2ce529 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -42,6 +42,7 @@ #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" #include "utils/Retranslator.h" +#include "utils/Units.h" #include "Branding.h" #include "GlobalStorage.h" @@ -417,30 +418,37 @@ ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice ) switch ( choice ) { case Erase: - if ( m_core->isDirty() ) { - ScanningDialog::run( QtConcurrent::run( [ = ] - { - QMutexLocker locker( &m_coreMutex ); - m_core->revertDevice( selectedDevice() ); - } ), - [ = ] - { - PartitionActions::doAutopartition( m_core, - selectedDevice(), - m_encryptWidget->passphrase() ); - emit deviceChosen(); - }, - this ); - } - else - { - PartitionActions::doAutopartition( m_core, - selectedDevice(), - m_encryptWidget->passphrase() ); - emit deviceChosen(); - } + auto gs = Calamares::JobQueue::instance()->globalStorage(); + PartitionActions::Choices::AutoPartitionOptions options { + gs->value( "defaultFileSystemType" ).toString(), + m_encryptWidget->passphrase(), + gs->value( "efiSystemPartition" ).toString(), + CalamaresUtils::GiBtoBytes( gs->value( "requiredStorageGB" ).toDouble() ), + static_cast( m_eraseSwapChoices->currentData().toInt() ) + }; + + if ( m_core->isDirty() ) + { + ScanningDialog::run( QtConcurrent::run( [ = ] + { + QMutexLocker locker( &m_coreMutex ); + m_core->revertDevice( selectedDevice() ); + } ), + [ = ] + { + PartitionActions::doAutopartition( m_core, selectedDevice(), options ); + emit deviceChosen(); + }, + this ); + } + else + { + PartitionActions::doAutopartition( m_core, selectedDevice(), options ); + emit deviceChosen(); + } + } break; case Replace: if ( m_core->isDirty() ) @@ -518,6 +526,7 @@ ChoicePage::doAlongsideSetupSplitter( const QModelIndex& current, ->value( "requiredStorageGB" ) .toDouble(); + // TODO: make this consistent qint64 requiredStorageB = qRound64( requiredStorageGB + 0.1 + 2.0 ) * 1024 * 1024 * 1024; m_afterPartitionSplitterWidget->setSplitPartition( @@ -802,14 +811,19 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) if ( homePartitionPath->isEmpty() ) doReuseHomePartition = false; - PartitionActions::doReplacePartition( m_core, - selectedDevice(), - selectedPartition, - m_encryptWidget->passphrase() ); + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + + PartitionActions::doReplacePartition( + m_core, + selectedDevice(), + selectedPartition, + { + gs->value( "defaultFileSystemType" ).toString(), + m_encryptWidget->passphrase() + } ); Partition* homePartition = KPMHelpers::findPartitionByPath( { selectedDevice() }, *homePartitionPath ); - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); if ( homePartition && doReuseHomePartition ) { PartitionInfo::setMountPoint( homePartition, "/home" ); diff --git a/src/modules/partition/gui/ReplaceWidget.cpp b/src/modules/partition/gui/ReplaceWidget.cpp index 524932057..faedc03d4 100644 --- a/src/modules/partition/gui/ReplaceWidget.cpp +++ b/src/modules/partition/gui/ReplaceWidget.cpp @@ -85,6 +85,8 @@ ReplaceWidget::reset() void ReplaceWidget::applyChanges() { + auto gs = Calamares::JobQueue::instance()->globalStorage(); + PartitionModel* model = qobject_cast< PartitionModel* >( m_ui->partitionTreeView->model() ); if ( model ) { @@ -93,7 +95,9 @@ ReplaceWidget::applyChanges() { Device* dev = model->device(); - PartitionActions::doReplacePartition( m_core, dev, partition ); + PartitionActions::doReplacePartition( + m_core, dev, partition, + { gs->value( "defaultFileSystemType" ).toString(), QString() } ); if ( m_isEfi ) { @@ -102,17 +106,13 @@ ReplaceWidget::applyChanges() { PartitionInfo::setMountPoint( efiSystemPartitions.first(), - Calamares::JobQueue::instance()-> - globalStorage()-> - value( "efiSystemPartition" ).toString() ); + gs->value( "efiSystemPartition" ).toString() ); } else if ( efiSystemPartitions.count() > 1 ) { PartitionInfo::setMountPoint( efiSystemPartitions.at( m_ui->bootComboBox->currentIndex() ), - Calamares::JobQueue::instance()-> - globalStorage()-> - value( "efiSystemPartition" ).toString() ); + gs->value( "efiSystemPartition" ).toString() ); } } From 4a2ca8bb77c15e90f24c520150e7ef60a00ba67c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Oct 2018 06:46:35 -0400 Subject: [PATCH 15/22] [libcalamares] Fix compilation of tests - QCOMPARE is picky with types, enum vs unsigned int, so just hit it with a hammer. --- src/libcalamares/Tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/Tests.cpp b/src/libcalamares/Tests.cpp index 7595718e4..acf5b03d3 100644 --- a/src/libcalamares/Tests.cpp +++ b/src/libcalamares/Tests.cpp @@ -42,7 +42,7 @@ LibCalamaresTests::testDebugLevels() { Logger::setupLogLevel( Logger::LOG_DISABLE ); - QCOMPARE( Logger::logLevel(), Logger::LOG_DISABLE ); + QCOMPARE( Logger::logLevel(), static_cast( Logger::LOG_DISABLE ) ); for ( unsigned int level = 0; level <= Logger::LOGVERBOSE ; ++level ) { From c489320af5fab068420a9dbb5cfecca7e4bc1a46 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Oct 2018 06:44:31 -0400 Subject: [PATCH 16/22] [calamares] Add option to obey XDG dirs - Prep-work for #941 - This does nothing, yet, just sets the stage for using XDG_CONFIG_DIRS and XDG_DATA_DIRS as well as the regular directories. --- src/calamares/main.cpp | 5 ++++ src/libcalamares/utils/CalamaresUtils.cpp | 28 +++++++++++++++++++++++ src/libcalamares/utils/CalamaresUtils.h | 7 ++++++ 3 files changed, 40 insertions(+) diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index 9893e6792..f855b060f 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -44,6 +44,8 @@ handle_args( CalamaresApplication& a ) "Verbose output for debugging purposes (0-8).", "level" ); QCommandLineOption configOption( QStringList{ "c", "config"}, "Configuration directory to use, for testing purposes.", "config" ); + QCommandLineOption xdgOption( QStringList{"X", "xdg-config"}, + "Use XDG_{CONFIG,DATA}_DIRS as well." ); QCommandLineParser parser; parser.setApplicationDescription( "Distribution-independent installer framework" ); @@ -53,6 +55,7 @@ handle_args( CalamaresApplication& a ) parser.addOption( debugOption ); parser.addOption( debugLevelOption ); parser.addOption( configOption ); + parser.addOption( xdgOption ); parser.process( a ); @@ -72,6 +75,8 @@ handle_args( CalamaresApplication& a ) } if ( parser.isSet( configOption ) ) CalamaresUtils::setAppDataDir( QDir( parser.value( configOption ) ) ); + if ( parser.isSet( xdgOption ) ) + CalamaresUtils::setXdgDirs(); } int diff --git a/src/libcalamares/utils/CalamaresUtils.cpp b/src/libcalamares/utils/CalamaresUtils.cpp index 6a892511a..bd8d02d1d 100644 --- a/src/libcalamares/utils/CalamaresUtils.cpp +++ b/src/libcalamares/utils/CalamaresUtils.cpp @@ -49,6 +49,9 @@ static QTranslator* s_brandingTranslator = nullptr; static QTranslator* s_translator = nullptr; static QString s_translatorLocaleName; +static bool s_haveExtraDirs = false; +static QStringList s_extraConfigDirs; +static QStringList s_extraDataDirs; static bool isWritableDir( const QDir& dir ) @@ -94,6 +97,31 @@ setAppDataDir( const QDir& dir ) s_isAppDataDirOverridden = true; } +void +setXdgDirs() +{ + s_haveExtraDirs = true; + s_extraConfigDirs.append( QString( qgetenv( "XDG_CONFIG_DIRS" ) ).split(':') ); + s_extraDataDirs.append( QString( qgetenv( "XDG_DATA_DIRS" ) ).split(':') ); +} + +QStringList +extraConfigDirs() +{ + if ( s_haveExtraDirs ) + return s_extraConfigDirs; + return QStringList(); +} + +QStringList +extraDataDirs() +{ + if ( s_haveExtraDirs ) + return s_extraDataDirs; + return QStringList(); +} + + bool isAppDataDirOverridden() diff --git a/src/libcalamares/utils/CalamaresUtils.h b/src/libcalamares/utils/CalamaresUtils.h index e64fe4eec..78362b01c 100644 --- a/src/libcalamares/utils/CalamaresUtils.h +++ b/src/libcalamares/utils/CalamaresUtils.h @@ -79,6 +79,13 @@ namespace CalamaresUtils DLLEXPORT void setQmlModulesDir( const QDir& dir ); + /** @brief Setup extra config and data dirs from the XDG variables. + * + */ + DLLEXPORT void setXdgDirs(); + DLLEXPORT QStringList extraConfigDirs(); + DLLEXPORT QStringList extraDataDirs(); + /** * @brief removeDiacritics replaces letters with diacritics and ligatures with * alternative forms and digraphs. From 3b8d2835e037edc6269737e4f667da66c684b668 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Oct 2018 10:28:30 -0400 Subject: [PATCH 17/22] [calamares] Use XDG_{DATA,CONFIG}_DIRS as appropriate - Use DATA for the qml and branding directories (looks for qml/ and branding// in those directories). - Use CONFIG for the global settings and module settings (looks for settings.conf and module// in those directories). FIXES #941 --- src/calamares/CalamaresApplication.cpp | 9 +++++++++ src/libcalamares/utils/CalamaresUtils.cpp | 21 ++++++++++++++++++--- src/libcalamares/utils/CalamaresUtils.h | 5 ++++- src/libcalamaresui/modulesystem/Module.cpp | 4 ++++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index 018e2b677..0b715d6df 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -145,6 +145,9 @@ qmlDirCandidates( bool assumeBuilddir ) { if ( assumeBuilddir ) qmlDirs << QDir::current().absoluteFilePath( "src/qml" ); // In build-dir + if ( CalamaresUtils::haveExtraDirs() ) + for ( auto s : CalamaresUtils::extraDataDirs() ) + qmlDirs << ( s + QML ); qmlDirs << CalamaresUtils::appDataDir().absoluteFilePath( QML ); } @@ -164,6 +167,9 @@ settingsFileCandidates( bool assumeBuilddir ) { if ( assumeBuilddir ) settingsPaths << QDir::current().absoluteFilePath( settings ); + if ( CalamaresUtils::haveExtraDirs() ) + for ( auto s : CalamaresUtils::extraConfigDirs() ) + settingsPaths << ( s + settings ); settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings ); } @@ -182,6 +188,9 @@ brandingFileCandidates( bool assumeBuilddir, const QString& brandingFilename ) { if ( assumeBuilddir ) brandingPaths << ( QDir::currentPath() + QStringLiteral( "/src/" ) + brandingFilename ); + if ( CalamaresUtils::haveExtraDirs() ) + for ( auto s : CalamaresUtils::extraDataDirs() ) + brandingPaths << ( s + brandingFilename ); brandingPaths << QDir( CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/" ).absoluteFilePath( brandingFilename ); brandingPaths << CalamaresUtils::appDataDir().absoluteFilePath( brandingFilename); } diff --git a/src/libcalamares/utils/CalamaresUtils.cpp b/src/libcalamares/utils/CalamaresUtils.cpp index bd8d02d1d..3ab758522 100644 --- a/src/libcalamares/utils/CalamaresUtils.cpp +++ b/src/libcalamares/utils/CalamaresUtils.cpp @@ -97,12 +97,23 @@ setAppDataDir( const QDir& dir ) s_isAppDataDirOverridden = true; } +/* Split $ENV{@p name} on :, append to @p l, making sure each ends in / */ +static void +mungeEnvironment( QStringList& l, const char *name ) +{ + for ( auto s : QString( qgetenv( name ) ).split(':') ) + if ( s.endsWith( '/' ) ) + l << s; + else + l << ( s + '/' ); +} + void setXdgDirs() { s_haveExtraDirs = true; - s_extraConfigDirs.append( QString( qgetenv( "XDG_CONFIG_DIRS" ) ).split(':') ); - s_extraDataDirs.append( QString( qgetenv( "XDG_DATA_DIRS" ) ).split(':') ); + mungeEnvironment( s_extraConfigDirs, "XDG_CONFIG_DIRS" ); + mungeEnvironment( s_extraDataDirs, "XDG_DATA_DIRS" ); } QStringList @@ -121,7 +132,11 @@ extraDataDirs() return QStringList(); } - +bool +haveExtraDirs() +{ + return s_haveExtraDirs && ( !s_extraConfigDirs.isEmpty() || !s_extraDataDirs.isEmpty() ); +} bool isAppDataDirOverridden() diff --git a/src/libcalamares/utils/CalamaresUtils.h b/src/libcalamares/utils/CalamaresUtils.h index 78362b01c..baf7a12dc 100644 --- a/src/libcalamares/utils/CalamaresUtils.h +++ b/src/libcalamares/utils/CalamaresUtils.h @@ -80,10 +80,13 @@ namespace CalamaresUtils DLLEXPORT void setQmlModulesDir( const QDir& dir ); /** @brief Setup extra config and data dirs from the XDG variables. - * */ DLLEXPORT void setXdgDirs(); + /** @brief Are any extra directories configured? */ + DLLEXPORT bool haveExtraDirs(); + /** @brief XDG_CONFIG_DIRS, each guaranteed to end with / */ DLLEXPORT QStringList extraConfigDirs(); + /** @brief XDG_DATA_DIRS, each guaranteed to end with / */ DLLEXPORT QStringList extraDataDirs(); /** diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index a1349c280..ef629ac4d 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -155,6 +155,10 @@ moduleConfigurationCandidates( bool assumeBuildDir, const QString& moduleName, c if ( assumeBuildDir && configFileName.contains( '/' ) ) paths << QDir().absoluteFilePath( configFileName ); + if ( CalamaresUtils::haveExtraDirs() ) + for ( auto s : CalamaresUtils::extraConfigDirs() ) + paths << ( s + QString( "modules/%1" ).arg( configFileName ) ); + paths << QString( "/etc/calamares/modules/%1" ).arg( configFileName ); paths << CalamaresUtils::appDataDir().absoluteFilePath( QString( "modules/%1" ).arg( configFileName ) ); } From 594618f2cc417cd42cfdf8a129b95c9e90e06dd9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Oct 2018 10:34:57 -0400 Subject: [PATCH 18/22] Changes: document -X option --- CHANGES | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 896a9fee2..7094f5866 100644 --- a/CHANGES +++ b/CHANGES @@ -14,7 +14,14 @@ This release contains contributions from (alphabetically by first name): ## Core ## -There are no core changes in this version. + * The Calamares application now recognizes the `-X` or `--xdg-config` + option, which adds XDG_DATA_DIRS to the places used to find QML + and branding directories, and XDG_CONFIG_DIRS to the places used + to find the global settings and module configurations. This allows + a more fine-grained, and more layered, approach to setting up + Calamares configurations (in particular, distro's can **add** + configuration files and give them priority, instead of **forking** + configuration files). ## Modules ## From 2a61116b3ca7cfa558e65b366ccf8f121385d1af Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 8 Oct 2018 15:32:02 -0400 Subject: [PATCH 19/22] [partition] Disable swap choice for replace & alongside --- src/modules/partition/gui/ChoicePage.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 5b1577369..cc7819778 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -252,11 +252,13 @@ ChoicePage::setupChoices() 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 m_itemsLayout->addWidget( m_alongsideButton ); m_itemsLayout->addWidget( m_replaceButton ); From caa4b8ab53c8f26d8506d59b357b8fb7773ca147 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Oct 2018 05:30:14 -0400 Subject: [PATCH 20/22] [partition] Document intention of new-style swap config --- .../partition/gui/PartitionViewStep.cpp | 35 +++++++++------ src/modules/partition/partition.conf | 43 +++++++++++-------- 2 files changed, 49 insertions(+), 29 deletions(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 6ad1a6c77..608ca0d22 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -487,25 +487,36 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) gs->insert( "efiSystemPartition", QStringLiteral( "/boot/efi" ) ); } + // SWAP SETTINGS + // + // This is a bit convoluted because there's legacy settings to handle as well + // as the new-style list of choices, with mapping back-and-forth. + if ( configurationMap.contains( "userSwapChoices" ) && + ( configurationMap.contains( "ensureSuspendToDisk" ) || configurationMap.contains( "neverCreateSwap" ) ) ) + cError() << "Partition-module configuration mixes old- and new-style swap settings."; + + bool ensureSuspendToDisk = true; + if ( configurationMap.contains( "ensureSuspendToDisk" ) ) + cWarning() << "Partition-module setting *ensureSuspendToDisk* is deprecated."; if ( configurationMap.contains( "ensureSuspendToDisk" ) && configurationMap.value( "ensureSuspendToDisk" ).type() == QVariant::Bool ) - { - gs->insert( "ensureSuspendToDisk", configurationMap.value( "ensureSuspendToDisk" ).toBool() ); - } + ensureSuspendToDisk = configurationMap.value( "ensureSuspendToDisk" ).toBool(); else - { - gs->insert( "ensureSuspendToDisk", true ); - } + ensureSuspendToDisk = true; + bool neverCreateSwap = false; + if ( configurationMap.contains( "neverCreateSwap" ) ) + cWarning() << "Partition-module setting *neverCreateSwap* is deprecated."; if ( configurationMap.contains( "neverCreateSwap" ) && configurationMap.value( "neverCreateSwap" ).type() == QVariant::Bool ) - { - gs->insert( "neverCreateSwap", configurationMap.value( "neverCreateSwap" ).toBool() ); - } + neverCreateSwap = configurationMap.value( "neverCreateSwap" ).toBool(); else - { - gs->insert( "neverCreateSwap", false ); - } + neverCreateSwap = false; + + // These gs settings seem to be unused (in upstream Calamares) outside of + // the partition module itself. + gs->insert( "ensureSuspendToDisk", ensureSuspendToDisk ); + gs->insert( "neverCreateSwap", neverCreateSwap ); if ( configurationMap.contains( "drawNestedPartitions" ) && configurationMap.value( "drawNestedPartitions" ).type() == QVariant::Bool ) diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index 3e0ce5950..70d0ea17f 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -3,28 +3,37 @@ # etc.) use just /boot. efiSystemPartition: "/boot/efi" -# Make sure an autogenerated swap partition is big enough for hibernation in -# automated partitioning modes. Swap can be disabled through *neverCreateSwap*. +# In autogenerated partitioning, allow the user to select a swap size? +# If there is exactly one choice, no UI is presented, and the user +# cannot make a choice -- this setting is used. If there is more than +# one choice, a UI is presented. # -# - *neverCreateSwap* is true: no swap is created -# - *neverCreateSwap* is false (the default): swap is created, as follows: -# - *ensureSuspendToDisk* is true (default): Swap is always at least total -# memory size, and up to 4GiB RAM follows the rule-of-thumb 2 * memory; +# Legacy settings *neverCreateSwap* and *ensureSuspendToDisk* correspond +# to values of *userSwapChoices* as follows: +# - *neverCreateSwap* is true, means [none] +# - *neverCreateSwap* is false, *ensureSuspendToDisk* is false, [small] +# - *neverCreateSwap* is false, *ensureSuspendToDisk* is true, [suspend] +# +# Autogenerated swap sizes are as follows: +# - *suspend*: Swap is always at least total memory size, +# and up to 4GiB RAM follows the rule-of-thumb 2 * memory; # from 4GiB to 8 GiB it stays steady at 8GiB, and over 8 GiB memory # swap is the size of main memory. -# - *ensureSuspendToDisk* is false: Follows the rules above, but Swap is at +# - *small*: Follows the rules above, but Swap is at # most 8GiB, and no more than 10% of available disk. -# In both cases, a fudge factor (usually 10% extra) is applied so that there -# is some space for administrative overhead (e.g. 8 GiB swap will allocate -# 8.8GiB on disk in the end). -# -# Default is true. -ensureSuspendToDisk: true +# In both cases, a fudge factor (usually 10% extra) is applied so that there +# is some space for administrative overhead (e.g. 8 GiB swap will allocate +# 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 + - small # Up to 4GB + - suspend # At least main memory size + # - file # To swap file instead of partition (unsupported right now) -# Never create swap partitions in automated partitioning modes. -# If this is true, ensureSuspendToDisk is ignored. -# Default is false. -neverCreateSwap: false +# LEGACY SETTINGS (these will generate a warning) +# ensureSuspendToDisk: true +# neverCreateSwap: false # Correctly draw nested (e.g. logical) partitions as such. drawNestedPartitions: false From 3d543e9063000e4e40ccd2d01a2f008c58162dfb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 9 Oct 2018 05:46:12 -0400 Subject: [PATCH 21/22] [partition] Refactor to use current config-reading methods --- .../partition/gui/PartitionViewStep.cpp | 86 ++++--------------- 1 file changed, 18 insertions(+), 68 deletions(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 608ca0d22..9e8a120a7 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -476,16 +476,10 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) // Copy the efiSystemPartition setting to the global storage. It is needed not only in // the EraseDiskPage, but also in the bootloader configuration modules (grub, bootloader). Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - if ( configurationMap.contains( "efiSystemPartition" ) && - configurationMap.value( "efiSystemPartition" ).type() == QVariant::String && - !configurationMap.value( "efiSystemPartition" ).toString().isEmpty() ) - { - gs->insert( "efiSystemPartition", configurationMap.value( "efiSystemPartition" ).toString() ); - } - else - { - gs->insert( "efiSystemPartition", QStringLiteral( "/boot/efi" ) ); - } + QString efiSP = CalamaresUtils::getString( configurationMap, "efiSystemPartition" ); + if ( efiSP.isEmpty() ) + efiSP = QStringLiteral( "/boot/efi" ); + gs->insert( "efiSystemPartition", efiSP ); // SWAP SETTINGS // @@ -495,78 +489,34 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) ( configurationMap.contains( "ensureSuspendToDisk" ) || configurationMap.contains( "neverCreateSwap" ) ) ) cError() << "Partition-module configuration mixes old- and new-style swap settings."; - bool ensureSuspendToDisk = true; if ( configurationMap.contains( "ensureSuspendToDisk" ) ) cWarning() << "Partition-module setting *ensureSuspendToDisk* is deprecated."; - if ( configurationMap.contains( "ensureSuspendToDisk" ) && - configurationMap.value( "ensureSuspendToDisk" ).type() == QVariant::Bool ) - ensureSuspendToDisk = configurationMap.value( "ensureSuspendToDisk" ).toBool(); - else - ensureSuspendToDisk = true; + bool ensureSuspendToDisk = CalamaresUtils::getBool( configurationMap, "ensureSuspendToDisk", true ); - bool neverCreateSwap = false; if ( configurationMap.contains( "neverCreateSwap" ) ) cWarning() << "Partition-module setting *neverCreateSwap* is deprecated."; - if ( configurationMap.contains( "neverCreateSwap" ) && - configurationMap.value( "neverCreateSwap" ).type() == QVariant::Bool ) - neverCreateSwap = configurationMap.value( "neverCreateSwap" ).toBool(); - else - neverCreateSwap = false; + bool neverCreateSwap = CalamaresUtils::getBool( configurationMap, "neverCreateSwap", false ); // These gs settings seem to be unused (in upstream Calamares) outside of // the partition module itself. gs->insert( "ensureSuspendToDisk", ensureSuspendToDisk ); gs->insert( "neverCreateSwap", neverCreateSwap ); - if ( configurationMap.contains( "drawNestedPartitions" ) && - configurationMap.value( "drawNestedPartitions" ).type() == QVariant::Bool ) - { - gs->insert( "drawNestedPartitions", - configurationMap.value( "drawNestedPartitions", false ).toBool() ); - } - else - { - gs->insert( "drawNestedPartitions", false ); - } + // OTHER SETTINGS + // + gs->insert( "drawNestedPartitions", CalamaresUtils::getBool( configurationMap, "drawNestedPartitions", false ) ); + gs->insert( "alwaysShowPartitionLabels", CalamaresUtils::getBool( configurationMap, "alwaysShowPartitionLabels", true ) ); + gs->insert( "enableLuksAutomatedPartitioning", CalamaresUtils::getBool( configurationMap, "enableLuksAutomatedPartitioning", true ) ); - if ( configurationMap.contains( "alwaysShowPartitionLabels" ) && - configurationMap.value( "alwaysShowPartitionLabels" ).type() == QVariant::Bool ) + QString defaultFS = CalamaresUtils::getString( configurationMap, "defaultFileSystemType" ); + if ( defaultFS.isEmpty() ) + defaultFS = QStringLiteral( "ext4" ); + if ( FileSystem::typeForName( defaultFS ) == FileSystem::Unknown ) { - gs->insert( "alwaysShowPartitionLabels", - configurationMap.value( "alwaysShowPartitionLabels", true ).toBool() ); - } - else - { - gs->insert( "alwaysShowPartitionLabels", true ); - } - - if ( configurationMap.contains( "defaultFileSystemType" ) && - configurationMap.value( "defaultFileSystemType" ).type() == QVariant::String && - !configurationMap.value( "defaultFileSystemType" ).toString().isEmpty() ) - { - QString typeString = configurationMap.value( "defaultFileSystemType" ).toString(); - gs->insert( "defaultFileSystemType", typeString ); - if ( FileSystem::typeForName( typeString ) == FileSystem::Unknown ) - { - cWarning() << "bad default filesystem configuration for partition module. Reverting to ext4 as default."; - gs->insert( "defaultFileSystemType", "ext4" ); - } - } - else - { - gs->insert( "defaultFileSystemType", QStringLiteral( "ext4" ) ); - } - - if ( configurationMap.contains( "enableLuksAutomatedPartitioning" ) && - configurationMap.value( "enableLuksAutomatedPartitioning" ).type() == QVariant::Bool ) - { - gs->insert( "enableLuksAutomatedPartitioning", - configurationMap.value( "enableLuksAutomatedPartitioning" ).toBool() ); - } - else - { - gs->insert( "enableLuksAutomatedPartitioning", true ); + cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << defaultFS << ") using ext4."; + defaultFS = QStringLiteral( "ext4" ); } + gs->insert( "defaultFileSystemType", defaultFS ); // Now that we have the config, we load the PartitionCoreModule in the background From c7645af358b548597def0d676e0a38b4b8dd4309 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 11 Oct 2018 06:27:39 -0400 Subject: [PATCH 22/22] [partition] Translate swap-choice-strings to enum - Handle legacy and modern config, mixed-configs, - Translate strings to enum values, - Default and warn as appropriate. - Doesn't **do** anything with the config, though. --- .../partition/gui/PartitionViewStep.cpp | 65 ++++++++++++++++++- 1 file changed, 64 insertions(+), 1 deletion(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 9e8a120a7..bfd52b35e 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -21,6 +21,7 @@ #include "gui/PartitionViewStep.h" #include "core/DeviceModel.h" +#include "core/PartitionActions.h" #include "core/PartitionCoreModule.h" #include "core/PartitionModel.h" #include "core/KPMHelpers.h" @@ -470,6 +471,31 @@ PartitionViewStep::onLeave() } +static PartitionActions::Choices::SwapChoice +nameToChoice( QString name, bool& ok ) +{ + ok = false; + name = name.toLower(); + + using namespace PartitionActions::Choices; + + // Each return here first sets ok to true, returns enum value + if ( name == QStringLiteral( "none" ) ) + return( ok=true, SwapChoice::NoSwap ); + else if ( name == QStringLiteral( "small" ) ) + return( ok=true, SwapChoice::SmallSwap); + else if ( name == QStringLiteral( "suspend" ) ) + return( ok=true, SwapChoice::FullSwap ); + else if ( name == QStringLiteral( "reuse" ) ) + return( ok=true, SwapChoice::ReuseSwap ); + else if ( name == QStringLiteral( "file" ) ) + return( ok=true, SwapChoice::SwapFile ); + + ok = false; + return SwapChoice::NoSwap; +} + + void PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { @@ -497,6 +523,43 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) cWarning() << "Partition-module setting *neverCreateSwap* is deprecated."; bool neverCreateSwap = CalamaresUtils::getBool( configurationMap, "neverCreateSwap", false ); + QSet< PartitionActions::Choices::SwapChoice > choices; // Available swap choices + if ( configurationMap.contains( "userSwapChoices" ) ) + { + // We've already warned about overlapping settings with the + // legacy *ensureSuspendToDisk* and *neverCreateSwap*. + QStringList l = configurationMap[ "userSwapChoices" ].toStringList(); + + for ( const auto& item : l ) + { + bool ok = false; + auto v = nameToChoice( item, ok ); + if ( ok ) + choices.insert( v ); + } + + if ( choices.isEmpty() ) + { + cWarning() << "Partition-module configuration for *userSwapChoices* is empty:" << l; + choices.insert( PartitionActions::Choices::SwapChoice::FullSwap ); + } + + // suspend if it's one of the possible choices; suppress swap only if it's + // the **only** choice available. + ensureSuspendToDisk = choices.contains( PartitionActions::Choices::SwapChoice::FullSwap ); + neverCreateSwap = ( choices.count() == 1 ) && choices.contains( PartitionActions::Choices::SwapChoice::NoSwap ); + } + else + { + // Convert the legacy settings into a single setting for now. + if ( neverCreateSwap ) + choices.insert( PartitionActions::Choices::SwapChoice::NoSwap ); + else if ( ensureSuspendToDisk ) + choices.insert( PartitionActions::Choices::SwapChoice::FullSwap ); + else + choices.insert( PartitionActions::Choices::SwapChoice::SmallSwap ); + } + // These gs settings seem to be unused (in upstream Calamares) outside of // the partition module itself. gs->insert( "ensureSuspendToDisk", ensureSuspendToDisk ); @@ -524,7 +587,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) // and remove the spinner. QFutureWatcher< void >* watcher = new QFutureWatcher< void >(); connect( watcher, &QFutureWatcher< void >::finished, - this, [ this, watcher ] + this, [ this, watcher, choices ] { continueLoading(); watcher->deleteLater();