Merge branch 'pr-1667' into calamares

Allow user-selection of FS type

FIXES #1667
main
Adriaan de Groot 4 years ago
commit 56ecf01dea

@ -14,6 +14,7 @@
#include <QObject>
#include <QSignalBlocker>
#include <optional>
#include <type_traits>
/** @brief Convenience to zero out and deleteLater of any QObject-derived-class
@ -58,4 +59,20 @@ struct cBoolSetter
/// @brief Blocks signals on a QObject until destruction
using cSignalBlocker = QSignalBlocker;
/** @brief Writes a value on destruction to a pointed-to location.
*
* If the pointer is non-null, write the last-given-value if there
* is one to the pointed-to object.
*/
template < typename T >
struct cPointerSetter
{
std::optional< T > m_value;
T* m_pointer;
cPointerSetter( T* p ) : m_pointer(p) {}
~cPointerSetter() { if ( m_pointer && m_value.has_value() ) { *m_pointer = m_value.value(); } }
const T& operator=(const T& v) { m_value = v; return v; }
};
#endif

@ -46,25 +46,27 @@ private Q_SLOTS:
void testCommands();
/** @brief Test that all the UMask objects work correctly. */
/** @section Test that all the UMask objects work correctly. */
void testUmask();
/** @brief Tests the entropy functions. */
/** @section Tests the entropy functions. */
void testEntropy();
void testPrintableEntropy();
void testOddSizedPrintable();
/** @brief Tests the RAII bits. */
/** @section Tests the RAII bits. */
void testBoolSetter();
void testPointerSetter();
/** @brief Tests the Traits bits. */
/** @section Tests the Traits bits. */
void testTraits();
/** @section Testing the variants-methods */
void testVariantStringListCode();
void testVariantStringListYAMLDashed();
void testVariantStringListYAMLBracketed();
/** @brief Test smart string truncation. */
/** @section Test smart string truncation. */
void testStringTruncation();
void testStringTruncationShorter();
void testStringTruncationDegenerate();
@ -360,6 +362,50 @@ LibCalamaresTests::testBoolSetter()
QVERIFY( b );
}
void
LibCalamaresTests::testPointerSetter()
{
int special = 17;
QCOMPARE( special, 17 );
{
cPointerSetter p( &special );
}
QCOMPARE( special, 17 );
{
cPointerSetter p( &special );
p = 18;
}
QCOMPARE( special, 18 );
{
cPointerSetter p( &special );
p = 20;
p = 3;
}
QCOMPARE( special, 3 );
{
cPointerSetter<int> p( nullptr );
}
QCOMPARE( special, 3 );
{
// "don't do this" .. order of destructors is important
cPointerSetter p( &special );
cPointerSetter q( &special );
p = 17;
}
QCOMPARE( special, 17 );
{
// "don't do this" .. order of destructors is important
cPointerSetter p( &special );
cPointerSetter q( &special );
p = 34;
q = 2;
// q destroyed first, then p
}
QCOMPARE( special, 34 );
}
/* Demonstration of Traits support for has-a-method or not.
*
* We have two classes, c1 and c2; one has a method do_the_thing() and the
@ -431,17 +477,31 @@ LibCalamaresTests::testVariantStringListCode()
QCOMPARE( getStringList( m, key ), QStringList {} );
m.insert( key, 17 );
QCOMPARE( getStringList( m, key ), QStringList {} );
m.insert( key, QString( "more strings" ) );
QCOMPARE( getStringList( m, key ),
QStringList { "more strings" } ); // A single string **can** be considered a stringlist!
m.insert( key, QVariant {} );
QCOMPARE( getStringList( m, key ), QStringList {} );
}
{
// Things that are stringlists
// Things that are **like** stringlists
QVariantMap m;
m.insert( key, QString( "astring" ) );
QCOMPARE( getStringList( m, key ).count(), 1 );
QCOMPARE( getStringList( m, key ),
QStringList { "astring" } ); // A single string **can** be considered a stringlist!
m.insert( key, QString( "more strings" ) );
QCOMPARE( getStringList( m, key ).count(), 1 );
QCOMPARE( getStringList( m, key ),
QStringList { "more strings" } );
m.insert( key, QString() );
QCOMPARE( getStringList( m, key ).count(), 1 );
QCOMPARE( getStringList( m, key ), QStringList { QString() } );
}
{
// Things that are definitely stringlists
QVariantMap m;
m.insert( key, QStringList { "aap", "noot" } );
QCOMPARE( getStringList( m, key ).count(), 2 );
QVERIFY( getStringList( m, key ).contains( "aap" ) );
QVERIFY( !getStringList( m, key ).contains( "mies" ) );
}

@ -25,13 +25,17 @@ namespace CalamaresUtils
*/
DLLEXPORT bool getBool( const QVariantMap& map, const QString& key, bool d = false );
/**
* Get a string value from a mapping with a given key; returns @p d if no value.
/** @brief Get a string value from a mapping with a given key; returns @p d if no value.
*
* The value must be an actual string; numbers are not automatically converted to strings,
* nor are lists flattened or converted.
*/
DLLEXPORT QString getString( const QVariantMap& map, const QString& key, const QString& d = QString() );
/**
* Get a string list from a mapping with a given key; returns @p d if no value.
/** @brief Get a string list from a mapping with a given key; returns @p d if no value.
*
* This is slightly more lenient that getString(), and a single-string value will
* be returned as a 1-item list.
*/
DLLEXPORT QStringList getStringList( const QVariantMap& map, const QString& key, const QStringList& d = QStringList() );

