diff --git a/CHANGES b/CHANGES index 280aa81f0..995b176a5 100644 --- a/CHANGES +++ b/CHANGES @@ -3,7 +3,7 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. -# 3.2.4 (unreleased) # +# 3.2.5 (unreleased) # This release contains contributions from (alphabetically by first name): - Alf Gaida @@ -57,6 +57,21 @@ This release contains contributions from (alphabetically by first name): these run as three separate shells, though). +# 3.2.4 (unreleased) # + +This release contains contributions from (alphabetically by first name): + - Collabora ltd. + +## Core ## + +There are no core changes in this release. + +## Modules ## + + - *partition* There is new support for partitioning layout presets. + See `partitionc.conf` for documentation and details. + + # 3.2.3 (2019-01-09) # This release contains contributions from (alphabetically by first name): diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index c166390e8..b9b2109a3 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -34,6 +34,7 @@ if ( KPMcore_FOUND ) core/PartitionCoreModule.cpp core/PartitionInfo.cpp core/PartitionIterator.cpp + core/PartitionLayout.cpp core/PartitionModel.cpp core/PartUtils.cpp gui/BootInfoWidget.cpp diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index a4f2baa17..08278a3b6 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -90,7 +90,7 @@ alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) return blocks * blocksize; } -constexpr qint64 +qint64 bytesToSectors( qint64 bytes, qint64 blocksize ) { return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize), MiBtoBytes(1) ) / blocksize; @@ -169,39 +169,7 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO lastSectorForRoot -= suggestedSwapSizeB / dev->logicalSize() + 1; } - Partition* rootPartition = nullptr; - if ( o.luksPassphrase.isEmpty() ) - { - rootPartition = KPMHelpers::createNewPartition( - dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::typeForName( defaultFsType ), - firstFreeSector, - lastSectorForRoot, - PartitionTable::FlagNone - ); - } - else - { - rootPartition = KPMHelpers::createNewEncryptedPartition( - dev->partitionTable(), - *dev, - PartitionRole( PartitionRole::Primary ), - FileSystem::typeForName( defaultFsType ), - firstFreeSector, - lastSectorForRoot, - o.luksPassphrase, - PartitionTable::FlagNone - ); - } - PartitionInfo::setFormat( rootPartition, true ); - PartitionInfo::setMountPoint( rootPartition, "/" ); - // Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set. - // Otherwise they ignore the device in boot-order, so add it here. - core->createPartition( dev, rootPartition, - rootPartition->activeFlags() | ( isEfi ? PartitionTable::FlagNone : PartitionTable::FlagBoot ) - ); + core->layoutApply( dev, firstFreeSector, lastSectorForRoot, o.luksPassphrase ); if ( shouldCreateSwap ) { @@ -245,6 +213,8 @@ doReplacePartition( PartitionCoreModule* core, Partition* partition, Choices::ReplacePartitionOptions o ) { + qint64 firstSector, lastSector; + cDebug() << "doReplacePartition for device" << partition->partitionPath(); QString defaultFsType = o.defaultFsType; @@ -267,38 +237,13 @@ doReplacePartition( PartitionCoreModule* core, } } - Partition* newPartition = nullptr; - if ( o.luksPassphrase.isEmpty() ) - { - newPartition = KPMHelpers::createNewPartition( - partition->parent(), - *dev, - newRoles, - FileSystem::typeForName( defaultFsType ), - partition->firstSector(), - partition->lastSector(), - PartitionTable::FlagNone - ); - } - else - { - newPartition = KPMHelpers::createNewEncryptedPartition( - partition->parent(), - *dev, - newRoles, - FileSystem::typeForName( defaultFsType ), - partition->firstSector(), - partition->lastSector(), - o.luksPassphrase, - PartitionTable::FlagNone - ); - } - PartitionInfo::setMountPoint( newPartition, "/" ); - PartitionInfo::setFormat( newPartition, true ); - + // Save the first and last sector values as the partition will be deleted + firstSector = partition->firstSector(); + lastSector = partition->lastSector(); if ( !partition->roles().has( PartitionRole::Unallocated ) ) core->deletePartition( dev, partition ); - core->createPartition( dev, newPartition ); + + core->layoutApply( dev, firstSector, lastSector, o.luksPassphrase ); core->dumpQueue(); } diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index 5acf444fa..1c543854b 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -72,6 +72,8 @@ namespace Choices } // namespace Choices +qint64 bytesToSectors( qint64 bytes, qint64 blocksize ); + /** * @brief doAutopartition sets up an autopartitioning operation on the given Device. * @param core a pointer to the PartitionCoreModule instance. diff --git a/src/modules/partition/core/PartitionCoreModule.cpp b/src/modules/partition/core/PartitionCoreModule.cpp index f41142b6a..e79fc21e4 100644 --- a/src/modules/partition/core/PartitionCoreModule.cpp +++ b/src/modules/partition/core/PartitionCoreModule.cpp @@ -43,6 +43,7 @@ #include "jobs/ResizePartitionJob.h" #include "jobs/ResizeVolumeGroupJob.h" #include "jobs/SetPartitionFlagsJob.h" +#include "utils/CalamaresUtils.h" #include "Typedefs.h" #include "utils/Logger.h" @@ -760,6 +761,71 @@ PartitionCoreModule::setBootLoaderInstallPath( const QString& path ) m_bootLoaderInstallPath = path; } +void +PartitionCoreModule::initLayout() +{ + m_partLayout = new PartitionLayout(); + + m_partLayout->addEntry( QString("/"), QString("100%") ); +} + +void +PartitionCoreModule::initLayout( const QVariantList& config ) +{ + m_partLayout = new PartitionLayout(); + + for ( const auto& r : config ) + { + QVariantMap pentry = r.toMap(); + + m_partLayout->addEntry( CalamaresUtils::getString( pentry, "name" ), + CalamaresUtils::getString( pentry, "mountPoint" ), + CalamaresUtils::getString( pentry, "filesystem" ), + CalamaresUtils::getString( pentry, "size" ), + CalamaresUtils::getString( pentry, "minSize" ) + ); + } +} + +void +PartitionCoreModule::layoutApply( Device *dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase, + PartitionNode* parent, + const PartitionRole& role ) +{ + bool isEfi = PartUtils::isEfiSystem(); + QList< Partition* > partList = m_partLayout->execute( dev, firstSector, lastSector, + luksPassphrase, parent, role + ); + + foreach ( Partition *part, partList ) + { + if ( part->mountPoint() == "/" ) + { + createPartition( dev, part, + part->activeFlags() | ( isEfi ? PartitionTable::FlagNone : PartitionTable::FlagBoot ) + ); + } + else + { + createPartition( dev, part ); + } + } +} + +void +PartitionCoreModule::layoutApply( Device *dev, + qint64 firstSector, + qint64 lastSector, + QString luksPassphrase ) +{ + layoutApply( dev, firstSector, lastSector, luksPassphrase, dev->partitionTable(), + PartitionRole( PartitionRole::Primary ) + ); +} + void PartitionCoreModule::revert() { diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index 15dadc7f5..52cb47a59 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -20,6 +20,7 @@ #ifndef PARTITIONCOREMODULE_H #define PARTITIONCOREMODULE_H +#include "core/PartitionLayout.h" #include "core/PartitionModel.h" #include "Typedefs.h" @@ -155,6 +156,12 @@ public: void setBootLoaderInstallPath( const QString& path ); + void initLayout(); + void initLayout( const QVariantList& config ); + + void layoutApply( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase ); + void layoutApply( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, PartitionNode* parent, const PartitionRole& role ); + /** * @brief jobs creates and returns a list of jobs which can then apply the changes * requested by the user. @@ -246,6 +253,7 @@ private: bool m_hasRootMountPoint = false; bool m_isDirty = false; QString m_bootLoaderInstallPath; + PartitionLayout* m_partLayout; void doInit(); void updateHasRootMountPoint(); diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp new file mode 100644 index 000000000..77ef4bb81 --- /dev/null +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -0,0 +1,218 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014-2017, Teo Mrnjavac + * Copyright 2017-2018, Adriaan de Groot + * Copyright 2018, Collabora Ltd + * + * 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 . + */ + +#include "core/PartitionLayout.h" + +#include "core/KPMHelpers.h" +#include "core/PartitionActions.h" +#include "core/PartitionInfo.h" + +#include +#include +#include + +PartitionLayout::PartitionLayout() +{ +} + +PartitionLayout::PartitionLayout( PartitionLayout::PartitionEntry entry ) +{ + partLayout.append( entry ); +} + +PartitionLayout::PartitionLayout( const PartitionLayout& layout ) + : partLayout( layout.partLayout ) +{ +} + +PartitionLayout::~PartitionLayout() +{ +} + +void +PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry ) +{ + partLayout.append( entry ); +} + +static double +parseSizeString( QString sizeString, PartitionLayout::SizeUnit *unit ) +{ + double value; + bool ok; + + QRegExp rx( "[KkMmGg%]" ); + int pos = rx.indexIn( sizeString ); + QString valueString = sizeString.mid( 0, pos ); + QString unitString = sizeString.mid( pos ); + + value = valueString.toDouble( &ok ); + if ( !ok ) + { + /* + * In case the conversion fails, a size of 100% allows a few cases to pass + * anyway (e.g. when it is the last partition of the layout) + */ + *unit = PartitionLayout::SizeUnit::Percent; + return 100; + } + + if ( unitString.length() > 0 ) + { + if ( unitString.at(0) == '%' ) + *unit = PartitionLayout::SizeUnit::Percent; + else if ( unitString.at(0).toUpper() == 'K' ) + *unit = PartitionLayout::SizeUnit::KiB; + else if ( unitString.at(0).toUpper() == 'M' ) + *unit = PartitionLayout::SizeUnit::MiB; + else if ( unitString.at(0).toUpper() == 'G' ) + *unit = PartitionLayout::SizeUnit::GiB; + else + *unit = PartitionLayout::SizeUnit::Byte; + } + else + { + *unit = PartitionLayout::SizeUnit::Byte; + } + + return value; +} + +void +PartitionLayout::addEntry( QString mountPoint, QString size, QString min ) +{ + PartitionLayout::PartitionEntry entry; + + entry.partMountPoint = mountPoint; + entry.partFileSystem = FileSystem::Ext4; + entry.partSize = parseSizeString( size , &entry.partSizeUnit ); + entry.partMinSize = parseSizeString( min , &entry.partMinSizeUnit ); + + partLayout.append( entry ); +} + +void +PartitionLayout::addEntry( QString label, QString mountPoint, QString fs, QString size, QString min ) +{ + PartitionLayout::PartitionEntry entry; + + entry.partLabel = label; + entry.partMountPoint = mountPoint; + entry.partFileSystem = FileSystem::typeForName( fs ); + entry.partSize = parseSizeString( size , &entry.partSizeUnit ); + entry.partMinSize = parseSizeString( min , &entry.partMinSizeUnit ); + + partLayout.append( entry ); +} + +static qint64 +sizeToSectors( double size, PartitionLayout::SizeUnit unit, qint64 totalSize, qint64 logicalSize ) +{ + qint64 sectors; + double tmp; + + if ( unit == PartitionLayout::SizeUnit::Percent ) + { + tmp = static_cast( totalSize ) * size / 100; + sectors = static_cast( tmp ); + } + else + { + tmp = size; + if ( unit >= PartitionLayout::SizeUnit::KiB ) + tmp *= 1024; + if ( unit >= PartitionLayout::SizeUnit::MiB ) + tmp *= 1024; + if ( unit >= PartitionLayout::SizeUnit::GiB ) + tmp *= 1024; + + sectors = PartitionActions::bytesToSectors( static_cast( tmp ), + logicalSize + ); + } + + return sectors; +} + +QList< Partition* > +PartitionLayout::execute( Device *dev, qint64 firstSector, + qint64 lastSector, QString luksPassphrase, + PartitionNode* parent, + const PartitionRole& role ) +{ + QList< Partition* > partList; + qint64 size, minSize, end; + qint64 totalSize = lastSector - firstSector + 1; + qint64 availableSize = totalSize; + + // TODO: Refine partition sizes to make sure there is room for every partition + // Use a default (200-500M ?) minimum size for partition without minSize + + foreach( const PartitionLayout::PartitionEntry& part, partLayout ) + { + Partition *currentPartition = nullptr; + + // Calculate partition size + size = sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() ); + minSize = sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() ); + if ( size < minSize ) + size = minSize; + if ( size > availableSize ) + size = availableSize; + end = firstSector + size - 1; + + if ( luksPassphrase.isEmpty() ) + { + currentPartition = KPMHelpers::createNewPartition( + parent, + *dev, + role, + static_cast(part.partFileSystem), + firstSector, + end, + PartitionTable::FlagNone + ); + } + else + { + currentPartition = KPMHelpers::createNewEncryptedPartition( + parent, + *dev, + role, + static_cast(part.partFileSystem), + firstSector, + end, + luksPassphrase, + PartitionTable::FlagNone + ); + } + PartitionInfo::setFormat( currentPartition, true ); + PartitionInfo::setMountPoint( currentPartition, part.partMountPoint ); + if ( !part.partLabel.isEmpty() ) + currentPartition->fileSystem().setLabel( part.partLabel ); + // Some buggy (legacy) BIOSes test if the bootflag of at least one partition is set. + // Otherwise they ignore the device in boot-order, so add it here. + partList.append( currentPartition ); + firstSector = end + 1; + availableSize -= size; + } + + return partList; +} diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h new file mode 100644 index 000000000..5ec65cf22 --- /dev/null +++ b/src/modules/partition/core/PartitionLayout.h @@ -0,0 +1,76 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, Collabora Ltd + * + * 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 . + */ + +#ifndef PARTITIONLAYOUT_H +#define PARTITIONLAYOUT_H + +#include "Typedefs.h" + +// KPMcore +#include + +// Qt +#include +#include + +class Partition; + +class PartitionLayout +{ +public: + + enum SizeUnit + { + Percent = 0, + Byte, + KiB, + MiB, + GiB + }; + + struct PartitionEntry + { + QString partLabel; + QString partMountPoint; + int partFileSystem; + double partSize; + SizeUnit partSizeUnit; + double partMinSize; + SizeUnit partMinSizeUnit; + }; + + PartitionLayout(); + PartitionLayout( PartitionEntry entry ); + PartitionLayout( const PartitionLayout& layout ); + ~PartitionLayout(); + + void addEntry( PartitionEntry entry ); + void addEntry( QString mountPoint, QString size, QString min = "" ); + void addEntry( QString label, QString mountPoint, QString fs, QString size, QString min = "" ); + + /** + * @brief Apply the current partition layout to the selected drive space. + * @return A list of Partition objects. + */ + QList< Partition* > execute( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, PartitionNode* parent, const PartitionRole& role ); + +private: + QList< PartitionEntry > partLayout; +}; + +#endif /* PARTITIONLAYOUT_H */ diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 3aeb4d258..2fd932e0c 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -93,6 +93,7 @@ ChoicePage::ChoicePage( QWidget* parent ) , m_bootloaderComboBox( nullptr ) , m_lastSelectedDeviceIndex( -1 ) , m_enableEncryptionWidget( true ) + , m_allowManualPartitioning( true ) { setupUi( this ); @@ -102,6 +103,9 @@ ChoicePage::ChoicePage( QWidget* parent ) m_enableEncryptionWidget = Calamares::JobQueue::instance()-> globalStorage()-> value( "enableLuksAutomatedPartitioning" ).toBool(); + m_allowManualPartitioning = Calamares::JobQueue::instance()-> + globalStorage()-> + value( "allowManualPartitioning" ).toBool(); if ( FileSystem::typeForName( m_defaultFsType ) == FileSystem::Unknown ) m_defaultFsType = "ext4"; @@ -671,41 +675,10 @@ ChoicePage::doAlongsideApply() dev->logicalSize(); m_core->resizePartition( dev, candidate, firstSector, newLastSector ); - Partition* newPartition = nullptr; - QString luksPassphrase = m_encryptWidget->passphrase(); - if ( luksPassphrase.isEmpty() ) - { - newPartition = KPMHelpers::createNewPartition( - candidate->parent(), - *dev, - candidate->roles(), - FileSystem::typeForName( m_defaultFsType ), - newLastSector + 2, // * - oldLastSector, - PartitionTable::FlagNone - ); - } - else - { - newPartition = KPMHelpers::createNewEncryptedPartition( - candidate->parent(), - *dev, - candidate->roles(), - FileSystem::typeForName( m_defaultFsType ), - newLastSector + 2, // * - oldLastSector, - luksPassphrase, - PartitionTable::FlagNone - ); - } - PartitionInfo::setMountPoint( newPartition, "/" ); - PartitionInfo::setFormat( newPartition, true ); - // * for some reason ped_disk_add_partition refuses to create a new partition - // if it starts on the sector immediately after the last used sector, so we - // have to push it one sector further, therefore + 2 instead of + 1. - - m_core->createPartition( dev, newPartition ); - + m_core->layoutApply( dev, newLastSector + 2, oldLastSector, + m_encryptWidget->passphrase(), candidate->parent(), + candidate->roles() + ); m_core->dumpQueue(); break; @@ -773,37 +746,10 @@ ChoicePage::doReplaceSelectedPartition( const QModelIndex& current ) } } - Partition* newPartition = nullptr; - if ( m_encryptWidget->state() == EncryptWidget::EncryptionConfirmed ) - { - newPartition = KPMHelpers::createNewEncryptedPartition( - newParent, - *selectedDevice(), - newRoles, - FileSystem::typeForName( m_defaultFsType ), - selectedPartition->firstSector(), - selectedPartition->lastSector(), - m_encryptWidget->passphrase(), - PartitionTable::FlagNone - ); - } - else - { - newPartition = KPMHelpers::createNewPartition( - newParent, - *selectedDevice(), - newRoles, - FileSystem::typeForName( m_defaultFsType ), - selectedPartition->firstSector(), - selectedPartition->lastSector(), - PartitionTable::FlagNone - ); - } - - PartitionInfo::setMountPoint( newPartition, "/" ); - PartitionInfo::setFormat( newPartition, true ); - - m_core->createPartition( selectedDevice(), newPartition); + m_core->layoutApply( selectedDevice(), selectedPartition->firstSector(), + selectedPartition->lastSector(), + m_encryptWidget->passphrase(), newParent, newRoles + ); } else { @@ -1246,8 +1192,10 @@ ChoicePage::setupActions() else m_deviceInfoWidget->setPartitionTableType( PartitionTable::unknownTableType ); - // Manual partitioning is always a possibility - m_somethingElseButton->show(); + if ( m_allowManualPartitioning ) + m_somethingElseButton->show(); + else + force_uncheck( m_grp, m_somethingElseButton ); bool atLeastOneCanBeResized = false; bool atLeastOneCanBeReplaced = false; diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index a53f3fff1..34154d7d5 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -169,6 +169,8 @@ private: QString m_defaultFsType; bool m_enableEncryptionWidget; + bool m_allowManualPartitioning; + QMutex m_coreMutex; }; diff --git a/src/modules/partition/gui/PartitionLabelsView.cpp b/src/modules/partition/gui/PartitionLabelsView.cpp index fbcc1de72..0a0850844 100644 --- a/src/modules/partition/gui/PartitionLabelsView.cpp +++ b/src/modules/partition/gui/PartitionLabelsView.cpp @@ -185,26 +185,35 @@ PartitionLabelsView::buildTexts( const QModelIndex& index ) const if ( index.data( PartitionModel::IsPartitionNewRole ).toBool() ) { - QString mountPoint = index.sibling( index.row(), - PartitionModel::MountPointColumn ) - .data().toString(); - if ( mountPoint == "/" ) - firstLine = m_customNewRootLabel.isEmpty() ? - tr( "Root" ) : - m_customNewRootLabel; - else if ( mountPoint == "/home" ) - firstLine = tr( "Home" ); - else if ( mountPoint == "/boot" ) - firstLine = tr( "Boot" ); - else if ( mountPoint.contains( "/efi" ) && - index.data( PartitionModel::FileSystemTypeRole ).toInt() == FileSystem::Fat32 ) - firstLine = tr( "EFI system" ); - else if ( index.data( PartitionModel::FileSystemTypeRole ).toInt() == FileSystem::LinuxSwap ) - firstLine = tr( "Swap" ); - else if ( !mountPoint.isEmpty() ) - firstLine = tr( "New partition for %1" ).arg( mountPoint ); + QString label = index.data( PartitionModel::FileSystemLabelRole ).toString(); + + if ( !label.isEmpty() ) + { + firstLine = label; + } else - firstLine = tr( "New partition" ); + { + QString mountPoint = index.sibling( index.row(), + PartitionModel::MountPointColumn ) + .data().toString(); + if ( mountPoint == "/" ) + firstLine = m_customNewRootLabel.isEmpty() ? + tr( "Root" ) : + m_customNewRootLabel; + else if ( mountPoint == "/home" ) + firstLine = tr( "Home" ); + else if ( mountPoint == "/boot" ) + firstLine = tr( "Boot" ); + else if ( mountPoint.contains( "/efi" ) && + index.data( PartitionModel::FileSystemTypeRole ).toInt() == FileSystem::Fat32 ) + firstLine = tr( "EFI system" ); + else if ( index.data( PartitionModel::FileSystemTypeRole ).toInt() == FileSystem::LinuxSwap ) + firstLine = tr( "Swap" ); + else if ( !mountPoint.isEmpty() ) + firstLine = tr( "New partition for %1" ).arg( mountPoint ); + else + firstLine = tr( "New partition" ); + } } else if ( index.data( PartitionModel::OsproberNameRole ).toString().isEmpty() ) { diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index aae377265..759b686db 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -623,6 +623,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) gs->insert( "drawNestedPartitions", CalamaresUtils::getBool( configurationMap, "drawNestedPartitions", false ) ); gs->insert( "alwaysShowPartitionLabels", CalamaresUtils::getBool( configurationMap, "alwaysShowPartitionLabels", true ) ); gs->insert( "enableLuksAutomatedPartitioning", CalamaresUtils::getBool( configurationMap, "enableLuksAutomatedPartitioning", true ) ); + gs->insert( "allowManualPartitioning", CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true ) ); gs->insert( "defaultFileSystemType", findFS( CalamaresUtils::getString( configurationMap, "defaultFileSystemType" ) ) ); @@ -640,6 +641,15 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) QFuture< void > future = QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule ); watcher->setFuture( future ); + + if ( configurationMap.contains( "partitionLayout" ) ) + { + m_core->initLayout( configurationMap.values( "partitionLayout" ).at(0).toList() ); + } + else + { + m_core->initLayout(); + } } diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index 229ffc32c..a7483f36f 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -77,3 +77,40 @@ 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: +# - name: "rootfs" +# filesystem: "ext4" +# mountPoint: "/" +# size: 20% +# minSize: 500M +# - name: "home" +# filesystem: "ext4" +# mountPoint: "/home" +# size: 3G +# minSize: 1.5G +# - name: "data" +# filesystem: "fat32" +# mountPoint: "/data" +# size: 100% +# +# There can be any number of partitions, each entry having the following attributes: +# - name: partition label +# - filesystem: filesystem type +# - mountPoint: partition mount point +# - size: partition size in bytes (append 'K', 'M' or 'G' for KiB, MiB or GiB) +# or +# % of the available drive space if a '%' is appended to the value +# - minSize: minimum partition size (optional parameter)