From 6d0752712369a66d61eb5cda19f9560f4da2de1b Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Thu, 16 Apr 2020 23:37:58 +0200
Subject: [PATCH 01/14] [partition] Comment-out unsupported swap options

 - I notice they get copied into distro configurations a lot,
   leading to warnings in the logs
---
 src/modules/partition/partition.conf | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf
index f6cc34ee4..758de0b97 100644
--- a/src/modules/partition/partition.conf
+++ b/src/modules/partition/partition.conf
@@ -34,10 +34,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 (unsupported right now)
     - small     # Up to 4GB
     - suspend   # At least main memory size
-    - file      # To swap file instead of partition (unsupported right now)
+    # - reuse     # Re-use existing swap, but don't create any (unsupported right now)
+    # - file      # To swap file instead of partition (unsupported right now)
 
 # LEGACY SETTINGS (these will generate a warning)
 # ensureSuspendToDisk:    true

From ca59c8419cbb2a0a8032f0e7399e8fd8015e2403 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Fri, 17 Apr 2020 00:24:00 +0200
Subject: [PATCH 02/14] [partition] Goal of this branch: configurable default
 action

---
 src/modules/partition/partition.conf | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf
index 758de0b97..4eb2bf878 100644
--- a/src/modules/partition/partition.conf
+++ b/src/modules/partition/partition.conf
@@ -39,6 +39,16 @@ userSwapChoices:
     # - reuse     # Re-use existing swap, but don't create any (unsupported right now)
     # - file      # To swap file instead of partition (unsupported right now)
 
+# By default, when the user arrives at the partitioning page, no action
+# is selected (out of erase, reuse, ...). You can explicitly set None
+# here to select no action on arrival, **or** pick one of these
+# actions and that will be selected if it is available. If it isn't
+# available on arrival, no action will be selected.
+#   - erase
+#   - replace
+#   - alongside
+userDefaultAction: None
+
 # LEGACY SETTINGS (these will generate a warning)
 # ensureSuspendToDisk:    true
 # neverCreateSwap:        false

From b33e54abb9622c0153abdb39d50ef5f8504084dc Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Fri, 17 Apr 2020 00:24:32 +0200
Subject: [PATCH 03/14] [partition] Stub of a Config object

- Even though this isn't a QML'able module, work towards
  a decoupled Config object anyway
- Not actually used yet.
---
 src/modules/partition/CMakeLists.txt  |  1 +
 src/modules/partition/core/Config.cpp | 19 ++++++++++++
 src/modules/partition/core/Config.h   | 44 +++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 src/modules/partition/core/Config.cpp
 create mode 100644 src/modules/partition/core/Config.h

diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt
index d40bbcd1c..65b1a91e9 100644
--- a/src/modules/partition/CMakeLists.txt
+++ b/src/modules/partition/CMakeLists.txt
@@ -56,6 +56,7 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND
         SOURCES
             core/BootLoaderModel.cpp
             core/ColorUtils.cpp
+            core/Config.cpp
             core/DeviceList.cpp
             core/DeviceModel.cpp
             core/KPMHelpers.cpp
diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
new file mode 100644
index 000000000..50dd052d0
--- /dev/null
+++ b/src/modules/partition/core/Config.cpp
@@ -0,0 +1,19 @@
+/* === This file is part of Calamares - <https://github.com/calamares> ===
+ *
+ *   Copyright 2020, 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 "Config.h"
diff --git a/src/modules/partition/core/Config.h b/src/modules/partition/core/Config.h
new file mode 100644
index 000000000..c9b2bd289
--- /dev/null
+++ b/src/modules/partition/core/Config.h
@@ -0,0 +1,44 @@
+/* === This file is part of Calamares - <https://github.com/calamares> ===
+ *
+ *   Copyright 2020, 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_CONFIG_H
+#define PARTITION_CONFIG_H
+
+#include "core/PartitionActions.h"
+
+#include <QObject>
+#include <QSet>
+
+class Config : public QObject
+{
+    Q_OBJECT
+
+public:
+    Config() = default;
+    virtual ~Config() = default;
+
+    using SwapChoiceSet = QSet< PartitionActions::Choices::SwapChoice >;
+
+private:
+    SwapChoiceSet m_swapChoices;
+
+    qreal m_requiredStorageGiB = 0.0;  // May duplicate setting in the welcome module
+};
+
+
+#endif

From c7857b7749b040a1d14fd376441f036b8dedebd1 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Fri, 17 Apr 2020 00:28:14 +0200
Subject: [PATCH 04/14] [partition] Coding style on tests

---
 .../partition/tests/ClearMountsJobTests.cpp   | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/src/modules/partition/tests/ClearMountsJobTests.cpp b/src/modules/partition/tests/ClearMountsJobTests.cpp
index 17ff48945..bdccc1bc4 100644
--- a/src/modules/partition/tests/ClearMountsJobTests.cpp
+++ b/src/modules/partition/tests/ClearMountsJobTests.cpp
@@ -26,19 +26,17 @@ QTEST_GUILESS_MAIN( ClearMountsJobTests )
 
 
 /* Not exactly public API */
-QStringList
-getPartitionsForDevice( const QString& deviceName );
+QStringList getPartitionsForDevice( const QString& deviceName );
 
 QStringList