@ -72,7 +72,7 @@ public:
*/
void updateGlobalStorage( const QStringList& selected ) const;
/// As updateGlobalStorage() with an empty selection list
void updateGlobalStorage() const { updateGlobalStorage( QStringList() ); }
void fillGSSecondaryConfiguration() const { updateGlobalStorage( QStringList() ); }
private:
PackageListModel* m_model = nullptr;

@ -49,9 +49,11 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND
TYPE viewmodule
EXPORT_MACRO PLUGINDLLEXPORT_PRO
SOURCES
Config.cpp
PartitionViewStep.cpp
core/BootLoaderModel.cpp
core/ColorUtils.cpp
core/Config.cpp
core/DeviceList.cpp
core/DeviceModel.cpp
core/KPMHelpers.cpp
@ -75,7 +77,6 @@ if ( KPMcore_FOUND AND Qt5DBus_FOUND AND KF5CoreAddons_FOUND AND KF5Config_FOUND
gui/PartitionLabelsView.cpp
gui/PartitionSizeController.cpp
gui/PartitionSplitterWidget.cpp
gui/PartitionViewStep.cpp
gui/ResizeVolumeGroupDialog.cpp
gui/ScanningDialog.cpp
gui/ReplaceWidget.cpp

@ -9,6 +9,8 @@
#include "Config.h"
#include "core/PartUtils.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "utils/Logger.h"
@ -180,7 +182,7 @@ Config::setInstallChoice( InstallChoice c )
if ( c != m_installChoice )
{
m_installChoice = c;
emit installChoiceChanged( c );
Q_EMIT installChoiceChanged( c );
::updateGlobalStorage( c, m_swapChoice );
}
}
@ -202,16 +204,98 @@ Config::setSwapChoice( Config::SwapChoice c )
if ( c != m_swapChoice )
{
m_swapChoice = c;
emit swapChoiceChanged( c );
Q_EMIT swapChoiceChanged( c );
::updateGlobalStorage( m_installChoice, c );
}
}
bool
Config::allowManualPartitioning() const
void
Config::setEraseFsTypeChoice( const QString& choice )
{
QString canonicalChoice = PartUtils::canonicalFilesystemName( choice, nullptr );
if ( canonicalChoice != m_eraseFsTypeChoice )
{
m_eraseFsTypeChoice = canonicalChoice;
Q_EMIT eraseModeFilesystemChanged( canonicalChoice );
}
}
static void
fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configurationMap )
{
// Set up firmwareType global storage entry. This is used, e.g. by the bootloader module.
QString firmwareType( PartUtils::isEfiSystem() ? QStringLiteral( "efi" ) : QStringLiteral( "bios" ) );
gs->insert( "firmwareType", firmwareType );
gs->insert( "efiSystemPartition", CalamaresUtils::getString( configurationMap, "efiSystemPartition", QStringLiteral( "/boot/efi" ) ) );
// Read and parse key efiSystemPartitionSize
if ( configurationMap.contains( "efiSystemPartitionSize" ) )
{
gs->insert( "efiSystemPartitionSize", CalamaresUtils::getString( configurationMap, "efiSystemPartitionSize" ) );
}
// Read and parse key efiSystemPartitionName
if ( configurationMap.contains( "efiSystemPartitionName" ) )
{
gs->insert( "efiSystemPartitionName", CalamaresUtils::getString( configurationMap, "efiSystemPartitionName" ) );
}
}
void
Config::fillConfigurationFSTypes(const QVariantMap& configurationMap)
{
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
return gs->value( "allowManualPartitioning" ).toBool();
// The defaultFileSystemType setting needs a bit more processing,
// as we want to cover various cases (such as different cases)
QString fsName = CalamaresUtils::getString( configurationMap, "defaultFileSystemType" );
QString fsRealName;
FileSystem::Type fsType = FileSystem::Type::Unknown;
if ( fsName.isEmpty() )
{
cWarning() << "Partition-module setting *defaultFileSystemType* is missing, will use ext4";
fsRealName = PartUtils::canonicalFilesystemName( QStringLiteral("ext4"), &fsType );
}
else
{
fsRealName = PartUtils::canonicalFilesystemName( fsName, &fsType );
if ( fsType == FileSystem::Type::Unknown )
{
cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << fsName << ") using ext4 instead";
fsRealName = PartUtils::canonicalFilesystemName( QStringLiteral("ext4"), &fsType );
}
else if ( fsRealName != fsName )
{
cWarning() << "Partition-module setting *defaultFileSystemType* changed to" << fsRealName;
}
}
Q_ASSERT( fsType != FileSystem::Type::Unknown );
m_defaultFsType = fsType;
gs->insert( "defaultFileSystemType", fsRealName );
// TODO: canonicalize the names? How is translation supposed to work?
m_eraseFsTypes = CalamaresUtils::getStringList( configurationMap, "availableFileSystemTypes" );
if ( !m_eraseFsTypes.contains( fsRealName ) )
{
if ( !m_eraseFsTypes.isEmpty() )
{
// Explicitly set, and doesn't include the default
cWarning() << "Partition-module *availableFileSystemTypes* does not contain the default" << fsRealName;
m_eraseFsTypes.prepend( fsRealName );
}
else
{
// Not explicitly set, so it's empty; don't complain
m_eraseFsTypes = QStringList { fsRealName };
}
}
Q_ASSERT( !m_eraseFsTypes.isEmpty() );
Q_ASSERT( m_eraseFsTypes.contains( fsRealName ) );
m_eraseFsTypeChoice = fsRealName;
Q_EMIT eraseModeFilesystemChanged( m_eraseFsTypeChoice );
}
@ -236,27 +320,18 @@ Config::setConfigurationMap( const QVariantMap& configurationMap )
}
setSwapChoice( m_initialSwapChoice );
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
gs->insert( "allowManualPartitioning",
CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true ) );
m_allowManualPartitioning = CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true );
if ( configurationMap.contains( "requiredPartitionTableType" )
&& configurationMap.value( "requiredPartitionTableType" ).type() == QVariant::List )
{
m_requiredPartitionTableType.clear();
m_requiredPartitionTableType.append( configurationMap.value( "requiredPartitionTableType" ).toStringList() );
}
else if ( configurationMap.contains( "requiredPartitionTableType" )
&& configurationMap.value( "requiredPartitionTableType" ).type() == QVariant::String )
{
m_requiredPartitionTableType.clear();
m_requiredPartitionTableType.append( configurationMap.value( "requiredPartitionTableType" ).toString() );
}
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
m_requiredPartitionTableType = CalamaresUtils::getStringList( configurationMap, "requiredPartitionTableType" );
gs->insert( "requiredPartitionTableType", m_requiredPartitionTableType );
fillGSConfigurationEFI(gs, configurationMap);
fillConfigurationFSTypes( configurationMap );
}
void
Config::updateGlobalStorage() const
Config::fillGSSecondaryConfiguration() const
{
// If there's no setting (e.g. from the welcome page) for required storage
// then use ours, if it was set.

@ -12,6 +12,8 @@
#include "utils/NamedEnum.h"
#include <kpmcore/fs/filesystem.h>
#include <QObject>
#include <QSet>
@ -24,6 +26,9 @@ class Config : public QObject
///@brief The swap choice (None, Small, Hibernate, ...) which only makes sense when Erase is chosen
Q_PROPERTY( SwapChoice swapChoice READ swapChoice WRITE setSwapChoice NOTIFY swapChoiceChanged )
///@brief Name of the FS that will be used when erasing type disk (e.g. "default filesystem")
Q_PROPERTY( QString eraseModeFilesystem READ eraseFsType WRITE setEraseFsTypeChoice NOTIFY eraseModeFilesystemChanged )
Q_PROPERTY( bool allowManualPartitioning READ allowManualPartitioning CONSTANT FINAL )
public:
@ -54,8 +59,19 @@ public:
static const NamedEnumTable< SwapChoice >& swapChoiceNames();
using SwapChoiceSet = QSet< SwapChoice >;
using EraseFsTypesSet = QStringList;
void setConfigurationMap( const QVariantMap& );
void updateGlobalStorage() const;
/** @brief Set GS values where other modules configuration has priority
*
* Some "required" values are duplicated between modules; if some
* othe module hasn't already set the GS value, take a value from
* the partitioning configuration.
*
* Applicable GS keys:
* - requiredStorageGiB
*/
void fillGSSecondaryConfiguration() const;
/** @brief What kind of installation (partitioning) is requested **initially**?
*
@ -94,20 +110,44 @@ public:
*/
SwapChoice swapChoice() const { return m_swapChoice; }
///@brief Is manual partitioning allowed (not explicitly disnabled in the config file)?
bool allowManualPartitioning() const;
/** @brief Get the list of configured FS types to use with *erase* mode
*
* This list is not empty.
*/
EraseFsTypesSet eraseFsTypes() const { return m_eraseFsTypes; }
/** @brief Currently-selected FS type for *erase* mode
*/
QString eraseFsType() const { return m_eraseFsTypeChoice; }
/** @brief Configured default FS type (for other modes than erase)
*
* This is not "Unknown" or "Unformatted"
*/
FileSystem::Type defaultFsType() const { return m_defaultFsType; }
///@brief Is manual partitioning allowed (not explicitly disabled in the config file)?
bool allowManualPartitioning() const { return m_allowManualPartitioning; }
public Q_SLOTS:
void setInstallChoice( int ); ///< Translates a button ID or so to InstallChoice
void setInstallChoice( InstallChoice );
void setSwapChoice( int ); ///< Translates a button ID or so to SwapChoice
void setSwapChoice( SwapChoice );
void setEraseFsTypeChoice( const QString& filesystemName ); ///< See property eraseModeFilesystem
Q_SIGNALS:
void installChoiceChanged( InstallChoice );
void swapChoiceChanged( SwapChoice );
void eraseModeFilesystemChanged( const QString& );
private:
/** @brief Handle FS-type configuration, for erase and default */
void fillConfigurationFSTypes( const QVariantMap& configurationMap );
EraseFsTypesSet m_eraseFsTypes;
QString m_eraseFsTypeChoice;
FileSystem::Type m_defaultFsType;
SwapChoiceSet m_swapChoices;
SwapChoice m_initialSwapChoice = NoSwap;
SwapChoice m_swapChoice = NoSwap;
@ -115,6 +155,8 @@ private:
InstallChoice m_installChoice = NoChoice;
qreal m_requiredStorageGiB = 0.0; // May duplicate setting in the welcome module
QStringList m_requiredPartitionTableType;
bool m_allowManualPartitioning = true;
};
/** @brief Given a set of swap choices, return a sensible value from it.

@ -11,10 +11,10 @@
*
*/
#include "gui/PartitionViewStep.h"
#include "PartitionViewStep.h"
#include "Config.h"
#include "core/BootLoaderModel.h"
#include "core/Config.h"
#include "core/DeviceModel.h"
#include "core/PartitionCoreModule.h"
#include "gui/ChoicePage.h"
@ -327,7 +327,7 @@ PartitionViewStep::isNextEnabled() const
void
PartitionViewStep::nextPossiblyChanged( bool )
{
emit nextStatusChanged( isNextEnabled() );
Q_EMIT nextStatusChanged( isNextEnabled() );
}
bool
@ -368,7 +368,7 @@ PartitionViewStep::isAtEnd() const
void
PartitionViewStep::onActivate()
{
m_config->updateGlobalStorage();
m_config->fillGSSecondaryConfiguration();
// if we're coming back to PVS from the next VS
if ( m_widget->currentWidget() == m_choicePage && m_config->installChoice() == Config::InstallChoice::Alongside )
@ -541,32 +541,11 @@ PartitionViewStep::onLeave()
void
PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
{
Logger::Once o;
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();
QString efiSP = CalamaresUtils::getString( configurationMap, "efiSystemPartition", QStringLiteral( "/boot/efi" ) );
gs->insert( "efiSystemPartition", efiSP );
// Set up firmwareType global storage entry. This is used, e.g. by the bootloader module.
QString firmwareType( PartUtils::isEfiSystem() ? QStringLiteral( "efi" ) : QStringLiteral( "bios" ) );
cDebug() << o << "Setting firmwareType to" << firmwareType;
gs->insert( "firmwareType", firmwareType );
// Read and parse key efiSystemPartitionSize
if ( configurationMap.contains( "efiSystemPartitionSize" ) )
{
gs->insert( "efiSystemPartitionSize", CalamaresUtils::getString( configurationMap, "efiSystemPartitionSize" ) );
}
// Read and parse key efiSystemPartitionName
if ( configurationMap.contains( "efiSystemPartitionName" ) )
{
gs->insert( "efiSystemPartitionName", CalamaresUtils::getString( configurationMap, "efiSystemPartitionName" ) );
}
// Read and parse key swapPartitionName
if ( configurationMap.contains( "swapPartitionName" ) )
@ -582,30 +561,6 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
gs->insert( "enableLuksAutomatedPartitioning",
CalamaresUtils::getBool( configurationMap, "enableLuksAutomatedPartitioning", true ) );
// The defaultFileSystemType setting needs a bit more processing,
// as we want to cover various cases (such as different cases)
QString fsName = CalamaresUtils::getString( configurationMap, "defaultFileSystemType" );
FileSystem::Type fsType;
if ( fsName.isEmpty() )
{
cWarning() << "Partition-module setting *defaultFileSystemType* is missing, will use ext4";
}
QString fsRealName = PartUtils::findFS( fsName, &fsType );
if ( fsRealName == fsName )
{
cDebug() << o << "Partition-module setting *defaultFileSystemType*" << fsRealName;
}
else if ( fsType != FileSystem::Unknown )
{
cWarning() << "Partition-module setting *defaultFileSystemType* changed" << fsRealName;
}
else
{
cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << fsName << ") using" << fsRealName
<< "instead.";
}
gs->insert( "defaultFileSystemType", fsRealName );
QString partitionTableName = CalamaresUtils::getString( configurationMap, "defaultPartitionTableType" );
if ( partitionTableName.isEmpty() )
{
@ -627,7 +582,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap )
QFuture< void > future = QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule );
m_future->setFuture( future );
m_core->initLayout( fsType == FileSystem::Unknown ? FileSystem::Ext4 : fsType,
m_core->initLayout( m_config->defaultFsType(),
configurationMap.value( "partitionLayout" ).toList() );
}

@ -132,7 +132,7 @@ DeviceModel::swapDevice( Device* oldDevice, Device* newDevice )
m_devices[ indexOfOldDevice ] = newDevice;
emit dataChanged( index( indexOfOldDevice ), index( indexOfOldDevice ) );
Q_EMIT dataChanged( index( indexOfOldDevice ), index( indexOfOldDevice ) );
}
void

