From e6c80ed5bddfdb3da0ff57a8a5d37beeb502934f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 09:54:30 +0200 Subject: [PATCH 01/28] Coding style --- .../partition/CreatePartitionDialog.cpp | 8 +++---- .../partition/EditExistingPartitionDialog.cpp | 12 +++++----- src/modules/partition/PMUtils.cpp | 22 +++++++++---------- src/modules/partition/PartitionCoreModule.cpp | 2 +- src/modules/partition/PartitionModel.cpp | 9 ++++---- src/modules/partition/PartitionPreview.cpp | 3 ++- 6 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/modules/partition/CreatePartitionDialog.cpp b/src/modules/partition/CreatePartitionDialog.cpp index 7ea7a5eca..a717848f5 100644 --- a/src/modules/partition/CreatePartitionDialog.cpp +++ b/src/modules/partition/CreatePartitionDialog.cpp @@ -124,10 +124,10 @@ CreatePartitionDialog::createPartition() ? FileSystem::Extended : FileSystem::typeForName( m_ui->fsComboBox->currentText() ); Partition* partition = PMUtils::createNewPartition( - m_parent, - *m_device, - m_role, - fsType, range.first, range.second ); + m_parent, + *m_device, + m_role, + fsType, range.first, range.second ); PartitionInfo::setMountPoint( partition, m_ui->mountPointComboBox->currentText() ); PartitionInfo::setFormat( partition, true ); diff --git a/src/modules/partition/EditExistingPartitionDialog.cpp b/src/modules/partition/EditExistingPartitionDialog.cpp index c8cc1fc78..18a25800c 100644 --- a/src/modules/partition/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/EditExistingPartitionDialog.cpp @@ -56,12 +56,12 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) if ( m_ui->formatRadioButton->isChecked() ) { Partition* newPartition = PMUtils::createNewPartition( - m_partition->parent(), - *m_device, - m_partition->roles(), - m_partition->fileSystem().type(), - range.first, - range.second); + m_partition->parent(), + *m_device, + m_partition->roles(), + m_partition->fileSystem().type(), + range.first, + range.second ); PartitionInfo::setMountPoint( newPartition, PartitionInfo::mountPoint( m_partition ) ); PartitionInfo::setFormat( newPartition, true ); diff --git a/src/modules/partition/PMUtils.cpp b/src/modules/partition/PMUtils.cpp index 5cc48ae55..7de100d27 100644 --- a/src/modules/partition/PMUtils.cpp +++ b/src/modules/partition/PMUtils.cpp @@ -53,17 +53,17 @@ createNewPartition( PartitionNode* parent, const Device& device, const Partition { FileSystem* fs = FileSystemFactory::create( fsType, firstSector, lastSector ); return new Partition( - parent, - device, - role, - fs, fs->firstSector(), fs->lastSector(), - QString() /* path */, - PartitionTable::FlagNone /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - PartitionTable::FlagNone /* activeFlags */, - Partition::StateNew - ); + parent, + device, + role, + fs, fs->firstSector(), fs->lastSector(), + QString() /* path */, + PartitionTable::FlagNone /* availableFlags */, + QString() /* mountPoint */, + false /* mounted */, + PartitionTable::FlagNone /* activeFlags */, + Partition::StateNew + ); } } // namespace diff --git a/src/modules/partition/PartitionCoreModule.cpp b/src/modules/partition/PartitionCoreModule.cpp index 4d46cd3cb..9f6bb829a 100644 --- a/src/modules/partition/PartitionCoreModule.cpp +++ b/src/modules/partition/PartitionCoreModule.cpp @@ -46,7 +46,7 @@ static bool hasRootPartition( Device* device ) { for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - if ( (*it)->mountPoint() == "/" ) + if ( ( *it )->mountPoint() == "/" ) return true; return false; } diff --git a/src/modules/partition/PartitionModel.cpp b/src/modules/partition/PartitionModel.cpp index e1c9aaa70..6364838ba 100644 --- a/src/modules/partition/PartitionModel.cpp +++ b/src/modules/partition/PartitionModel.cpp @@ -33,7 +33,8 @@ // Qt #include -static QColor COLORS[ 4 ] = { +static QColor COLORS[ 4 ] = +{ "#448eca", "#a5cc42", "#d87e30", @@ -54,7 +55,7 @@ static QColor colorForPartition( Partition* partition, int row ) //- ResetHelper -------------------------------------------- PartitionModel::ResetHelper::ResetHelper( PartitionModel* model ) -: m_model( model ) + : m_model( model ) { m_model->beginResetModel(); } @@ -98,8 +99,8 @@ QModelIndex PartitionModel::index( int row, int column, const QModelIndex& parent ) const { PartitionNode* parentPartition = parent.isValid() - ? static_cast< PartitionNode* >( partitionForIndex( parent )) - : static_cast< PartitionNode* >( m_device->partitionTable() ); + ? static_cast< PartitionNode* >( partitionForIndex( parent ) ) + : static_cast< PartitionNode* >( m_device->partitionTable() ); if ( !parentPartition ) return QModelIndex(); auto lst = parentPartition->children(); diff --git a/src/modules/partition/PartitionPreview.cpp b/src/modules/partition/PartitionPreview.cpp index 491747b2f..fd1749b32 100644 --- a/src/modules/partition/PartitionPreview.cpp +++ b/src/modules/partition/PartitionPreview.cpp @@ -99,7 +99,8 @@ PartitionPreview::drawPartitions( QPainter* painter, const QRect& rect, const QM return; const int count = modl->rowCount( parent ); const int totalWidth = rect.width(); - struct Item { + struct Item + { qreal size; QModelIndex index; }; From fc3f3eaa3a7e0b3249e94493fb222f8ef567afbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 14:55:49 +0200 Subject: [PATCH 02/28] Update partitionmanager submodule: Make it possible to set partition sectors from the outside world --- src/modules/partition/partitionmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/partitionmanager b/src/modules/partition/partitionmanager index f958c7be7..838f13e9d 160000 --- a/src/modules/partition/partitionmanager +++ b/src/modules/partition/partitionmanager @@ -1 +1 @@ -Subproject commit f958c7be734135f22454e464518c1f7110298a95 +Subproject commit 838f13e9dcd1702a8fa4ec49e04163087e56f7e2 From 09c3240364bccfb7df454b0b4e36bf459367c7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 14:57:00 +0200 Subject: [PATCH 03/28] Scaffolding and tests for ResizePartitionJob --- src/modules/partition/CMakeLists.txt | 1 + .../partition/EditExistingPartitionDialog.cpp | 4 +- src/modules/partition/PartitionCoreModule.cpp | 15 ++ src/modules/partition/PartitionCoreModule.h | 2 + src/modules/partition/ResizePartitionJob.cpp | 230 ++++++++++++++++++ src/modules/partition/ResizePartitionJob.h | 55 +++++ src/modules/partition/tests/CMakeLists.txt | 1 + src/modules/partition/tests/JobTests.cpp | 79 +++++- src/modules/partition/tests/JobTests.h | 3 + 9 files changed, 385 insertions(+), 5 deletions(-) create mode 100644 src/modules/partition/ResizePartitionJob.cpp create mode 100644 src/modules/partition/ResizePartitionJob.h diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 4e96e039e..0323af79c 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -41,6 +41,7 @@ calamares_add_plugin( partition PartitionSizeWidget.cpp PartitionViewStep.cpp PMUtils.cpp + ResizePartitionJob.cpp UI CreatePartitionDialog.ui CreatePartitionTableDialog.ui diff --git a/src/modules/partition/EditExistingPartitionDialog.cpp b/src/modules/partition/EditExistingPartitionDialog.cpp index 18a25800c..e946fec91 100644 --- a/src/modules/partition/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/EditExistingPartitionDialog.cpp @@ -69,9 +69,7 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) core->createPartition( m_device, newPartition ); } else - { - //core->resizePartition( m_device, m_partition ); - } + core->resizePartition( m_device, m_partition, range.first, range.second ); } else { diff --git a/src/modules/partition/PartitionCoreModule.cpp b/src/modules/partition/PartitionCoreModule.cpp index 9f6bb829a..2ad439950 100644 --- a/src/modules/partition/PartitionCoreModule.cpp +++ b/src/modules/partition/PartitionCoreModule.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -257,6 +258,20 @@ PartitionCoreModule::formatPartition( Device* device, Partition* partition ) refresh(); } +void +PartitionCoreModule::resizePartition( Device* device, Partition* partition, qint64 first, qint64 last ) +{ + auto deviceInfo = infoForDevice( device ); + Q_ASSERT( deviceInfo ); + PartitionModel::ResetHelper helper( partitionModelForDevice( device ) ); + + ResizePartitionJob* job = new ResizePartitionJob( device, partition, first, last ); + job->updatePreview(); + deviceInfo->jobs << Calamares::job_ptr( job ); + + refresh(); +} + QList< Calamares::job_ptr > PartitionCoreModule::jobs() const { diff --git a/src/modules/partition/PartitionCoreModule.h b/src/modules/partition/PartitionCoreModule.h index 4a29f0994..7d3fb5f3b 100644 --- a/src/modules/partition/PartitionCoreModule.h +++ b/src/modules/partition/PartitionCoreModule.h @@ -69,6 +69,8 @@ public: void formatPartition( Device* device, Partition* partition ); + void resizePartition( Device* device, Partition* partition, qint64 first, qint64 last ); + void setBootLoaderInstallPath( const QString& path ); QList< Calamares::job_ptr > jobs() const; diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp new file mode 100644 index 000000000..0ad5bd7a3 --- /dev/null +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -0,0 +1,230 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 . + */ + +// This class is heavily based on the ResizeOperation class from KDE Partition +// Manager. Original copyright follow: + +/*************************************************************************** + * Copyright (C) 2008,2012 by Volker Lanz * + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include + +//#include + +// CalaPM +#include +#include +#include +#include +#include +#include +#include +/* +#include +#include +*/ +#include + +// Qt +#include + +//- Context -------------------------------------------------------------------- +struct Context +{ + Context( ResizePartitionJob* job_ ) + : job( job_ ) + {} + + ResizePartitionJob* job; +}; + +//- ResizeFileSystemJob -------------------------------------------------------- +class ResizeFileSystemJob : public Calamares::Job +{ +public: + ResizeFileSystemJob( Context* context, qint64 length ) + {} + + QString prettyName() const override + { + return QString(); + } + + Calamares::JobResult exec() override + { + return Calamares::JobResult::ok(); + } +}; + +//- SetPartGeometryJob --------------------------------------------------------- +class SetPartGeometryJob : public Calamares::Job +{ +public: + SetPartGeometryJob( Context* context, qint64 firstSector, qint64 length ) + {} + + QString prettyName() const override + { + return QString(); + } + + Calamares::JobResult exec() override + { + return Calamares::JobResult::ok(); + } +}; + +//- MoveFileSystemJob ---------------------------------------------------------- +class MoveFileSystemJob : public Calamares::Job +{ +public: + MoveFileSystemJob( Context* context, qint64 firstSector ) + {} + + QString prettyName() const override + { + return QString(); + } + + Calamares::JobResult exec() override + { + return Calamares::JobResult::ok(); + } +}; + +//- ResizePartitionJob --------------------------------------------------------- +ResizePartitionJob::ResizePartitionJob( Device* device, Partition* partition, qint64 firstSector, qint64 lastSector ) + : PartitionJob( partition ) + , m_device( device ) + , m_newFirstSector( firstSector ) + , m_newLastSector( lastSector ) +{ +} + +QString +ResizePartitionJob::prettyName() const +{ + /* + return tr( "Format partition %1 (file system: %2, size: %3 MB) on %4." ) + .arg( m_partition->partitionPath() ) + .arg( m_partition->fileSystem().name() ) + .arg( m_partition->capacity() / 1024 / 1024 ) + .arg( m_device->name() ); + */ + return QString(); +} + +Calamares::JobResult +ResizePartitionJob::exec() +{ + /* + Report report( 0 ); + QString partitionPath = m_partition->partitionPath(); + QString message = tr( "The installer failed to format partition %1 on disk '%2'." ).arg( partitionPath, m_device->name() ); + + CoreBackend* backend = CoreBackendManager::self()->backend(); + QScopedPointer backendDevice( backend->openDevice( m_device->deviceNode() ) ); + if ( !backendDevice.data() ) + { + return Calamares::JobResult::error( + message, + tr( "Could not open device '%1'." ).arg( m_device->deviceNode() ) + ); + } + + QScopedPointer backendPartitionTable( backendDevice->openPartitionTable() ); + backendPartitionTable->commit(); + return Calamares::JobResult::ok(); + */ + qint64 oldLength = m_partition->lastSector() - m_partition->firstSector() + 1; + qint64 newLength = m_newLastSector - m_newFirstSector + 1; + + Context context( this ); + QList< Calamares::job_ptr > jobs; + if ( m_partition->roles().has( PartitionRole::Extended ) ) + jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_newFirstSector, newLength ) ); + else + { + bool shrink = newLength < oldLength; + bool grow = newLength > oldLength; + bool moveRight = m_newFirstSector > m_partition->firstSector(); + bool moveLeft = m_newFirstSector < m_partition->firstSector(); + if ( shrink ) + { + jobs << Calamares::job_ptr( new ResizeFileSystemJob( &context, newLength ) ); + jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_partition->firstSector(), newLength ) ); + } + if ( moveRight || moveLeft ) + { + // At this point, we need to set the partition's length to either the resized length, if it has already been + // shrunk, or to the original length (it may or may not then later be grown, we don't care here) + const qint64 length = shrink ? newLength : oldLength; + jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_newFirstSector, length ) ); + jobs << Calamares::job_ptr( new MoveFileSystemJob( &context, m_newFirstSector ) ); + } + if ( grow ) + { + jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_newFirstSector, newLength ) ); + jobs << Calamares::job_ptr( new ResizeFileSystemJob( &context, newLength ) ); + } + } + return execJobList( jobs ); +} + +void +ResizePartitionJob::updatePreview() +{ + m_device->partitionTable()->removeUnallocated(); + m_partition->parent()->remove( m_partition ); + m_partition->setFirstSector( m_newFirstSector ); + m_partition->setLastSector( m_newLastSector ); + m_partition->parent()->insert( m_partition ); + m_device->partitionTable()->updateUnallocated( *m_device ); +} + +Calamares::JobResult +ResizePartitionJob::execJobList( const QList< Calamares::job_ptr >& jobs ) +{ + int nbJobs = jobs.size(); + int count = 0; + for ( Calamares::job_ptr job : jobs ) + { + Calamares::JobResult result = job->exec(); + if ( !result ) + return result; + ++count; + progress( qreal( count ) / nbJobs ); + } + return Calamares::JobResult::ok(); +} diff --git a/src/modules/partition/ResizePartitionJob.h b/src/modules/partition/ResizePartitionJob.h new file mode 100644 index 000000000..15761b1c5 --- /dev/null +++ b/src/modules/partition/ResizePartitionJob.h @@ -0,0 +1,55 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 RESIZEPARTITIONJOB_H +#define RESIZEPARTITIONJOB_H + +#include + +class Device; +class Partition; +class FileSystem; + +struct Context; + +class ResizePartitionJob : public PartitionJob +{ + Q_OBJECT +public: + ResizePartitionJob( Device* device, Partition* partition, qint64 firstSector, qint64 lastSector ); + QString prettyName() const override; + Calamares::JobResult exec() override; + + void updatePreview(); + + Device* device() const + { + return m_device; + } + +private: + Device* m_device; + qint64 m_newFirstSector; + qint64 m_newLastSector; + + Calamares::JobResult execJobList( const QList< Calamares::job_ptr >& jobs ); + + friend struct Context; +}; + +#endif /* RESIZEPARTITIONJOB_H */ diff --git a/src/modules/partition/tests/CMakeLists.txt b/src/modules/partition/tests/CMakeLists.txt index 9b0c54767..aa1663f43 100644 --- a/src/modules/partition/tests/CMakeLists.txt +++ b/src/modules/partition/tests/CMakeLists.txt @@ -9,6 +9,7 @@ set( jobtests_SRCS ${PartitionModule_SOURCE_DIR}/PartitionIterator.cpp ${PartitionModule_SOURCE_DIR}/PartitionJob.cpp ${PartitionModule_SOURCE_DIR}/PMUtils.cpp + ${PartitionModule_SOURCE_DIR}/ResizePartitionJob.cpp JobTests.cpp ) diff --git a/src/modules/partition/tests/JobTests.cpp b/src/modules/partition/tests/JobTests.cpp index 169683c5d..6228d6bed 100644 --- a/src/modules/partition/tests/JobTests.cpp +++ b/src/modules/partition/tests/JobTests.cpp @@ -2,6 +2,7 @@ #include #include +#include #include // CalaPM @@ -77,12 +78,18 @@ JobTests::initTestCase() } QVERIFY( CalaPM::init() ); + FileSystemFactory::init(); + + refreshDevice(); +} +void +JobTests::refreshDevice() +{ + QString devicePath = qgetenv( "CALAMARES_TEST_DISK" ); CoreBackend* backend = CoreBackendManager::self()->backend(); m_device.reset( backend->scanDevice( devicePath ) ); QVERIFY( !m_device.isNull() ); - - FileSystemFactory::init(); } void @@ -216,3 +223,71 @@ JobTests::testCreatePartitionExtended() QCOMPARE( extendedPartition->partitionPath(), devicePath + "2" ); QCOMPARE( partition2->partitionPath(), devicePath + "5" ); } + +void +JobTests::testResizePartition_data() +{ + QTest::addColumn< int >( "oldStartMB" ); + QTest::addColumn< int >( "oldSizeMB" ); + QTest::addColumn< int >( "newStartMB" ); + QTest::addColumn< int >( "newSizeMB" ); + + QTest::newRow("grow") << 10 << 5 << 10 << 7; + QTest::newRow("shrink") << 10 << 6 << 10 << 3; + QTest::newRow("moveLeft") << 10 << 5 << 8 << 5; + QTest::newRow("moveRight") << 10 << 5 << 12 << 5; +} + +void +JobTests::testResizePartition() +{ + QFETCH( int, oldStartMB ); + QFETCH( int, oldSizeMB ); + QFETCH( int, newStartMB ); + QFETCH( int, newSizeMB ); + + const qint64 sectorSize = m_device->logicalSectorSize(); + const qint64 sectorForMB = MB / sectorSize; + + qint64 oldFirst = sectorForMB * oldStartMB; + qint64 oldLast = oldFirst + sectorForMB * oldSizeMB - 1; + qint64 newFirst = sectorForMB * newStartMB; + qint64 newLast = newFirst + sectorForMB * newSizeMB - 1; + + // Setup: create the test partition + { + queuePartitionTableCreation( PartitionTable::msdos ); + + Partition* freePartition = firstFreePartition( m_device->partitionTable() ); + QVERIFY( freePartition ); + Partition* partition = PMUtils::createNewPartition( freePartition->parent(), *m_device, PartitionRole( PartitionRole::Primary ), FileSystem::Ext4, oldFirst, oldLast ); + CreatePartitionJob* job = new CreatePartitionJob( m_device.data(), partition ); + job->updatePreview(); + m_queue.enqueue( job_ptr( job ) ); + + QVERIFY( m_runner.run() ); + } + + // Resize + { + refreshDevice(); + QVERIFY( m_device->partitionTable() ); + Partition* partition = m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) ); + QVERIFY( partition ); + + ResizePartitionJob* job = new ResizePartitionJob( m_device.data(), partition, newFirst, newLast ); + QVERIFY( m_runner.run() ); + } + + // Test + { + refreshDevice(); + QVERIFY( m_device->partitionTable() ); + Partition* partition = m_device->partitionTable()->findPartitionBySector( newFirst, PartitionRole( PartitionRole::Primary ) ); + QVERIFY( partition ); + QCOMPARE( partition->firstSector(), newFirst ); + QCOMPARE( partition->lastSector(), newLast ); + QCOMPARE( partition->fileSystem().firstSector(), newFirst ); + QCOMPARE( partition->fileSystem().lastSector(), newLast ); + } +} diff --git a/src/modules/partition/tests/JobTests.h b/src/modules/partition/tests/JobTests.h index e4a35cb3f..281450cc5 100644 --- a/src/modules/partition/tests/JobTests.h +++ b/src/modules/partition/tests/JobTests.h @@ -43,6 +43,8 @@ private Q_SLOTS: void testPartitionTable(); void testCreatePartition(); void testCreatePartitionExtended(); + void testResizePartition_data(); + void testResizePartition(); private: QScopedPointer< Device > m_device; @@ -51,6 +53,7 @@ private: void queuePartitionTableCreation( PartitionTable::TableType type ); CreatePartitionJob* newCreatePartitionJob( Partition* freeSpacePartition, PartitionRole, FileSystem::Type type, qint64 size ); + void refreshDevice(); }; #endif /* JOBTESTS_H */ From 9dac375a31a615af66c7c83392af39fff3c82d67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 16:09:30 +0200 Subject: [PATCH 04/28] Don't forget to queue the job! --- src/modules/partition/tests/JobTests.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/partition/tests/JobTests.cpp b/src/modules/partition/tests/JobTests.cpp index 6228d6bed..adde20f60 100644 --- a/src/modules/partition/tests/JobTests.cpp +++ b/src/modules/partition/tests/JobTests.cpp @@ -276,6 +276,8 @@ JobTests::testResizePartition() QVERIFY( partition ); ResizePartitionJob* job = new ResizePartitionJob( m_device.data(), partition, newFirst, newLast ); + job->updatePreview(); + m_queue.enqueue( job_ptr( job ) ); QVERIFY( m_runner.run() ); } From 60a224e5cda0cc55feea096b70f5cbdb74180652 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 16:10:20 +0200 Subject: [PATCH 05/28] 3MB is too small for ext4: set a bigger new size for shrink --- src/modules/partition/tests/JobTests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/tests/JobTests.cpp b/src/modules/partition/tests/JobTests.cpp index adde20f60..dc08d21e5 100644 --- a/src/modules/partition/tests/JobTests.cpp +++ b/src/modules/partition/tests/JobTests.cpp @@ -233,7 +233,7 @@ JobTests::testResizePartition_data() QTest::addColumn< int >( "newSizeMB" ); QTest::newRow("grow") << 10 << 5 << 10 << 7; - QTest::newRow("shrink") << 10 << 6 << 10 << 3; + QTest::newRow("shrink") << 10 << 7 << 10 << 5; QTest::newRow("moveLeft") << 10 << 5 << 8 << 5; QTest::newRow("moveRight") << 10 << 5 << 12 << 5; } From f00781011829409aabfdfc0b53d6627cbb837993 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 16:11:34 +0200 Subject: [PATCH 06/28] Implement SetPartGeometryJob and ResizeFileSystemJob Now testResizePartition:grow and testResizePartition:shrink pass --- src/modules/partition/ResizePartitionJob.cpp | 98 +++++++++++++++++--- src/modules/partition/ResizePartitionJob.h | 2 + 2 files changed, 88 insertions(+), 12 deletions(-) diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index 0ad5bd7a3..7c67bba8d 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -67,6 +67,11 @@ struct Context {} ResizePartitionJob* job; + qint64 oldFirstSector; + qint64 oldLastSector; + + QScopedPointer< CoreBackendPartitionTable > backendPartitionTable; + QString errorMessage; }; //- ResizeFileSystemJob -------------------------------------------------------- @@ -74,6 +79,8 @@ class ResizeFileSystemJob : public Calamares::Job { public: ResizeFileSystemJob( Context* context, qint64 length ) + : m_context( context ) + , m_length( length ) {} QString prettyName() const override @@ -83,8 +90,53 @@ public: Calamares::JobResult exec() override { + Report report( nullptr ); + Device* device = m_context->job->device(); + Partition* partition = m_context->job->partition(); + FileSystem& fs = partition->fileSystem(); + FileSystem::CommandSupportType support = m_length < fs.length() ? fs.supportShrink() : fs.supportGrow(); + + switch (support) + { + case FileSystem::cmdSupportBackend: + if ( !backendResize( &report ) ) + return Calamares::JobResult::error( + m_context->errorMessage, + tr( "Parted failed to resize filesystem." ) + '\n' + report.toText() + ); + break; + case FileSystem::cmdSupportFileSystem: + { + qint64 byteLength = device->logicalSectorSize() * m_length; + bool ok = fs.resize( report, partition->partitionPath(), byteLength ); + if ( !ok ) + return Calamares::JobResult::error( + m_context->errorMessage, + tr( "Failed to resize filesystem." ) + '\n' + report.toText() + ); + break; + } + default: + break; + } + + fs.setLastSector( fs.firstSector() + m_length - 1 ); return Calamares::JobResult::ok(); } + +private: + Context* m_context; + qint64 m_length; + + bool backendResize( Report* report ) + { + Partition* partition = m_context->job->partition(); + bool ok = m_context->backendPartitionTable->resizeFileSystem( *report, *partition, m_length ); + if ( !ok ) + return false; + m_context->backendPartitionTable->commit(); + return true; + } }; //- SetPartGeometryJob --------------------------------------------------------- @@ -92,6 +144,9 @@ class SetPartGeometryJob : public Calamares::Job { public: SetPartGeometryJob( Context* context, qint64 firstSector, qint64 length ) + : m_context( context ) + , m_firstSector( firstSector ) + , m_length( length ) {} QString prettyName() const override @@ -101,8 +156,26 @@ public: Calamares::JobResult exec() override { + Report report( nullptr ); + Partition* partition = m_context->job->partition(); + qint64 lastSector = m_firstSector + m_length - 1; + bool ok = m_context->backendPartitionTable->updateGeometry( report, *partition, m_firstSector, lastSector ); + if ( !ok ) + { + return Calamares::JobResult::error( + m_context->errorMessage, + tr( "Failed to change the geometry of the partition." ) + '\n' + report.toText() ); + } + partition->setFirstSector( m_firstSector ); + partition->setLastSector( lastSector ); + m_context->backendPartitionTable->commit(); return Calamares::JobResult::ok(); } + +private: + Context* m_context; + qint64 m_firstSector; + qint64 m_length; }; //- MoveFileSystemJob ---------------------------------------------------------- @@ -127,6 +200,8 @@ public: ResizePartitionJob::ResizePartitionJob( Device* device, Partition* partition, qint64 firstSector, qint64 lastSector ) : PartitionJob( partition ) , m_device( device ) + , m_oldFirstSector( partition->firstSector() ) // Keep a copy of old sectors because they will be overwritten in updatePreview() + , m_oldLastSector( partition->lastSector() ) , m_newFirstSector( firstSector ) , m_newLastSector( lastSector ) { @@ -148,29 +223,28 @@ ResizePartitionJob::prettyName() const Calamares::JobResult ResizePartitionJob::exec() { - /* - Report report( 0 ); + qint64 oldLength = m_oldLastSector - m_oldFirstSector + 1; + qint64 newLength = m_newLastSector - m_newFirstSector + 1; + + // Setup context QString partitionPath = m_partition->partitionPath(); - QString message = tr( "The installer failed to format partition %1 on disk '%2'." ).arg( partitionPath, m_device->name() ); + Context context( this ); + context.oldFirstSector = m_oldFirstSector; + context.oldLastSector = m_oldLastSector; + context.errorMessage = tr( "The installer failed to resize partition %1 on disk '%2'." ).arg( partitionPath, m_device->name() ); CoreBackend* backend = CoreBackendManager::self()->backend(); QScopedPointer backendDevice( backend->openDevice( m_device->deviceNode() ) ); if ( !backendDevice.data() ) { return Calamares::JobResult::error( - message, + context.errorMessage, tr( "Could not open device '%1'." ).arg( m_device->deviceNode() ) ); } + context.backendPartitionTable.reset( backendDevice->openPartitionTable() ); - QScopedPointer backendPartitionTable( backendDevice->openPartitionTable() ); - backendPartitionTable->commit(); - return Calamares::JobResult::ok(); - */ - qint64 oldLength = m_partition->lastSector() - m_partition->firstSector() + 1; - qint64 newLength = m_newLastSector - m_newFirstSector + 1; - - Context context( this ); + // Create jobs QList< Calamares::job_ptr > jobs; if ( m_partition->roles().has( PartitionRole::Extended ) ) jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_newFirstSector, newLength ) ); diff --git a/src/modules/partition/ResizePartitionJob.h b/src/modules/partition/ResizePartitionJob.h index 15761b1c5..7deb3baa5 100644 --- a/src/modules/partition/ResizePartitionJob.h +++ b/src/modules/partition/ResizePartitionJob.h @@ -44,6 +44,8 @@ public: private: Device* m_device; + qint64 m_oldFirstSector; + qint64 m_oldLastSector; qint64 m_newFirstSector; qint64 m_newLastSector; From 1314bf944f0293e3834822daf5b0cf836c4478e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 17:35:54 +0200 Subject: [PATCH 07/28] Update partitionmanager submodule: Include CopySourceDevice and CopyTargetDevice --- src/modules/partition/partitionmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/partitionmanager b/src/modules/partition/partitionmanager index 838f13e9d..6892180de 160000 --- a/src/modules/partition/partitionmanager +++ b/src/modules/partition/partitionmanager @@ -1 +1 @@ -Subproject commit 838f13e9dcd1702a8fa4ec49e04163087e56f7e2 +Subproject commit 6892180de21684cd90c50ec2b663dd0caa6bc9f3 From 249a28910a7126a8368788df467d10241a82118f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 17:37:24 +0200 Subject: [PATCH 08/28] Make it possible to update message and details fields of a JobResult --- src/libcalamares/Job.cpp | 14 ++++++++++++++ src/libcalamares/Job.h | 2 ++ 2 files changed, 16 insertions(+) diff --git a/src/libcalamares/Job.cpp b/src/libcalamares/Job.cpp index 9e32ff47f..5a63c100e 100644 --- a/src/libcalamares/Job.cpp +++ b/src/libcalamares/Job.cpp @@ -35,6 +35,13 @@ JobResult::message() const } +void +JobResult::setMessage( const QString& message ) +{ + m_message = message; +} + + QString JobResult::details() const { @@ -42,6 +49,13 @@ JobResult::details() const } +void +JobResult::setDetails( const QString& details ) +{ + m_details = details; +} + + JobResult JobResult::ok() { diff --git a/src/libcalamares/Job.h b/src/libcalamares/Job.h index 85eb93cf4..f6a2f10dc 100644 --- a/src/libcalamares/Job.h +++ b/src/libcalamares/Job.h @@ -32,8 +32,10 @@ public: operator bool() const; QString message() const; + void setMessage( const QString& message ); QString details() const; + void setDetails( const QString& details ); static JobResult ok(); From 3db6d607caf01795ef2d67b0454f8f1f804483cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 17:38:26 +0200 Subject: [PATCH 09/28] move MoveFileSystemJob to its own file It's going to be bigger than the others. --- src/modules/partition/CMakeLists.txt | 1 + src/modules/partition/MoveFileSystemJob.cpp | 125 +++++++++++++++++++ src/modules/partition/MoveFileSystemJob.h | 62 +++++++++ src/modules/partition/ResizePartitionJob.cpp | 44 +++---- src/modules/partition/tests/CMakeLists.txt | 1 + 5 files changed, 203 insertions(+), 30 deletions(-) create mode 100644 src/modules/partition/MoveFileSystemJob.cpp create mode 100644 src/modules/partition/MoveFileSystemJob.h diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 0323af79c..663ba8913 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -31,6 +31,7 @@ calamares_add_plugin( partition EditExistingPartitionDialog.cpp FillGlobalStorageJob.cpp FormatPartitionJob.cpp + MoveFileSystemJob.cpp PartitionCoreModule.cpp PartitionInfo.cpp PartitionIterator.cpp diff --git a/src/modules/partition/MoveFileSystemJob.cpp b/src/modules/partition/MoveFileSystemJob.cpp new file mode 100644 index 000000000..f704cb14c --- /dev/null +++ b/src/modules/partition/MoveFileSystemJob.cpp @@ -0,0 +1,125 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 . + */ + +// This class is heavily based on the MoveFileSystemJob class from KDE Partition +// Manager. Original copyright follow: + +/*************************************************************************** + * Copyright (C) 2008 by Volker Lanz * + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ + +#include + +// CalaPM +#include +#include +#include +#include +#include +#include + +static bool +copyBlocks( Report& report, CopyTargetDevice& target, CopySourceDevice& source ) +{ + return false; +} + +static bool +rollbackCopyBlocks( Report& report, CopyTargetDevice& target, CopySourceDevice& source ) +{ + return false; +} + +MoveFileSystemJob::MoveFileSystemJob( Device* device, Partition* partition, qint64 firstSector ) + : PartitionJob( partition ) + , m_device( device ) + , m_firstSector( firstSector ) +{} + +QString +MoveFileSystemJob::prettyName() const +{ + return tr( "Moving file system of partition %1." ).arg( partition()->partitionPath() ); +} + +Calamares::JobResult +MoveFileSystemJob::exec() +{ + Report report( nullptr ); + QString partitionPath = partition()->partitionPath(); + FileSystem& fs = partition()->fileSystem(); + CopySourceDevice moveSource( *m_device, fs.firstSector(), fs.lastSector() ); + CopyTargetDevice moveTarget( *m_device, m_firstSector, m_firstSector + fs.length() ); + + if ( !moveSource.open() ) + return Calamares::JobResult::error( + QString(), + tr( "Could not open file system on partition %1 for moving." ).arg( partitionPath ) + ); + + if ( !moveTarget.open() ) + return Calamares::JobResult::error( + QString(), + tr( "Could not create target for moving file system on partition %1." ).arg( partitionPath ) + ); + + bool ok = copyBlocks( report, moveTarget, moveSource ); + if ( !ok ) + { + if ( rollbackCopyBlocks( report, moveTarget, moveSource ) ) + return Calamares::JobResult::error( + QString(), + tr( "Moving of partition %1 failed, changes have been rolled back." ).arg( partitionPath ) + + '\n' + report.toText() + ); + else + return Calamares::JobResult::error( + QString(), + tr( "Moving of partition %1 failed. Roll back of the changes have failed." ).arg( partitionPath ) + + '\n' + report.toText() + ); + } + + const qint64 savedLength = fs.length(); + fs.setFirstSector( m_firstSector ); + fs.setLastSector( m_firstSector + savedLength - 1 ); + + if ( !fs.updateBootSector( report, partitionPath ) ) + return Calamares::JobResult::error( + QString(), + tr( "Updating boot sector after the moving of partition %1 failed." ).arg( partitionPath ) + + '\n' + report.toText() + ); + + return Calamares::JobResult::ok(); +} diff --git a/src/modules/partition/MoveFileSystemJob.h b/src/modules/partition/MoveFileSystemJob.h new file mode 100644 index 000000000..38c34ad83 --- /dev/null +++ b/src/modules/partition/MoveFileSystemJob.h @@ -0,0 +1,62 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 . + */ + +// This class is heavily based on the MoveFileSystemJob class from KDE Partition +// Manager. Original copyright follow: + +/*************************************************************************** + * Copyright (C) 2008 by Volker Lanz * + * * + * This program 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 2 of the License, or * + * (at your option) any later version. * + * * + * This program 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 this program; if not, write to the * + * Free Software Foundation, Inc., * + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * + ***************************************************************************/ +#ifndef MOVEFILESYSTEMJOB_H +#define MOVEFILESYSTEMJOB_H + +#include + +class Device; +class Partition; + +class MoveFileSystemJob : public PartitionJob +{ +public: + MoveFileSystemJob( Device* device, Partition* partition, qint64 firstSector ); + + QString prettyName() const override; + + Calamares::JobResult exec() override; + +private: + Device* m_device; + qint64 m_firstSector; +}; + +#endif /* MOVEFILESYSTEMJOB_H */ diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index 7c67bba8d..dc1c06d2d 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -40,7 +40,7 @@ #include -//#include +#include // CalaPM #include @@ -50,10 +50,6 @@ #include #include #include -/* -#include -#include -*/ #include // Qt @@ -71,7 +67,6 @@ struct Context qint64 oldLastSector; QScopedPointer< CoreBackendPartitionTable > backendPartitionTable; - QString errorMessage; }; //- ResizeFileSystemJob -------------------------------------------------------- @@ -101,7 +96,7 @@ public: case FileSystem::cmdSupportBackend: if ( !backendResize( &report ) ) return Calamares::JobResult::error( - m_context->errorMessage, + QString(), tr( "Parted failed to resize filesystem." ) + '\n' + report.toText() ); break; @@ -111,7 +106,7 @@ public: bool ok = fs.resize( report, partition->partitionPath(), byteLength ); if ( !ok ) return Calamares::JobResult::error( - m_context->errorMessage, + QString(), tr( "Failed to resize filesystem." ) + '\n' + report.toText() ); break; @@ -163,7 +158,7 @@ public: if ( !ok ) { return Calamares::JobResult::error( - m_context->errorMessage, + QString(), tr( "Failed to change the geometry of the partition." ) + '\n' + report.toText() ); } partition->setFirstSector( m_firstSector ); @@ -178,24 +173,6 @@ private: qint64 m_length; }; -//- MoveFileSystemJob ---------------------------------------------------------- -class MoveFileSystemJob : public Calamares::Job -{ -public: - MoveFileSystemJob( Context* context, qint64 firstSector ) - {} - - QString prettyName() const override - { - return QString(); - } - - Calamares::JobResult exec() override - { - return Calamares::JobResult::ok(); - } -}; - //- ResizePartitionJob --------------------------------------------------------- ResizePartitionJob::ResizePartitionJob( Device* device, Partition* partition, qint64 firstSector, qint64 lastSector ) : PartitionJob( partition ) @@ -231,14 +208,13 @@ ResizePartitionJob::exec() Context context( this ); context.oldFirstSector = m_oldFirstSector; context.oldLastSector = m_oldLastSector; - context.errorMessage = tr( "The installer failed to resize partition %1 on disk '%2'." ).arg( partitionPath, m_device->name() ); CoreBackend* backend = CoreBackendManager::self()->backend(); QScopedPointer backendDevice( backend->openDevice( m_device->deviceNode() ) ); if ( !backendDevice.data() ) { return Calamares::JobResult::error( - context.errorMessage, + QString(), tr( "Could not open device '%1'." ).arg( m_device->deviceNode() ) ); } @@ -265,7 +241,7 @@ ResizePartitionJob::exec() // shrunk, or to the original length (it may or may not then later be grown, we don't care here) const qint64 length = shrink ? newLength : oldLength; jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_newFirstSector, length ) ); - jobs << Calamares::job_ptr( new MoveFileSystemJob( &context, m_newFirstSector ) ); + jobs << Calamares::job_ptr( new MoveFileSystemJob( m_device, m_partition, m_newFirstSector ) ); } if ( grow ) { @@ -290,13 +266,21 @@ ResizePartitionJob::updatePreview() Calamares::JobResult ResizePartitionJob::execJobList( const QList< Calamares::job_ptr >& jobs ) { + QString errorMessage = tr( "The installer failed to resize partition %1 on disk '%2'." ) + .arg( m_partition->partitionPath() ) + .arg( m_device->name() ); + int nbJobs = jobs.size(); int count = 0; for ( Calamares::job_ptr job : jobs ) { Calamares::JobResult result = job->exec(); if ( !result ) + { + if ( result.message().isEmpty() ) + result.setMessage( errorMessage ); return result; + } ++count; progress( qreal( count ) / nbJobs ); } diff --git a/src/modules/partition/tests/CMakeLists.txt b/src/modules/partition/tests/CMakeLists.txt index aa1663f43..65e64af57 100644 --- a/src/modules/partition/tests/CMakeLists.txt +++ b/src/modules/partition/tests/CMakeLists.txt @@ -5,6 +5,7 @@ set( jobtests_SRCS ${PartitionModule_SOURCE_DIR}/CreatePartitionJob.cpp ${PartitionModule_SOURCE_DIR}/CreatePartitionTableJob.cpp ${PartitionModule_SOURCE_DIR}/DeletePartitionJob.cpp + ${PartitionModule_SOURCE_DIR}/MoveFileSystemJob.cpp ${PartitionModule_SOURCE_DIR}/PartitionInfo.cpp ${PartitionModule_SOURCE_DIR}/PartitionIterator.cpp ${PartitionModule_SOURCE_DIR}/PartitionJob.cpp From 4716b1c9b4ee6c7f9088ef48951308f12874e3bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 17:53:10 +0200 Subject: [PATCH 10/28] Coding style --- src/modules/partition/ResizePartitionJob.cpp | 22 ++++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index dc1c06d2d..b2c63a19a 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -91,14 +91,14 @@ public: FileSystem& fs = partition->fileSystem(); FileSystem::CommandSupportType support = m_length < fs.length() ? fs.supportShrink() : fs.supportGrow(); - switch (support) + switch ( support ) { case FileSystem::cmdSupportBackend: if ( !backendResize( &report ) ) return Calamares::JobResult::error( - QString(), - tr( "Parted failed to resize filesystem." ) + '\n' + report.toText() - ); + QString(), + tr( "Parted failed to resize filesystem." ) + '\n' + report.toText() + ); break; case FileSystem::cmdSupportFileSystem: { @@ -106,9 +106,9 @@ public: bool ok = fs.resize( report, partition->partitionPath(), byteLength ); if ( !ok ) return Calamares::JobResult::error( - QString(), - tr( "Failed to resize filesystem." ) + '\n' + report.toText() - ); + QString(), + tr( "Failed to resize filesystem." ) + '\n' + report.toText() + ); break; } default: @@ -158,8 +158,8 @@ public: if ( !ok ) { return Calamares::JobResult::error( - QString(), - tr( "Failed to change the geometry of the partition." ) + '\n' + report.toText() ); + QString(), + tr( "Failed to change the geometry of the partition." ) + '\n' + report.toText() ); } partition->setFirstSector( m_firstSector ); partition->setLastSector( lastSector ); @@ -267,8 +267,8 @@ Calamares::JobResult ResizePartitionJob::execJobList( const QList< Calamares::job_ptr >& jobs ) { QString errorMessage = tr( "The installer failed to resize partition %1 on disk '%2'." ) - .arg( m_partition->partitionPath() ) - .arg( m_device->name() ); + .arg( m_partition->partitionPath() ) + .arg( m_device->name() ); int nbJobs = jobs.size(); int count = 0; From dac23c90a173f857081181b1e79d806b3d63359c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Tue, 5 Aug 2014 18:27:24 +0200 Subject: [PATCH 11/28] Implement MoveFileSystemJob: all testResizePartition tests pass --- src/modules/partition/MoveFileSystemJob.cpp | 191 +++++++++++++++---- src/modules/partition/MoveFileSystemJob.h | 11 +- src/modules/partition/ResizePartitionJob.cpp | 17 +- src/modules/partition/tests/JobTests.cpp | 5 + 4 files changed, 179 insertions(+), 45 deletions(-) diff --git a/src/modules/partition/MoveFileSystemJob.cpp b/src/modules/partition/MoveFileSystemJob.cpp index f704cb14c..bca301cdd 100644 --- a/src/modules/partition/MoveFileSystemJob.cpp +++ b/src/modules/partition/MoveFileSystemJob.cpp @@ -17,7 +17,9 @@ */ // This class is heavily based on the MoveFileSystemJob class from KDE Partition -// Manager. Original copyright follow: +// Manager. +// The copyBlock functions come from Partition Manager Job class. +// Original copyright follow: /*************************************************************************** * Copyright (C) 2008 by Volker Lanz * @@ -40,6 +42,8 @@ #include +#include + // CalaPM #include #include @@ -48,22 +52,12 @@ #include #include -static bool -copyBlocks( Report& report, CopyTargetDevice& target, CopySourceDevice& source ) -{ - return false; -} - -static bool -rollbackCopyBlocks( Report& report, CopyTargetDevice& target, CopySourceDevice& source ) -{ - return false; -} - -MoveFileSystemJob::MoveFileSystemJob( Device* device, Partition* partition, qint64 firstSector ) +MoveFileSystemJob::MoveFileSystemJob( Device* device, Partition* partition, qint64 oldFirstSector, qint64 newFirstSector, qint64 length ) : PartitionJob( partition ) , m_device( device ) - , m_firstSector( firstSector ) + , m_oldFirstSector( oldFirstSector ) + , m_newFirstSector( newFirstSector ) + , m_length( length ) {} QString @@ -77,49 +71,168 @@ MoveFileSystemJob::exec() { Report report( nullptr ); QString partitionPath = partition()->partitionPath(); - FileSystem& fs = partition()->fileSystem(); - CopySourceDevice moveSource( *m_device, fs.firstSector(), fs.lastSector() ); - CopyTargetDevice moveTarget( *m_device, m_firstSector, m_firstSector + fs.length() ); + CopySourceDevice moveSource( *m_device, m_oldFirstSector, m_oldFirstSector + m_length - 1 ); + CopyTargetDevice moveTarget( *m_device, m_newFirstSector, m_newFirstSector + m_length - 1 ); if ( !moveSource.open() ) return Calamares::JobResult::error( - QString(), - tr( "Could not open file system on partition %1 for moving." ).arg( partitionPath ) - ); + QString(), + tr( "Could not open file system on partition %1 for moving." ).arg( partitionPath ) + ); if ( !moveTarget.open() ) return Calamares::JobResult::error( - QString(), - tr( "Could not create target for moving file system on partition %1." ).arg( partitionPath ) - ); + QString(), + tr( "Could not create target for moving file system on partition %1." ).arg( partitionPath ) + ); bool ok = copyBlocks( report, moveTarget, moveSource ); if ( !ok ) { if ( rollbackCopyBlocks( report, moveTarget, moveSource ) ) return Calamares::JobResult::error( - QString(), - tr( "Moving of partition %1 failed, changes have been rolled back." ).arg( partitionPath ) - + '\n' + report.toText() - ); + QString(), + tr( "Moving of partition %1 failed, changes have been rolled back." ).arg( partitionPath ) + + '\n' + report.toText() + ); else return Calamares::JobResult::error( - QString(), - tr( "Moving of partition %1 failed. Roll back of the changes have failed." ).arg( partitionPath ) - + '\n' + report.toText() - ); + QString(), + tr( "Moving of partition %1 failed. Roll back of the changes have failed." ).arg( partitionPath ) + + '\n' + report.toText() + ); } - const qint64 savedLength = fs.length(); - fs.setFirstSector( m_firstSector ); - fs.setLastSector( m_firstSector + savedLength - 1 ); + FileSystem& fs = partition()->fileSystem(); + fs.setFirstSector( m_newFirstSector ); + fs.setLastSector( m_newFirstSector + m_length - 1 ); if ( !fs.updateBootSector( report, partitionPath ) ) return Calamares::JobResult::error( - QString(), - tr( "Updating boot sector after the moving of partition %1 failed." ).arg( partitionPath ) - + '\n' + report.toText() - ); + QString(), + tr( "Updating boot sector after the moving of partition %1 failed." ).arg( partitionPath ) + + '\n' + report.toText() + ); return Calamares::JobResult::ok(); } + +bool +MoveFileSystemJob::copyBlocks( Report& report, CopyTargetDevice& target, CopySourceDevice& source ) +{ + /** @todo copyBlocks() assumes that source.sectorSize() == target.sectorSize(). */ + + if ( source.sectorSize() != target.sectorSize() ) + { + report.line() << tr( "The logical sector sizes in the source and target for copying are not the same. This is currently unsupported." ); + return false; + } + + bool rval = true; + const qint64 blockSize = 16065 * 8; // number of sectors per block to copy + const qint64 blocksToCopy = source.length() / blockSize; + + qint64 readOffset = source.firstSector(); + qint64 writeOffset = target.firstSector(); + qint32 copyDir = 1; + + if ( target.firstSector() > source.firstSector() ) + { + readOffset = source.firstSector() + source.length() - blockSize; + writeOffset = target.firstSector() + source.length() - blockSize; + copyDir = -1; + } + + qint64 blocksCopied = 0; + + void* buffer = malloc( blockSize * source.sectorSize() ); + int percent = 0; + + while ( blocksCopied < blocksToCopy ) + { + rval = source.readSectors( buffer, readOffset + blockSize * blocksCopied * copyDir, blockSize ); + if ( !rval ) + break; + + rval = target.writeSectors( buffer, writeOffset + blockSize * blocksCopied * copyDir, blockSize ); + if ( !rval ) + break; + + if ( ++blocksCopied * 100 / blocksToCopy != percent ) + { + percent = blocksCopied * 100 / blocksToCopy; + progress( qreal( percent ) / 100. ); + } + } + + const qint64 lastBlock = source.length() % blockSize; + + // copy the remainder + if ( rval && lastBlock > 0 ) + { + Q_ASSERT( lastBlock < blockSize ); + + if ( lastBlock >= blockSize ) + cLog() << "warning: lastBlock: " << lastBlock << ", blockSize: " << blockSize; + + const qint64 lastBlockReadOffset = copyDir > 0 ? readOffset + blockSize * blocksCopied : source.firstSector(); + const qint64 lastBlockWriteOffset = copyDir > 0 ? writeOffset + blockSize * blocksCopied : target.firstSector(); + + rval = source.readSectors( buffer, lastBlockReadOffset, lastBlock ); + + if ( rval ) + rval = target.writeSectors( buffer, lastBlockWriteOffset, lastBlock ); + + if ( rval ) + emit progress( 1.0 ); + } + + free( buffer ); + + return rval; +} + +bool +MoveFileSystemJob::rollbackCopyBlocks( Report& report, CopyTargetDevice& origTarget, CopySourceDevice& origSource ) +{ + if ( !origSource.overlaps( origTarget ) ) + { + report.line() << tr( "Source and target for copying do not overlap: Rollback is not required." ); + return true; + } + + // default: use values as if we were copying from front to back. + qint64 undoSourceFirstSector = origTarget.firstSector(); + qint64 undoSourceLastSector = origTarget.firstSector() + origTarget.sectorsWritten() - 1; + + qint64 undoTargetFirstSector = origSource.firstSector(); + qint64 undoTargetLastSector = origSource.firstSector() + origTarget.sectorsWritten() - 1; + + if ( origTarget.firstSector() > origSource.firstSector() ) + { + // we were copying from back to front + undoSourceFirstSector = origTarget.firstSector() + origSource.length() - origTarget.sectorsWritten(); + undoSourceLastSector = origTarget.firstSector() + origSource.length() - 1; + + undoTargetFirstSector = origSource.lastSector() - origTarget.sectorsWritten() + 1; + undoTargetLastSector = origSource.lastSector(); + } + + CopySourceDevice undoSource( origTarget.device(), undoSourceFirstSector, undoSourceLastSector ); + if ( !undoSource.open() ) + { + report.line() << tr( "Could not open device %1 to rollback copying." ) + .arg( origTarget.device().deviceNode() ); + return false; + } + + CopyTargetDevice undoTarget( origSource.device(), undoTargetFirstSector, undoTargetLastSector ); + if ( !undoTarget.open() ) + { + report.line() << tr( "Could not open device %1 to rollback copying." ) + .arg( origSource.device().deviceNode() ); + return false; + } + + return copyBlocks( report, undoTarget, undoSource ); +} diff --git a/src/modules/partition/MoveFileSystemJob.h b/src/modules/partition/MoveFileSystemJob.h index 38c34ad83..1ae3534c6 100644 --- a/src/modules/partition/MoveFileSystemJob.h +++ b/src/modules/partition/MoveFileSystemJob.h @@ -42,13 +42,16 @@ #include +class CopySourceDevice; +class CopyTargetDevice; class Device; class Partition; +class Report; class MoveFileSystemJob : public PartitionJob { public: - MoveFileSystemJob( Device* device, Partition* partition, qint64 firstSector ); + MoveFileSystemJob( Device* device, Partition* partition, qint64 oldFirstSector, qint64 newFirstSector, qint64 length ); QString prettyName() const override; @@ -56,7 +59,11 @@ public: private: Device* m_device; - qint64 m_firstSector; + qint64 m_oldFirstSector; + qint64 m_newFirstSector; + qint64 m_length; + bool copyBlocks( Report& report, CopyTargetDevice& target, CopySourceDevice& source ); + bool rollbackCopyBlocks( Report& report, CopyTargetDevice& origTarget, CopySourceDevice& origSource ); }; #endif /* MOVEFILESYSTEMJOB_H */ diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index b2c63a19a..7596f13c4 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -203,6 +203,15 @@ ResizePartitionJob::exec() qint64 oldLength = m_oldLastSector - m_oldFirstSector + 1; qint64 newLength = m_newLastSector - m_newFirstSector + 1; + // Assuming updatePreview() has been called, `partition` uses its new + // position and size. Reset it to the old values: part of the libparted + // backend relies on this (for example: + // LibPartedPartitionTable::updateGeometry()) + // The jobs are responsible for updating the partition back when they are + // done. + m_partition->setFirstSector( m_oldFirstSector ); + m_partition->setLastSector( m_oldLastSector ); + // Setup context QString partitionPath = m_partition->partitionPath(); Context context( this ); @@ -228,12 +237,12 @@ ResizePartitionJob::exec() { bool shrink = newLength < oldLength; bool grow = newLength > oldLength; - bool moveRight = m_newFirstSector > m_partition->firstSector(); - bool moveLeft = m_newFirstSector < m_partition->firstSector(); + bool moveRight = m_newFirstSector > m_oldFirstSector; + bool moveLeft = m_newFirstSector < m_oldFirstSector; if ( shrink ) { jobs << Calamares::job_ptr( new ResizeFileSystemJob( &context, newLength ) ); - jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_partition->firstSector(), newLength ) ); + jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_oldFirstSector, newLength ) ); } if ( moveRight || moveLeft ) { @@ -241,7 +250,7 @@ ResizePartitionJob::exec() // shrunk, or to the original length (it may or may not then later be grown, we don't care here) const qint64 length = shrink ? newLength : oldLength; jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_newFirstSector, length ) ); - jobs << Calamares::job_ptr( new MoveFileSystemJob( m_device, m_partition, m_newFirstSector ) ); + jobs << Calamares::job_ptr( new MoveFileSystemJob( m_device, m_partition, m_oldFirstSector, m_newFirstSector, length ) ); } if ( grow ) { diff --git a/src/modules/partition/tests/JobTests.cpp b/src/modules/partition/tests/JobTests.cpp index dc08d21e5..08337d68c 100644 --- a/src/modules/partition/tests/JobTests.cpp +++ b/src/modules/partition/tests/JobTests.cpp @@ -274,11 +274,16 @@ JobTests::testResizePartition() QVERIFY( m_device->partitionTable() ); Partition* partition = m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) ); QVERIFY( partition ); + QCOMPARE( partition->firstSector(), oldFirst ); + QCOMPARE( partition->lastSector(), oldLast ); ResizePartitionJob* job = new ResizePartitionJob( m_device.data(), partition, newFirst, newLast ); job->updatePreview(); m_queue.enqueue( job_ptr( job ) ); QVERIFY( m_runner.run() ); + + QCOMPARE( partition->firstSector(), newFirst ); + QCOMPARE( partition->lastSector(), newLast ); } // Test From e2fe559f9dbbeb6c19d583f768a1a7b82100c616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 11:46:03 +0200 Subject: [PATCH 12/28] testResizePartition: more reliability tests - use bigger partition sizes - write a file before resizing, test it is the same after resizing --- src/modules/partition/tests/JobTests.cpp | 116 ++++++++++++++++++++--- 1 file changed, 105 insertions(+), 11 deletions(-) diff --git a/src/modules/partition/tests/JobTests.cpp b/src/modules/partition/tests/JobTests.cpp index 08337d68c..40edce79b 100644 --- a/src/modules/partition/tests/JobTests.cpp +++ b/src/modules/partition/tests/JobTests.cpp @@ -13,6 +13,7 @@ // Qt #include +#include #include QTEST_GUILESS_MAIN( JobTests ) @@ -21,8 +22,77 @@ static const qint64 MB = 1024 * 1024; using namespace Calamares; -static -Partition* firstFreePartition( PartitionNode* parent ) +class PartitionMounter +{ +public: + PartitionMounter( const QString& devicePath ) + : m_mountPointDir( "calamares-partitiontests-mountpoint" ) + { + QStringList args = QStringList() << devicePath << m_mountPointDir.path(); + int ret = QProcess::execute( "mount", args ); + m_mounted = ret == 0; + QCOMPARE( ret, 0 ); + } + + ~PartitionMounter() + { + if ( !m_mounted ) + return; + int ret = QProcess::execute( "umount", QStringList() << m_mountPointDir.path() ); + QCOMPARE( ret, 0 ); + } + + QString mountPoint() const + { + return m_mounted ? m_mountPointDir.path() : QString(); + } + +private: + QString m_devicePath; + QTemporaryDir m_mountPointDir; + bool m_mounted; +}; + +static QByteArray +generateTestData( qint64 size ) +{ + QByteArray ba; + ba.resize( size ); + // Fill the array explicitly to keep Valgrind happy + for ( auto it = ba.data() ; it < ba.data() + size ; ++it ) + { + *it = rand() % 256; + } + return ba; +} + +static void +writeFile( const QString& path, const QByteArray data ) +{ + QFile file( path ); + QVERIFY( file.open( QIODevice::WriteOnly ) ); + + const char* ptr = data.constData(); + const char* end = data.constData() + data.size(); + const qint64 chunkSize = 16384; + + while ( ptr < end ) + { + qint64 count = file.write( ptr, chunkSize ); + if ( count < 0 ) + { + QString msg = QString( "Writing file failed. Only %1 bytes written out of %2. Error: '%3'." ) + .arg( ptr - data.constData() ) + .arg( data.size() ) + .arg( file.errorString() ); + QFAIL( qPrintable( msg ) ); + } + ptr += count; + } +} + +static Partition* +firstFreePartition( PartitionNode* parent ) { for( auto child : parent->children() ) if ( PMUtils::isPartitionFreeSpace( child ) ) @@ -30,6 +100,7 @@ Partition* firstFreePartition( PartitionNode* parent ) return nullptr; } +//- QueueRunner --------------------------------------------------------------- QueueRunner::QueueRunner( JobQueue* queue ) : m_queue( queue ) { @@ -63,7 +134,7 @@ QueueRunner::onFailed( const QString& message, const QString& details ) QFAIL( qPrintable( msg ) ); } -//---------------------------------------------------------- +//- JobTests ------------------------------------------------------------------ JobTests::JobTests() : m_runner( &m_queue ) {} @@ -232,10 +303,10 @@ JobTests::testResizePartition_data() QTest::addColumn< int >( "newStartMB" ); QTest::addColumn< int >( "newSizeMB" ); - QTest::newRow("grow") << 10 << 5 << 10 << 7; - QTest::newRow("shrink") << 10 << 7 << 10 << 5; - QTest::newRow("moveLeft") << 10 << 5 << 8 << 5; - QTest::newRow("moveRight") << 10 << 5 << 12 << 5; + QTest::newRow("grow") << 10 << 50 << 10 << 70; + QTest::newRow("shrink") << 10 << 70 << 10 << 50; + QTest::newRow("moveLeft") << 10 << 50 << 8 << 50; + QTest::newRow("moveRight") << 10 << 50 << 12 << 50; } void @@ -246,14 +317,18 @@ JobTests::testResizePartition() QFETCH( int, newStartMB ); QFETCH( int, newSizeMB ); - const qint64 sectorSize = m_device->logicalSectorSize(); - const qint64 sectorForMB = MB / sectorSize; + const qint64 sectorForMB = MB / m_device->logicalSectorSize(); qint64 oldFirst = sectorForMB * oldStartMB; qint64 oldLast = oldFirst + sectorForMB * oldSizeMB - 1; qint64 newFirst = sectorForMB * newStartMB; qint64 newLast = newFirst + sectorForMB * newSizeMB - 1; + // Make the test data file smaller than the full size of the partition to + // accomodate for the file system overhead + const QByteArray testData = generateTestData( ( qMin( oldSizeMB, newSizeMB ) ) * MB * 3 / 4 ); + const QString testName = "test.data"; + // Setup: create the test partition { queuePartitionTableCreation( PartitionTable::msdos ); @@ -268,15 +343,22 @@ JobTests::testResizePartition() QVERIFY( m_runner.run() ); } - // Resize { + // Write a test file in the partition refreshDevice(); QVERIFY( m_device->partitionTable() ); Partition* partition = m_device->partitionTable()->findPartitionBySector( oldFirst, PartitionRole( PartitionRole::Primary ) ); QVERIFY( partition ); QCOMPARE( partition->firstSector(), oldFirst ); QCOMPARE( partition->lastSector(), oldLast ); - + { + PartitionMounter mounter( partition->partitionPath() ); + QString mountPoint = mounter.mountPoint(); + QVERIFY( !mountPoint.isEmpty() ); + writeFile( mountPoint + '/' + testName, testData ); + } + + // Resize ResizePartitionJob* job = new ResizePartitionJob( m_device.data(), partition, newFirst, newLast ); job->updatePreview(); m_queue.enqueue( job_ptr( job ) ); @@ -296,5 +378,17 @@ JobTests::testResizePartition() QCOMPARE( partition->lastSector(), newLast ); QCOMPARE( partition->fileSystem().firstSector(), newFirst ); QCOMPARE( partition->fileSystem().lastSector(), newLast ); + + + PartitionMounter mounter( partition->partitionPath() ); + QString mountPoint = mounter.mountPoint(); + QVERIFY( !mountPoint.isEmpty() ); + { + QFile file( mountPoint + '/' + testName ); + QVERIFY( file.open( QIODevice::ReadOnly ) ); + QByteArray outData = file.readAll(); + QCOMPARE( outData.size(), testData.size() ); + QCOMPARE( outData, testData ); + } } } From d48644a49cfb671bd63ecf9908082a08f91c2fdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 11:48:03 +0200 Subject: [PATCH 13/28] Improve prettyName of all jobs, log them in execJobList() --- src/modules/partition/MoveFileSystemJob.cpp | 2 +- src/modules/partition/ResizePartitionJob.cpp | 19 +++++++++---------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/src/modules/partition/MoveFileSystemJob.cpp b/src/modules/partition/MoveFileSystemJob.cpp index bca301cdd..eb1391f57 100644 --- a/src/modules/partition/MoveFileSystemJob.cpp +++ b/src/modules/partition/MoveFileSystemJob.cpp @@ -63,7 +63,7 @@ MoveFileSystemJob::MoveFileSystemJob( Device* device, Partition* partition, qint QString MoveFileSystemJob::prettyName() const { - return tr( "Moving file system of partition %1." ).arg( partition()->partitionPath() ); + return tr( "Move file system of partition %1." ).arg( partition()->partitionPath() ); } Calamares::JobResult diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index 7596f13c4..6b4b18664 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -41,6 +41,7 @@ #include #include +#include // CalaPM #include @@ -80,7 +81,8 @@ public: QString prettyName() const override { - return QString(); + QString path = m_context->job->partition()->partitionPath(); + return tr( "Resize file system on partition %1." ).arg( path ); } Calamares::JobResult exec() override @@ -146,7 +148,8 @@ public: QString prettyName() const override { - return QString(); + QString path = m_context->job->partition()->partitionPath(); + return tr( "Update geometry of partition %1." ).arg( path ); } Calamares::JobResult exec() override @@ -187,14 +190,9 @@ ResizePartitionJob::ResizePartitionJob( Device* device, Partition* partition, qi QString ResizePartitionJob::prettyName() const { - /* - return tr( "Format partition %1 (file system: %2, size: %3 MB) on %4." ) - .arg( m_partition->partitionPath() ) - .arg( m_partition->fileSystem().name() ) - .arg( m_partition->capacity() / 1024 / 1024 ) - .arg( m_device->name() ); - */ - return QString(); + // FIXME: Copy PM ResizeOperation code which generates a description of the + // operation + return tr( "Resize partition %1." ).arg( partition()->partitionPath() ); } Calamares::JobResult @@ -283,6 +281,7 @@ ResizePartitionJob::execJobList( const QList< Calamares::job_ptr >& jobs ) int count = 0; for ( Calamares::job_ptr job : jobs ) { + cLog() << "- " + job->prettyName(); Calamares::JobResult result = job->exec(); if ( !result ) { From f5ccc616b9b9ac70ee04ba87987d1a01bd948a82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 11:49:04 +0200 Subject: [PATCH 14/28] Check file system before resizing: necessary for testResizePartition:shrink to pass --- src/modules/partition/CMakeLists.txt | 1 + src/modules/partition/CheckFileSystemJob.cpp | 56 ++++++++++++++++++++ src/modules/partition/CheckFileSystemJob.h | 33 ++++++++++++ src/modules/partition/ResizePartitionJob.cpp | 2 + src/modules/partition/tests/CMakeLists.txt | 1 + 5 files changed, 93 insertions(+) create mode 100644 src/modules/partition/CheckFileSystemJob.cpp create mode 100644 src/modules/partition/CheckFileSystemJob.h diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 663ba8913..753e8eae6 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -23,6 +23,7 @@ calamares_add_plugin( partition CONFIG_FILE module.conf SOURCES BootLoaderModel.cpp + CheckFileSystemJob.cpp CreatePartitionDialog.cpp CreatePartitionJob.cpp CreatePartitionTableJob.cpp diff --git a/src/modules/partition/CheckFileSystemJob.cpp b/src/modules/partition/CheckFileSystemJob.cpp new file mode 100644 index 000000000..3d353bd7a --- /dev/null +++ b/src/modules/partition/CheckFileSystemJob.cpp @@ -0,0 +1,56 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 + +// CalaPM +#include +#include +#include + +CheckFileSystemJob::CheckFileSystemJob( Partition* partition ) + : PartitionJob( partition ) +{} + +QString +CheckFileSystemJob::prettyName() const +{ + QString path = partition()->partitionPath(); + return tr( "Checking file system on partition %1." ).arg( path ); +} + +Calamares::JobResult +CheckFileSystemJob::exec() +{ + FileSystem& fs = partition()->fileSystem(); + + // if we cannot check, assume everything is fine + if ( fs.supportCheck() != FileSystem::cmdSupportFileSystem ) + return Calamares::JobResult::ok(); + + Report report( nullptr ); + bool ok = fs.check( report, partition()->partitionPath() ); + if ( !ok ) + return Calamares::JobResult::error( + tr( "The file system check on partition %1 failed." ) + .arg( partition()->partitionPath() ), + report.toText() + ); + + return Calamares::JobResult::ok(); +} diff --git a/src/modules/partition/CheckFileSystemJob.h b/src/modules/partition/CheckFileSystemJob.h new file mode 100644 index 000000000..2eb32d2be --- /dev/null +++ b/src/modules/partition/CheckFileSystemJob.h @@ -0,0 +1,33 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 CHECKFILESYSTEMJOB_H +#define CHECKFILESYSTEMJOB_H + +#include + +class CheckFileSystemJob : public PartitionJob +{ +public: + CheckFileSystemJob( Partition* partition ); + + QString prettyName() const override; + Calamares::JobResult exec() override; +}; + +#endif /* CHECKFILESYSTEMJOB_H */ diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index 6b4b18664..d48d4bd25 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -40,6 +40,7 @@ #include +#include #include #include @@ -229,6 +230,7 @@ ResizePartitionJob::exec() // Create jobs QList< Calamares::job_ptr > jobs; + jobs << Calamares::job_ptr( new CheckFileSystemJob( partition() ) ); if ( m_partition->roles().has( PartitionRole::Extended ) ) jobs << Calamares::job_ptr( new SetPartGeometryJob( &context, m_newFirstSector, newLength ) ); else diff --git a/src/modules/partition/tests/CMakeLists.txt b/src/modules/partition/tests/CMakeLists.txt index 65e64af57..8eb8c3fc0 100644 --- a/src/modules/partition/tests/CMakeLists.txt +++ b/src/modules/partition/tests/CMakeLists.txt @@ -2,6 +2,7 @@ find_package( Qt5 COMPONENTS Test REQUIRED ) include( ECMAddTests ) set( jobtests_SRCS + ${PartitionModule_SOURCE_DIR}/CheckFileSystemJob.cpp ${PartitionModule_SOURCE_DIR}/CreatePartitionJob.cpp ${PartitionModule_SOURCE_DIR}/CreatePartitionTableJob.cpp ${PartitionModule_SOURCE_DIR}/DeletePartitionJob.cpp From a267ef856ed727465c87338d64c21ce47115e7cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 11:52:27 +0200 Subject: [PATCH 15/28] Check file system after the resize, like PM does --- src/modules/partition/ResizePartitionJob.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index d48d4bd25..40f467048 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -258,6 +258,7 @@ ResizePartitionJob::exec() jobs << Calamares::job_ptr( new ResizeFileSystemJob( &context, newLength ) ); } } + jobs << Calamares::job_ptr( new CheckFileSystemJob( partition() ) ); return execJobList( jobs ); } From 415ad2c50676d6c02154c4caa73dd5638480c4fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 11:53:23 +0200 Subject: [PATCH 16/28] Fix empty error message --- src/modules/partition/ResizePartitionJob.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/partition/ResizePartitionJob.cpp b/src/modules/partition/ResizePartitionJob.cpp index 40f467048..f9dcdb692 100644 --- a/src/modules/partition/ResizePartitionJob.cpp +++ b/src/modules/partition/ResizePartitionJob.cpp @@ -221,8 +221,11 @@ ResizePartitionJob::exec() QScopedPointer backendDevice( backend->openDevice( m_device->deviceNode() ) ); if ( !backendDevice.data() ) { + QString errorMessage = tr( "The installer failed to resize partition %1 on disk '%2'." ) + .arg( m_partition->partitionPath() ) + .arg( m_device->name() ); return Calamares::JobResult::error( - QString(), + errorMessage, tr( "Could not open device '%1'." ).arg( m_device->deviceNode() ) ); } From 493e368bf08017a8124d9a4122a9fc950a00d0d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 15:08:19 +0200 Subject: [PATCH 17/28] update partitionmanager submodule: Build PartResizerWidget --- src/modules/partition/partitionmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/partitionmanager b/src/modules/partition/partitionmanager index 6892180de..54eb43c62 160000 --- a/src/modules/partition/partitionmanager +++ b/src/modules/partition/partitionmanager @@ -1 +1 @@ -Subproject commit 6892180de21684cd90c50ec2b663dd0caa6bc9f3 +Subproject commit 54eb43c62efef49f08ad862b5e23d93604838b32 From c3efa65668fce65f944cb10e785ff26897d20158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 16:15:34 +0200 Subject: [PATCH 18/28] Make sure all PM filesystem classes are initialized early enough If FileSystemFactory::init() is not called early enough, we won't get access to some information such as the number of used sectors. --- src/modules/partition/CreatePartitionDialog.cpp | 2 -- src/modules/partition/PartitionCoreModule.cpp | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/modules/partition/CreatePartitionDialog.cpp b/src/modules/partition/CreatePartitionDialog.cpp index a717848f5..dc5fd8fee 100644 --- a/src/modules/partition/CreatePartitionDialog.cpp +++ b/src/modules/partition/CreatePartitionDialog.cpp @@ -47,8 +47,6 @@ CreatePartitionDialog::CreatePartitionDialog( Device* device, PartitionNode* par { m_ui->setupUi( this ); - FileSystemFactory::init(); - if ( device->partitionTable()->type() == PartitionTable::msdos ) initMbrPartitionTypeUi(); else diff --git a/src/modules/partition/PartitionCoreModule.cpp b/src/modules/partition/PartitionCoreModule.cpp index 2ad439950..017a8e6b6 100644 --- a/src/modules/partition/PartitionCoreModule.cpp +++ b/src/modules/partition/PartitionCoreModule.cpp @@ -39,6 +39,7 @@ #include #include #include +#include // Qt #include @@ -90,10 +91,9 @@ PartitionCoreModule::PartitionCoreModule( QObject* parent ) , m_deviceModel( new DeviceModel( this ) ) , m_bootLoaderModel( new BootLoaderModel( this ) ) { - // FIXME: Should be done at startup if ( !CalaPM::init() ) qFatal( "Failed to init CalaPM" ); - + FileSystemFactory::init(); init(); } From 55f4231c92cd2a6898e3c718a33bda96934a7491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Wed, 6 Aug 2014 18:31:46 +0200 Subject: [PATCH 19/28] EditExistingPartitionDialog: Visual resizing of partitions --- src/modules/partition/CMakeLists.txt | 1 + .../partition/EditExistingPartitionDialog.cpp | 80 +++++++++++- .../partition/EditExistingPartitionDialog.h | 5 + .../partition/EditExistingPartitionDialog.ui | 74 +++++++---- .../partition/PartitionSizeController.cpp | 115 ++++++++++++++++++ .../partition/PartitionSizeController.h | 57 +++++++++ 6 files changed, 300 insertions(+), 32 deletions(-) create mode 100644 src/modules/partition/PartitionSizeController.cpp create mode 100644 src/modules/partition/PartitionSizeController.h diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 753e8eae6..0b99a9dff 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -40,6 +40,7 @@ calamares_add_plugin( partition PartitionModel.cpp PartitionPage.cpp PartitionPreview.cpp + PartitionSizeController.cpp PartitionSizeWidget.cpp PartitionViewStep.cpp PMUtils.cpp diff --git a/src/modules/partition/EditExistingPartitionDialog.cpp b/src/modules/partition/EditExistingPartitionDialog.cpp index e946fec91..6a991143f 100644 --- a/src/modules/partition/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/EditExistingPartitionDialog.cpp @@ -20,6 +20,7 @@ #include #include +#include #include #include #include @@ -27,6 +28,7 @@ // CalaPM #include #include +#include // Qt #include @@ -36,10 +38,37 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit , m_ui( new Ui_EditExistingPartitionDialog ) , m_device( device ) , m_partition( partition ) + , m_partitionSizeController( new PartitionSizeController( this ) ) { m_ui->setupUi( this ); - m_ui->sizeSpinBox->init( device, partition ); + + // Create a partition for partResizerWidget because it alters the first and + // last sectors when used + FileSystem* fs = FileSystemFactory::create( + m_partition->fileSystem().type(), + m_partition->firstSector(), + m_partition->lastSector() + ); + m_partResizerWidgetPartition.reset( new Partition( + m_partition->parent(), + *m_device, + m_partition->roles(), + fs, fs->firstSector(), fs->lastSector(), + m_partition->partitionPath() + ) + ); + + m_partitionSizeController->init( m_device, m_partResizerWidgetPartition.data() ); + m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox ); + m_ui->mountPointComboBox->setCurrentText( PartitionInfo::mountPoint( partition ) ); + + replacePartResizerWidget(); + + connect( m_ui->formatRadioButton, &QAbstractButton::toggled, [ this ]( bool ) + { + replacePartResizerWidget(); + } ); } EditExistingPartitionDialog::~EditExistingPartitionDialog() @@ -50,9 +79,12 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) { PartitionInfo::setMountPoint( m_partition, m_ui->mountPointComboBox->currentText() ); - if ( m_ui->sizeSpinBox->isDirty() ) + qint64 newFirstSector = m_partResizerWidgetPartition->firstSector(); + qint64 newLastSector = m_partResizerWidgetPartition->lastSector(); + bool partitionChanged = newFirstSector != m_partition->firstSector() || newLastSector != m_partition->lastSector(); + + if ( partitionChanged ) { - PartitionSizeWidget::SectorRange range = m_ui->sizeSpinBox->sectorRange(); if ( m_ui->formatRadioButton->isChecked() ) { Partition* newPartition = PMUtils::createNewPartition( @@ -60,8 +92,8 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) *m_device, m_partition->roles(), m_partition->fileSystem().type(), - range.first, - range.second ); + newFirstSector, + newLastSector ); PartitionInfo::setMountPoint( newPartition, PartitionInfo::mountPoint( m_partition ) ); PartitionInfo::setFormat( newPartition, true ); @@ -69,7 +101,7 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) core->createPartition( m_device, newPartition ); } else - core->resizePartition( m_device, m_partition, range.first, range.second ); + core->resizePartition( m_device, m_partition, newFirstSector, newLastSector ); } else { @@ -80,3 +112,39 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) core->refreshPartition( m_device, m_partition ); } } + +void +EditExistingPartitionDialog::replacePartResizerWidget() +{ + /* + * There is no way to reliably update the partition used by + * PartResizerWidget, which is necessary when we switch between "format" and + * "keep". This is a hack which replaces the existing PartResizerWidget + * with a new one. + */ + + bool format = m_ui->formatRadioButton->isChecked(); + + qint64 used = format ? 0 : m_partition->fileSystem().sectorsUsed(); + m_partResizerWidgetPartition->fileSystem().setSectorsUsed( used ); + + qint64 minFirstSector = m_partition->firstSector() - m_device->partitionTable()->freeSectorsBefore( *m_partition ); + qint64 maxLastSector = m_partition->lastSector() + m_device->partitionTable()->freeSectorsAfter( *m_partition ); + + PartResizerWidget* widget = new PartResizerWidget( this ); + widget->init( *m_device, *m_partResizerWidgetPartition, minFirstSector, maxLastSector ); + + if ( !format ) + { + // If we are not formatting, make sure the space between the first and + // last sectors is big enough to fit the existing content. + widget->updateLastSector( m_partResizerWidgetPartition->lastSector() ); + widget->updateFirstSector( m_partResizerWidgetPartition->firstSector() ); + } + + layout()->replaceWidget( m_ui->partResizerWidget, widget ); + delete m_ui->partResizerWidget; + m_ui->partResizerWidget = widget; + + m_partitionSizeController->setPartResizerWidget( widget ); +} diff --git a/src/modules/partition/EditExistingPartitionDialog.h b/src/modules/partition/EditExistingPartitionDialog.h index 270bbb0e5..779e318d0 100644 --- a/src/modules/partition/EditExistingPartitionDialog.h +++ b/src/modules/partition/EditExistingPartitionDialog.h @@ -25,6 +25,7 @@ class PartitionCoreModule; class Device; class Partition; +class PartitionSizeController; class Ui_EditExistingPartitionDialog; class EditExistingPartitionDialog : public QDialog @@ -40,6 +41,10 @@ private: QScopedPointer< Ui_EditExistingPartitionDialog > m_ui; Device* m_device; Partition* m_partition; + QScopedPointer< Partition > m_partResizerWidgetPartition; + PartitionSizeController* m_partitionSizeController; + + void replacePartResizerWidget(); }; #endif /* EDITEXISTINGPARTITIONDIALOG_H */ diff --git a/src/modules/partition/EditExistingPartitionDialog.ui b/src/modules/partition/EditExistingPartitionDialog.ui index 3cbfeebd7..3618302b3 100644 --- a/src/modules/partition/EditExistingPartitionDialog.ui +++ b/src/modules/partition/EditExistingPartitionDialog.ui @@ -7,11 +7,11 @@ 0 0 350 - 203 + 236 - + 0 0 @@ -20,29 +20,31 @@ Edit Existing Partition + + QLayout::SetMinimumSize + + + + + + 0 + 0 + + + + + 0 + 59 + + + + QFormLayout::ExpandingFieldsGrow - - - - Si&ze: - - - sizeSpinBox - - - - - - - MB - - - - + Content: @@ -52,7 +54,7 @@ - + Keep @@ -62,15 +64,21 @@ - + Format - + + + + 0 + 0 + + Warning: Formatting the partition will erase all existing data. @@ -129,6 +137,19 @@ + + + + Size: + + + sizeSpinBox + + + + + + @@ -145,9 +166,10 @@ - PartitionSizeWidget - QSpinBox -
PartitionSizeWidget.h
+ PartResizerWidget + QWidget +
gui/partresizerwidget.h
+ 1
diff --git a/src/modules/partition/PartitionSizeController.cpp b/src/modules/partition/PartitionSizeController.cpp new file mode 100644 index 000000000..25f25151f --- /dev/null +++ b/src/modules/partition/PartitionSizeController.cpp @@ -0,0 +1,115 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 + +// Qt +#include + +// CalaPM +#include +#include +#include + +// stdc++ +#include + +PartitionSizeController::PartitionSizeController( QObject* parent ) + : QObject( parent ) +{} + +void +PartitionSizeController::setPartResizerWidget( PartResizerWidget* widget ) +{ + if ( m_partResizerWidget ) + disconnect( m_partResizerWidget, 0, this, 0 ); + m_partResizerWidget = widget; + // FIXME: Should be set by PartResizerWidget itself + m_partResizerWidget->setFixedHeight( PartResizerWidget::handleHeight() ); + updateConnections(); +} + +void +PartitionSizeController::setSpinBox( QSpinBox* spinBox ) +{ + if ( m_spinBox ) + disconnect( m_spinBox, 0, this, 0 ); + m_spinBox = spinBox; + m_spinBox->setMaximum( std::numeric_limits< int >::max() ); + updateConnections(); +} + +void +PartitionSizeController::init( Device* device, Partition* partition ) +{ + m_device = device; + m_partition = partition; +} + +void +PartitionSizeController::updateConnections() +{ + if ( !m_spinBox || !m_partResizerWidget ) + return; + + connect( m_spinBox, SIGNAL( editingFinished() ), SLOT( updatePartResizerWidget() ) ); + connect( m_partResizerWidget, SIGNAL( firstSectorChanged( qint64 ) ), SLOT( updateSpinBox() ) ); + connect( m_partResizerWidget, SIGNAL( lastSectorChanged( qint64 ) ), SLOT( updateSpinBox() ) ); + updateSpinBox(); +} + +void +PartitionSizeController::updatePartResizerWidget() +{ + if ( m_updating ) + return; + m_updating = true; + qint64 sectorSize = qint64( m_spinBox->value() ) * 1024 * 1024 / m_device->logicalSectorSize(); + + qint64 firstSector = m_partition->firstSector(); + qint64 lastSector = firstSector + sectorSize - 1; + if ( lastSector > m_partResizerWidget->maximumLastSector() ) + { + qint64 delta = lastSector - m_partResizerWidget->maximumLastSector(); + firstSector -= delta; + lastSector -= delta; + } + m_partResizerWidget->updateLastSector( lastSector ); + m_partResizerWidget->updateFirstSector( firstSector ); + + // Update spinbox value in case it was an impossible value + doUpdateSpinBox(); + m_updating = false; +} + +void +PartitionSizeController::updateSpinBox() +{ + if ( m_updating ) + return; + m_updating = true; + doUpdateSpinBox(); + m_updating = false; +} + +void +PartitionSizeController::doUpdateSpinBox() +{ + qint64 mbSize = ( m_partition->lastSector() - m_partition->firstSector() + 1 ) * m_device->logicalSectorSize() / 1024 / 1024; + m_spinBox->setValue( mbSize ); +} diff --git a/src/modules/partition/PartitionSizeController.h b/src/modules/partition/PartitionSizeController.h new file mode 100644 index 000000000..6b1e0e204 --- /dev/null +++ b/src/modules/partition/PartitionSizeController.h @@ -0,0 +1,57 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 PARTITIONSIZECONTROLLER_H +#define PARTITIONSIZECONTROLLER_H + +#include + +class QSpinBox; + +class Device; +class Partition; +class PartResizerWidget; + +/** + * Synchronize a PartResizerWidget and a QSpinBox + */ +class PartitionSizeController : public QObject +{ + Q_OBJECT +public: + explicit PartitionSizeController( QObject* parent = nullptr ); + void setPartResizerWidget( PartResizerWidget* widget ); + void setSpinBox( QSpinBox* spinBox ); + void init( Device* device, Partition* partition ); + +private: + PartResizerWidget* m_partResizerWidget = nullptr; + QSpinBox* m_spinBox = nullptr; + Device* m_device = nullptr; + Partition* m_partition = nullptr; + bool m_updating = false; + + void updateConnections(); + void doUpdateSpinBox(); + +private Q_SLOTS: + void updatePartResizerWidget(); + void updateSpinBox(); +}; + +#endif /* PARTITIONSIZECONTROLLER_H */ From c109059eb718ef390bc6ff1f821d9d73a950b9ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 12:58:28 +0200 Subject: [PATCH 20/28] Fix crash if widgets are deleted before new ones are set --- src/modules/partition/PartitionSizeController.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/PartitionSizeController.h b/src/modules/partition/PartitionSizeController.h index 6b1e0e204..6c46fccb9 100644 --- a/src/modules/partition/PartitionSizeController.h +++ b/src/modules/partition/PartitionSizeController.h @@ -20,6 +20,7 @@ #define PARTITIONSIZECONTROLLER_H #include +#include class QSpinBox; @@ -40,8 +41,8 @@ public: void init( Device* device, Partition* partition ); private: - PartResizerWidget* m_partResizerWidget = nullptr; - QSpinBox* m_spinBox = nullptr; + QPointer< PartResizerWidget > m_partResizerWidget; + QPointer< QSpinBox > m_spinBox; Device* m_device = nullptr; Partition* m_partition = nullptr; bool m_updating = false; From 38c685dc10c774a95bb114aca0e650b9c667611e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 12:59:24 +0200 Subject: [PATCH 21/28] Move code cloning the partition for PartResizerWidget to PMUtils --- .../partition/EditExistingPartitionDialog.cpp | 14 +------------- src/modules/partition/PMUtils.cpp | 17 +++++++++++++++++ src/modules/partition/PMUtils.h | 1 + 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/modules/partition/EditExistingPartitionDialog.cpp b/src/modules/partition/EditExistingPartitionDialog.cpp index 6a991143f..f80e05108 100644 --- a/src/modules/partition/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/EditExistingPartitionDialog.cpp @@ -44,19 +44,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit // Create a partition for partResizerWidget because it alters the first and // last sectors when used - FileSystem* fs = FileSystemFactory::create( - m_partition->fileSystem().type(), - m_partition->firstSector(), - m_partition->lastSector() - ); - m_partResizerWidgetPartition.reset( new Partition( - m_partition->parent(), - *m_device, - m_partition->roles(), - fs, fs->firstSector(), fs->lastSector(), - m_partition->partitionPath() - ) - ); + m_partResizerWidgetPartition.reset( PMUtils::clonePartition( m_device, m_partition ) ); m_partitionSizeController->init( m_device, m_partResizerWidgetPartition.data() ); m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox ); diff --git a/src/modules/partition/PMUtils.cpp b/src/modules/partition/PMUtils.cpp index 7de100d27..5be9afb00 100644 --- a/src/modules/partition/PMUtils.cpp +++ b/src/modules/partition/PMUtils.cpp @@ -66,4 +66,21 @@ createNewPartition( PartitionNode* parent, const Device& device, const Partition ); } +Partition* +clonePartition( Device* device, Partition* partition ) +{ + FileSystem* fs = FileSystemFactory::create( + partition->fileSystem().type(), + partition->firstSector(), + partition->lastSector() + ); + return new Partition( + partition->parent(), + *device, + partition->roles(), + fs, fs->firstSector(), fs->lastSector(), + partition->partitionPath() + ); +} + } // namespace diff --git a/src/modules/partition/PMUtils.h b/src/modules/partition/PMUtils.h index 23eed5708..b04cef8b0 100644 --- a/src/modules/partition/PMUtils.h +++ b/src/modules/partition/PMUtils.h @@ -40,6 +40,7 @@ Partition* findPartitionByMountPoint( const QList< Device* >& devices, const QSt Partition* createNewPartition( PartitionNode* parent, const Device& device, const PartitionRole& role, FileSystem::Type fsType, qint64 firstSector, qint64 lastSector ); +Partition* clonePartition( Device* device, Partition* partition ); } #endif /* PMUTILS_H */ From 5c9c414988464aad0c631ff14bc7540dff21efa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 13:04:02 +0200 Subject: [PATCH 22/28] Use PartResizerWidget in CreatePartitionDialog --- .../partition/CreatePartitionDialog.cpp | 25 +++++- src/modules/partition/CreatePartitionDialog.h | 3 +- .../partition/CreatePartitionDialog.ui | 76 +++++++++++-------- 3 files changed, 69 insertions(+), 35 deletions(-) diff --git a/src/modules/partition/CreatePartitionDialog.cpp b/src/modules/partition/CreatePartitionDialog.cpp index dc5fd8fee..593ef6558 100644 --- a/src/modules/partition/CreatePartitionDialog.cpp +++ b/src/modules/partition/CreatePartitionDialog.cpp @@ -18,6 +18,7 @@ #include +#include #include #include #include @@ -116,7 +117,8 @@ CreatePartitionDialog::createPartition() ); } - PartitionSizeWidget::SectorRange range = m_ui->sizeSpinBox->sectorRange(); + qint64 first = m_partResizerWidgetPartition->firstSector(); + qint64 last = m_partResizerWidgetPartition->lastSector(); FileSystem::Type fsType = m_role.has( PartitionRole::Extended ) ? FileSystem::Extended @@ -125,7 +127,7 @@ CreatePartitionDialog::createPartition() m_parent, *m_device, m_role, - fsType, range.first, range.second ); + fsType, first, last ); PartitionInfo::setMountPoint( partition, m_ui->mountPointComboBox->currentText() ); PartitionInfo::setFormat( partition, true ); @@ -145,10 +147,25 @@ CreatePartitionDialog::updateMountPointUi() m_ui->mountPointComboBox->setEnabled( enabled ); } +void +CreatePartitionDialog::initPartResizerWidget( Partition* partition ) +{ + PartitionSizeController* controller = new PartitionSizeController( this ); + m_partResizerWidgetPartition.reset( PMUtils::clonePartition( m_device, partition ) ); + + qint64 minFirstSector = partition->firstSector() - m_device->partitionTable()->freeSectorsBefore( *partition ); + qint64 maxLastSector = partition->lastSector() + m_device->partitionTable()->freeSectorsAfter( *partition ); + m_ui->partResizerWidget->init( *m_device, *m_partResizerWidgetPartition, minFirstSector, maxLastSector ); + + controller->init( m_device, m_partResizerWidgetPartition.data() ); + controller->setPartResizerWidget( m_ui->partResizerWidget ); + controller->setSpinBox( m_ui->sizeSpinBox ); +} + void CreatePartitionDialog::initFromFreeSpace( Partition* freeSpacePartition ) { - m_ui->sizeSpinBox->init( m_device, freeSpacePartition ); + initPartResizerWidget( freeSpacePartition ); } void @@ -164,7 +181,7 @@ CreatePartitionDialog::initFromPartitionToCreate( Partition* partition ) return; } - m_ui->sizeSpinBox->init( m_device, partition ); + initPartResizerWidget( partition ); // File System FileSystem::Type fsType = partition->fileSystem().type(); diff --git a/src/modules/partition/CreatePartitionDialog.h b/src/modules/partition/CreatePartitionDialog.h index 289d25c5a..5680637aa 100644 --- a/src/modules/partition/CreatePartitionDialog.h +++ b/src/modules/partition/CreatePartitionDialog.h @@ -49,10 +49,11 @@ private: Device* m_device; PartitionNode* m_parent; PartitionRole m_role = PartitionRole( PartitionRole::None ); + QScopedPointer< Partition > m_partResizerWidgetPartition; void initGptPartitionTypeUi(); void initMbrPartitionTypeUi(); - void initSectorRange( Partition* ); + void initPartResizerWidget( Partition* ); }; #endif /* CREATEPARTITIONDIALOG_H */ diff --git a/src/modules/partition/CreatePartitionDialog.ui b/src/modules/partition/CreatePartitionDialog.ui index c14074c8c..2671ca9a6 100644 --- a/src/modules/partition/CreatePartitionDialog.ui +++ b/src/modules/partition/CreatePartitionDialog.ui @@ -14,9 +14,25 @@ Create a Partition + + + + + 0 + 0 + + + + + 0 + 59 + + + + - + Partition &Type: @@ -26,7 +42,7 @@ - + @@ -67,7 +83,7 @@ - + F&ile System: @@ -77,27 +93,10 @@ - - - - - - - Si&ze: - - - sizeSpinBox - - - - - - MB - - + - + Qt::Vertical @@ -113,7 +112,7 @@ - + &Mount Point: @@ -123,7 +122,7 @@ - + true @@ -163,7 +162,7 @@ - + Qt::Vertical @@ -176,7 +175,7 @@ - + Qt::Vertical @@ -189,6 +188,23 @@ + + + + Si&ze: + + + sizeSpinBox + + + + + + + MB + + + @@ -205,15 +221,15 @@ - PartitionSizeWidget - QSpinBox -
PartitionSizeWidget.h
+ PartResizerWidget + QWidget +
gui/partresizerwidget.h
+ 1
primaryRadioButton fsComboBox - sizeSpinBox From 06e30b829099e9576217cf540b7aa13d95bce51c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 13:05:16 +0200 Subject: [PATCH 23/28] Remove PartitionSizeWidget --- src/modules/partition/CMakeLists.txt | 1 - src/modules/partition/PartitionSizeWidget.cpp | 100 ------------------ src/modules/partition/PartitionSizeWidget.h | 50 --------- 3 files changed, 151 deletions(-) delete mode 100644 src/modules/partition/PartitionSizeWidget.cpp delete mode 100644 src/modules/partition/PartitionSizeWidget.h diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 0b99a9dff..7910f39a4 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -41,7 +41,6 @@ calamares_add_plugin( partition PartitionPage.cpp PartitionPreview.cpp PartitionSizeController.cpp - PartitionSizeWidget.cpp PartitionViewStep.cpp PMUtils.cpp ResizePartitionJob.cpp diff --git a/src/modules/partition/PartitionSizeWidget.cpp b/src/modules/partition/PartitionSizeWidget.cpp deleted file mode 100644 index 485770138..000000000 --- a/src/modules/partition/PartitionSizeWidget.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* === This file is part of Calamares - === - * - * Copyright 2014, Aurélien Gâteau - * - * 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 - -#include - -// CalaPM -#include -#include -#include - -PartitionSizeWidget::PartitionSizeWidget( QWidget* parent ) - : QSpinBox( parent ) -{ -} - -void -PartitionSizeWidget::init( Device* device, Partition* partition ) -{ - m_device = device; - m_partition = partition; - Q_ASSERT( m_device->partitionTable() ); - - qint64 minSector = computeMinSector(); - qint64 maxSector = computeMaxSector(); - cLog() << minSector << maxSector; - setMaximum( mbSizeForSectorRange( minSector, maxSector ) ); - - m_initialValue = mbSizeForSectorRange( partition->firstSector(), partition->lastSector() ); - setValue( m_initialValue ); -} - -PartitionSizeWidget::SectorRange -PartitionSizeWidget::sectorRange() const -{ - qint64 minSector = computeMinSector(); - qint64 maxSector = computeMaxSector(); - - int mbSize = value(); - if ( mbSize == maximum() ) - { - // If we are at the maximum value, select the last sector to avoid - // potential rounding errors which could leave a few sectors at the end - // unused - return SectorRange( minSector, maxSector ); - } - - qint64 lastSector = minSector + qint64( mbSize ) * 1024 * 1024 / m_device->logicalSectorSize(); - Q_ASSERT( lastSector <= maxSector ); - if ( lastSector > maxSector ) - { - cLog() << "lastSector (" << lastSector << ") > maxSector (" << maxSector << "). This should not happen!"; - lastSector = maxSector; - } - return SectorRange( minSector, lastSector ); -} - -bool -PartitionSizeWidget::isDirty() const -{ - return m_initialValue != value(); -} - -qint64 -PartitionSizeWidget::mbSizeForSectorRange( qint64 first, qint64 last ) const -{ - return ( last - first + 1 ) * m_device->logicalSectorSize() / 1024 / 1024; -} - -qint64 -PartitionSizeWidget::computeMaxSector() const -{ - Q_ASSERT( m_device ); - Q_ASSERT( m_partition ); - return m_partition->lastSector() + m_device->partitionTable()->freeSectorsAfter( *m_partition ); -} - -qint64 -PartitionSizeWidget::computeMinSector() const -{ - Q_ASSERT( m_device ); - Q_ASSERT( m_partition ); - return m_partition->firstSector() - m_device->partitionTable()->freeSectorsBefore( *m_partition ); -} diff --git a/src/modules/partition/PartitionSizeWidget.h b/src/modules/partition/PartitionSizeWidget.h deleted file mode 100644 index 028de980d..000000000 --- a/src/modules/partition/PartitionSizeWidget.h +++ /dev/null @@ -1,50 +0,0 @@ -/* === This file is part of Calamares - === - * - * Copyright 2014, Aurélien Gâteau - * - * 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 PARTITIONSIZEWIDGET_H -#define PARTITIONSIZEWIDGET_H - -#include - -class Device; -class Partition; - -class PartitionSizeWidget : public QSpinBox -{ -public: - typedef QPair< qint64, qint64 > SectorRange; - - explicit PartitionSizeWidget( QWidget* parent = nullptr ); - void init( Device* device, Partition* partition ); - - SectorRange sectorRange() const; - - bool isDirty() const; - -private: - Device* m_device = nullptr; - Partition* m_partition = nullptr; - int m_initialValue; - - qint64 mbSizeForSectorRange( qint64 first, qint64 last ) const; - - qint64 computeMinSector() const; - qint64 computeMaxSector() const; -}; - -#endif /* PARTITIONSIZEWIDGET_H */ From cf4416a171a2145b47bdc6469849f0b6152cf8ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 16:13:46 +0200 Subject: [PATCH 24/28] Keep partition color if space is inserted/removed before it --- src/modules/partition/PartitionModel.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/PartitionModel.cpp b/src/modules/partition/PartitionModel.cpp index 6364838ba..f161d0d00 100644 --- a/src/modules/partition/PartitionModel.cpp +++ b/src/modules/partition/PartitionModel.cpp @@ -49,8 +49,20 @@ static QColor colorForPartition( Partition* partition, int row ) return FREE_SPACE_COLOR; if ( partition->roles().has( PartitionRole::Extended ) ) return EXTENDED_COLOR; - // No partition-specific color needed, pick one from our list - return COLORS[ row % 4 ]; + // No partition-specific color needed, pick one from our list, but skip + // free space: we don't want a partition to change colors if space before + // it is inserted or removed + PartitionNode* parent = partition->parent(); + Q_ASSERT( parent ); + int colorIdx = 0; + for ( auto child : parent->children() ) + { + if ( child == partition ) + break; + if ( !PMUtils::isPartitionFreeSpace( child ) ) + ++colorIdx; + } + return COLORS[ colorIdx % 4 ]; } //- ResetHelper -------------------------------------------- From 86481461fdddfc40cc47215b56777f3d65e16d0f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 17:24:39 +0200 Subject: [PATCH 25/28] Move color handling to a separate namespace --- src/modules/partition/CMakeLists.txt | 1 + src/modules/partition/ColorUtils.cpp | 85 ++++++++++++++++++++++++ src/modules/partition/ColorUtils.h | 36 ++++++++++ src/modules/partition/PartitionModel.cpp | 35 +--------- 4 files changed, 124 insertions(+), 33 deletions(-) create mode 100644 src/modules/partition/ColorUtils.cpp create mode 100644 src/modules/partition/ColorUtils.h diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index 7910f39a4..c8aaf8ad9 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -24,6 +24,7 @@ calamares_add_plugin( partition SOURCES BootLoaderModel.cpp CheckFileSystemJob.cpp + ColorUtils.cpp CreatePartitionDialog.cpp CreatePartitionJob.cpp CreatePartitionTableJob.cpp diff --git a/src/modules/partition/ColorUtils.cpp b/src/modules/partition/ColorUtils.cpp new file mode 100644 index 000000000..f9ef94793 --- /dev/null +++ b/src/modules/partition/ColorUtils.cpp @@ -0,0 +1,85 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 + +#include + +// CalaPM +#include + +// Qt +#include + +static QColor COLORS[ 4 ] = +{ + "#448eca", + "#a5cc42", + "#d87e30", + "#ffbdbd", +}; +static QColor FREE_SPACE_COLOR = "#777777"; +static QColor EXTENDED_COLOR = "#aaaaaa"; + + +namespace ColorUtils +{ + +QColor freeSpaceColor() +{ + return FREE_SPACE_COLOR; +} + +QColor colorForPartition( Partition* partition ) +{ + if ( PMUtils::isPartitionFreeSpace( partition ) ) + return FREE_SPACE_COLOR; + if ( partition->roles().has( PartitionRole::Extended ) ) + return EXTENDED_COLOR; + // No partition-specific color needed, pick one from our list, but skip + // free space: we don't want a partition to change colors if space before + // it is inserted or removed + PartitionNode* parent = partition->parent(); + Q_ASSERT( parent ); + int colorIdx = 0; + for ( auto child : parent->children() ) + { + if ( child == partition ) + break; + if ( !PMUtils::isPartitionFreeSpace( child ) ) + ++colorIdx; + } + return COLORS[ colorIdx % 4 ]; +} + +QColor colorForPartitionInFreeSpace( Partition* partition ) +{ + PartitionNode* parent = partition->parent(); + Q_ASSERT( parent ); + int colorIdx = 0; + for ( auto child : parent->children() ) + { + if ( child == partition ) + break; + if ( !PMUtils::isPartitionFreeSpace( child ) ) + ++colorIdx; + } + return COLORS[ colorIdx % 4 ]; +} + +} // namespace diff --git a/src/modules/partition/ColorUtils.h b/src/modules/partition/ColorUtils.h new file mode 100644 index 000000000..b1e79a2dc --- /dev/null +++ b/src/modules/partition/ColorUtils.h @@ -0,0 +1,36 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Aurélien Gâteau + * + * 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 COLORUTILS_H +#define COLORUTILS_H + +class QColor; + +class Partition; + +namespace ColorUtils +{ + +QColor freeSpaceColor(); + +QColor colorForPartition( Partition* partition ); + +QColor colorForPartitionInFreeSpace( Partition* partition ); + +} + +#endif /* COLORUTILS_H */ diff --git a/src/modules/partition/PartitionModel.cpp b/src/modules/partition/PartitionModel.cpp index f161d0d00..3ce3f4df2 100644 --- a/src/modules/partition/PartitionModel.cpp +++ b/src/modules/partition/PartitionModel.cpp @@ -17,6 +17,7 @@ */ #include +#include #include #include #include @@ -33,38 +34,6 @@ // Qt #include -static QColor COLORS[ 4 ] = -{ - "#448eca", - "#a5cc42", - "#d87e30", - "#ffbdbd", -}; -static QColor FREE_SPACE_COLOR = "#777777"; -static QColor EXTENDED_COLOR = "#aaaaaa"; - -static QColor colorForPartition( Partition* partition, int row ) -{ - if ( PMUtils::isPartitionFreeSpace( partition ) ) - return FREE_SPACE_COLOR; - if ( partition->roles().has( PartitionRole::Extended ) ) - return EXTENDED_COLOR; - // No partition-specific color needed, pick one from our list, but skip - // free space: we don't want a partition to change colors if space before - // it is inserted or removed - PartitionNode* parent = partition->parent(); - Q_ASSERT( parent ); - int colorIdx = 0; - for ( auto child : parent->children() ) - { - if ( child == partition ) - break; - if ( !PMUtils::isPartitionFreeSpace( child ) ) - ++colorIdx; - } - return COLORS[ colorIdx % 4 ]; -} - //- ResetHelper -------------------------------------------- PartitionModel::ResetHelper::ResetHelper( PartitionModel* model ) : m_model( model ) @@ -182,7 +151,7 @@ PartitionModel::data( const QModelIndex& index, int role ) const } case Qt::DecorationRole: if ( index.column() == NameColumn ) - return colorForPartition( partition, index.row() ); + return ColorUtils::colorForPartition( partition ); else return QVariant(); case SizeRole: From 055904b20a3f5392bf8afa61860075db18d73f3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 17:25:45 +0200 Subject: [PATCH 26/28] Coding style --- src/modules/partition/PMUtils.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/modules/partition/PMUtils.cpp b/src/modules/partition/PMUtils.cpp index 5be9afb00..10cfb8911 100644 --- a/src/modules/partition/PMUtils.cpp +++ b/src/modules/partition/PMUtils.cpp @@ -75,12 +75,12 @@ clonePartition( Device* device, Partition* partition ) partition->lastSector() ); return new Partition( - partition->parent(), - *device, - partition->roles(), - fs, fs->firstSector(), fs->lastSector(), - partition->partitionPath() - ); + partition->parent(), + *device, + partition->roles(), + fs, fs->firstSector(), fs->lastSector(), + partition->partitionPath() + ); } } // namespace From 310fdc56d991b67196f7c839b267bb0a06a503f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 17:26:26 +0200 Subject: [PATCH 27/28] Set proper colors in PartResizeWidget --- src/modules/partition/CreatePartitionDialog.cpp | 8 ++++++-- src/modules/partition/EditExistingPartitionDialog.cpp | 4 +++- src/modules/partition/PartitionSizeController.cpp | 10 +++++++++- src/modules/partition/PartitionSizeController.h | 4 +++- 4 files changed, 21 insertions(+), 5 deletions(-) diff --git a/src/modules/partition/CreatePartitionDialog.cpp b/src/modules/partition/CreatePartitionDialog.cpp index 593ef6558..06d12827e 100644 --- a/src/modules/partition/CreatePartitionDialog.cpp +++ b/src/modules/partition/CreatePartitionDialog.cpp @@ -18,8 +18,9 @@ #include -#include +#include #include +#include #include #include #include @@ -157,7 +158,10 @@ CreatePartitionDialog::initPartResizerWidget( Partition* partition ) qint64 maxLastSector = partition->lastSector() + m_device->partitionTable()->freeSectorsAfter( *partition ); m_ui->partResizerWidget->init( *m_device, *m_partResizerWidgetPartition, minFirstSector, maxLastSector ); - controller->init( m_device, m_partResizerWidgetPartition.data() ); + QColor color = PMUtils::isPartitionFreeSpace( partition ) + ? ColorUtils::colorForPartitionInFreeSpace( partition ) + : ColorUtils::colorForPartition( partition ); + controller->init( m_device, m_partResizerWidgetPartition.data(), color ); controller->setPartResizerWidget( m_ui->partResizerWidget ); controller->setSpinBox( m_ui->sizeSpinBox ); } diff --git a/src/modules/partition/EditExistingPartitionDialog.cpp b/src/modules/partition/EditExistingPartitionDialog.cpp index f80e05108..3d20e9793 100644 --- a/src/modules/partition/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/EditExistingPartitionDialog.cpp @@ -18,6 +18,7 @@ #include +#include #include #include #include @@ -46,7 +47,8 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, Partit // last sectors when used m_partResizerWidgetPartition.reset( PMUtils::clonePartition( m_device, m_partition ) ); - m_partitionSizeController->init( m_device, m_partResizerWidgetPartition.data() ); + QColor color = ColorUtils::colorForPartition( m_partition ); + m_partitionSizeController->init( m_device, m_partResizerWidgetPartition.data(), color ); m_partitionSizeController->setSpinBox( m_ui->sizeSpinBox ); m_ui->mountPointComboBox->setCurrentText( PartitionInfo::mountPoint( partition ) ); diff --git a/src/modules/partition/PartitionSizeController.cpp b/src/modules/partition/PartitionSizeController.cpp index 25f25151f..4fa4dc3e0 100644 --- a/src/modules/partition/PartitionSizeController.cpp +++ b/src/modules/partition/PartitionSizeController.cpp @@ -18,6 +18,8 @@ #include +#include + // Qt #include @@ -41,6 +43,11 @@ PartitionSizeController::setPartResizerWidget( PartResizerWidget* widget ) m_partResizerWidget = widget; // FIXME: Should be set by PartResizerWidget itself m_partResizerWidget->setFixedHeight( PartResizerWidget::handleHeight() ); + + QPalette pal = widget->palette(); + pal.setColor( QPalette::Base, ColorUtils::freeSpaceColor() ); + pal.setColor( QPalette::Button, m_partitionColor ); + m_partResizerWidget->setPalette( pal ); updateConnections(); } @@ -55,10 +62,11 @@ PartitionSizeController::setSpinBox( QSpinBox* spinBox ) } void -PartitionSizeController::init( Device* device, Partition* partition ) +PartitionSizeController::init( Device* device, Partition* partition, const QColor& color ) { m_device = device; m_partition = partition; + m_partitionColor = color; } void diff --git a/src/modules/partition/PartitionSizeController.h b/src/modules/partition/PartitionSizeController.h index 6c46fccb9..0ed4c4a2d 100644 --- a/src/modules/partition/PartitionSizeController.h +++ b/src/modules/partition/PartitionSizeController.h @@ -19,6 +19,7 @@ #ifndef PARTITIONSIZECONTROLLER_H #define PARTITIONSIZECONTROLLER_H +#include #include #include @@ -38,13 +39,14 @@ public: explicit PartitionSizeController( QObject* parent = nullptr ); void setPartResizerWidget( PartResizerWidget* widget ); void setSpinBox( QSpinBox* spinBox ); - void init( Device* device, Partition* partition ); + void init( Device* device, Partition* partition, const QColor& color ); private: QPointer< PartResizerWidget > m_partResizerWidget; QPointer< QSpinBox > m_spinBox; Device* m_device = nullptr; Partition* m_partition = nullptr; + QColor m_partitionColor; bool m_updating = false; void updateConnections(); From 9b30e27f5e777bf19f55e75d25325c225ed56283 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aur=C3=A9lien=20G=C3=A2teau?= Date: Thu, 7 Aug 2014 17:30:07 +0200 Subject: [PATCH 28/28] update partitionmanager submodule: Nicer rendering of PartResizerWidget --- src/modules/partition/partitionmanager | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/partitionmanager b/src/modules/partition/partitionmanager index 54eb43c62..8726fc2b3 160000 --- a/src/modules/partition/partitionmanager +++ b/src/modules/partition/partitionmanager @@ -1 +1 @@ -Subproject commit 54eb43c62efef49f08ad862b5e23d93604838b32 +Subproject commit 8726fc2b3f2a703b9a72cf76038be1bab22d8a3f