-getPartitionsForDevice_other(const QString& deviceName)
+getPartitionsForDevice_other( const QString& deviceName )
 {
     QProcess process;
     process.setProgram( "sh" );
-    process.setArguments( {
-                              "-c",
-                              QString( "echo $(awk '{print $4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" )
-                                      .arg( deviceName )
-                          } );
+    process.setArguments(
+        { "-c",
+          QString( "echo $(awk '{print $4}' /proc/partitions | sed -e '/name/d' -e '/^$/d' -e '/[1-9]/!d' | grep %1)" )
+              .arg( deviceName ) } );
     process.start();
     process.waitForFinished();
 
@@ -55,10 +53,11 @@ getPartitionsForDevice_other(const QString& deviceName)
 
 ClearMountsJobTests::ClearMountsJobTests()
 {
-    Logger::setupLogLevel(6);
+    Logger::setupLogLevel( Logger::LOGDEBUG );
 }
 
-void ClearMountsJobTests::testFindPartitions()
+void
+ClearMountsJobTests::testFindPartitions()
 {
     QStringList partitions = getPartitionsForDevice( "sda" );
     QStringList other_part = getPartitionsForDevice_other( "sda" );

From a381d6794f0e013ff9ef99d8b3352674fb456920 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Mon, 18 May 2020 13:07:12 +0200
Subject: [PATCH 05/14] [partition] Migrate required-storage setting to Config
 object

- Create and use the config object in the view step
- Add setConfigurationMap() to Config
---
 src/modules/partition/core/Config.cpp         | 28 +++++++++++++++++++
 src/modules/partition/core/Config.h           |  8 +++---
 .../partition/gui/PartitionViewStep.cpp       | 16 ++++-------
 src/modules/partition/gui/PartitionViewStep.h |  5 ++--
 4 files changed, 40 insertions(+), 17 deletions(-)

diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
index 50dd052d0..5026169fb 100644
--- a/src/modules/partition/core/Config.cpp
+++ b/src/modules/partition/core/Config.cpp
@@ -17,3 +17,31 @@
  */
 
 #include "Config.h"
+
+#include "GlobalStorage.h"
+#include "JobQueue.h"
+#include "utils/Variant.h"
+
+Config::Config( QObject* parent )
+    : QObject( parent )
+{
+}
+
+void
+Config::setConfigurationMap( const QVariantMap& configurationMap )
+{
+    // Settings that overlap with the Welcome module
+    m_requiredStorageGiB = CalamaresUtils::getDouble( configurationMap, "requiredStorage", -1.0 );
+}
+
+void
+Config::updateGlobalStorage() const
+{
+    // If there's no setting (e.g. from the welcome page) for required storage
+    // then use ours, if it was set.
+    auto* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
+    if ( m_requiredStorageGiB >= 0.0 && gs && !gs->contains( "requiredStorageGiB" ) )
+    {
+        gs->insert( "requiredStorageGiB", m_requiredStorageGiB );
+    }
+}
diff --git a/src/modules/partition/core/Config.h b/src/modules/partition/core/Config.h
index c9b2bd289..2543700be 100644
--- a/src/modules/partition/core/Config.h
+++ b/src/modules/partition/core/Config.h
@@ -29,14 +29,14 @@ class Config : public QObject
     Q_OBJECT
 
 public:
-    Config() = default;
+    Config( QObject* parent );
     virtual ~Config() = default;
 
-    using SwapChoiceSet = QSet< PartitionActions::Choices::SwapChoice >;
+    void setConfigurationMap( const QVariantMap& );
 
-private:
-    SwapChoiceSet m_swapChoices;
+    void updateGlobalStorage() const;
 
+private:
     qreal m_requiredStorageGiB = 0.0;  // May duplicate setting in the welcome module
 };
 
diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp
index a583a4b96..02666097b 100644
--- a/src/modules/partition/gui/PartitionViewStep.cpp
+++ b/src/modules/partition/gui/PartitionViewStep.cpp
@@ -22,6 +22,7 @@
 
 #include "gui/PartitionViewStep.h"
 
+#include "core/Config.h"
 #include "core/DeviceModel.h"
 #include "core/KPMHelpers.h"
 #include "core/OsproberEntry.h"
@@ -64,11 +65,11 @@
 
 PartitionViewStep::PartitionViewStep( QObject* parent )
     : Calamares::ViewStep( parent )
+    , m_config( new Config( this ) )
     , m_core( nullptr )
     , m_widget( new QStackedWidget() )
     , m_choicePage( nullptr )
     , m_manualPartitionPage( nullptr )
-    , m_requiredStorageGiB( 0.0 )
 {
     m_widget->setContentsMargins( 0, 0, 0, 0 );
 
@@ -385,13 +386,7 @@ PartitionViewStep::isAtEnd() const
 void
 PartitionViewStep::onActivate()
 {
-    // If there's no setting (e.g. from the welcome page) for required storage
-    // then use ours, if it was set.
-    auto* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr;
-    if ( m_requiredStorageGiB >= 0.0 && gs && !gs->contains( "requiredStorageGiB" ) )
-    {
-        gs->insert( "requiredStorageGiB", m_requiredStorageGiB );
-    }
+    m_config->updateGlobalStorage();
 
     // if we're coming back to PVS from the next VS
     if ( m_widget->currentWidget() == m_choicePage && m_choicePage->currentChoice() == ChoicePage::Alongside )
@@ -525,6 +520,8 @@ PartitionViewStep::onLeave()
 void
 PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
 {
+    m_config->setConfigurationMap( 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();
@@ -635,9 +632,6 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
 
     m_swapChoices = choices;
 
-    // Settings that overlap with the Welcome module
-    m_requiredStorageGiB = CalamaresUtils::getDouble( configurationMap, "requiredStorage", -1.0 );
-
     // These gs settings seem to be unused (in upstream Calamares) outside of
     // the partition module itself.
     gs->insert( "ensureSuspendToDisk", ensureSuspendToDisk );
diff --git a/src/modules/partition/gui/PartitionViewStep.h b/src/modules/partition/gui/PartitionViewStep.h
index 63d11c816..efe2cb343 100644
--- a/src/modules/partition/gui/PartitionViewStep.h
+++ b/src/modules/partition/gui/PartitionViewStep.h
@@ -32,6 +32,7 @@
 #include <QSet>
 
 class ChoicePage;
+class Config;
 class PartitionPage;
 class PartitionCoreModule;
 class QStackedWidget;
@@ -78,6 +79,8 @@ private:
     void initPartitionCoreModule();
     void continueLoading();
 
+    Config* m_config;
+
     PartitionCoreModule* m_core;
     QStackedWidget*   m_widget;
     ChoicePage*       m_choicePage;
@@ -87,8 +90,6 @@ private:
     QFutureWatcher<void>* m_future;
 
     QSet< PartitionActions::Choices::SwapChoice > m_swapChoices;
-
-    qreal m_requiredStorageGiB;  // May duplicate setting in the welcome module
 };
 
 CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionViewStepFactory )

From 4ae398c18d9a71dccb125268b587b3a2f1185d1a Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Mon, 18 May 2020 14:03:31 +0200
Subject: [PATCH 06/14] [partition] Move swap choices into config

---
 src/modules/partition/core/Config.cpp         | 89 +++++++++++++++++++
 src/modules/partition/core/Config.h           |  3 +
 .../partition/gui/PartitionViewStep.cpp       | 88 ------------------
 src/modules/partition/gui/PartitionViewStep.h |  4 -
 4 files changed, 92 insertions(+), 92 deletions(-)

diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
index 5026169fb..b8e68a137 100644
--- a/src/modules/partition/core/Config.cpp
+++ b/src/modules/partition/core/Config.cpp
@@ -20,6 +20,7 @@
 
 #include "GlobalStorage.h"
 #include "JobQueue.h"
+#include "utils/Logger.h"
 #include "utils/Variant.h"
 
 Config::Config( QObject* parent )
@@ -27,11 +28,99 @@ Config::Config( QObject* parent )
 {
 }
 
+Config::SwapChoices
+getSwapChoices( const QVariantMap& configurationMap )
+{
+    // 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.";
+    }
+
+    if ( configurationMap.contains( "ensureSuspendToDisk" ) )
+    {
+        cWarning() << "Partition-module setting *ensureSuspendToDisk* is deprecated.";
+    }
+    bool ensureSuspendToDisk = CalamaresUtils::getBool( configurationMap, "ensureSuspendToDisk", true );
+
+    if ( configurationMap.contains( "neverCreateSwap" ) )
+    {
+        cWarning() << "Partition-module setting *neverCreateSwap* is deprecated.";
+    }
+    bool neverCreateSwap = CalamaresUtils::getBool( configurationMap, "neverCreateSwap", false );
+
+    Config::SwapChoices 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 = PartitionActions::Choices::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 );
+        }
+    }
+
+    // Not all are supported right now // FIXME
+    static const char unsupportedSetting[] = "Partition-module does not support *userSwapChoices* setting";
+
+#define COMPLAIN_UNSUPPORTED( x ) \
+    if ( choices.contains( x ) ) \
+    { \
+        cWarning() << unsupportedSetting << PartitionActions::Choices::choiceToName( x ); \
+        choices.remove( x ); \
+    }
+
+    COMPLAIN_UNSUPPORTED( PartitionActions::Choices::SwapChoice::SwapFile )
+    COMPLAIN_UNSUPPORTED( PartitionActions::Choices::SwapChoice::ReuseSwap )
+#undef COMPLAIN_UNSUPPORTED
+
+    return choices;
+}
+
 void
 Config::setConfigurationMap( const QVariantMap& configurationMap )
 {
     // Settings that overlap with the Welcome module
     m_requiredStorageGiB = CalamaresUtils::getDouble( configurationMap, "requiredStorage", -1.0 );
+    m_swapChoices = getSwapChoices( configurationMap );
 }
 
 void