@ -22,6 +22,7 @@
#include "partition/PartitionQuery.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include "utils/RAII.h"
#include <kpmcore/backend/corebackend.h>
#include <kpmcore/backend/corebackendmanager.h>
@ -479,21 +480,19 @@ isEfiBootable( const Partition* candidate )
}
QString
findFS( QString fsName, FileSystem::Type* fsType )
canonicalFilesystemName( const QString& fsName, FileSystem::Type* fsType )
{
QStringList fsLanguage { QLatin1String( "C" ) }; // Required language list to turn off localization
cPointerSetter type( fsType );
if ( fsName.isEmpty() )
{
fsName = QStringLiteral( "ext4" );
type = FileSystem::Ext4;
return QStringLiteral( "ext4" );
}
FileSystem::Type tmpType = FileSystem::typeForName( fsName, fsLanguage );
if ( tmpType != FileSystem::Unknown )
QStringList fsLanguage { QLatin1String( "C" ) }; // Required language list to turn off localization
if ( ( type = FileSystem::typeForName( fsName, fsLanguage ) ) != FileSystem::Unknown )
{
if ( fsType )
{
*fsType = tmpType;
}
return fsName;
}
@ -513,7 +512,6 @@ findFS( QString fsName, FileSystem::Type* fsType )
}
cWarning() << "Filesystem" << fsName << "not found, using ext4";
fsName = QStringLiteral( "ext4" );
// fsType can be used to check whether fsName was a valid filesystem.
if ( fsType )
{
@ -533,7 +531,8 @@ findFS( QString fsName, FileSystem::Type* fsType )
}
}
#endif
return fsName;
type = FileSystem::Unknown;
return QStringLiteral( "ext4" );
}
} // namespace PartUtils

