From e7995ad54012ce695165aa7502a5405f9567a62b Mon Sep 17 00:00:00 2001 From: Teo Mrnjavac Date: Tue, 23 Sep 2014 17:42:11 +0200 Subject: [PATCH] Improve Osprober logic to immediately check if entries are resizable. --- src/modules/partition/gui/AlongsidePage.cpp | 5 +- src/modules/partition/gui/AlongsidePage.h | 4 +- src/modules/partition/gui/ChoicePage.cpp | 177 +++++------------- src/modules/partition/gui/ChoicePage.h | 7 +- src/modules/partition/gui/OsproberEntry.h | 34 ++++ .../partition/gui/PartitionViewStep.cpp | 85 ++++++++- src/modules/partition/gui/PartitionViewStep.h | 2 + 7 files changed, 177 insertions(+), 137 deletions(-) create mode 100644 src/modules/partition/gui/OsproberEntry.h diff --git a/src/modules/partition/gui/AlongsidePage.cpp b/src/modules/partition/gui/AlongsidePage.cpp index aab68d2c3..3e940349d 100644 --- a/src/modules/partition/gui/AlongsidePage.cpp +++ b/src/modules/partition/gui/AlongsidePage.cpp @@ -32,10 +32,9 @@ AlongsidePage::AlongsidePage( QWidget* parent ) void -AlongsidePage::init( PartitionCoreModule* core , const QStringList& osproberLines ) +AlongsidePage::init( PartitionCoreModule* core , const OsproberEntryList& osproberEntries ) { - QLabel* placeholder = new QLabel( "Alongside partitioning goes here.\nOsprober:\n" + - osproberLines.join( '\n' ) ); + QLabel* placeholder = new QLabel( "Alongside partitioning goes here." ); layout()->addWidget( placeholder ); } diff --git a/src/modules/partition/gui/AlongsidePage.h b/src/modules/partition/gui/AlongsidePage.h index e1306f961..67e8e5352 100644 --- a/src/modules/partition/gui/AlongsidePage.h +++ b/src/modules/partition/gui/AlongsidePage.h @@ -21,6 +21,8 @@ #include +#include "OsproberEntry.h" + class PartitionCoreModule; class AlongsidePage : public QWidget @@ -29,7 +31,7 @@ class AlongsidePage : public QWidget public: explicit AlongsidePage( QWidget* parent = nullptr ); - void init( PartitionCoreModule* core, const QStringList& osproberLines ); + void init( PartitionCoreModule* core, const OsproberEntryList& osproberEntries ); bool isNextEnabled() const; diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index bf048b2cf..67617e8a7 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -21,11 +21,8 @@ #include "core/PartitionCoreModule.h" #include "core/DeviceModel.h" #include "core/PartitionModel.h" -#include "core/partition.h" -#include "core/device.h" +#include "OsproberEntry.h" -#include "JobQueue.h" -#include "GlobalStorage.h" #include "PrettyRadioButton.h" #include "utils/CalamaresUtilsGui.h" @@ -61,10 +58,9 @@ ChoicePage::~ChoicePage() void -ChoicePage::init( PartitionCoreModule* core, const QStringList& osproberLines ) +ChoicePage::init( PartitionCoreModule* core, const OsproberEntryList& osproberEntries ) { m_core = core; - m_osproberLines = osproberLines; // sample os-prober output: // /dev/sda2:Windows 7 (loader):Windows:chain @@ -103,9 +99,7 @@ ChoicePage::init( PartitionCoreModule* core, const QStringList& osproberLines ) m_itemsLayout->addWidget( eraseButton ); m_itemsLayout->setSpacing( CalamaresUtils::defaultFontHeight() / 2 ); - cDebug() << "Osprober lines, clean:\n" << m_osproberLines.join( '\n' ); - - if ( m_osproberLines.count() == 0 ) + if ( osproberEntries.count() == 0 ) { m_messageLabel->setText( tr( "This computer currently does not seem to have an operating system on it. " "What would you like to do?" ) ); @@ -117,56 +111,47 @@ ChoicePage::init( PartitionCoreModule* core, const QStringList& osproberLines ) alongsideButton->hide(); } - else if ( m_osproberLines.count() == 1 ) + else if ( osproberEntries.count() == 1 ) { - QStringList osLine = m_osproberLines.first().split( ':' ); - QString osName; - if ( !osLine.value( 1 ).simplified().isEmpty() ) - osName = osLine.value( 1 ).simplified(); - else if ( !osLine.value( 2 ).simplified().isEmpty() ) - osName = osLine.value( 2 ).simplified(); - - if ( canBeResized( osLine ) ) + QString osName = osproberEntries.first().prettyName; + + if ( !osName.isEmpty() ) { + m_messageLabel->setText( tr( "This computer currently has %1 on it. " + "What would you like to do?" ) + .arg( osName ) ); - if ( !osName.isEmpty() ) - { - m_messageLabel->setText( tr( "This computer currently has %1 on it. " - "What would you like to do?" ) - .arg( osName ) ); - - alongsideButton->setText( tr( "Install %2 alongside %1
" - "Documents, music and other personal files will be kept. " - "You can choose which operating system you want each time the " - "computer starts up." ) - .arg( osName ) - .arg( "$RELEASE" ) ); - - eraseButton->setText( tr( "Replace %1 with %2
" - "Warning: This will erase the whole disk and " - "delete all of your %1 programs, " - "documents, photos, music, and any other files." ) + alongsideButton->setText( tr( "Install %2 alongside %1
" + "Documents, music and other personal files will be kept. " + "You can choose which operating system you want each time the " + "computer starts up." ) .arg( osName ) .arg( "$RELEASE" ) ); - } - else - { - m_messageLabel->setText( tr( "This computer already has an operating system on it. " - "What would you like to do?" ) ); - - alongsideButton->setText( tr( "Install %1 alongside your current operating system
" - "Documents, music and other personal files will be kept. " - "You can choose which operating system you want each time the " - "computer starts up." ) - .arg( "$RELEASE" ) ); - - eraseButton->setText( tr( "Erase disk and install %1
" - "Warning: This will delete all of your Windows 7 programs, " - "documents, photos, music, and any other files." ) - .arg( "$RELEASE" ) ); - } + + eraseButton->setText( tr( "Replace %1 with %2
" + "Warning: This will erase the whole disk and " + "delete all of your %1 programs, " + "documents, photos, music, and any other files." ) + .arg( osName ) + .arg( "$RELEASE" ) ); } else + { + m_messageLabel->setText( tr( "This computer already has an operating system on it. " + "What would you like to do?" ) ); + + alongsideButton->setText( tr( "Install %1 alongside your current operating system
" + "Documents, music and other personal files will be kept. " + "You can choose which operating system you want each time the " + "computer starts up." ) + .arg( "$RELEASE" ) ); + + eraseButton->setText( tr( "Erase disk and install %1
" + "Warning: This will delete all of your Windows 7 programs, " + "documents, photos, music, and any other files." ) + .arg( "$RELEASE" ) ); + } + if ( !osproberEntries.first().canBeResized ) alongsideButton->hide(); } else @@ -175,33 +160,30 @@ ChoicePage::init( PartitionCoreModule* core, const QStringList& osproberLines ) bool atLeastOneCanBeResized = false; - foreach ( QString line, m_osproberLines ) + foreach ( const OsproberEntry& entry, osproberEntries ) { - QStringList osLine = line.split( ':' ); - if ( canBeResized( osLine ) ) + if ( entry.canBeResized ) { atLeastOneCanBeResized = true; break; } } - if ( atLeastOneCanBeResized ) - { - m_messageLabel->setText( tr( "This computer currently has multiple operating systems on it. " - "What would you like to do?" ) ); - - alongsideButton->setText( tr( "Install %1 alongside your current operating systems
" - "Documents, music and other personal files will be kept. " - "You can choose which operating system you want each time the " - "computer starts up." ) - .arg( "$RELEASE" ) ); + m_messageLabel->setText( tr( "This computer currently has multiple operating systems on it. " + "What would you like to do?" ) ); - eraseButton->setText( tr( "Erase disk and install %1
" - "Warning: This will delete all of your Windows 7 programs, " - "documents, photos, music, and any other files." ) + alongsideButton->setText( tr( "Install %1 alongside your current operating systems
" + "Documents, music and other personal files will be kept. " + "You can choose which operating system you want each time the " + "computer starts up." ) .arg( "$RELEASE" ) ); - } - else + + eraseButton->setText( tr( "Erase disk and install %1
" + "Warning: This will delete all of your Windows 7 programs, " + "documents, photos, music, and any other files." ) + .arg( "$RELEASE" ) ); + + if ( !atLeastOneCanBeResized ) alongsideButton->hide(); } @@ -272,58 +254,3 @@ ChoicePage::setNextEnabled( bool enabled ) emit nextStatusChanged( enabled ); } - -bool -ChoicePage::canBeResized( const QStringList& osproberLine ) -{ - cDebug() << "checking if" << osproberLine << "can be resized."; - QString partitionWithOs = osproberLine.value( 0 ).simplified(); - if ( partitionWithOs.startsWith( "/dev/" ) ) - { - cDebug() << partitionWithOs << "seems like a good path"; - bool canResize = false; - DeviceModel* dm = m_core->deviceModel(); - for ( int i = 0; i < dm->rowCount(); ++i ) - { - Device* dev = dm->deviceForIndex( dm->index( i ) ); - PartitionModel* pm = m_core->partitionModelForDevice( dev ); - for ( int j = 0; j < pm->rowCount(); ++j ) - { - QModelIndex index = pm->index( j, 0 ); - Partition* candidate = pm->partitionForIndex( index ); - if ( candidate->partitionPath() == partitionWithOs ) - { - cDebug() << "found Partition* for" << partitionWithOs; - bool ok = false; - double requiredStorageGB = Calamares::JobQueue::instance() - ->globalStorage() - ->value( "requiredStorageGB" ) - .toDouble( &ok ); - - qint64 availableStorageB = candidate->available() * dev->logicalSectorSize(); - - // We require a little more for partitioning overhead and swap file - // TODO: maybe make this configurable? - qint64 requiredStorageB = ( requiredStorageGB + 0.1 + 2.0 ) * 1024 * 1024 * 1024; - cDebug() << "Required storage B:" << requiredStorageB; - cDebug() << "Available storage B:" << availableStorageB; - if ( ok && - availableStorageB > requiredStorageB ) - { - canResize = true; - } - } - if ( canResize ) - break; - } - if ( canResize ) - break; - } - - cDebug() << "Partition" << osproberLine << "authorized for resize + autopartition install."; - return canResize; - } - - cDebug() << "Partition" << osproberLine << "CANNOT BE RESIZED FOR AUTOINSTALL."; - return false; -} diff --git a/src/modules/partition/gui/ChoicePage.h b/src/modules/partition/gui/ChoicePage.h index 19a1d6d2a..af758ed4e 100644 --- a/src/modules/partition/gui/ChoicePage.h +++ b/src/modules/partition/gui/ChoicePage.h @@ -21,6 +21,8 @@ #include +#include "OsproberEntry.h" + class QBoxLayout; class QLabel; @@ -41,7 +43,7 @@ public: explicit ChoicePage( QWidget* parent = nullptr ); virtual ~ChoicePage(); - void init( PartitionCoreModule* core, const QStringList& osproberLines ); + void init( PartitionCoreModule* core, const OsproberEntryList& osproberEntries ); bool isNextEnabled(); @@ -53,14 +55,11 @@ signals: private: void setNextEnabled( bool enabled ); - bool canBeResized( const QStringList& osproberLine ); - bool m_nextEnabled; PartitionCoreModule* m_core; QBoxLayout* m_itemsLayout; QLabel* m_messageLabel; - QStringList m_osproberLines; Choice m_choice; }; diff --git a/src/modules/partition/gui/OsproberEntry.h b/src/modules/partition/gui/OsproberEntry.h new file mode 100644 index 000000000..58e7bc9d7 --- /dev/null +++ b/src/modules/partition/gui/OsproberEntry.h @@ -0,0 +1,34 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014, Teo Mrnjavac + * + * 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 OSPROBERENTRY_H +#define OSPROBERENTRY_H + +#include + +struct OsproberEntry +{ + QString prettyName; + QString path; + bool canBeResized; + QStringList line; +}; + +typedef QList< OsproberEntry > OsproberEntryList; + +#endif // OSPROBERENTRY_H diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 558472a34..3ee7b68f8 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -21,16 +21,21 @@ #include #include #include +#include "core/partition.h" +#include "core/device.h" #include #include #include #include #include +#include "OsproberEntry.h" #include "CalamaresVersion.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" #include "widgets/WaitingWidget.h" +#include "GlobalStorage.h" +#include "JobQueue.h" // Qt #include @@ -79,16 +84,32 @@ PartitionViewStep::PartitionViewStep( QObject* parent ) osprober.readAllStandardOutput() ).trimmed() ); } - QStringList osproberLines; + QString osProberReport( "Osprober lines, clean:\n" ); + OsproberEntryList osproberEntries; foreach ( const QString& line, osproberOutput.split( '\n' ) ) { if ( !line.simplified().isEmpty() ) - osproberLines.append( line ); + { + QStringList lineColumns = line.split( ':' ); + QString prettyName; + if ( !lineColumns.value( 1 ).simplified().isEmpty() ) + prettyName = lineColumns.value( 1 ).simplified(); + else if ( !lineColumns.value( 2 ).simplified().isEmpty() ) + prettyName = lineColumns.value( 2 ).simplified(); + + QString path = lineColumns.value( 0 ).simplified(); + if ( !path.startsWith( "/dev/" ) ) //basic sanity check + continue; + + osproberEntries.append( { prettyName, path, canBeResized( path ), lineColumns } ); + osProberReport.append( line ); + } } + cDebug() << osProberReport; - m_choicePage->init( m_core, osproberLines ); + m_choicePage->init( m_core, osproberEntries ); m_erasePage->init( m_core ); - m_alongsidePage->init( m_core, osproberLines ); + m_alongsidePage->init( m_core, osproberEntries ); m_widget->addWidget( m_choicePage ); m_widget->addWidget( m_manualPartitionPage ); @@ -239,3 +260,59 @@ PartitionViewStep::jobs() const { return m_core->jobs(); } + + +bool +PartitionViewStep::canBeResized( const QString& partitionPath ) +{ + cDebug() << "checking if" << partitionPath << "can be resized."; + QString partitionWithOs = partitionPath; + if ( partitionWithOs.startsWith( "/dev/" ) ) + { + cDebug() << partitionWithOs << "seems like a good path"; + bool canResize = false; + DeviceModel* dm = m_core->deviceModel(); + for ( int i = 0; i < dm->rowCount(); ++i ) + { + Device* dev = dm->deviceForIndex( dm->index( i ) ); + PartitionModel* pm = m_core->partitionModelForDevice( dev ); + for ( int j = 0; j < pm->rowCount(); ++j ) + { + QModelIndex index = pm->index( j, 0 ); + Partition* candidate = pm->partitionForIndex( index ); + if ( candidate->partitionPath() == partitionWithOs ) + { + cDebug() << "found Partition* for" << partitionWithOs; + bool ok = false; + double requiredStorageGB = Calamares::JobQueue::instance() + ->globalStorage() + ->value( "requiredStorageGB" ) + .toDouble( &ok ); + + qint64 availableStorageB = candidate->available() * dev->logicalSectorSize(); + + // We require a little more for partitioning overhead and swap file + // TODO: maybe make this configurable? + qint64 requiredStorageB = ( requiredStorageGB + 0.1 + 2.0 ) * 1024 * 1024 * 1024; + cDebug() << "Required storage B:" << requiredStorageB; + cDebug() << "Available storage B:" << availableStorageB; + if ( ok && + availableStorageB > requiredStorageB ) + { + canResize = true; + } + } + if ( canResize ) + break; + } + if ( canResize ) + break; + } + + cDebug() << "Partition" << partitionWithOs << "authorized for resize + autopartition install."; + return canResize; + } + + cDebug() << "Partition" << partitionWithOs << "CANNOT BE RESIZED FOR AUTOINSTALL."; + return false; +} diff --git a/src/modules/partition/gui/PartitionViewStep.h b/src/modules/partition/gui/PartitionViewStep.h index 2749c758c..dc2ed9e1d 100644 --- a/src/modules/partition/gui/PartitionViewStep.h +++ b/src/modules/partition/gui/PartitionViewStep.h @@ -61,6 +61,8 @@ public: QList< Calamares::job_ptr > jobs() const override; private: + bool canBeResized( const QString& partitionPath ); + PartitionCoreModule* m_core; QStackedWidget* m_widget; ChoicePage* m_choicePage;