diff --git a/src/modules/partition/core/Config.h b/src/modules/partition/core/Config.h
index 2543700be..dcd8199d7 100644
--- a/src/modules/partition/core/Config.h
+++ b/src/modules/partition/core/Config.h
@@ -36,7 +36,10 @@ public:
 
     void updateGlobalStorage() const;
 
+    using SwapChoices = QSet< PartitionActions::Choices::SwapChoice >;
+
 private:
+    SwapChoices m_swapChoices;
     qreal m_requiredStorageGiB = 0.0;  // May duplicate setting in the welcome module
 };
 
diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp
index 02666097b..608d8c70c 100644
--- a/src/modules/partition/gui/PartitionViewStep.cpp
+++ b/src/modules/partition/gui/PartitionViewStep.cpp
@@ -549,94 +549,6 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
         gs->insert( "efiSystemPartitionName", CalamaresUtils::getString( configurationMap, "efiSystemPartitionName" ) );
     }
 
-    // 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.";
-    }
-
-    if ( configurationMap.contains( "ensureSuspendToDisk" ) )
-    {
-        cWarning() << "Partition-module setting *ensureSuspendToDisk* is deprecated.";
-    }
-    bool ensureSuspendToDisk = CalamaresUtils::getBool( configurationMap, "ensureSuspendToDisk", true );
-
-    if ( configurationMap.contains( "neverCreateSwap" ) )
-    {
-        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 = PartitionActions::Choices::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 );
-        }
-    }
-
-    // Not all are supported right now // FIXME
-    static const char unsupportedSetting[] = "Partition-module does not support *userSwapChoices* setting";
-
-#define COMPLAIN_UNSUPPORTED( x ) \
-    if ( choices.contains( x ) ) \
-    { \
-        cWarning() << unsupportedSetting << PartitionActions::Choices::choiceToName( x ); \
-        choices.remove( x ); \
-    }
-
-    COMPLAIN_UNSUPPORTED( PartitionActions::Choices::SwapChoice::SwapFile )
-    COMPLAIN_UNSUPPORTED( PartitionActions::Choices::SwapChoice::ReuseSwap )
-#undef COMPLAIN_UNSUPPORTED
-
-    m_swapChoices = choices;
-
-    // These gs settings seem to be unused (in upstream Calamares) outside of
-    // the partition module itself.
-    gs->insert( "ensureSuspendToDisk", ensureSuspendToDisk );
-    gs->insert( "neverCreateSwap", neverCreateSwap );
-
     // OTHER SETTINGS
     //
     gs->insert( "drawNestedPartitions", CalamaresUtils::getBool( configurationMap, "drawNestedPartitions", false ) );
diff --git a/src/modules/partition/gui/PartitionViewStep.h b/src/modules/partition/gui/PartitionViewStep.h
index efe2cb343..c2f7afdb3 100644
--- a/src/modules/partition/gui/PartitionViewStep.h
+++ b/src/modules/partition/gui/PartitionViewStep.h
@@ -26,8 +26,6 @@
 
 #include "DllMacro.h"
 
-#include "core/PartitionActions.h"
-
 #include <QObject>
 #include <QSet>
 
@@ -88,8 +86,6 @@ private:
 
     WaitingWidget* m_waitingWidget;
     QFutureWatcher<void>* m_future;
-
-    QSet< PartitionActions::Choices::SwapChoice > m_swapChoices;
 };
 
 CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionViewStepFactory )

From 68bb06675567a952996af4c3ec9f30d8229fbe60 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Mon, 18 May 2020 14:12:50 +0200
Subject: [PATCH 07/14] [partition] Consolidate SwapChoice handling

- pickOne() may be useful, given a set of swap choices; expose it
- move type definitions to PartitionActions, where some of them
  come from.
---
 src/modules/partition/core/Config.cpp         |  4 ++--
 src/modules/partition/core/Config.h           |  4 +---
 .../partition/core/PartitionActions.cpp       | 19 ++++++++++++++++++
 src/modules/partition/core/PartitionActions.h | 10 ++++++++++
 src/modules/partition/gui/ChoicePage.cpp      | 20 +------------------
 5 files changed, 33 insertions(+), 24 deletions(-)

diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
index b8e68a137..d3b5a0310 100644
--- a/src/modules/partition/core/Config.cpp
+++ b/src/modules/partition/core/Config.cpp
@@ -28,7 +28,7 @@ Config::Config( QObject* parent )
 {
 }
 
-Config::SwapChoices
+static PartitionActions::Choices::SwapChoiceSet
 getSwapChoices( const QVariantMap& configurationMap )
 {
     // SWAP SETTINGS
@@ -53,7 +53,7 @@ getSwapChoices( const QVariantMap& configurationMap )
     }
     bool neverCreateSwap = CalamaresUtils::getBool( configurationMap, "neverCreateSwap", false );
 
-    Config::SwapChoices choices;  // Available swap choices
+    PartitionActions::Choices::SwapChoiceSet choices;  // Available swap choices
     if ( configurationMap.contains( "userSwapChoices" ) )
     {
         // We've already warned about overlapping settings with the
diff --git a/src/modules/partition/core/Config.h b/src/modules/partition/core/Config.h
index dcd8199d7..c18506f7b 100644
--- a/src/modules/partition/core/Config.h
+++ b/src/modules/partition/core/Config.h
@@ -36,10 +36,8 @@ public:
 
     void updateGlobalStorage() const;
 
-    using SwapChoices = QSet< PartitionActions::Choices::SwapChoice >;
-
 private:
-    SwapChoices m_swapChoices;
+    PartitionActions::Choices::SwapChoiceSet m_swapChoices;
     qreal m_requiredStorageGiB = 0.0;  // May duplicate setting in the welcome module
 };
 
diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp
index d0de2c0d4..3bf5d35d4 100644
--- a/src/modules/partition/core/PartitionActions.cpp
+++ b/src/modules/partition/core/PartitionActions.cpp
@@ -293,6 +293,25 @@ choiceToName( SwapChoice c )
     return nameTable().find( c, ok );
 }
 
+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() );
+}
+
 }  // namespace Choices
 
 }  // namespace PartitionActions
diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h
index ed7045822..558ccb4b9 100644
--- a/src/modules/partition/core/PartitionActions.h
+++ b/src/modules/partition/core/PartitionActions.h
@@ -19,6 +19,7 @@
 #ifndef PARTITIONACTIONS_H
 #define PARTITIONACTIONS_H
 
+#include <QSet>
 #include <QString>
 
 class PartitionCoreModule;
@@ -42,10 +43,19 @@ enum SwapChoice
     FullSwap,  // ensureSuspendToDisk -- at least RAM size
     SwapFile  // use a file (if supported)
 };
+using SwapChoiceSet = QSet< SwapChoice >;
 
 SwapChoice nameToChoice( QString name, bool& ok );
 QString choiceToName( 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 );
+
 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 5c90ea7b0..b7d4c33ad 100644
--- a/src/modules/partition/gui/ChoicePage.cpp
+++ b/src/modules/partition/gui/ChoicePage.cpp
@@ -70,24 +70,6 @@ using CalamaresUtils::Partition::isPartitionFreeSpace;
 using CalamaresUtils::Partition::findPartitionByPath;
 using Calamares::PrettyRadioButton;
 