@ -91,11 +91,13 @@ bool isEfiBootable( const Partition* candidate );
/** @brief translate @p fsName into a recognized name and type
*
* Makes several attempts to translate the string into a
* name that KPMCore will recognize.
* name that KPMCore will recognize. Returns the canonical
* filesystem name (e.g. asking for "EXT4" will return "ext4").
*
* The corresponding filesystem type is stored in @p fsType, and
* its value is FileSystem::Unknown if @p fsName is not recognized.
*/
QString findFS( QString fsName, FileSystem::Type* fsType );
QString canonicalFilesystemName( const QString& fsName, FileSystem::Type* fsType );
} // namespace PartUtils

@ -16,13 +16,12 @@
#include "core/PartitionCoreModule.h"
#include "core/PartitionInfo.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/NamedEnum.h"
#include "utils/Units.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include "utils/CalamaresUtilsSystem.h"
#include "utils/Logger.h"
#include "utils/NamedEnum.h"
#include "utils/Units.h"
#include <kpmcore/core/device.h>
#include <kpmcore/core/partition.h>
@ -109,6 +108,12 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO
partType = isEfi ? PartitionTable::gpt : PartitionTable::msdos;
}
// Looking up the defaultFsType (which should name a filesystem type)
// will log an error and set the type to Unknown if there's something wrong.
FileSystem::Type type = FileSystem::Unknown;
PartUtils::canonicalFilesystemName( o.defaultFsType, &type );
core->initLayout( type == FileSystem::Unknown ? FileSystem::Ext4 : type );
core->createPartitionTable( dev, partType );
if ( isEfi )