-/** @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.
@@ -112,7 +94,7 @@ ChoicePage::ChoicePage( const SwapChoiceSet& swapChoices, QWidget* parent )
     , m_lastSelectedDeviceIndex( -1 )
     , m_enableEncryptionWidget( true )
     , m_availableSwapChoices( swapChoices )
-    , m_eraseSwapChoice( pickOne( swapChoices ) )
+    , m_eraseSwapChoice( PartitionActions::Choices::pickOne( swapChoices ) )
     , m_allowManualPartitioning( true )
 {
     setupUi( this );

From 14df0328031dd020d693e16cb669ee402bdf7b59 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Wed, 29 Jul 2020 22:32:52 +0200
Subject: [PATCH 08/14] CI: build verbose the first time, too

---
 ci/travis-continuous.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/ci/travis-continuous.sh b/ci/travis-continuous.sh
index aefaca6f8..567a55d3d 100755
--- a/ci/travis-continuous.sh
+++ b/ci/travis-continuous.sh
@@ -24,7 +24,7 @@ section "cmake $CMAKE_ARGS $SRCDIR"
 cmake $CMAKE_ARGS $SRCDIR || { echo "! CMake failed" ; exit 1 ; }
 
 section "make"
-make -j2 || { echo "! Make recheck" ; pwd -P ; df -h ; make -j1 VERBOSE=1 ; echo "! Make failed" ; exit 1 ; }
+make -j2 VERBOSE=1 || { echo "! Make recheck" ; pwd -P ; df -h ; make -j1 VERBOSE=1 ; echo "! Make failed" ; exit 1 ; }
 
 section "make install"
 

From d103c42091542a60be2204db7fd12af04e024718 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Thu, 30 Jul 2020 10:26:58 +0200
Subject: [PATCH 09/14] [partition] Fix build now swapChoices lives in config

---
 src/modules/partition/core/Config.cpp           | 3 ++-
 src/modules/partition/core/Config.h             | 6 ++++--
 src/modules/partition/gui/PartitionViewStep.cpp | 2 +-
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
index d3b5a0310..aaf9cb906 100644
--- a/src/modules/partition/core/Config.cpp
+++ b/src/modules/partition/core/Config.cpp
@@ -1,6 +1,7 @@
 /* === This file is part of Calamares - <https://github.com/calamares> ===
  *
- *   Copyright 2020, Adriaan de Groot <groot@kde.org>
+ *   SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
+ *   SPDX-License-Identifier: GPL-3.0-or-later
  *
  *   Calamares is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
diff --git a/src/modules/partition/core/Config.h b/src/modules/partition/core/Config.h
index c18506f7b..f6823e640 100644
--- a/src/modules/partition/core/Config.h
+++ b/src/modules/partition/core/Config.h
@@ -1,6 +1,7 @@
 /* === This file is part of Calamares - <https://github.com/calamares> ===
  *
- *   Copyright 2020, Adriaan de Groot <groot@kde.org>
+ *   SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
+ *   SPDX-License-Identifier: GPL-3.0-or-later
  *
  *   Calamares is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License as published by
@@ -33,9 +34,10 @@ public:
     virtual ~Config() = default;
 
     void setConfigurationMap( const QVariantMap& );
-
     void updateGlobalStorage() const;
 
+    PartitionActions::Choices::SwapChoiceSet swapChoices() const { return m_swapChoices; }
+
 private:
     PartitionActions::Choices::SwapChoiceSet m_swapChoices;
     qreal m_requiredStorageGiB = 0.0;  // May duplicate setting in the welcome module
diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp
index ef43e0584..04f14dd84 100644
--- a/src/modules/partition/gui/PartitionViewStep.cpp
+++ b/src/modules/partition/gui/PartitionViewStep.cpp
@@ -94,7 +94,7 @@ void
 PartitionViewStep::continueLoading()
 {
     Q_ASSERT( !m_choicePage );
-    m_choicePage = new ChoicePage( m_swapChoices );
+    m_choicePage = new ChoicePage( m_config->swapChoices() );
     m_choicePage->init( m_core );
     m_widget->addWidget( m_choicePage );
 

From 824dac62d8fab29decefb6d03364fdcbb8b20f60 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Thu, 30 Jul 2020 10:44:10 +0200
Subject: [PATCH 10/14] [partition] ChoicePage to use Config object

---
 src/modules/partition/gui/ChoicePage.cpp      | 23 ++++++++++---------
 src/modules/partition/gui/ChoicePage.h        |  6 +++--
 .../partition/gui/PartitionViewStep.cpp       |  2 +-
 3 files changed, 17 insertions(+), 14 deletions(-)

diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp
index 4640315c8..055595ba0 100644
--- a/src/modules/partition/gui/ChoicePage.cpp
+++ b/src/modules/partition/gui/ChoicePage.cpp
@@ -20,7 +20,15 @@
 
 #include "ChoicePage.h"
 
+#include "BootInfoWidget.h"
+#include "DeviceInfoWidget.h"
+#include "PartitionBarsView.h"
+#include "PartitionLabelsView.h"
+#include "PartitionSplitterWidget.h"
+#include "ReplaceWidget.h"
+#include "ScanningDialog.h"
 #include "core/BootLoaderModel.h"
+#include "core/Config.h"
 #include "core/DeviceModel.h"
 #include "core/KPMHelpers.h"
 #include "core/OsproberEntry.h"
@@ -30,14 +38,6 @@
 #include "core/PartitionInfo.h"
 #include "core/PartitionModel.h"
 
-#include "BootInfoWidget.h"
-#include "DeviceInfoWidget.h"
-#include "PartitionBarsView.h"
-#include "PartitionLabelsView.h"
-#include "PartitionSplitterWidget.h"
-#include "ReplaceWidget.h"
-#include "ScanningDialog.h"
-
 #include "Branding.h"
 #include "GlobalStorage.h"
 #include "JobQueue.h"
@@ -75,8 +75,9 @@ using Calamares::PrettyRadioButton;
  *      the module loading code path.
  * @param parent the QWidget parent.
  */
-ChoicePage::ChoicePage( const SwapChoiceSet& swapChoices, QWidget* parent )
+ChoicePage::ChoicePage( Config* config, QWidget* parent )
     : QWidget( parent )
+    , m_config( config )
     , m_nextEnabled( false )
     , m_core( nullptr )
     , m_choice( NoChoice )
@@ -93,8 +94,8 @@ ChoicePage::ChoicePage( const SwapChoiceSet& swapChoices, QWidget* parent )
     , m_bootloaderComboBox( nullptr )
     , m_lastSelectedDeviceIndex( -1 )
     , m_enableEncryptionWidget( true )
-    , m_availableSwapChoices( swapChoices )
-    , m_eraseSwapChoice( PartitionActions::Choices::pickOne( swapChoices ) )
+    , m_availableSwapChoices( config->swapChoices() )
+    , m_eraseSwapChoice( PartitionActions::Choices::pickOne( m_availableSwapChoices ) )
     , m_allowManualPartitioning( true )
 {
     setupUi( this );
diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h
index a28892011..f985178d5 100644
--- a/src/modules/partition/gui/ChoicePage.h
+++ b/src/modules/partition/gui/ChoicePage.h
@@ -42,11 +42,12 @@ namespace Calamares
 class PrettyRadioButton;
 }
 
+class Config;
+class DeviceInfoWidget;
 class PartitionBarsView;
 class PartitionSplitterWidget;
 class PartitionLabelsView;
 class PartitionCoreModule;
-class DeviceInfoWidget;
 
 class Device;
 