@ -10,7 +10,7 @@
#ifndef PARTITIONACTIONS_H
#define PARTITIONACTIONS_H
#include "core/Config.h"
#include "Config.h"
#include <QSet>
#include <QString>

@ -687,7 +687,7 @@ void
PartitionCoreModule::refreshPartition( Device* device, Partition* )
{
// Keep it simple for now: reset the model. This can be improved to cause
// the model to emit dataChanged() for the affected row instead, avoiding
// the model to Q_EMIT dataChanged() for the affected row instead, avoiding
// the loss of the current selection.
auto model = partitionModelForDevice( device );
Q_ASSERT( model );
@ -966,7 +966,7 @@ PartitionCoreModule::revert()
m_deviceInfos.clear();
doInit();
updateIsDirty();
emit reverted();
Q_EMIT reverted();
}
@ -1040,7 +1040,7 @@ PartitionCoreModule::revertDevice( Device* dev, bool individualRevert )
{
refreshAfterModelChange();
}
emit deviceReverted( newDev );
Q_EMIT deviceReverted( newDev );
}

@ -75,7 +75,7 @@ PartitionLayout::PartitionEntry::PartitionEntry( const QString& label,
, partMinSize( minSize )
, partMaxSize( maxSize )
{
PartUtils::findFS( fs, &partFileSystem );
PartUtils::canonicalFilesystemName( fs, &partFileSystem );
}
@ -95,7 +95,7 @@ PartitionLayout::addEntry( const PartitionEntry& entry )
void
PartitionLayout::init( FileSystem::Type defaultFsType, const QVariantList& config )
{
bool ok;
bool ok = true; // bogus argument to getSubMap()
m_partLayout.clear();
@ -130,10 +130,71 @@ PartitionLayout::init( FileSystem::Type defaultFsType, const QVariantList& confi
if ( !m_partLayout.count() )
{
addEntry( { defaultFsType, QString( "/" ), QString( "100%" ) } );
// Unknown will be translated to defaultFsType at apply-time
addEntry( { FileSystem::Type::Unknown, QString( "/" ), QString( "100%" ) } );
}
setDefaultFsType( defaultFsType );
}
void
PartitionLayout::setDefaultFsType(FileSystem::Type defaultFsType)
{
using T = FileSystem::Type;
switch ( defaultFsType )
{
case T::Unknown:
case T::Unformatted:
case T::Extended:
case T::LinuxSwap:
case T::Luks:
case T::Ocfs2:
case T::Lvm2_PV:
case T::Udf:
case T::Iso9660:
case T::Luks2:
case T::LinuxRaidMember:
case T::BitLocker:
// bad bad
cWarning() << "The selected default FS" << defaultFsType << "is not suitable." << "Using ext4 instead.";
defaultFsType = T::Ext4;
break;
case T::Ext2:
case T::Ext3:
case T::Ext4:
case T::Fat32:
case T::Ntfs:
case T::Reiser4:
case T::ReiserFS:
case T::Xfs:
case T::Jfs:
case T::Btrfs:
case T::Exfat:
case T::F2fs:
// ok
break;
case T::Fat12:
case T::Fat16:
case T::Hfs:
case T::HfsPlus:
case T::Ufs:
case T::Hpfs:
case T::Zfs:
case T::Nilfs2:
case T::Apfs:
case T::Minix:
// weird
cWarning() << "The selected default FS" << defaultFsType << "is unusual, but not wrong.";
break;
default:
cWarning() << "The selected default FS" << defaultFsType << "is not known to Calamares." << "Using ext4 instead.";
defaultFsType = T::Ext4;
}
m_defaultFsType = defaultFsType;
}
QList< Partition* >
PartitionLayout::createPartitions( Device* dev,
qint64 firstSector,
@ -142,6 +203,9 @@ PartitionLayout::createPartitions( Device* dev,
PartitionNode* parent,
const PartitionRole& role )
{
// Make sure the default FS is sensible; warn and use ext4 if not
setDefaultFsType( m_defaultFsType );
QList< Partition* > partList;
// Map each partition entry to its requested size (0 when calculated later)
QMap< const PartitionLayout::PartitionEntry*, qint64 > partSectorsMap;
@ -210,6 +274,8 @@ PartitionLayout::createPartitions( Device* dev,
}
}
auto correctFS = [d=m_defaultFsType]( FileSystem::Type t ) { return t == FileSystem::Type::Unknown ? d : t; };
// Create the partitions.
currentSector = firstSector;
availableSectors = totalSectors;
@ -229,7 +295,7 @@ PartitionLayout::createPartitions( Device* dev,
part = KPMHelpers::createNewPartition( parent,
*dev,
role,
entry.partFileSystem,
correctFS( entry.partFileSystem ),
entry.partLabel,
currentSector,
currentSector + sectors - 1,
@ -240,7 +306,7 @@ PartitionLayout::createPartitions( Device* dev,
part = KPMHelpers::createNewEncryptedPartition( parent,
*dev,
role,
entry.partFileSystem,
correctFS( entry.partFileSystem ),
entry.partLabel,
currentSector,
currentSector + sectors - 1,

@ -87,11 +87,28 @@ public:
*
* @p config is a list of partition entries (in QVariant form,
* read from YAML). If no entries are given, then a single
* partition is created with the given @p defaultFsType
* partition is created with type Unkown.
*
* Any partitions with FS type Unknown will get the default filesystem
* that is set at **apply** time (e.g. when createPartitions() is
* called as well.
*
* @see setDefaultFsType()
*/
void init( FileSystem::Type defaultFsType, const QVariantList& config );
/** @brief add an entry as if it had been listed in the config
*
* The same comments about filesystem type apply.
*/
bool addEntry( const PartitionEntry& entry );
/** @brief set the default filesystem type
*
* Any partitions in the layout with type Unknown will get
* the default type when createPartitions() is called.
*/
void setDefaultFsType( FileSystem::Type defaultFsType );
/**
* @brief Apply the current partition layout to the selected drive space.
* @return A list of Partition objects.
@ -105,6 +122,7 @@ public:
private:
QList< PartitionEntry > m_partLayout;
FileSystem::Type m_defaultFsType = FileSystem::Type::Unknown;
};
#endif /* PARTITIONLAYOUT_H */

@ -327,5 +327,5 @@ PartitionModel::partitionForIndex( const QModelIndex& index ) const
void
PartitionModel::update()
{
emit dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
Q_EMIT dataChanged( index( 0, 0 ), index( rowCount() - 1, columnCount() - 1 ) );
}

@ -41,7 +41,7 @@ public:
/**
* This helper class must be instantiated on the stack *before* making
* changes to the device represented by this model. It will cause the model
* to emit modelAboutToBeReset() when instantiated and modelReset() when
* to Q_EMIT modelAboutToBeReset() when instantiated and modelReset() when
* destructed.
*/
class ResetHelper

@ -11,15 +11,9 @@
#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 "Config.h"
#include "core/BootLoaderModel.h"
#include "core/Config.h"
#include "core/DeviceModel.h"
#include "core/KPMHelpers.h"
#include "core/OsproberEntry.h"
@ -28,6 +22,13 @@
#include "core/PartitionCoreModule.h"
#include "core/PartitionInfo.h"
#include "core/PartitionModel.h"
#include "gui/BootInfoWidget.h"
#include "gui/DeviceInfoWidget.h"
#include "gui/PartitionBarsView.h"
#include "gui/PartitionLabelsView.h"
#include "gui/PartitionSplitterWidget.h"
#include "gui/ReplaceWidget.h"
#include "gui/ScanningDialog.h"
#include "Branding.h"
#include "GlobalStorage.h"
@ -269,6 +270,15 @@ ChoicePage::setupChoices()
m_eraseButton->addOptionsComboBox( m_eraseSwapChoiceComboBox );
}
if ( m_config->eraseFsTypes().count() > 1)
{
m_eraseFsTypesChoiceComboBox = new QComboBox;
m_eraseFsTypesChoiceComboBox->addItems(m_config->eraseFsTypes());
connect( m_eraseFsTypesChoiceComboBox, &QComboBox::currentTextChanged, m_config, &Config::setEraseFsTypeChoice );
connect( m_config, &Config::eraseModeFilesystemChanged, this, &ChoicePage::onActionChanged );
m_eraseButton->addOptionsComboBox( m_eraseFsTypesChoiceComboBox );
}
m_itemsLayout->addWidget( m_alongsideButton );
m_itemsLayout->addWidget( m_replaceButton );
m_itemsLayout->addWidget( m_eraseButton );
@ -293,7 +303,7 @@ ChoicePage::setupChoices()
m_config->setInstallChoice( id );
updateNextEnabled();
emit actionChosen();
Q_EMIT actionChosen();
}
else // An action was unpicked, either on its own or because of another selection.
{
@ -303,7 +313,7 @@ ChoicePage::setupChoices()
m_config->setInstallChoice( InstallChoice::NoChoice );
updateNextEnabled();
emit actionChosen();
Q_EMIT actionChosen();
}
}
} );
@ -426,8 +436,8 @@ ChoicePage::continueApplyDeviceChoice()
checkInstallChoiceRadioButton( m_config->installChoice() );
}
emit actionChosen();
emit deviceChosen();
Q_EMIT actionChosen();
Q_EMIT deviceChosen();
}
@ -465,9 +475,8 @@ ChoicePage::applyActionChoice( InstallChoice choice )
case InstallChoice::Erase:
{
auto gs = Calamares::JobQueue::instance()->globalStorage();
PartitionActions::Choices::AutoPartitionOptions options { gs->value( "defaultPartitionTableType" ).toString(),
gs->value( "defaultFileSystemType" ).toString(),
m_config->eraseFsType(),
m_encryptWidget->passphrase(),
gs->value( "efiSystemPartition" ).toString(),
CalamaresUtils::GiBtoBytes(
@ -483,14 +492,14 @@ ChoicePage::applyActionChoice( InstallChoice choice )
} ),
[=] {
PartitionActions::doAutopartition( m_core, selectedDevice(), options );
emit deviceChosen();
Q_EMIT deviceChosen();
},
this );
}
else
{
PartitionActions::doAutopartition( m_core, selectedDevice(), options );
emit deviceChosen();
Q_EMIT deviceChosen();
}
}
break;
@ -1595,7 +1604,7 @@ ChoicePage::updateNextEnabled()
if ( enabled != m_nextEnabled )
{
m_nextEnabled = enabled;
emit nextStatusChanged( enabled );
Q_EMIT nextStatusChanged( enabled );
}
}

@ -15,7 +15,7 @@
#include "ui_ChoicePage.h"
#include "core/Config.h"
#include "Config.h"
#include "core/OsproberEntry.h"
#include <QMutex>
@ -138,7 +138,9 @@ private:
Calamares::PrettyRadioButton* m_eraseButton;
Calamares::PrettyRadioButton* m_replaceButton;
Calamares::PrettyRadioButton* m_somethingElseButton;
QComboBox* m_eraseSwapChoiceComboBox; // UI, see also m_eraseSwapChoice
QComboBox* m_eraseSwapChoiceComboBox = nullptr; // UI, see also Config's swap choice
QComboBox* m_eraseFsTypesChoiceComboBox = nullptr; // UI, see also Config's erase-mode FS
DeviceInfoWidget* m_deviceInfoWidget;

@ -92,7 +92,7 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device,
// File system; the config value is translated (best-effort) to a type
FileSystem::Type defaultFSType;
QString untranslatedFSName = PartUtils::findFS(
QString untranslatedFSName = PartUtils::canonicalFilesystemName(
Calamares::JobQueue::instance()->globalStorage()->value( "defaultFileSystemType" ).toString(), &defaultFSType );
if ( defaultFSType == FileSystem::Type::Unknown )
{

@ -97,7 +97,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device,
m_ui->fileSystemComboBox->addItems( fsNames );
FileSystem::Type defaultFSType;
QString untranslatedFSName = PartUtils::findFS(
QString untranslatedFSName = PartUtils::canonicalFilesystemName(
Calamares::JobQueue::instance()->globalStorage()->value( "defaultFileSystemType" ).toString(), &defaultFSType );
if ( defaultFSType == FileSystem::Type::Unknown )
{

@ -136,7 +136,7 @@ EncryptWidget::updateState()
if ( newState != m_state )
{
m_state = newState;
emit stateChanged( m_state );
Q_EMIT stateChanged( m_state );
}
}

@ -225,7 +225,7 @@ PartitionSplitterWidget::setSplitPartition( const QString& path, qint64 minSize,
}
}
emit partitionResized( m_itemToResize.itemPath, m_itemToResize.size, m_itemToResizeNext.size );
Q_EMIT partitionResized( m_itemToResize.itemPath, m_itemToResize.size, m_itemToResizeNext.size );
cDebug() << "Items updated. Status:";
foreach ( const PartitionSplitterItem& item, m_items )
@ -374,7 +374,7 @@ PartitionSplitterWidget::mouseMoveEvent( QMouseEvent* event )
repaint();
emit partitionResized( itemPath, m_itemToResize.size, m_itemToResizeNext.size );
Q_EMIT partitionResized( itemPath, m_itemToResize.size, m_itemToResizeNext.size );
}
else
{

@ -311,7 +311,7 @@ ReplaceWidget::setNextEnabled( bool enabled )
}
m_nextEnabled = enabled;
emit nextStatusChanged( enabled );
Q_EMIT nextStatusChanged( enabled );
}