@@ -70,7 +71,7 @@ public:
         Manual
     };
 
-    explicit ChoicePage( const SwapChoiceSet& swapChoices, QWidget* parent = nullptr );
+    explicit ChoicePage( Config* config, QWidget* parent = nullptr );
     virtual ~ChoicePage();
 
     /**
@@ -147,6 +148,7 @@ private:
     // Translations support
     void updateSwapChoicesTr( QComboBox* box );
 
+    Config* m_config;
     bool m_nextEnabled;
     PartitionCoreModule* m_core;
 
diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp
index 04f14dd84..999c94505 100644
--- a/src/modules/partition/gui/PartitionViewStep.cpp
+++ b/src/modules/partition/gui/PartitionViewStep.cpp
@@ -94,7 +94,7 @@ void
 PartitionViewStep::continueLoading()
 {
     Q_ASSERT( !m_choicePage );
-    m_choicePage = new ChoicePage( m_config->swapChoices() );
+    m_choicePage = new ChoicePage( m_config );
     m_choicePage->init( m_core );
     m_widget->addWidget( m_choicePage );
 

From fec8361ed5640ee5c7ae47ae7652655d4201cac0 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Thu, 30 Jul 2020 10:51:48 +0200
Subject: [PATCH 11/14] [partition] Drop "convenience" functions

- the functions are used just once
- thin wrappers for named-enum methods that are just as convenient
---
 src/modules/partition/core/Config.cpp           |  5 +++--
 src/modules/partition/core/PartitionActions.cpp | 17 ++---------------
 src/modules/partition/core/PartitionActions.h   |  7 ++++---
 3 files changed, 9 insertions(+), 20 deletions(-)

diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
index aaf9cb906..7af004942 100644
--- a/src/modules/partition/core/Config.cpp
+++ b/src/modules/partition/core/Config.cpp
@@ -64,7 +64,7 @@ getSwapChoices( const QVariantMap& configurationMap )
         for ( const auto& item : l )
         {
             bool ok = false;
-            auto v = PartitionActions::Choices::nameToChoice( item, ok );
+            auto v = PartitionActions::Choices::swapChoiceNames().find( item, ok );
             if ( ok )
             {
                 choices.insert( v );
@@ -105,7 +105,8 @@ getSwapChoices( const QVariantMap& configurationMap )
 #define COMPLAIN_UNSUPPORTED( x ) \
     if ( choices.contains( x ) ) \
     { \
-        cWarning() << unsupportedSetting << PartitionActions::Choices::choiceToName( x ); \
+        bool bogus = false; \
+        cWarning() << unsupportedSetting << PartitionActions::Choices::swapChoiceNames().find( x, bogus ); \
         choices.remove( x ); \
     }
 
diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp
index 0c7ed6e6d..dc4d4eeb4 100644
--- a/src/modules/partition/core/PartitionActions.cpp
+++ b/src/modules/partition/core/PartitionActions.cpp
@@ -257,8 +257,8 @@ doReplacePartition( PartitionCoreModule* core, Device* dev, Partition* partition
 
 namespace Choices
 {
-static const NamedEnumTable< SwapChoice >&
-nameTable()
+const NamedEnumTable< SwapChoice >&
+swapChoiceNames()
 {
     static const NamedEnumTable< SwapChoice > names { { QStringLiteral( "none" ), SwapChoice::NoSwap },
                                                       { QStringLiteral( "small" ), SwapChoice::SmallSwap },
@@ -269,19 +269,6 @@ nameTable()
     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 );
-}
-
 SwapChoice
 pickOne( const SwapChoiceSet& s )
 {
diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h
index 558ccb4b9..706fbaea3 100644
--- a/src/modules/partition/core/PartitionActions.h
+++ b/src/modules/partition/core/PartitionActions.h
@@ -19,6 +19,8 @@
 #ifndef PARTITIONACTIONS_H
 #define PARTITIONACTIONS_H
 
+#include "utils/NamedEnum.h"
+
 #include <QSet>
 #include <QString>
 
@@ -34,7 +36,7 @@ namespace PartitionActions
  */
 namespace Choices
 {
-/** @brief Ccchoice of swap (size and type) */
+/** @brief Choice of swap (size and type) */
 enum SwapChoice
 {
     NoSwap,  // don't create any swap, don't use any
@@ -45,8 +47,7 @@ enum SwapChoice
 };
 using SwapChoiceSet = QSet< SwapChoice >;
 
-SwapChoice nameToChoice( QString name, bool& ok );
-QString choiceToName( SwapChoice );
+const NamedEnumTable< SwapChoice >& swapChoiceNames();
 
 /** @brief Given a set of swap choices, return a sensible value from it.
  *

From 380e2b361323768fbe3d1e72d38d93c81f9581a0 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Fri, 31 Jul 2020 14:13:08 +0200
Subject: [PATCH 12/14] [partition] Fix up schema file

---
 src/modules/partition/partition.schema.yaml | 21 ++++++++++++++++++---
 1 file changed, 18 insertions(+), 3 deletions(-)

diff --git a/src/modules/partition/partition.schema.yaml b/src/modules/partition/partition.schema.yaml
index 198123dd5..d08f4a6cd 100644
--- a/src/modules/partition/partition.schema.yaml
+++ b/src/modules/partition/partition.schema.yaml
@@ -4,8 +4,23 @@ $id: https://calamares.io/schemas/partition
 additionalProperties: false
 type: object
 properties:
-    efiSystemPartition: { type: string, required: true }
-    ensureSuspendToDisk: { type: boolean, default: true }
+    efiSystemPartition: { type: string }  # Mount point
+    efiSystemPartitionSize: { type: string }
+    efiSystemPartitionName: { type: string }
+
+    userSwapChoices: { type: array, items: { type: string, enum: [ none, reuse, small, suspend, file ] } }
+    # ensureSuspendToDisk: { type: boolean, default: true }  # Legacy
+    # neverCreateSwap: { type: boolean, default: false }  # Legacy
+
     drawNestedPartitions: { type: boolean, default: false }
     alwaysShowPartitionLabels: { type: boolean, default: true }
-    defaultFileSystemType: { type: string, required: true }
+
+    defaultFileSystemType: { type: string }
+    enableLuksAutomatedPartitioning: { type: boolean, default: false }
+    allowManualPartitioning: { type: boolean, default: true }
+    partitionLayout: { type: array }  # TODO: specify items
+
+    requiredStorage: { type: number }
+required:
+    - efiSystemPartition
+    - userSwapChoices

From e21a2f0676a7dfa17ca31be89545760c4cdd8273 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Thu, 30 Jul 2020 11:36:59 +0200
Subject: [PATCH 13/14] [partition] Add InitialInstallChoice to Config

- add an option to select what button should be selected when the
  partitioning module is started; TODO: the actual functionality is
  **not** implemented.
- drop the previously suggested name, which didn't get beyond the
  comments-in-the-config-file stage (but which intended to do the
  same things as this one)
- add option to schema already, even if it's not implemented.

See #1297

FIXUP conf
---
 src/modules/partition/core/Config.cpp         |  3 ++
 src/modules/partition/core/Config.h           |  8 ++++
 .../partition/core/PartitionActions.cpp       | 13 ++++++
 src/modules/partition/core/PartitionActions.h | 11 ++++-
 src/modules/partition/partition.conf          | 43 ++++++++++---------
 src/modules/partition/partition.schema.yaml   |  1 +
 6 files changed, 58 insertions(+), 21 deletions(-)

diff --git a/src/modules/partition/core/Config.cpp b/src/modules/partition/core/Config.cpp
index 7af004942..086d87da5 100644
--- a/src/modules/partition/core/Config.cpp
+++ b/src/modules/partition/core/Config.cpp
@@ -123,6 +123,9 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
     // Settings that overlap with the Welcome module
     m_requiredStorageGiB = CalamaresUtils::getDouble( configurationMap, "requiredStorage", -1.0 );
     m_swapChoices = getSwapChoices( configurationMap );
+
+    bool nameFound = false;  // In the name table (ignored, falls back to first entry in table)
+    m_initialInstallChoice = PartitionActions::Choices::installChoiceNames().find( CalamaresUtils::getString( configurationMap, "initialPartitioningChoice" ), nameFound );
 }
 
 void
diff --git a/src/modules/partition/core/Config.h b/src/modules/partition/core/Config.h
index f6823e640..fb2f8116c 100644
--- a/src/modules/partition/core/Config.h
+++ b/src/modules/partition/core/Config.h
@@ -38,8 +38,16 @@ public:
 
     PartitionActions::Choices::SwapChoiceSet swapChoices() const { return m_swapChoices; }
 
+    /**
+     * @brief What kind of installation (partitioning) is requested **initially**?
+     *
+     * @return the partitioning choice (may by @c NoChoice)
+     */
+    PartitionActions::Choices::InstallChoice initialInstallChoice() const { return m_initialInstallChoice; }
+
 private:
     PartitionActions::Choices::SwapChoiceSet m_swapChoices;
+    PartitionActions::Choices::InstallChoice m_initialInstallChoice = PartitionActions::Choices::NoChoice;
     qreal m_requiredStorageGiB = 0.0;  // May duplicate setting in the welcome module
 };
 
diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp
index dc4d4eeb4..cae5025bf 100644
--- a/src/modules/partition/core/PartitionActions.cpp
+++ b/src/modules/partition/core/PartitionActions.cpp
@@ -288,6 +288,19 @@ pickOne( const SwapChoiceSet& s )
     return *( s.begin() );
 }
 
+const NamedEnumTable< InstallChoice >&
+installChoiceNames()
+{
+    static const NamedEnumTable< InstallChoice > names { { QStringLiteral( "none" ), InstallChoice::NoChoice },
+                                                         { QStringLiteral( "nochoice" ), InstallChoice::NoChoice },
+                                                         { QStringLiteral( "alongside" ), InstallChoice::Alongside },
+                                                         { QStringLiteral( "erase" ), InstallChoice::Erase },
+                                                         { QStringLiteral( "replace" ), InstallChoice::Replace },
+                                                         { QStringLiteral( "manual" ), InstallChoice::Manual } };
+    return names;
+}
+
+
 }  // namespace Choices
 
 }  // namespace PartitionActions
diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h
index 706fbaea3..6f4b41cc8 100644
--- a/src/modules/partition/core/PartitionActions.h
+++ b/src/modules/partition/core/PartitionActions.h
@@ -46,7 +46,6 @@ enum SwapChoice
     SwapFile  // use a file (if supported)
 };
 using SwapChoiceSet = QSet< SwapChoice >;
-
 const NamedEnumTable< SwapChoice >& swapChoiceNames();
 
 /** @brief Given a set of swap choices, return a sensible value from it.
@@ -57,6 +56,16 @@ const NamedEnumTable< SwapChoice >& swapChoiceNames();
  */
 SwapChoice pickOne( const SwapChoiceSet& s );
 
+enum InstallChoice
+{
+    NoChoice,
+    Alongside,
+    Erase,
+    Replace,
+    Manual
+};
+const NamedEnumTable< InstallChoice >& installChoiceNames();
+
 struct ReplacePartitionOptions
 {
     QString defaultFsType;  // e.g. "ext4" or "btrfs"
diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf
index 5413c10f1..363ef7db1 100644
--- a/src/modules/partition/partition.conf
+++ b/src/modules/partition/partition.conf
@@ -39,16 +39,6 @@ userSwapChoices:
     # - reuse     # Re-use existing swap, but don't create any (unsupported right now)
     # - file      # To swap file instead of partition (unsupported right now)
 
-# By default, when the user arrives at the partitioning page, no action
-# is selected (out of erase, reuse, ...). You can explicitly set None
-# here to select no action on arrival, **or** pick one of these
-# actions and that will be selected if it is available. If it isn't
-# available on arrival, no action will be selected.
-#   - erase
-#   - replace
-#   - alongside
-userDefaultAction: None
-
 # LEGACY SETTINGS (these will generate a warning)
 # ensureSuspendToDisk:    true
 # neverCreateSwap:        false
@@ -59,6 +49,29 @@ drawNestedPartitions:   false
 # Show/hide partition labels on manual partitioning page.
 alwaysShowPartitionLabels: true
 
+# Allow manual partitioning.
+#
+# When set to false, this option hides the "Manual partitioning" button,
+# limiting the user's choice to "Erase", "Replace" or "Alongside".
+# This can be useful when using a custom partition layout we don't want
+# the user to modify.
+#
+# If nothing is specified, manual partitioning is enabled.
+#allowManualPartitioning:   true
+
+# Initial selection on the Choice page
+#
+# There are four radio buttons (in principle: erase, replace, alongside, manual),
+# and you can pick which of them, if any, is initially selected. For most
+# installers, "none" is the right choice: it makes the user pick something specific,
+# rather than accidentally being able to click past an important choice (in particular,
+# "erase" is a dangerous choice).
+#
+# The default is "none"
+#
+# TODO: this isn't implemented
+# initialPartitioningChoice: none
+
 # Default filesystem type, used when a "new" partition is made.
 #
 # When replacing a partition, the existing filesystem inside the
@@ -96,16 +109,6 @@ defaultFileSystemType:  "ext4"
 # If nothing is specified, LUKS is enabled in automated modes.
 #enableLuksAutomatedPartitioning:    true
 
-# Allow manual partitioning.
-#
-# When set to false, this option hides the "Manual partitioning" button,
-# limiting the user's choice to "Erase", "Replace" or "Alongside".
-# This can be useful when using a custom partition layout we don't want
-# the user to modify.
-#
-# If nothing is specified, manual partitioning is enabled.
-#allowManualPartitioning:   true
-
 # To apply a custom partition layout, it has to be defined this way :
 #
 # partitionLayout:
diff --git a/src/modules/partition/partition.schema.yaml b/src/modules/partition/partition.schema.yaml
index d08f4a6cd..157f416d7 100644
--- a/src/modules/partition/partition.schema.yaml
+++ b/src/modules/partition/partition.schema.yaml
@@ -19,6 +19,7 @@ properties:
     enableLuksAutomatedPartitioning: { type: boolean, default: false }
     allowManualPartitioning: { type: boolean, default: true }
     partitionLayout: { type: array }  # TODO: specify items
+    initialPartitioningChoice: { type: string, enum: [ none, erase, replace, alongside, manual ] }
 
     requiredStorage: { type: number }
 required:

From 41ce42cd4b8ed0f33283ec0ef49794189d620461 Mon Sep 17 00:00:00 2001
From: Adriaan de Groot <groot@kde.org>
Date: Thu, 30 Jul 2020 11:51:26 +0200
Subject: [PATCH 14/14] [partition] Drop InstallChoice enum from Page

- The enum for install choice was copied into PartitionActions and
  used in the Config object; its definition does not belong in the UI.
- Chase the renamings required.
---
 src/modules/partition/gui/ChoicePage.cpp      | 68 +++++++++----------
 src/modules/partition/gui/ChoicePage.h        |  9 +--
 .../partition/gui/PartitionViewStep.cpp       | 30 ++++----
 3 files changed, 50 insertions(+), 57 deletions(-)

diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp
index 055595ba0..d7b5e497e 100644
--- a/src/modules/partition/gui/ChoicePage.cpp
+++ b/src/modules/partition/gui/ChoicePage.cpp
@@ -80,7 +80,7 @@ ChoicePage::ChoicePage( Config* config, QWidget* parent )
     , m_config( config )
     , m_nextEnabled( false )
     , m_core( nullptr )
-    , m_choice( NoChoice )
+    , m_choice( InstallChoice::NoChoice )
     , m_isEfi( false )
     , m_grp( nullptr )
     , m_alongsideButton( nullptr )
@@ -242,14 +242,14 @@ ChoicePage::setupChoices()
     m_alongsideButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionAlongside,
                                                                CalamaresUtils::Original,
                                                                iconSize ) );