@ -68,5 +68,5 @@ void
ScanningDialog::setVisible( bool visible )
{
QDialog::setVisible( visible );
emit visibilityChanged();
Q_EMIT visibilityChanged();
}

@ -25,5 +25,5 @@ PartitionJob::iprogress( int percent )
{
percent = 100;
}
emit progress( qreal( percent / 100.0 ) );
Q_EMIT progress( qreal( percent / 100.0 ) );
}

@ -113,12 +113,11 @@ initialSwapChoice: none
# Restrict the installation on disks that match the type of partition
# tables that are specified.
#
# Suggested values: msdos, gpt
# If nothing is specified, Calamares defaults to both "msdos" and "mbr".
# Possible values: msdos, gpt. Names are case-sensitive and defined by KPMCore.
#
# If nothing is specified, Calamares defaults to both "msdos" and "gpt".
#
# Names are case-sensitive and defined by KPMCore.
# requiredPartitionTableType: gpt
# or,
# requiredPartitionTableType:
# - msdos
# - gpt
@ -139,6 +138,17 @@ initialSwapChoice: none
# Names are case-sensitive and defined by KPMCore.
defaultFileSystemType: "ext4"
# Selectable filesystem type, used when "erase" is done.
#
# When erasing the disk, the *defaultFileSystemType* is used (see
# above), but it is also possible to give users a choice:
# list suitable filesystems here. A drop-down is provided
# to pick which is the filesystems will be used.
#
# The value *defaultFileSystemType* is added to this list (with a warning)
# if not present; the default pick is the *defaultFileSystemType*.
availableFileSystemTypes: ["ext4", "btrfs", "f2fs"]
# Show/hide LUKS related functionality in automated partitioning modes.
# Disable this if you choose not to deploy early unlocking support in GRUB2
# and/or your distribution's initramfs solution.
@ -205,7 +215,12 @@ defaultFileSystemType: "ext4"
# - uuid: partition uuid (optional parameter; gpt only; requires KPMCore >= 4.2.0)
# - type: partition type (optional parameter; gpt only; requires KPMCore >= 4.2.0)
# - attributes: partition attributes (optional parameter; gpt only; requires KPMCore >= 4.2.0)
# - filesystem: filesystem type (optional parameter; fs not created if "unformatted" or unset)
# - filesystem: filesystem type (optional parameter)
# - if not set at all, treat as "unformatted"
# - if "unformatted", no filesystem will be created
# - if "unknown" (or an unknown FS name, like "elephant") then the
# default filesystem type, or the user's choice, will be applied instead
# of "unknown" (e.g. the user might pick ext4, or xfs).
# - mountPoint: partition mount point (optional parameter; not mounted if unset)
# - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB)
# or

@ -18,6 +18,8 @@ properties:
alwaysShowPartitionLabels: { type: boolean, default: true }
defaultFileSystemType: { type: string }
availableFileSystemTypes: { type: array, items: { type: string } }
enableLuksAutomatedPartitioning: { type: boolean, default: false }
allowManualPartitioning: { type: boolean, default: true }
partitionLayout: { type: array } # TODO: specify items

Loading…
Cancel
Save