-    m_alongsideButton->addToGroup( m_grp, Alongside );
+    m_alongsideButton->addToGroup( m_grp, InstallChoice::Alongside );
 
     m_eraseButton = new PrettyRadioButton;
     m_eraseButton->setIconSize( iconSize );
     m_eraseButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionEraseAuto,
                                                            CalamaresUtils::Original,
                                                            iconSize ) );
-    m_eraseButton->addToGroup( m_grp, Erase );
+    m_eraseButton->addToGroup( m_grp, InstallChoice::Erase );
 
     m_replaceButton = new PrettyRadioButton;
 
@@ -257,7 +257,7 @@ ChoicePage::setupChoices()
     m_replaceButton->setIcon( CalamaresUtils::defaultPixmap( CalamaresUtils::PartitionReplaceOs,
                                                              CalamaresUtils::Original,
                                                              iconSize ) );
-    m_replaceButton->addToGroup( m_grp, Replace );
+    m_replaceButton->addToGroup( m_grp, InstallChoice::Replace );
 
     // Fill up swap options
     // .. TODO: only if enabled in the config
@@ -277,7 +277,7 @@ ChoicePage::setupChoices()
                                                                    CalamaresUtils::Original,
                                                                    iconSize ) );
     m_itemsLayout->addWidget( m_somethingElseButton );
-    m_somethingElseButton->addToGroup( m_grp, Manual );
+    m_somethingElseButton->addToGroup( m_grp, InstallChoice::Manual );
 
     m_itemsLayout->addStretch();
 
@@ -295,7 +295,7 @@ ChoicePage::setupChoices()
         {
             if ( m_grp->checkedButton() == nullptr )  // If no other action is chosen, we must
             {                                         // set m_choice to NoChoice and reset previews.
-                m_choice = NoChoice;
+                m_choice = InstallChoice::NoChoice;
                 updateNextEnabled();
 
                 emit actionChosen();
@@ -441,7 +441,7 @@ ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice )
 
     switch ( choice )
     {
-    case Erase:
+    case InstallChoice::Erase:
         {
             auto gs = Calamares::JobQueue::instance()->globalStorage();
 
@@ -474,7 +474,7 @@ ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice )
             }
         }
         break;
-    case Replace:
+    case InstallChoice::Replace:
         if ( m_core->isDirty() )
         {
             ScanningDialog::run( QtConcurrent::run( [ = ]
@@ -492,7 +492,7 @@ ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice )
                  Qt::UniqueConnection );
         break;
 
-    case Alongside:
+    case InstallChoice::Alongside:
         if ( m_core->isDirty() )
         {
             ScanningDialog::run( QtConcurrent::run( [ = ]
@@ -515,8 +515,8 @@ ChoicePage::applyActionChoice( ChoicePage::InstallChoice choice )
                  this, SLOT( doAlongsideSetupSplitter( QModelIndex, QModelIndex ) ),
                  Qt::UniqueConnection );
         break;
-    case NoChoice:
-    case Manual:
+    case InstallChoice::NoChoice:
+    case InstallChoice::Manual:
         break;
     }
     updateActionChoicePreview( choice );
@@ -571,13 +571,13 @@ void
 ChoicePage::onEncryptWidgetStateChanged()
 {
     EncryptWidget::Encryption state = m_encryptWidget->state();
-    if ( m_choice == Erase )
+    if ( m_choice == InstallChoice::Erase )
     {
         if ( state == EncryptWidget::Encryption::Confirmed ||
              state == EncryptWidget::Encryption::Disabled )
             applyActionChoice( m_choice );
     }
-    else if ( m_choice == Replace )
+    else if ( m_choice == InstallChoice::Replace )
     {
         if ( m_beforePartitionBarsView &&
              m_beforePartitionBarsView->selectionModel()->currentIndex().isValid() &&
@@ -596,7 +596,7 @@ ChoicePage::onEncryptWidgetStateChanged()
 void
 ChoicePage::onHomeCheckBoxStateChanged()
 {
-    if ( currentChoice() == Replace &&
+    if ( currentChoice() == InstallChoice::Replace &&
          m_beforePartitionBarsView->selectionModel()->currentIndex().isValid() )
     {
         doReplaceSelectedPartition( m_beforePartitionBarsView->
@@ -609,10 +609,10 @@ ChoicePage::onHomeCheckBoxStateChanged()
 void
 ChoicePage::onLeave()
 {
-    if ( m_choice == Alongside )
+    if ( m_choice == InstallChoice::Alongside )
         doAlongsideApply();
 
-    if ( m_isEfi && ( m_choice == Alongside || m_choice == Replace ) )
+    if ( m_isEfi && ( m_choice == InstallChoice::Alongside || m_choice == InstallChoice::Replace ) )
     {
         QList< Partition* > efiSystemPartitions = m_core->efiSystemPartitions();
         if ( efiSystemPartitions.count() == 1 )
@@ -879,8 +879,8 @@ ChoicePage::updateDeviceStatePreview()
 
     switch ( m_choice )
     {
-    case Replace:
-    case Alongside:
+    case InstallChoice::Replace:
+    case InstallChoice::Alongside:
         m_beforePartitionBarsView->setSelectionMode( QAbstractItemView::SingleSelection );
         m_beforePartitionLabelsView->setSelectionMode( QAbstractItemView::SingleSelection );
         break;
@@ -931,7 +931,7 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
 
     switch ( choice )
     {
-    case Alongside:
+    case InstallChoice::Alongside:
         {
             if ( m_enableEncryptionWidget )
                 m_encryptWidget->show();
@@ -975,8 +975,8 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
 
             break;
         }
-    case Erase:
-    case Replace:
+    case InstallChoice::Erase:
+    case InstallChoice::Replace:
         {
             if ( m_enableEncryptionWidget )
                 m_encryptWidget->show();
@@ -1042,7 +1042,7 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
             m_previewAfterFrame->show();
             m_previewAfterLabel->show();
 
-            if ( m_choice == Erase )
+            if ( m_choice == InstallChoice::Erase )
                 m_selectLabel->hide();
             else
             {
@@ -1062,8 +1062,8 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
 
             break;
         }
-    case NoChoice:
-    case Manual:
+    case InstallChoice::NoChoice:
+    case InstallChoice::Manual:
         m_selectLabel->hide();
         m_previewAfterFrame->hide();
         m_previewBeforeLabel->setText( tr( "Current:" ) );
@@ -1072,7 +1072,7 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
         break;
     }
 
-    if ( m_isEfi && ( m_choice == Alongside || m_choice == Replace ) )
+    if ( m_isEfi && ( m_choice == InstallChoice::Alongside || m_choice == InstallChoice::Replace ) )
     {
         QHBoxLayout* efiLayout = new QHBoxLayout;
         layout->addLayout( efiLayout );
@@ -1089,8 +1089,8 @@ ChoicePage::updateActionChoicePreview( ChoicePage::InstallChoice choice )
     QAbstractItemView::SelectionMode previewSelectionMode;
     switch ( m_choice )
     {
-    case Replace:
-    case Alongside:
+    case InstallChoice::Replace:
+    case InstallChoice::Alongside:
         previewSelectionMode = QAbstractItemView::SingleSelection;
         break;
     default:
@@ -1433,11 +1433,11 @@ ChoicePage::calculateNextEnabled() const
 
     switch ( m_choice )
     {
-    case NoChoice:
+    case InstallChoice::NoChoice:
         cDebug() << "No partitioning choice";
         return false;
-    case Replace:
-    case Alongside:
+    case InstallChoice::Replace:
+    case InstallChoice::Alongside:
         if ( !( sm_p && sm_p->currentIndex().isValid() ) )
         {
             cDebug() << "No partition selected";
@@ -1445,8 +1445,8 @@ ChoicePage::calculateNextEnabled() const
         }
         enabled = true;
         break;
-    case Erase:
-    case Manual:
+    case InstallChoice::Erase:
+    case InstallChoice::Manual:
         enabled = true;
     }
 
@@ -1457,7 +1457,7 @@ ChoicePage::calculateNextEnabled() const
     }
 
 
-    if ( m_isEfi && ( m_choice == Alongside || m_choice == Replace ) )
+    if ( m_isEfi && ( m_choice == InstallChoice::Alongside || m_choice == InstallChoice::Replace ) )
     {
         if ( m_core->efiSystemPartitions().count() == 0 )
         {
@@ -1466,7 +1466,7 @@ ChoicePage::calculateNextEnabled() const
         }
     }
 
-    if ( m_choice != Manual && m_encryptWidget->isVisible() )
+    if ( m_choice != InstallChoice::Manual && m_encryptWidget->isVisible() )
     {
         switch ( m_encryptWidget->state() )
         {
diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h
index f985178d5..af8ee9060 100644
--- a/src/modules/partition/gui/ChoicePage.h
+++ b/src/modules/partition/gui/ChoicePage.h
@@ -62,14 +62,7 @@ class ChoicePage : public QWidget, private Ui::ChoicePage
 {
     Q_OBJECT
 public:
-    enum InstallChoice
-    {
-        NoChoice,
-        Alongside,
-        Erase,
-        Replace,
-        Manual
-    };
+    using InstallChoice = PartitionActions::Choices::InstallChoice;
 
     explicit ChoicePage( Config* config, QWidget* parent = nullptr );
     virtual ~ChoicePage();
diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp
index 999c94505..c05ed3177 100644
--- a/src/modules/partition/gui/PartitionViewStep.cpp
+++ b/src/modules/partition/gui/PartitionViewStep.cpp
@@ -167,20 +167,20 @@ PartitionViewStep::createSummaryWidget() const
         QString modeText;
         switch ( choice )
         {
-        case ChoicePage::Alongside:
+        case ChoicePage::InstallChoice::Alongside:
             modeText = tr( "Install %1 <strong>alongside</strong> another operating system." )
                            .arg( branding->shortVersionedName() );
             break;
-        case ChoicePage::Erase:
+        case ChoicePage::InstallChoice::Erase:
             modeText
                 = tr( "<strong>Erase</strong> disk and install %1." ).arg( branding->shortVersionedName() );
             break;
-        case ChoicePage::Replace:
+        case ChoicePage::InstallChoice::Replace:
             modeText
                 = tr( "<strong>Replace</strong> a partition with %1." ).arg( branding->shortVersionedName() );
             break;
-        case ChoicePage::NoChoice:
-        case ChoicePage::Manual:
+        case ChoicePage::InstallChoice::NoChoice:
+        case ChoicePage::InstallChoice::Manual:
             modeText = tr( "<strong>Manual</strong> partitioning." );
         }
         modeLabel->setText( modeText );
@@ -193,27 +193,27 @@ PartitionViewStep::createSummaryWidget() const
             QString modeText;
             switch ( choice )
             {
-            case ChoicePage::Alongside:
+            case ChoicePage::InstallChoice::Alongside:
                 modeText = tr( "Install %1 <strong>alongside</strong> another operating system on disk "
                                "<strong>%2</strong> (%3)." )
                                .arg( branding->shortVersionedName() )
                                .arg( info.deviceNode )
                                .arg( info.deviceName );
                 break;
-            case ChoicePage::Erase:
+            case ChoicePage::InstallChoice::Erase:
                 modeText = tr( "<strong>Erase</strong> disk <strong>%2</strong> (%3) and install %1." )
                                .arg( branding->shortVersionedName() )
                                .arg( info.deviceNode )
                                .arg( info.deviceName );
                 break;
-            case ChoicePage::Replace:
+            case ChoicePage::InstallChoice::Replace:
                 modeText = tr( "<strong>Replace</strong> a partition on disk <strong>%2</strong> (%3) with %1." )
                                .arg( branding->shortVersionedName() )
                                .arg( info.deviceNode )
                                .arg( info.deviceName );
                 break;
-            case ChoicePage::NoChoice:
-            case ChoicePage::Manual:
+            case ChoicePage::InstallChoice::NoChoice:
+            case ChoicePage::InstallChoice::Manual:
                 modeText = tr( "<strong>Manual</strong> partitioning on disk <strong>%1</strong> (%2)." )
                                .arg( info.deviceNode )
                                .arg( info.deviceName );
@@ -296,7 +296,7 @@ PartitionViewStep::next()
 {
     if ( m_choicePage == m_widget->currentWidget() )
     {
-        if ( m_choicePage->currentChoice() == ChoicePage::Manual )
+        if ( m_choicePage->currentChoice() == ChoicePage::InstallChoice::Manual )
         {
             if ( !m_manualPartitionPage )
             {
@@ -378,8 +378,8 @@ PartitionViewStep::isAtEnd() const
 {
     if ( m_widget->currentWidget() == m_choicePage )
     {
-        if ( m_choicePage->currentChoice() == ChoicePage::Erase || m_choicePage->currentChoice() == ChoicePage::Replace
-             || m_choicePage->currentChoice() == ChoicePage::Alongside )
+        if ( m_choicePage->currentChoice() == ChoicePage::InstallChoice::Erase || m_choicePage->currentChoice() == ChoicePage::InstallChoice::Replace
+             || m_choicePage->currentChoice() == ChoicePage::InstallChoice::Alongside )
         {
             return true;
         }
@@ -395,9 +395,9 @@ PartitionViewStep::onActivate()
     m_config->updateGlobalStorage();
 
     // if we're coming back to PVS from the next VS
-    if ( m_widget->currentWidget() == m_choicePage && m_choicePage->currentChoice() == ChoicePage::Alongside )
+    if ( m_widget->currentWidget() == m_choicePage && m_choicePage->currentChoice() == ChoicePage::InstallChoice::Alongside )
     {
-        m_choicePage->applyActionChoice( ChoicePage::Alongside );
+        m_choicePage->applyActionChoice( ChoicePage::InstallChoice::Alongside );
         //        m_choicePage->reset();
         //FIXME: ReplaceWidget should be reset maybe?
     }