From 8917d153dac5de60822f31da66971c2cdff2e324 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 27 Sep 2017 05:34:06 -0400 Subject: [PATCH 01/89] Drop the (inter-)module dependencies system. - Was marked incomplete and unused; none of the existing modules set any requirements, and the descriptors are not set up to hold the requirements information anyway. - Dependencies are generally through globalStorage values, or if there are dependent jobs they should be created in-order by one source (e.g. though a View or a subclass of CppJob which overrides jobs() ). - It is the responsibility of deployers to formulate a settings.conf that includes all the required modules. - A 'real' dependency system is going to lead to the introduction of interface-definitions and a great deal of complexity, for a use case that can be handled with careful deployment instead. --- src/libcalamaresui/modulesystem/Module.cpp | 7 ---- src/libcalamaresui/modulesystem/Module.h | 9 +---- .../modulesystem/ModuleManager.cpp | 36 +------------------ .../modulesystem/ModuleManager.h | 2 -- 4 files changed, 2 insertions(+), 52 deletions(-) diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index 96ec0cceb..7af5dbb75 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -233,13 +233,6 @@ Module::instanceKey() const } -QStringList -Module::requiredModules() const -{ - return m_requiredModules; -} - - QString Module::location() const { diff --git a/src/libcalamaresui/modulesystem/Module.h b/src/libcalamaresui/modulesystem/Module.h index 5f756938f..b32d14a8e 100644 --- a/src/libcalamaresui/modulesystem/Module.h +++ b/src/libcalamaresui/modulesystem/Module.h @@ -106,13 +106,6 @@ public: */ virtual QString instanceKey() const final; - /** - * @brief requiredModules a list of names of modules required by this one. - * @return the list of names. - * The module dependencies system is currently incomplete and unused. - */ - virtual QStringList requiredModules() const; - /** * @brief location returns the full path of this module's directory. * @return the path. @@ -176,8 +169,8 @@ protected: private: void loadConfigurationFile( const QString& configFileName ); //throws YAML::Exception + QString m_name; - QStringList m_requiredModules; QString m_directory; QString m_instanceId; diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 44eed30f0..f5eed42b0 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -150,9 +150,6 @@ ModuleManager::doInit() cDebug() << "ModuleManager bad search path" << path; } } - // At this point m_availableModules is filled with whatever was found in the - // search paths. - checkDependencies(); emit initDone(); } @@ -318,35 +315,4 @@ ModuleManager::loadModules() } ); } - -void -ModuleManager::checkDependencies() -{ - // This goes through the map of available modules, and deletes those whose - // dependencies are not met, if any. - bool somethingWasRemovedBecauseOfUnmetDependencies = false; - forever - { - for ( auto it = m_availableDescriptorsByModuleName.begin(); - it != m_availableDescriptorsByModuleName.end(); ++it ) - { - foreach ( const QString& depName, - (*it).value( "requiredModules" ).toStringList() ) - { - if ( !m_availableDescriptorsByModuleName.contains( depName ) ) - { - somethingWasRemovedBecauseOfUnmetDependencies = true; - m_availableDescriptorsByModuleName.erase( it ); - break; - } - } - if ( somethingWasRemovedBecauseOfUnmetDependencies ) - break; - } - if ( !somethingWasRemovedBecauseOfUnmetDependencies ) - break; - } -} - - -} +} // namespace diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index 05ad15178..daa988064 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -88,8 +88,6 @@ private slots: void doInit(); private: - void checkDependencies(); - QMap< QString, QVariantMap > m_availableDescriptorsByModuleName; QMap< QString, QString > m_moduleDirectoriesByModuleName; QMap< QString, Module* > m_loadedModulesByInstanceKey; From d63f8f692210f16d1db5e3211364d2396abe58fc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 29 Nov 2017 09:46:15 -0500 Subject: [PATCH 02/89] [welcome] Document welcome.conf - explain requirements keys - document show-buttons keys --- src/modules/welcome/welcome.conf | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index 18e71b1ef..eef03bf89 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -1,18 +1,37 @@ +# Configuration for the welcome module. The welcome page +# displays some information from the branding file. +# Which parts it displays can be configured through +# the show* variables. +# +# In addition to displaying the welcome page, this module +# can check requirements for installation. --- +# Display settings for various buttons on the welcome page. showSupportUrl: true showKnownIssuesUrl: true showReleaseNotesUrl: true +# Requirements checking. These are general, generic, things +# that are checked. They may not match with the actual requirements +# imposed by other modules in the system. requirements: + # Amount of available disk, in GB. Floating-point is allowed here. + # Note that this does not account for *usable* disk, so it is possible + # to pass this requirement, yet have no space to install to. requiredStorage: 5.5 + + # Amount of available RAM, in GB. Floating-point is allowed here. requiredRam: 1.0 + + # To check for internet connectivity, Calamares does a HTTP GET + # on this URL; on success (e.g. HTTP code 200) internet is OK. internetCheckUrl: http://google.com # List conditions to check. Each listed condition will be # probed in some way, and yields true or false according to # the host system satisfying the condition. # - # This sample file lists all the conditions that are know. + # This sample file lists all the conditions that are known. check: - storage - ram @@ -20,7 +39,7 @@ requirements: - internet - root - screen - # List conditions that must be satisfied (from the list + # List conditions that **must** be satisfied (from the list # of conditions, above) for installation to proceed. # If any of these conditions are not met, the user cannot # continue past the welcome page. From 24e04645b688fc76052aac08fdfb0469ade46014 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 30 Nov 2017 12:01:11 -0500 Subject: [PATCH 03/89] [libcalamaresui] Stub requirements checking. Introduce a method checkRequirements() into the module system so that individual modules can do their own checking (as opposed to stuffing it all into the welcome module). --- src/calamares/CalamaresApplication.cpp | 1 + src/libcalamaresui/modulesystem/Module.cpp | 5 +++++ src/libcalamaresui/modulesystem/Module.h | 6 ++++++ src/libcalamaresui/modulesystem/ModuleManager.cpp | 14 ++++++++++++++ src/libcalamaresui/modulesystem/ModuleManager.h | 7 +++++++ 5 files changed, 33 insertions(+) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index caba96f5d..58190fae5 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -355,6 +355,7 @@ void CalamaresApplication::initViewSteps() { cDebug() << "STARTUP: loadModules for all modules done"; + m_moduleManager->checkRequirements(); m_mainwindow->show(); ProgressTreeModel* m = new ProgressTreeModel( nullptr ); ProgressTreeView::instance()->setModel( m ); diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index 7af5dbb75..0af30e08e 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -297,4 +297,9 @@ Module::initFrom( const QVariantMap& moduleDescriptor ) m_name = moduleDescriptor.value( "name" ).toString(); } +void +Module::checkRequirements() +{ +} + } //ns diff --git a/src/libcalamaresui/modulesystem/Module.h b/src/libcalamaresui/modulesystem/Module.h index 4da904dae..294b516e2 100644 --- a/src/libcalamaresui/modulesystem/Module.h +++ b/src/libcalamaresui/modulesystem/Module.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2017, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -161,6 +162,11 @@ public: */ QVariantMap configurationMap(); + /** + * @brief Check the requirements of this module. + */ + virtual void checkRequirements(); + protected: explicit Module(); virtual void initFrom( const QVariantMap& moduleDescriptor ); diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index f5eed42b0..573cfa915 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -315,4 +315,18 @@ ModuleManager::loadModules() } ); } +void +ModuleManager::checkRequirements() +{ + QTimer::singleShot( 0, this, [ this ]() + { + for (const auto& module : m_loadedModulesByInstanceKey ) + { + module->checkRequirements(); + } + + emit modulesChecked(); + } ); +} + } // namespace diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index daa988064..9444b96f3 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -80,9 +80,16 @@ public: */ void loadModules(); + /** + * @brief Starts asynchronous requirements checking for each module. + * When this is done, the signal modulesChecked is emitted. + */ + void checkRequirements(); + signals: void initDone(); void modulesLoaded(); + void modulesChecked(); private slots: void doInit(); From 27b921bde17c63919dd7be86c218f9362547c814 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 30 Nov 2017 12:42:59 -0500 Subject: [PATCH 04/89] [libcalamaresui] Move requirements information out of welcome module. - Move type and rename it; put in Calamares namespace - Emit signals from the viewmanager as results come in - Remove state changing from welcome view step based on its internal requirements checking (for now this breaks progressing past the welcome page) - Log checking of the requirements --- src/libcalamaresui/CMakeLists.txt | 1 + src/libcalamaresui/modulesystem/Module.cpp | 3 +- src/libcalamaresui/modulesystem/Module.h | 3 +- .../modulesystem/ModuleManager.cpp | 17 +++++- .../modulesystem/ModuleManager.h | 5 +- .../modulesystem/Requirement.cpp | 19 +++++++ src/libcalamaresui/modulesystem/Requirement.h | 52 +++++++++++++++++++ src/modules/welcome/WelcomeViewStep.cpp | 2 - src/modules/welcome/checker/CheckerWidget.cpp | 8 +-- src/modules/welcome/checker/CheckerWidget.h | 5 +- .../welcome/checker/RequirementsChecker.cpp | 6 ++- .../welcome/checker/RequirementsChecker.h | 22 -------- 12 files changed, 106 insertions(+), 37 deletions(-) create mode 100644 src/libcalamaresui/modulesystem/Requirement.cpp create mode 100644 src/libcalamaresui/modulesystem/Requirement.h diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 7c3e8fca2..335dc712a 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -5,6 +5,7 @@ set( calamaresui_SOURCES modulesystem/Module.cpp modulesystem/ModuleManager.cpp modulesystem/ProcessJobModule.cpp + modulesystem/Requirement.cpp modulesystem/ViewModule.cpp utils/CalamaresUtilsGui.cpp diff --git a/src/libcalamaresui/modulesystem/Module.cpp b/src/libcalamaresui/modulesystem/Module.cpp index 0af30e08e..671881646 100644 --- a/src/libcalamaresui/modulesystem/Module.cpp +++ b/src/libcalamaresui/modulesystem/Module.cpp @@ -297,9 +297,10 @@ Module::initFrom( const QVariantMap& moduleDescriptor ) m_name = moduleDescriptor.value( "name" ).toString(); } -void +RequirementsList Module::checkRequirements() { + return RequirementsList(); } } //ns diff --git a/src/libcalamaresui/modulesystem/Module.h b/src/libcalamaresui/modulesystem/Module.h index 294b516e2..468475930 100644 --- a/src/libcalamaresui/modulesystem/Module.h +++ b/src/libcalamaresui/modulesystem/Module.h @@ -20,6 +20,7 @@ #ifndef CALAMARES_MODULE_H #define CALAMARES_MODULE_H +#include "Requirement.h" #include "UiDllMacro.h" #include @@ -165,7 +166,7 @@ public: /** * @brief Check the requirements of this module. */ - virtual void checkRequirements(); + virtual RequirementsList checkRequirements(); protected: explicit Module(); diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 573cfa915..ac01b851a 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -318,14 +318,27 @@ ModuleManager::loadModules() void ModuleManager::checkRequirements() { + cDebug() << "Checking module requirements .."; QTimer::singleShot( 0, this, [ this ]() { + bool acceptable = true; + for (const auto& module : m_loadedModulesByInstanceKey ) { - module->checkRequirements(); + auto l = module->checkRequirements(); + if ( l.length() > 0 ) + { + cDebug() << " .." << module->name() << l.length() << "requirements"; + emit requirementsResult( l ); + } + for (const auto& r : l) + { + if (r.required && !r.checked) + acceptable = false; + } } - emit modulesChecked(); + emit requirementsComplete( acceptable ); } ); } diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index 9444b96f3..8eff846ce 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -19,6 +19,7 @@ #ifndef MODULELOADER_H #define MODULELOADER_H +#include "Requirement.h" #include "Typedefs.h" #include @@ -29,6 +30,7 @@ namespace Calamares { class Module; +class RequirementEntry; // from Requirement.h /** * @brief The ModuleManager class is a singleton which manages Calamares modules. @@ -89,7 +91,8 @@ public: signals: void initDone(); void modulesLoaded(); - void modulesChecked(); + void requirementsComplete( bool ); + void requirementsResult( RequirementsList& ); private slots: void doInit(); diff --git a/src/libcalamaresui/modulesystem/Requirement.cpp b/src/libcalamaresui/modulesystem/Requirement.cpp new file mode 100644 index 000000000..3347a2ae8 --- /dev/null +++ b/src/libcalamaresui/modulesystem/Requirement.cpp @@ -0,0 +1,19 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, Adriaan de Groot + * + * 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 "Requirement.h" + diff --git a/src/libcalamaresui/modulesystem/Requirement.h b/src/libcalamaresui/modulesystem/Requirement.h new file mode 100644 index 000000000..a90d5775b --- /dev/null +++ b/src/libcalamaresui/modulesystem/Requirement.h @@ -0,0 +1,52 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, Adriaan de Groot + * + * 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 CALAMARES_REQUIREMENT_H +#define CALAMARES_REQUIREMENT_H + +#include +#include + +#include + +namespace Calamares +{ + +/** + * An indication of a requirement, which is checked in preparation + * for system installation. An entry has a name and some explanation, + * as well as three meaningful states: + * - checked = true, the requirement is met (green) + * - checked = false, the requirement is not met + * - required = false, warn about it (yellow), no failure + * - required = true, prohibit installation (red) + */ +struct RequirementEntry +{ + QString name; + std::function< QString() > enumerationText; //Partial string, inserted in a + //list of requirements to satisfy. + std::function< QString() > negatedText; //Complete sentence about this requirement + //not having been met. + bool checked; + bool required; +}; + +using RequirementsList = QList< RequirementEntry >; + +} // namespace Calamares +#endif diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 3c9d29993..755a74210 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -33,8 +33,6 @@ WelcomeViewStep::WelcomeViewStep( QObject* parent ) { emit nextStatusChanged( true ); m_widget = new WelcomePage( m_requirementsChecker ); - connect( m_requirementsChecker, &RequirementsChecker::verdictChanged, - this, &WelcomeViewStep::nextStatusChanged ); } diff --git a/src/modules/welcome/checker/CheckerWidget.cpp b/src/modules/welcome/checker/CheckerWidget.cpp index 2476847b6..44ac35982 100644 --- a/src/modules/welcome/checker/CheckerWidget.cpp +++ b/src/modules/welcome/checker/CheckerWidget.cpp @@ -53,12 +53,12 @@ CheckerWidget::CheckerWidget( QWidget* parent ) void -CheckerWidget::init( const QList< PrepareEntry >& checkEntries ) +CheckerWidget::init( const Calamares::RequirementsList& checkEntries ) { bool allChecked = true; bool requirementsSatisfied = true; - for ( const PrepareEntry& entry : checkEntries ) + for ( const auto& entry : checkEntries ) { if ( !entry.checked ) { @@ -162,7 +162,7 @@ CheckerWidget::init( const QList< PrepareEntry >& checkEntries ) void -CheckerWidget::showDetailsDialog( const QList< PrepareEntry >& checkEntries ) +CheckerWidget::showDetailsDialog( const Calamares::RequirementsList& checkEntries ) { QDialog* detailsDialog = new QDialog( this ); QBoxLayout* mainLayout = new QVBoxLayout; @@ -177,7 +177,7 @@ CheckerWidget::showDetailsDialog( const QList< PrepareEntry >& checkEntries ) CalamaresUtils::unmarginLayout( entriesLayout ); mainLayout->addLayout( entriesLayout ); - for ( const PrepareEntry& entry : checkEntries ) + for ( const auto& entry : checkEntries ) { if ( entry.enumerationText().isEmpty() ) continue; diff --git a/src/modules/welcome/checker/CheckerWidget.h b/src/modules/welcome/checker/CheckerWidget.h index 9e4accf23..922d6b0ea 100644 --- a/src/modules/welcome/checker/CheckerWidget.h +++ b/src/modules/welcome/checker/CheckerWidget.h @@ -19,6 +19,7 @@ #ifndef CHECKERWIDGET_H #define CHECKERWIDGET_H +#include "modulesystem/Requirement.h" #include "RequirementsChecker.h" #include @@ -30,10 +31,10 @@ class CheckerWidget : public QWidget public: explicit CheckerWidget( QWidget* parent = nullptr ); - void init( const QList< PrepareEntry >& checkEntries ); + void init( const Calamares::RequirementsList& checkEntries ); private: - void showDetailsDialog( const QList< PrepareEntry >& checkEntries ); + void showDetailsDialog( const Calamares::RequirementsList& checkEntries ); QBoxLayout* m_mainLayout; QBoxLayout* m_entriesLayout; diff --git a/src/modules/welcome/checker/RequirementsChecker.cpp b/src/modules/welcome/checker/RequirementsChecker.cpp index 741802fb5..e198b60c8 100644 --- a/src/modules/welcome/checker/RequirementsChecker.cpp +++ b/src/modules/welcome/checker/RequirementsChecker.cpp @@ -23,6 +23,7 @@ #include "CheckerWidget.h" #include "partman_devices.h" +#include "modulesystem/Requirement.h" #include "widgets/WaitingWidget.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" @@ -30,6 +31,7 @@ #include "utils/CalamaresUtilsSystem.h" #include "utils/Units.h" + #include "JobQueue.h" #include "GlobalStorage.h" @@ -107,7 +109,7 @@ RequirementsChecker::RequirementsChecker( QObject* parent ) << " hasInternet:" << hasInternet << " isRoot:" << isRoot; - QList< PrepareEntry > checkEntries; + Calamares::RequirementsList checkEntries; foreach ( const QString& entry, m_entriesToCheck ) { if ( entry == "storage" ) @@ -171,7 +173,7 @@ RequirementsChecker::RequirementsChecker( QObject* parent ) m_widget->layout()->addWidget( m_actualWidget ); bool canGoNext = true; - foreach ( const PrepareEntry& entry, checkEntries ) + foreach ( const auto& entry, checkEntries ) { if ( !entry.checked && entry.required ) { diff --git a/src/modules/welcome/checker/RequirementsChecker.h b/src/modules/welcome/checker/RequirementsChecker.h index 23ee39f74..e320d3f1d 100644 --- a/src/modules/welcome/checker/RequirementsChecker.h +++ b/src/modules/welcome/checker/RequirementsChecker.h @@ -23,31 +23,9 @@ #include #include -#include - class CheckerWidget; class QWidget; -/** - * An indication of a requirement, which is checked in preparation - * for system installation. An entry has a name and some explanation, - * as well as three meaningful states: - * - checked = true, the requirement is met (green) - * - checked = false, the requirement is not met - * - required = false, warn about it (yellow), no failure - * - required = true, prohibit installation (red) - */ -struct PrepareEntry -{ - QString name; - std::function< QString() > enumerationText; //Partial string, inserted in a - //list of requirements to satisfy. - std::function< QString() > negatedText; //Complete sentence about this requirement - //not having been met. - bool checked; - bool required; -}; - class RequirementsChecker : public QObject { Q_OBJECT From b6fed964ce6072ee34211a915cd3198755c22529 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 2 Dec 2017 11:20:45 -0500 Subject: [PATCH 05/89] [libcalamaresui] Defer requirements checking of ViewModules to their ViewSteps --- src/libcalamaresui/modulesystem/ViewModule.cpp | 6 ++++++ src/libcalamaresui/modulesystem/ViewModule.h | 2 ++ src/libcalamaresui/viewpages/ViewStep.cpp | 6 ++++++ src/libcalamaresui/viewpages/ViewStep.h | 3 +++ 4 files changed, 17 insertions(+) diff --git a/src/libcalamaresui/modulesystem/ViewModule.cpp b/src/libcalamaresui/modulesystem/ViewModule.cpp index 419cad611..b6270f397 100644 --- a/src/libcalamaresui/modulesystem/ViewModule.cpp +++ b/src/libcalamaresui/modulesystem/ViewModule.cpp @@ -126,4 +126,10 @@ ViewModule::~ViewModule() delete m_loader; } +RequirementsList +ViewModule::checkRequirements() +{ + return m_viewStep->checkRequirements(); +} + } // namespace Calamares diff --git a/src/libcalamaresui/modulesystem/ViewModule.h b/src/libcalamaresui/modulesystem/ViewModule.h index 323315947..50a374e56 100644 --- a/src/libcalamaresui/modulesystem/ViewModule.h +++ b/src/libcalamaresui/modulesystem/ViewModule.h @@ -39,6 +39,8 @@ public: void loadSelf() override; JobList jobs() const override; + RequirementsList checkRequirements() override; + protected: void initFrom( const QVariantMap& moduleDescriptor ) override; diff --git a/src/libcalamaresui/viewpages/ViewStep.cpp b/src/libcalamaresui/viewpages/ViewStep.cpp index 96d80cb5f..1694d5bad 100644 --- a/src/libcalamaresui/viewpages/ViewStep.cpp +++ b/src/libcalamaresui/viewpages/ViewStep.cpp @@ -66,4 +66,10 @@ ViewStep::setConfigurationMap( const QVariantMap& configurationMap ) Q_UNUSED( configurationMap ); } + +RequirementsList ViewStep::checkRequirements() +{ + return RequirementsList(); +} + } diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index f69f872e2..0cfbec84a 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -22,6 +22,7 @@ #include +#include "modulesystem/Requirement.h" #include "../UiDllMacro.h" #include "Typedefs.h" @@ -101,6 +102,8 @@ public: virtual void setConfigurationMap( const QVariantMap& configurationMap ); + virtual RequirementsList checkRequirements(); + signals: void nextStatusChanged( bool status ); void done(); From bd27dda4746074c55e3e18c03371ca08eb619e14 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 2 Dec 2017 09:56:03 -0500 Subject: [PATCH 06/89] [welcome] Restructure requirements checking - Move widget behavior into its own container / widget class - Change the RequirementsChecker class to just check the requirements, returning a results list - Connect from the module manager to the results widget. --- src/modules/welcome/CMakeLists.txt | 3 +- src/modules/welcome/WelcomePage.cpp | 15 +- src/modules/welcome/WelcomePage.h | 9 +- src/modules/welcome/WelcomeViewStep.cpp | 5 +- src/modules/welcome/WelcomeViewStep.h | 2 +- .../welcome/checker/CheckerContainer.cpp | 72 +++++ .../welcome/checker/CheckerContainer.h | 62 +++++ .../welcome/checker/RequirementsChecker.cpp | 245 +++++++----------- .../welcome/checker/RequirementsChecker.h | 15 +- 9 files changed, 251 insertions(+), 177 deletions(-) create mode 100644 src/modules/welcome/checker/CheckerContainer.cpp create mode 100644 src/modules/welcome/checker/CheckerContainer.h diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index 42ce62beb..8267e652b 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -6,8 +6,9 @@ find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) set( CHECKER_SOURCES - checker/CheckItemWidget.cpp + checker/CheckerContainer.cpp checker/CheckerWidget.cpp + checker/CheckItemWidget.cpp checker/RequirementsChecker.cpp checker/partman_devices.c ) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 8b5c604b4..1deb7b9e8 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -22,10 +22,13 @@ #include "ui_WelcomePage.h" #include "CalamaresVersion.h" +#include "checker/CheckerContainer.h" #include "checker/RequirementsChecker.h" #include "utils/Logger.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Retranslator.h" + +#include "modulesystem/ModuleManager.h" #include "ViewManager.h" #include @@ -39,11 +42,13 @@ #include "Branding.h" -WelcomePage::WelcomePage( RequirementsChecker* requirementsChecker, QWidget* parent ) +WelcomePage::WelcomePage( QWidget* parent ) : QWidget( parent ) , ui( new Ui::WelcomePage ) - , m_requirementsChecker( requirementsChecker ) + , m_checkingWidget( new CheckerContainer( this ) ) { + connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsResult, m_checkingWidget, &CheckerContainer::requirementsChecked ); + connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, m_checkingWidget, &CheckerContainer::requirementsComplete ); ui->setupUi( this ); ui->verticalLayout->insertSpacing( 1, CalamaresUtils::defaultFontHeight() * 2 ); @@ -102,7 +107,7 @@ WelcomePage::WelcomePage( RequirementsChecker* requirementsChecker, QWidget* par mb.exec(); } ); - ui->verticalLayout->insertWidget( 3, m_requirementsChecker->widget() ); + ui->verticalLayout->insertWidget( 3, m_checkingWidget); } @@ -257,3 +262,7 @@ WelcomePage::focusInEvent( QFocusEvent* e ) e->accept(); } +bool WelcomePage::verdict() const +{ + return m_checkingWidget->verdict(); +} diff --git a/src/modules/welcome/WelcomePage.h b/src/modules/welcome/WelcomePage.h index 79546802a..7c105f03d 100644 --- a/src/modules/welcome/WelcomePage.h +++ b/src/modules/welcome/WelcomePage.h @@ -26,26 +26,27 @@ namespace Ui class WelcomePage; } -class RequirementsChecker; +class CheckerContainer; class WelcomePage : public QWidget { Q_OBJECT public: - explicit WelcomePage( RequirementsChecker* requirementsChecker, - QWidget* parent = nullptr ); + explicit WelcomePage( QWidget* parent = nullptr ); void setUpLinks( bool showSupportUrl, bool showKnownIssuesUrl, bool showReleaseNotesUrl ); + bool verdict() const; + protected: void focusInEvent( QFocusEvent* e ) override; //choose the child widget to focus private: void initLanguages(); Ui::WelcomePage* ui; - RequirementsChecker* m_requirementsChecker; + CheckerContainer* m_checkingWidget; }; #endif // WELCOMEPAGE_H diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 755a74210..4571141d6 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -32,7 +32,7 @@ WelcomeViewStep::WelcomeViewStep( QObject* parent ) , m_requirementsChecker( new RequirementsChecker( this ) ) { emit nextStatusChanged( true ); - m_widget = new WelcomePage( m_requirementsChecker ); + m_widget = new WelcomePage(); } @@ -72,7 +72,7 @@ WelcomeViewStep::back() bool WelcomeViewStep::isNextEnabled() const { - return m_requirementsChecker->verdict(); + return m_widget->verdict(); } @@ -131,4 +131,3 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) cDebug() << "WARNING: no valid requirements map found in welcome " "module configuration."; } - diff --git a/src/modules/welcome/WelcomeViewStep.h b/src/modules/welcome/WelcomeViewStep.h index fbcbd8ded..9d1b5d97f 100644 --- a/src/modules/welcome/WelcomeViewStep.h +++ b/src/modules/welcome/WelcomeViewStep.h @@ -21,6 +21,7 @@ #include +#include #include #include @@ -58,7 +59,6 @@ public: private: WelcomePage* m_widget; - RequirementsChecker* m_requirementsChecker; }; diff --git a/src/modules/welcome/checker/CheckerContainer.cpp b/src/modules/welcome/checker/CheckerContainer.cpp new file mode 100644 index 000000000..cf843f399 --- /dev/null +++ b/src/modules/welcome/checker/CheckerContainer.cpp @@ -0,0 +1,72 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014-2017, Teo Mrnjavac + * Copyright 2017, Adriaan de Groot + * Copyright 2017, Gabriel Craciunescu + * + * 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 . + */ + +/* Based on code extracted from RequirementsChecker.cpp */ + +#include "CheckerContainer.h" + +#include "CheckerWidget.h" + +#include "utils/CalamaresUtilsGui.h" +#include "utils/Logger.h" +#include "utils/Retranslator.h" +#include "widgets/WaitingWidget.h" + +CheckerContainer::CheckerContainer(QWidget* parent) + : QWidget( parent ) + , m_waitingWidget( new WaitingWidget( QString() ) ) + , m_checkerWidget( new CheckerWidget() ) + , m_verdict( false ) +{ + QBoxLayout* mainLayout = new QHBoxLayout; + setLayout( mainLayout ); + CalamaresUtils::unmarginLayout( mainLayout ); + + mainLayout->addWidget( m_waitingWidget ); + CALAMARES_RETRANSLATE( m_waitingWidget->setText( tr( "Gathering system information..." ) ); ) +} + +CheckerContainer::~CheckerContainer() +{ + delete m_waitingWidget; + delete m_checkerWidget; +} + +void CheckerContainer::requirementsComplete( bool ok ) +{ + m_checkerWidget->init( m_requirements ); + layout()->removeWidget( m_waitingWidget ); + m_waitingWidget->deleteLater(); + m_waitingWidget = nullptr; // Don't delete in constructor + m_checkerWidget->setParent( this ); + layout()->addWidget( m_checkerWidget ); + + m_verdict = ok; +} + +void CheckerContainer::requirementsChecked(const Calamares::RequirementsList& l) +{ + m_requirements.append( l ); +} + +bool CheckerContainer::verdict() const +{ + return m_verdict; +} diff --git a/src/modules/welcome/checker/CheckerContainer.h b/src/modules/welcome/checker/CheckerContainer.h new file mode 100644 index 000000000..3f8f9ce92 --- /dev/null +++ b/src/modules/welcome/checker/CheckerContainer.h @@ -0,0 +1,62 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014-2017, Teo Mrnjavac + * Copyright 2017, Adriaan de Groot + * Copyright 2017, Gabriel Craciunescu + * + * 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 . + */ + +/* Based on code extracted from RequirementsChecker.cpp */ + +#ifndef CHECKERCONTAINER_H +#define CHECKERCONTAINER_H + +#include + +#include "modulesystem/Requirement.h" + +class CheckerWidget; +class WaitingWidget; + +/** + * A widget that collects requirements results; until the results are + * all in, displays a spinner / waiting widget. Then it switches to + * a (list) diplay of the results, plus some explanation of the + * overall state of the entire list of results. + */ +class CheckerContainer : public QWidget +{ + Q_OBJECT +public: + explicit CheckerContainer( QWidget* parent = nullptr ); + virtual ~CheckerContainer(); + + bool verdict() const; + +public slots: + void requirementsChecked( const Calamares::RequirementsList& ); + + /** @brief All the requirements are complete, switch to list view */ + void requirementsComplete( bool ); + +protected: + WaitingWidget *m_waitingWidget; + CheckerWidget *m_checkerWidget; + + Calamares::RequirementsList m_requirements; + bool m_verdict; +} ; + +#endif diff --git a/src/modules/welcome/checker/RequirementsChecker.cpp b/src/modules/welcome/checker/RequirementsChecker.cpp index e198b60c8..8fc8d20b0 100644 --- a/src/modules/welcome/checker/RequirementsChecker.cpp +++ b/src/modules/welcome/checker/RequirementsChecker.cpp @@ -20,7 +20,7 @@ #include "RequirementsChecker.h" -#include "CheckerWidget.h" +#include "CheckerContainer.h" #include "partman_devices.h" #include "modulesystem/Requirement.h" @@ -55,157 +55,105 @@ RequirementsChecker::RequirementsChecker( QObject* parent ) : QObject( parent ) - , m_widget( new QWidget() ) , m_requiredStorageGB( -1 ) , m_requiredRamGB( -1 ) - , m_actualWidget( new CheckerWidget() ) - , m_verdict( false ) { - QBoxLayout* mainLayout = new QHBoxLayout; - m_widget->setLayout( mainLayout ); - CalamaresUtils::unmarginLayout( mainLayout ); +} - WaitingWidget* waitingWidget = new WaitingWidget( QString() ); - mainLayout->addWidget( waitingWidget ); - CALAMARES_RETRANSLATE( waitingWidget->setText( tr( "Gathering system information..." ) ); ) +Calamares::RequirementsList RequirementsChecker::checkRequirements(QWidget* some_widget) +{ + QSize availableSize = qApp->desktop()->availableGeometry( some_widget ).size(); - QSize availableSize = qApp->desktop()->availableGeometry( m_widget ).size(); + bool enoughStorage = false; + bool enoughRam = false; + bool hasPower = false; + bool hasInternet = false; + bool isRoot = false; + bool enoughScreen = (availableSize.width() >= CalamaresUtils::windowMinimumWidth) && (availableSize.height() >= CalamaresUtils::windowMinimumHeight); - QTimer* timer = new QTimer; - timer->setSingleShot( true ); - connect( timer, &QTimer::timeout, - [=]() + qint64 requiredStorageB = CalamaresUtils::GiBtoBytes(m_requiredStorageGB); + cDebug() << "Need at least storage bytes:" << requiredStorageB; + if ( m_entriesToCheck.contains( "storage" ) ) + enoughStorage = checkEnoughStorage( requiredStorageB ); + + qint64 requiredRamB = CalamaresUtils::GiBtoBytes(m_requiredRamGB); + cDebug() << "Need at least ram bytes:" << requiredRamB; + if ( m_entriesToCheck.contains( "ram" ) ) + enoughRam = checkEnoughRam( requiredRamB ); + + if ( m_entriesToCheck.contains( "power" ) ) + hasPower = checkHasPower(); + + if ( m_entriesToCheck.contains( "internet" ) ) + hasInternet = checkHasInternet(); + + if ( m_entriesToCheck.contains( "root" ) ) + isRoot = checkIsRoot(); + + cDebug() << "RequirementsChecker output:" + << " enoughStorage:" << enoughStorage + << " enoughRam:" << enoughRam + << " hasPower:" << hasPower + << " hasInternet:" << hasInternet + << " isRoot:" << isRoot; + + Calamares::RequirementsList checkEntries; + foreach ( const QString& entry, m_entriesToCheck ) { - bool enoughStorage = false; - bool enoughRam = false; - bool hasPower = false; - bool hasInternet = false; - bool isRoot = false; - bool enoughScreen = (availableSize.width() >= CalamaresUtils::windowMinimumWidth) && (availableSize.height() >= CalamaresUtils::windowMinimumHeight); - - qint64 requiredStorageB = CalamaresUtils::GiBtoBytes(m_requiredStorageGB); - cDebug() << "Need at least storage bytes:" << requiredStorageB; - if ( m_entriesToCheck.contains( "storage" ) ) - enoughStorage = checkEnoughStorage( requiredStorageB ); - - qint64 requiredRamB = CalamaresUtils::GiBtoBytes(m_requiredRamGB); - cDebug() << "Need at least ram bytes:" << requiredRamB; - if ( m_entriesToCheck.contains( "ram" ) ) - enoughRam = checkEnoughRam( requiredRamB ); - - if ( m_entriesToCheck.contains( "power" ) ) - hasPower = checkHasPower(); - - if ( m_entriesToCheck.contains( "internet" ) ) - hasInternet = checkHasInternet(); - - if ( m_entriesToCheck.contains( "root" ) ) - isRoot = checkIsRoot(); - - cDebug() << "RequirementsChecker output:" - << " enoughStorage:" << enoughStorage - << " enoughRam:" << enoughRam - << " hasPower:" << hasPower - << " hasInternet:" << hasInternet - << " isRoot:" << isRoot; - - Calamares::RequirementsList checkEntries; - foreach ( const QString& entry, m_entriesToCheck ) - { - if ( entry == "storage" ) - checkEntries.append( { - entry, - [this]{ return tr( "has at least %1 GB available drive space" ) - .arg( m_requiredStorageGB ); }, - [this]{ return tr( "There is not enough drive space. At least %1 GB is required." ) - .arg( m_requiredStorageGB ); }, - enoughStorage, - m_entriesToRequire.contains( entry ) - } ); - else if ( entry == "ram" ) - checkEntries.append( { - entry, - [this]{ return tr( "has at least %1 GB working memory" ) - .arg( m_requiredRamGB ); }, - [this]{ return tr( "The system does not have enough working memory. At least %1 GB is required." ) - .arg( m_requiredRamGB ); }, - enoughRam, - m_entriesToRequire.contains( entry ) - } ); - else if ( entry == "power" ) - checkEntries.append( { - entry, - [this]{ return tr( "is plugged in to a power source" ); }, - [this]{ return tr( "The system is not plugged in to a power source." ); }, - hasPower, - m_entriesToRequire.contains( entry ) - } ); - else if ( entry == "internet" ) - checkEntries.append( { - entry, - [this]{ return tr( "is connected to the Internet" ); }, - [this]{ return tr( "The system is not connected to the Internet." ); }, - hasInternet, - m_entriesToRequire.contains( entry ) - } ); - else if ( entry == "root" ) - checkEntries.append( { - entry, - [this]{ return QString(); }, //we hide it - [this]{ return tr( "The installer is not running with administrator rights." ); }, - isRoot, - m_entriesToRequire.contains( entry ) - } ); - else if ( entry == "screen" ) - checkEntries.append( { - entry, - [this]{ return QString(); }, // we hide it - [this]{ return tr( "The screen is too small to display the installer." ); }, - enoughScreen, - false - } ); - } - - m_actualWidget->init( checkEntries ); - m_widget->layout()->removeWidget( waitingWidget ); - waitingWidget->deleteLater(); - m_actualWidget->setParent( m_widget ); - m_widget->layout()->addWidget( m_actualWidget ); - - bool canGoNext = true; - foreach ( const auto& entry, checkEntries ) - { - if ( !entry.checked && entry.required ) - { - canGoNext = false; - break; - } - } - m_verdict = canGoNext; - emit verdictChanged( m_verdict ); - - if ( canGoNext ) - detectFirmwareType(); - - timer->deleteLater(); - } ); - timer->start( 0 ); - - emit verdictChanged( true ); -} - - -RequirementsChecker::~RequirementsChecker() -{ - if ( m_widget && m_widget->parent() == nullptr ) - m_widget->deleteLater(); -} - - -QWidget* -RequirementsChecker::widget() const -{ - return m_widget; + if ( entry == "storage" ) + checkEntries.append( { + entry, + [this]{ return tr( "has at least %1 GB available drive space" ) + .arg( m_requiredStorageGB ); }, + [this]{ return tr( "There is not enough drive space. At least %1 GB is required." ) + .arg( m_requiredStorageGB ); }, + enoughStorage, + m_entriesToRequire.contains( entry ) + } ); + else if ( entry == "ram" ) + checkEntries.append( { + entry, + [this]{ return tr( "has at least %1 GB working memory" ) + .arg( m_requiredRamGB ); }, + [this]{ return tr( "The system does not have enough working memory. At least %1 GB is required." ) + .arg( m_requiredRamGB ); }, + enoughRam, + m_entriesToRequire.contains( entry ) + } ); + else if ( entry == "power" ) + checkEntries.append( { + entry, + [this]{ return tr( "is plugged in to a power source" ); }, + [this]{ return tr( "The system is not plugged in to a power source." ); }, + hasPower, + m_entriesToRequire.contains( entry ) + } ); + else if ( entry == "internet" ) + checkEntries.append( { + entry, + [this]{ return tr( "is connected to the Internet" ); }, + [this]{ return tr( "The system is not connected to the Internet." ); }, + hasInternet, + m_entriesToRequire.contains( entry ) + } ); + else if ( entry == "root" ) + checkEntries.append( { + entry, + [this]{ return QString(); }, //we hide it + [this]{ return tr( "The installer is not running with administrator rights." ); }, + isRoot, + m_entriesToRequire.contains( entry ) + } ); + else if ( entry == "screen" ) + checkEntries.append( { + entry, + [this]{ return QString(); }, // we hide it + [this]{ return tr( "The screen is too small to display the installer." ); }, + enoughScreen, + false + } ); + } + return checkEntries; } @@ -300,13 +248,6 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) } -bool -RequirementsChecker::verdict() const -{ - return m_verdict; -} - - bool RequirementsChecker::checkEnoughStorage( qint64 requiredSpace ) { diff --git a/src/modules/welcome/checker/RequirementsChecker.h b/src/modules/welcome/checker/RequirementsChecker.h index e320d3f1d..6a208d1ee 100644 --- a/src/modules/welcome/checker/RequirementsChecker.h +++ b/src/modules/welcome/checker/RequirementsChecker.h @@ -23,24 +23,17 @@ #include #include -class CheckerWidget; -class QWidget; +#include "modulesystem/Requirement.h" class RequirementsChecker : public QObject { Q_OBJECT public: explicit RequirementsChecker( QObject* parent = nullptr ); - virtual ~RequirementsChecker(); - - QWidget* widget() const; void setConfigurationMap( const QVariantMap& configurationMap ); - bool verdict() const; - -signals: - void verdictChanged( bool ); + Calamares::RequirementsList checkRequirements( QWidget* some_widget ); private: QStringList m_entriesToCheck; @@ -54,13 +47,9 @@ private: bool checkIsRoot(); void detectFirmwareType(); - QWidget* m_widget; qreal m_requiredStorageGB; qreal m_requiredRamGB; QString m_checkHasInternetUrl; - - CheckerWidget* m_actualWidget; - bool m_verdict; }; #endif // REQUIREMENTSCHECKER_H From c8e42e690967adda741b0aaa89a8919ba02915c0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 2 Dec 2017 11:25:26 -0500 Subject: [PATCH 07/89] [welcome] Implement requirements checking at module level. - Hook up the requirements checker (which only checks) to the module-and-viewstep method called to do the checking. --- src/modules/welcome/WelcomeViewStep.cpp | 5 +++++ src/modules/welcome/WelcomeViewStep.h | 2 ++ 2 files changed, 7 insertions(+) diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 4571141d6..d8aed9f37 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -131,3 +131,8 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) cDebug() << "WARNING: no valid requirements map found in welcome " "module configuration."; } + +Calamares::RequirementsList WelcomeViewStep::checkRequirements() +{ + return m_requirementsChecker->checkRequirements( m_widget ); +} diff --git a/src/modules/welcome/WelcomeViewStep.h b/src/modules/welcome/WelcomeViewStep.h index 9d1b5d97f..bdcf30eaf 100644 --- a/src/modules/welcome/WelcomeViewStep.h +++ b/src/modules/welcome/WelcomeViewStep.h @@ -57,6 +57,8 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; + Calamares::RequirementsList checkRequirements() override; + private: WelcomePage* m_widget; RequirementsChecker* m_requirementsChecker; From 16fbe4dc8c998d1c2aa3dc64f0488128dd976118 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 2 Dec 2017 11:42:56 -0500 Subject: [PATCH 08/89] [partition] Sample of requirement checking - There should be at least device to select, overwise we can't continue. The check currently **always** fails, so it blocks installation. --- src/modules/partition/gui/PartitionViewStep.cpp | 16 ++++++++++++++++ src/modules/partition/gui/PartitionViewStep.h | 2 ++ 2 files changed, 18 insertions(+) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 7f113ce88..07a6920fe 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -579,5 +579,21 @@ PartitionViewStep::jobs() const return m_core->jobs(); } +Calamares::RequirementsList PartitionViewStep::checkRequirements() +{ + Calamares::RequirementsList l; + l.append( + { + QLatin1Literal("partitions"), + []{ return QString(); }, + [this]{ return tr("There are no partitons to install on."); }, + false, // satisfied + true // required + }); + + return l; + +} + CALAMARES_PLUGIN_FACTORY_DEFINITION( PartitionViewStepFactory, registerPlugin(); ) diff --git a/src/modules/partition/gui/PartitionViewStep.h b/src/modules/partition/gui/PartitionViewStep.h index 1aa8190f9..5a57d5074 100644 --- a/src/modules/partition/gui/PartitionViewStep.h +++ b/src/modules/partition/gui/PartitionViewStep.h @@ -66,6 +66,8 @@ public: QList< Calamares::job_ptr > jobs() const override; + Calamares::RequirementsList checkRequirements() override; + private: void initPartitionCoreModule(); void continueLoading(); From ba21a221df832af340eb2ffe4c65dfa1dad5fdd7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 2 Dec 2017 11:43:20 -0500 Subject: [PATCH 09/89] [partition] C++ style --- .../partition/gui/PartitionViewStep.cpp | 76 +++++++------------ 1 file changed, 28 insertions(+), 48 deletions(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 07a6920fe..264ec98f6 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -209,8 +209,8 @@ PartitionViewStep::createSummaryWidget() const else // multiple disk previews! { diskInfoLabel->setText( tr( "Disk %1 (%2)" ) - .arg( info.deviceNode ) - .arg( info.deviceName ) ); + .arg( info.deviceNode ) + .arg( info.deviceName ) ); } formLayout->addRow( diskInfoLabel ); @@ -219,9 +219,9 @@ PartitionViewStep::createSummaryWidget() const QVBoxLayout* field; PartitionBarsView::NestedPartitionsMode mode = Calamares::JobQueue::instance()->globalStorage()-> - value( "drawNestedPartitions" ).toBool() ? - PartitionBarsView::DrawNestedPartitions : - PartitionBarsView::NoNestedPartitions; + value( "drawNestedPartitions" ).toBool() ? + PartitionBarsView::DrawNestedPartitions : + PartitionBarsView::NoNestedPartitions; preview = new PartitionBarsView; preview->setNestedPartitionsMode( mode ); previewLabels = new PartitionLabelsView; @@ -259,7 +259,7 @@ PartitionViewStep::createSummaryWidget() const foreach ( const Calamares::job_ptr& job, jobs() ) { if ( !job->prettyDescription().isEmpty() ) - jobsLines.append( job->prettyDescription() ); + jobsLines.append( job->prettyDescription() ); } if ( !jobsLines.isEmpty() ) { @@ -352,8 +352,8 @@ PartitionViewStep::isAtEnd() const if ( m_choicePage == m_widget->currentWidget() ) { if ( m_choicePage->currentChoice() == ChoicePage::Erase || - m_choicePage->currentChoice() == ChoicePage::Replace || - m_choicePage->currentChoice() == ChoicePage::Alongside ) + m_choicePage->currentChoice() == ChoicePage::Replace || + m_choicePage->currentChoice() == ChoicePage::Alongside ) return true; return false; } @@ -366,7 +366,7 @@ PartitionViewStep::onActivate() { // if we're coming back to PVS from the next VS if ( m_widget->currentWidget() == m_choicePage && - m_choicePage->currentChoice() == ChoicePage::Alongside ) + m_choicePage->currentChoice() == ChoicePage::Alongside ) { m_choicePage->applyActionChoice( ChoicePage::Alongside ); // m_choicePage->reset(); @@ -389,7 +389,7 @@ PartitionViewStep::onLeave() if ( PartUtils::isEfiSystem() ) { QString espMountPoint = Calamares::JobQueue::instance()->globalStorage()-> - value( "efiSystemPartition").toString(); + value( "efiSystemPartition" ).toString(); Partition* esp = m_core->findPartitionByMountPoint( espMountPoint ); QString message; @@ -443,7 +443,7 @@ PartitionViewStep::onLeave() // If the root partition is encrypted, and there's a separate boot // partition which is not encrypted if ( root_p->fileSystem().type() == FileSystem::Luks && - boot_p->fileSystem().type() != FileSystem::Luks ) + boot_p->fileSystem().type() != FileSystem::Luks ) { message = tr( "Boot partition not encrypted" ); description = tr( "A separate boot partition was set up together with " @@ -475,61 +475,45 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) // the EraseDiskPage, but also in the bootloader configuration modules (grub, bootloader). Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); if ( configurationMap.contains( "efiSystemPartition" ) && - configurationMap.value( "efiSystemPartition" ).type() == QVariant::String && - !configurationMap.value( "efiSystemPartition" ).toString().isEmpty() ) - { + configurationMap.value( "efiSystemPartition" ).type() == QVariant::String && + !configurationMap.value( "efiSystemPartition" ).toString().isEmpty() ) gs->insert( "efiSystemPartition", configurationMap.value( "efiSystemPartition" ).toString() ); - } else - { gs->insert( "efiSystemPartition", QStringLiteral( "/boot/efi" ) ); - } if ( configurationMap.contains( "ensureSuspendToDisk" ) && - configurationMap.value( "ensureSuspendToDisk" ).type() == QVariant::Bool ) - { + configurationMap.value( "ensureSuspendToDisk" ).type() == QVariant::Bool ) gs->insert( "ensureSuspendToDisk", configurationMap.value( "ensureSuspendToDisk" ).toBool() ); - } else - { gs->insert( "ensureSuspendToDisk", true ); - } if ( configurationMap.contains( "neverCreateSwap" ) && - configurationMap.value( "neverCreateSwap" ).type() == QVariant::Bool ) - { + configurationMap.value( "neverCreateSwap" ).type() == QVariant::Bool ) gs->insert( "neverCreateSwap", configurationMap.value( "neverCreateSwap" ).toBool() ); - } else - { gs->insert( "neverCreateSwap", false ); - } if ( configurationMap.contains( "drawNestedPartitions" ) && - configurationMap.value( "drawNestedPartitions" ).type() == QVariant::Bool ) + configurationMap.value( "drawNestedPartitions" ).type() == QVariant::Bool ) { gs->insert( "drawNestedPartitions", configurationMap.value( "drawNestedPartitions", false ).toBool() ); } else - { gs->insert( "drawNestedPartitions", false ); - } if ( configurationMap.contains( "alwaysShowPartitionLabels" ) && - configurationMap.value( "alwaysShowPartitionLabels" ).type() == QVariant::Bool ) + configurationMap.value( "alwaysShowPartitionLabels" ).type() == QVariant::Bool ) { gs->insert( "alwaysShowPartitionLabels", configurationMap.value( "alwaysShowPartitionLabels", true ).toBool() ); } else - { gs->insert( "alwaysShowPartitionLabels", true ); - } if ( configurationMap.contains( "defaultFileSystemType" ) && - configurationMap.value( "defaultFileSystemType" ).type() == QVariant::String && - !configurationMap.value( "defaultFileSystemType" ).toString().isEmpty() ) + configurationMap.value( "defaultFileSystemType" ).type() == QVariant::String && + !configurationMap.value( "defaultFileSystemType" ).toString().isEmpty() ) { QString typeString = configurationMap.value( "defaultFileSystemType" ).toString(); gs->insert( "defaultFileSystemType", typeString ); @@ -540,20 +524,16 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) } } else - { gs->insert( "defaultFileSystemType", QStringLiteral( "ext4" ) ); - } if ( configurationMap.contains( "enableLuksAutomatedPartitioning" ) && - configurationMap.value( "enableLuksAutomatedPartitioning" ).type() == QVariant::Bool ) + configurationMap.value( "enableLuksAutomatedPartitioning" ).type() == QVariant::Bool ) { gs->insert( "enableLuksAutomatedPartitioning", configurationMap.value( "enableLuksAutomatedPartitioning" ).toBool() ); } else - { gs->insert( "enableLuksAutomatedPartitioning", true ); - } // Now that we have the config, we load the PartitionCoreModule in the background @@ -568,7 +548,7 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) } ); QFuture< void > future = - QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule ); + QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule ); watcher->setFuture( future ); } @@ -583,13 +563,13 @@ Calamares::RequirementsList PartitionViewStep::checkRequirements() { Calamares::RequirementsList l; l.append( - { - QLatin1Literal("partitions"), - []{ return QString(); }, - [this]{ return tr("There are no partitons to install on."); }, - false, // satisfied - true // required - }); + { + QLatin1Literal( "partitions" ), + []{ return QString(); }, + [this]{ return tr( "There are no partitons to install on." ); }, + false, // satisfied + true // required + } ); return l; From 4566e53d016f50b6bad9ec6fe2ef3fb79f02072c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 2 Dec 2017 12:11:56 -0500 Subject: [PATCH 10/89] [partition] Delay requirements checking until pmcore is initialized --- src/modules/partition/gui/PartitionViewStep.cpp | 16 ++++++++++------ src/modules/partition/gui/PartitionViewStep.h | 3 +++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 264ec98f6..84d3ecc2c 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -539,17 +539,18 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) // Now that we have the config, we load the PartitionCoreModule in the background // because it could take a while. Then when it's done, we can set up the widgets // and remove the spinner. - QFutureWatcher< void >* watcher = new QFutureWatcher< void >(); - connect( watcher, &QFutureWatcher< void >::finished, - this, [ this, watcher ] + m_future = new QFutureWatcher< void >(); + connect( m_future, &QFutureWatcher< void >::finished, + this, [ this ] { continueLoading(); - watcher->deleteLater(); + this->m_future->deleteLater(); + this->m_future = nullptr; } ); QFuture< void > future = QtConcurrent::run( this, &PartitionViewStep::initPartitionCoreModule ); - watcher->setFuture( future ); + m_future->setFuture( future ); } @@ -561,13 +562,16 @@ PartitionViewStep::jobs() const Calamares::RequirementsList PartitionViewStep::checkRequirements() { + if (m_future) + m_future->waitForFinished(); + Calamares::RequirementsList l; l.append( { QLatin1Literal( "partitions" ), []{ return QString(); }, [this]{ return tr( "There are no partitons to install on." ); }, - false, // satisfied + m_core->deviceModel()->rowCount() > 0, // satisfied true // required } ); diff --git a/src/modules/partition/gui/PartitionViewStep.h b/src/modules/partition/gui/PartitionViewStep.h index 5a57d5074..c2b903d04 100644 --- a/src/modules/partition/gui/PartitionViewStep.h +++ b/src/modules/partition/gui/PartitionViewStep.h @@ -33,6 +33,8 @@ class PartitionPage; class PartitionCoreModule; class QStackedWidget; +template class QFutureWatcher; + /** * The starting point of the module. Instantiates PartitionCoreModule, * ChoicePage and PartitionPage, then connects them. @@ -78,6 +80,7 @@ private: PartitionPage* m_manualPartitionPage; QWidget* m_waitingWidget; + QFutureWatcher* m_future; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PartitionViewStepFactory ) From 29e532a790da53eea553118e05d98e5ac9d99edb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 Dec 2017 07:17:16 -0500 Subject: [PATCH 11/89] [partition] Insert annoying 3-sec delay This is intended for testing -- it helps debug where a slow requirement check blocks the UI. --- src/modules/partition/gui/PartitionViewStep.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 84d3ecc2c..d39d2a84f 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -56,6 +56,8 @@ #include #include +#include // For sleep(3) + PartitionViewStep::PartitionViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_core( nullptr ) @@ -565,6 +567,8 @@ Calamares::RequirementsList PartitionViewStep::checkRequirements() if (m_future) m_future->waitForFinished(); + sleep(3); + Calamares::RequirementsList l; l.append( { From 7ed74cefa1381612b617cfb7083293eb0af40fde Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 Feb 2019 08:25:24 -0500 Subject: [PATCH 12/89] CMake: bump version --- CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index cc7d91d43..e3740c141 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -75,8 +75,8 @@ set( CALAMARES_DESCRIPTION_SUMMARY set( CALAMARES_VERSION_MAJOR 3 ) set( CALAMARES_VERSION_MINOR 2 ) -set( CALAMARES_VERSION_PATCH 4 ) -set( CALAMARES_VERSION_RC 0 ) +set( CALAMARES_VERSION_PATCH 5 ) +set( CALAMARES_VERSION_RC 1 ) ### Transifex (languages) info From 0f80a6295bc4177f4a61f8b009e72de9190e5c77 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 12 Feb 2019 17:11:01 +0100 Subject: [PATCH 13/89] [libcalamares] Reduce warnings about trailing ; --- src/libcalamares/utils/NamedEnum.h | 2 +- src/modules/locale/LocaleConfiguration.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/NamedEnum.h b/src/libcalamares/utils/NamedEnum.h index 69abf4bd1..047ae6f19 100644 --- a/src/libcalamares/utils/NamedEnum.h +++ b/src/libcalamares/utils/NamedEnum.h @@ -51,7 +51,7 @@ struct NamedEnumTable * * static const NamedEnumTable c{ {"red", Colors::Red } }; */ - NamedEnumTable( const std::initializer_list< pair_t >& v ) : table( v ) { /* static_assert( v.size() > 0 ); */ }; + NamedEnumTable( const std::initializer_list< pair_t >& v ) : table( v ) { /* static_assert( v.size() > 0 ); */ } /** @brief Find a name @p s in the table. * diff --git a/src/modules/locale/LocaleConfiguration.h b/src/modules/locale/LocaleConfiguration.h index abe90ffcb..5e99b1f37 100644 --- a/src/modules/locale/LocaleConfiguration.h +++ b/src/modules/locale/LocaleConfiguration.h @@ -31,7 +31,7 @@ public: explicit LocaleConfiguration(); /// @brief Create a locale with everything set to the given @p localeName explicit LocaleConfiguration( const QString& localeName /* "en_US.UTF-8" */ ) - : LocaleConfiguration( localeName, localeName ) { }; + : LocaleConfiguration( localeName, localeName ) { } /// @brief Create a locale with language and formats separate explicit LocaleConfiguration( const QString& localeName, const QString& formatsName ); From 4178d5841c9486399bfa65232f68f6c915b1956d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Feb 2019 12:36:17 +0100 Subject: [PATCH 14/89] [modules] Enable translations on some Python modules - Python modules should have human-readable names, which means that the description should be translated in `pretty_name()` --- src/modules/machineid/main.py | 1 + src/modules/plymouthcfg/main.py | 11 +++++++++++ src/modules/removeuser/main.py | 11 +++++++++++ 3 files changed, 23 insertions(+) diff --git a/src/modules/machineid/main.py b/src/modules/machineid/main.py index c4c473246..092fc7196 100644 --- a/src/modules/machineid/main.py +++ b/src/modules/machineid/main.py @@ -6,6 +6,7 @@ # Copyright 2014, Kevin Kofler # Copyright 2016, Philip Müller # Copyright 2017, Alf Gaida +# Copyright 2019, Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by diff --git a/src/modules/plymouthcfg/main.py b/src/modules/plymouthcfg/main.py index 6f1128b7e..e224f5df0 100644 --- a/src/modules/plymouthcfg/main.py +++ b/src/modules/plymouthcfg/main.py @@ -6,6 +6,7 @@ # Copyright 2016, Artoo # Copyright 2017, Alf Gaida # Copyright 2018, Gabriel Craciunescu +# Copyright 2019, Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -24,6 +25,16 @@ import libcalamares from libcalamares.utils import debug, target_env_call +import gettext +_ = gettext.translation("calamares-python", + localedir=libcalamares.utils.gettext_path(), + languages=libcalamares.utils.gettext_languages(), + fallback=True).gettext + + +def pretty_name(): + return _("Configure Plymouth theme") + class PlymouthController: diff --git a/src/modules/removeuser/main.py b/src/modules/removeuser/main.py index 9acc20b54..bd876edcd 100644 --- a/src/modules/removeuser/main.py +++ b/src/modules/removeuser/main.py @@ -5,6 +5,7 @@ # # Copyright 2015, Teo Mrnjavac # Copyright 2017. Alf Gaida +# Copyright 2019, Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -22,6 +23,16 @@ import subprocess import libcalamares +import gettext +_ = gettext.translation("calamares-python", + localedir=libcalamares.utils.gettext_path(), + languages=libcalamares.utils.gettext_languages(), + fallback=True).gettext + + +def pretty_name(): + return _("Remove live user from target system") + def run(): """ From c9f89e292974cc65c9e2705514e8ba10f5797166 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Feb 2019 15:29:04 +0100 Subject: [PATCH 15/89] [modules] Translate name of services-* modules. --- src/modules/services-openrc/main.py | 13 ++++++++++++- src/modules/services-systemd/main.py | 13 ++++++++++++- 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index c3e14b481..34f80cdf2 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -6,7 +6,7 @@ # Copyright 2016, Artoo # Copyright 2017, Philip Müller # Copyright 2018, Artoo -# Copyright 2018, Adriaan de Groot +# Copyright 2018-2019, Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -27,6 +27,17 @@ from libcalamares.utils import target_env_call, warning from os.path import exists, join +import gettext +_ = gettext.translation("calamares-python", + localedir=libcalamares.utils.gettext_path(), + languages=libcalamares.utils.gettext_languages(), + fallback=True).gettext + + +def pretty_name(): + return _("Configure OpenRC services") + + class OpenrcController: """ This is the openrc service controller. diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index 09263b9f0..7367f988c 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -6,7 +6,7 @@ # Copyright 2014, Philip Müller # Copyright 2014, Teo Mrnjavac # Copyright 2017, Alf Gaida -# Copyright 2018, Adriaan de Groot +# Copyright 2018-2019, Adriaan de Groot # # Calamares is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by @@ -24,6 +24,17 @@ import libcalamares +import gettext +_ = gettext.translation("calamares-python", + localedir=libcalamares.utils.gettext_path(), + languages=libcalamares.utils.gettext_languages(), + fallback=True).gettext + + +def pretty_name(): + return _("Configure systemd services") + + def systemctl(targets, command, suffix): """ For each entry in @p targets, run "systemctl ", From 544c1b708c1518117edf40047200cdf1dcd50c2f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Feb 2019 18:50:29 +0100 Subject: [PATCH 16/89] [services-openrc] Make user-visible messages translatable --- src/modules/services-openrc/main.py | 22 ++++++++++------------ 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index 34f80cdf2..46890dd98 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -80,24 +80,22 @@ class OpenrcController: if exists(runlevel_path): ec = target_env_call(["rc-update", state, name, runlevel]) if ec != 0: + warning("Cannot {} service {} to {}".format(state, name, runlevel)) + warning("rc-update returned error code {!s}".format(ec)) if mandatory: - return ("Cannot {} service {} to {}".format(state, name, runlevel), - "rc-update {} call in chroot returned error code {}".format(state, ec) + return (_("Cannot {} service {} to {}").format(state, name, runlevel), + _("rc-update {} call in chroot returned error code {}").format(state, ec) ) - else: - warning("Could not {} service {} in {}, error {!s}".format(state, name, runlevel, ec)) else: + warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) if mandatory: - return ("Target runlevel {} does not exist for {}.".format(runlevel, name), - "No {} found.".format(runlevel_path)) - else: - warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) + return (_("Target runlevel {} does not exist for {}.").format(runlevel, name), + _("No {} found.").format(runlevel_path)) else: + warning("Target service {} does not exist in {}.".format(name, self.initdDir)) if mandatory: - return ("Target service {} does not exist.".format(name), - "No {} found.".format(service_path)) - else: - warning("Target service {} does not exist in {}.".format(name, self.initdDir)) + return (_("Target service {} does not exist.").format(name), + _("No {} found.").format(service_path)) def run(self): From b7c77e7323f4a972ff5de427c27c2832a3befb5c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Feb 2019 18:52:19 +0100 Subject: [PATCH 17/89] [services-systemd] Make user-visible messages translatable --- src/modules/services-systemd/main.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index 7367f988c..1cb5899ae 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -58,17 +58,16 @@ def systemctl(targets, command, suffix): ) if ec != 0: + libcalamares.utils.warning( + "Cannot {} systemd {} {}".format(command, suffix, name) + ) + libcalamares.utils.warning( + "systemctl {} call in chroot returned error code {}".format(command, ec) + ) if mandatory: - return ("Cannot {} systemd {} {}".format(command, suffix, name), - "systemctl {} call in chroot returned error code {}".format(command, ec) + return (_("Cannot {} systemd {} {}").format(command, suffix, name), + _("systemctl {} call in chroot returned error code {}").format(command, ec) ) - else: - libcalamares.utils.warning( - "Cannot {} systemd {} {}".format(command, suffix, name) - ) - libcalamares.utils.warning( - "systemctl {} call in chroot returned error code {}".format(command, ec) - ) return None @@ -103,6 +102,4 @@ def run(): if r is not None: return r - - # This could have just been return r return None From 6fbc467795cb7f524133070526a46f09011759b3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Feb 2019 16:08:55 -0500 Subject: [PATCH 18/89] [partition] Reduce Transifex warnings - the string here has no context (no QObject-derived class that it is called in) so use the static method instead. --- src/modules/partition/gui/PartitionDialogHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/gui/PartitionDialogHelpers.cpp b/src/modules/partition/gui/PartitionDialogHelpers.cpp index 3dcf41f58..02d91ca4b 100644 --- a/src/modules/partition/gui/PartitionDialogHelpers.cpp +++ b/src/modules/partition/gui/PartitionDialogHelpers.cpp @@ -44,7 +44,7 @@ void standardMountPoints(QComboBox& combo) { combo.clear(); - combo.addItem( combo.tr( "(no mount point)" ) ); + combo.addItem( QObject::tr( "(no mount point)" ) ); combo.addItems( standardMountPoints() ); } From 723358e145e48c0f4b14cb8d1d4c2620f50b3203 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 14 Feb 2019 16:12:43 -0500 Subject: [PATCH 19/89] [partition] Reduce Transifex warnings - Add a (superfluous, since they don't have their own signals or slots) Q_OBJECT macro to the VG jobs, to silence a Transifex warning (this does make sure that the tool knows about the context for the translated messages) --- src/modules/partition/jobs/CreateVolumeGroupJob.h | 1 + src/modules/partition/jobs/DeactivateVolumeGroupJob.h | 1 + src/modules/partition/jobs/RemoveVolumeGroupJob.h | 1 + src/modules/partition/jobs/ResizeVolumeGroupJob.h | 1 + 4 files changed, 4 insertions(+) diff --git a/src/modules/partition/jobs/CreateVolumeGroupJob.h b/src/modules/partition/jobs/CreateVolumeGroupJob.h index 9e84fba73..6f85eaab8 100644 --- a/src/modules/partition/jobs/CreateVolumeGroupJob.h +++ b/src/modules/partition/jobs/CreateVolumeGroupJob.h @@ -27,6 +27,7 @@ class CreateVolumeGroupJob : public Calamares::Job { + Q_OBJECT public: CreateVolumeGroupJob( QString& vgName, QVector< const Partition* > pvList, const qint32 peSize ); diff --git a/src/modules/partition/jobs/DeactivateVolumeGroupJob.h b/src/modules/partition/jobs/DeactivateVolumeGroupJob.h index 5b59c2c4f..17be7cdef 100644 --- a/src/modules/partition/jobs/DeactivateVolumeGroupJob.h +++ b/src/modules/partition/jobs/DeactivateVolumeGroupJob.h @@ -25,6 +25,7 @@ class LvmDevice; class DeactivateVolumeGroupJob : public Calamares::Job { + Q_OBJECT public: DeactivateVolumeGroupJob( LvmDevice* device ); diff --git a/src/modules/partition/jobs/RemoveVolumeGroupJob.h b/src/modules/partition/jobs/RemoveVolumeGroupJob.h index 426dde7fb..009e6f44d 100644 --- a/src/modules/partition/jobs/RemoveVolumeGroupJob.h +++ b/src/modules/partition/jobs/RemoveVolumeGroupJob.h @@ -25,6 +25,7 @@ class LvmDevice; class RemoveVolumeGroupJob : public Calamares::Job { + Q_OBJECT public: RemoveVolumeGroupJob( LvmDevice* device ); diff --git a/src/modules/partition/jobs/ResizeVolumeGroupJob.h b/src/modules/partition/jobs/ResizeVolumeGroupJob.h index 380bee416..fb0ff715b 100644 --- a/src/modules/partition/jobs/ResizeVolumeGroupJob.h +++ b/src/modules/partition/jobs/ResizeVolumeGroupJob.h @@ -28,6 +28,7 @@ class Partition; class ResizeVolumeGroupJob : public Calamares::Job { + Q_OBJECT public: ResizeVolumeGroupJob( LvmDevice* device, QVector< const Partition* >& partitionList ); From 879c5e3ceee2309b3a2e653389f6f98daf101aa5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 15 Feb 2019 00:08:02 +0100 Subject: [PATCH 20/89] Changes: start notes for next release --- CHANGES | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/CHANGES b/CHANGES index 70e7ec8c9..b893b76bd 100644 --- a/CHANGES +++ b/CHANGES @@ -3,6 +3,15 @@ contributors are listed. Note that Calamares does not have a historical changelog -- this log starts with version 3.2.0. The release notes on the website will have to do for older versions. +# 3.2.5 (unreleased) # + +This release contains contributions from (alphabetically by first name): + +## Core ## + +## Modules ## + + # 3.2.4 (2019-02-12) # This release contains contributions from (alphabetically by first name): @@ -66,6 +75,7 @@ This release contains contributions from (alphabetically by first name): the installation media to the target stystem. This can be used, for instance, for block-level-identical installations. + # 3.2.3 (2019-01-09) # This release contains contributions from (alphabetically by first name): From d33752c66ce5de240884b926b68368aa97d9669a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 15 Feb 2019 20:53:55 +0100 Subject: [PATCH 21/89] [libcalamaresui] Refactor Requirements classes - improve naming of member variables - expand documentation --- .../modulesystem/ModuleManager.cpp | 4 +-- src/libcalamaresui/modulesystem/Requirement.h | 32 ++++++++++++------- src/modules/welcome/checker/CheckerWidget.cpp | 8 ++--- 3 files changed, 26 insertions(+), 18 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 722aa7296..ef618de86 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -317,7 +317,7 @@ ModuleManager::checkRequirements() for (const auto& module : m_loadedModulesByInstanceKey ) { - auto l = module->checkRequirements(); + RequirementsList l = module->checkRequirements(); if ( l.length() > 0 ) { cDebug() << " .." << module->name() << l.length() << "requirements"; @@ -325,7 +325,7 @@ ModuleManager::checkRequirements() } for (const auto& r : l) { - if (r.required && !r.checked) + if ( r.mandatory && !r.satisfied ) acceptable = false; } } diff --git a/src/libcalamaresui/modulesystem/Requirement.h b/src/libcalamaresui/modulesystem/Requirement.h index a90d5775b..69e170c94 100644 --- a/src/libcalamaresui/modulesystem/Requirement.h +++ b/src/libcalamaresui/modulesystem/Requirement.h @@ -28,22 +28,30 @@ namespace Calamares /** * An indication of a requirement, which is checked in preparation - * for system installation. An entry has a name and some explanation, - * as well as three meaningful states: - * - checked = true, the requirement is met (green) - * - checked = false, the requirement is not met - * - required = false, warn about it (yellow), no failure - * - required = true, prohibit installation (red) + * for system installation. An entry has a name and some explanation functions + * (functions, because they need to respond to translations). + * + * A requirement can be *satisfied* or not. + * A requirement can be optional (i.e. a "good to have") or mandatory. + * + * Requirements which are not satisfied, and also mandatory, will prevent the + * installation from proceeding. */ struct RequirementEntry { + using TextFunction = std::function< QString() >; + + /// @brief name of this requirement; not shown to user and used as ID QString name; - std::function< QString() > enumerationText; //Partial string, inserted in a - //list of requirements to satisfy. - std::function< QString() > negatedText; //Complete sentence about this requirement - //not having been met. - bool checked; - bool required; + + /// @brief Description of this requirement, for use in user-visible lists + TextFunction enumerationText; + + /// @brief User-visible string to show that the requirement is not met + std::function< QString() > negatedText; + + bool satisfied; + bool mandatory; }; using RequirementsList = QList< RequirementEntry >; diff --git a/src/modules/welcome/checker/CheckerWidget.cpp b/src/modules/welcome/checker/CheckerWidget.cpp index 2f1d7b909..2ad79abfd 100644 --- a/src/modules/welcome/checker/CheckerWidget.cpp +++ b/src/modules/welcome/checker/CheckerWidget.cpp @@ -60,15 +60,15 @@ CheckerWidget::init( const Calamares::RequirementsList& checkEntries ) for ( const auto& entry : checkEntries ) { - if ( !entry.checked ) + if ( !entry.satisfied ) { - CheckItemWidget* ciw = new CheckItemWidget( entry.checked, entry.required ); + CheckItemWidget* ciw = new CheckItemWidget( entry.satisfied, entry.mandatory ); CALAMARES_RETRANSLATE( ciw->setText( entry.negatedText() ); ) m_entriesLayout->addWidget( ciw ); ciw->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); allChecked = false; - if ( entry.required ) + if ( entry.mandatory ) { requirementsSatisfied = false; } @@ -182,7 +182,7 @@ CheckerWidget::showDetailsDialog( const Calamares::RequirementsList& checkEntrie if ( entry.enumerationText().isEmpty() ) continue; - CheckItemWidget* ciw = new CheckItemWidget( entry.checked, entry.required ); + CheckItemWidget* ciw = new CheckItemWidget( entry.satisfied, entry.mandatory ); CALAMARES_RETRANSLATE( ciw->setText( entry.enumerationText() ); ) entriesLayout->addWidget( ciw ); ciw->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); From 946c5a493f53c517b90e58a18f1cffa5694093b7 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Feb 2019 06:27:36 -0500 Subject: [PATCH 22/89] [services-*] Fix translations - Strings like "{} the {} with {}" are terrible for translators: - no context - no possibility to re-order grammatical units - substituting in English parts-of-speech is going to make a mess - Write the strings out with explicitly named substitutions, no part-of-speech substitution, and better formatting. --- src/modules/services-openrc/main.py | 37 +++++++++++++++++++++++----- src/modules/services-systemd/main.py | 20 +++++++++++++-- 2 files changed, 49 insertions(+), 8 deletions(-) diff --git a/src/modules/services-openrc/main.py b/src/modules/services-openrc/main.py index 46890dd98..23591fb84 100644 --- a/src/modules/services-openrc/main.py +++ b/src/modules/services-openrc/main.py @@ -56,6 +56,22 @@ class OpenrcController: self.initdDir = libcalamares.job.configuration['initdDir'] self.runlevelsDir = libcalamares.job.configuration['runlevelsDir'] + + def make_failure_description(self, state, name, runlevel): + """ + Returns a generic "could not " failure message, specialized + for the action @p state and the specific service @p name in @p runlevel. + """ + if state == "add": + description = _("Cannot add service {name!s} to run-level {level!s}.") + elif state == "del": + description = _("Cannot remove service {name!s} from run-level {level!s}.") + else: + description = _("Unknown service-action {arg!s} for service {name!s} in run-level {level!s}.") + + return description.format(arg=state, name=name, level=runlevel) + + def update(self, state): """ Call rc-update for each service listed @@ -83,19 +99,28 @@ class OpenrcController: warning("Cannot {} service {} to {}".format(state, name, runlevel)) warning("rc-update returned error code {!s}".format(ec)) if mandatory: - return (_("Cannot {} service {} to {}").format(state, name, runlevel), - _("rc-update {} call in chroot returned error code {}").format(state, ec) + title = _("Cannot modify service") + diagnostic = _("rc-update {arg!s} call in chroot returned error code {num!s}.").format(arg=state, num=ec) + return (title, + self.make_failure_description(state, name, runlevel) + " " + diagnostic ) else: warning("Target runlevel {} does not exist for {}.".format(runlevel, name)) if mandatory: - return (_("Target runlevel {} does not exist for {}.").format(runlevel, name), - _("No {} found.").format(runlevel_path)) + title = _("Target runlevel does not exist") + diagnostic = _("The path for runlevel {level!s} is {path!s}, which does not exist.").format(level=runlevel, path=runlevel_path) + + return (title, + self.make_failure_description(state, name, runlevel) + " " + diagnostic + ) else: warning("Target service {} does not exist in {}.".format(name, self.initdDir)) if mandatory: - return (_("Target service {} does not exist.").format(name), - _("No {} found.").format(service_path)) + title = _("Target service does not exist") + diagnostic = _("The path for service {name!s} is {path!s}, which does not exist.").format(name=name, path=service_path) + return (title, + self.make_failure_description(state, name, runlevel) + " " + diagnostic + ) def run(self): diff --git a/src/modules/services-systemd/main.py b/src/modules/services-systemd/main.py index 1cb5899ae..cd13d9ce9 100644 --- a/src/modules/services-systemd/main.py +++ b/src/modules/services-systemd/main.py @@ -65,8 +65,24 @@ def systemctl(targets, command, suffix): "systemctl {} call in chroot returned error code {}".format(command, ec) ) if mandatory: - return (_("Cannot {} systemd {} {}").format(command, suffix, name), - _("systemctl {} call in chroot returned error code {}").format(command, ec) + title = _("Cannot modify service") + diagnostic = _("systemctl {arg!s} call in chroot returned error code {num!s}.").format(arg=command, num=ec) + + if command == "enable" and suffix == ".service": + description = _("Cannot enable systemd service {name!s}.") + elif command == "enable" and suffix == ".target": + description = _("Cannot enable systemd target {name!s}.") + elif command == "disable" and suffix == ".service": + description = _("Cannot enable systemd service {name!s}.") + elif command == "disable" and suffix == ".target": + description = _("Cannot disable systemd target {name!s}.") + elif command == "mask": + description = _("Cannot mask systemd unit {name!s}.") + else: + description = _("Unknown systemd commands {command!s} and {suffix!s} for unit {name!s}.") + + return (title, + description.format(name=name, command=command, suffix=suffix) + " " + diagnostic ) return None From cbc0100add0ffa1bf277b9dd37149db413b89876 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Feb 2019 08:52:52 -0500 Subject: [PATCH 23/89] Changes: mention updated Python-module translations --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index b893b76bd..b0a823883 100644 --- a/CHANGES +++ b/CHANGES @@ -11,6 +11,10 @@ This release contains contributions from (alphabetically by first name): ## Modules ## + * Python modules: several modules have had translations added. This is + usually only visible when the module runs as part of the *exec* step, + when the module's *pretty name* is displayed. In addition, error + messages are now translated. # 3.2.4 (2019-02-12) # From 5aa4e52452c5a9c647a9db3bf33abe2d1a10dcdf Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Feb 2019 09:09:37 -0500 Subject: [PATCH 24/89] [libcalamaresui] Improve debug-logging --- src/libcalamaresui/modulesystem/ModuleManager.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index ef618de86..d2d324451 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -320,13 +320,18 @@ ModuleManager::checkRequirements() RequirementsList l = module->checkRequirements(); if ( l.length() > 0 ) { - cDebug() << " .." << module->name() << l.length() << "requirements"; + cDebug() << " .." << module->name() << "has" << l.length() << "requirements"; emit requirementsResult( l ); } + int count = 0; for (const auto& r : l) { if ( r.mandatory && !r.satisfied ) + { + cDebug() << " .. requirement" << count << r.name << "is not satisfied."; acceptable = false; + } + ++count; } } From 18efcf22006053b58c7ebb6d387820059661b202 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Feb 2019 09:42:22 -0500 Subject: [PATCH 25/89] [welcome] Drop unnecessary parameter --- src/modules/welcome/WelcomeViewStep.cpp | 2 +- src/modules/welcome/checker/RequirementsChecker.cpp | 4 ++-- src/modules/welcome/checker/RequirementsChecker.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 305184218..003de802f 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -135,5 +135,5 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) Calamares::RequirementsList WelcomeViewStep::checkRequirements() { - return m_requirementsChecker->checkRequirements( m_widget ); + return m_requirementsChecker->checkRequirements(); } diff --git a/src/modules/welcome/checker/RequirementsChecker.cpp b/src/modules/welcome/checker/RequirementsChecker.cpp index 08b43eee6..5225d1dbe 100644 --- a/src/modules/welcome/checker/RequirementsChecker.cpp +++ b/src/modules/welcome/checker/RequirementsChecker.cpp @@ -60,9 +60,9 @@ RequirementsChecker::RequirementsChecker( QObject* parent ) { } -Calamares::RequirementsList RequirementsChecker::checkRequirements(QWidget* some_widget) +Calamares::RequirementsList RequirementsChecker::checkRequirements() { - QSize availableSize = qApp->desktop()->availableGeometry( some_widget ).size(); + QSize availableSize = qApp->desktop()->availableGeometry().size(); bool enoughStorage = false; bool enoughRam = false; diff --git a/src/modules/welcome/checker/RequirementsChecker.h b/src/modules/welcome/checker/RequirementsChecker.h index 889443fcb..40f984c05 100644 --- a/src/modules/welcome/checker/RequirementsChecker.h +++ b/src/modules/welcome/checker/RequirementsChecker.h @@ -33,7 +33,7 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ); - Calamares::RequirementsList checkRequirements( QWidget* some_widget ); + Calamares::RequirementsList checkRequirements(); private: QStringList m_entriesToCheck; From ff10e1301d497e10068a0707a39c1ef9b5c44f42 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Feb 2019 10:10:16 -0500 Subject: [PATCH 26/89] [libcalamaresui] Fix struct/class mismatch --- src/libcalamaresui/modulesystem/ModuleManager.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index 20ebffd7e..fc88ef0b5 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -31,7 +31,7 @@ namespace Calamares { class Module; -class RequirementEntry; // from Requirement.h +struct RequirementEntry; // from Requirement.h /** * @brief The ModuleManager class is a singleton which manages Calamares modules. From bbb9ff0cbfef6d29bb7c431939a648f582fdc91d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Feb 2019 10:19:06 -0500 Subject: [PATCH 27/89] [libcalamaresui] Remove useless #define --- src/libcalamaresui/modulesystem/ModuleManager.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index d2d324451..c909d75cb 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -32,15 +32,10 @@ #include #include -#define MODULE_CONFIG_FILENAME "module.desc" - namespace Calamares { - - ModuleManager* ModuleManager::s_instance = nullptr; - ModuleManager* ModuleManager::instance() { @@ -94,7 +89,7 @@ ModuleManager::doInit() bool success = currentDir.cd( subdir ); if ( success ) { - QFileInfo descriptorFileInfo( currentDir.absoluteFilePath( MODULE_CONFIG_FILENAME ) ); + QFileInfo descriptorFileInfo( currentDir.absoluteFilePath( QLatin1Literal( "module.desc") ) ); if ( ! ( descriptorFileInfo.exists() && descriptorFileInfo.isReadable() ) ) { cDebug() << Q_FUNC_INFO << "unreadable file: " From 651b52ead94c34e9f3d91f281f880b22d5252f43 Mon Sep 17 00:00:00 2001 From: Dan Simmons Date: Wed, 20 Feb 2019 05:00:58 -0500 Subject: [PATCH 28/89] Fix spelling typo --- src/modules/partition/gui/ChoicePage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 7c980cf49..21783c251 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -1248,7 +1248,7 @@ ChoicePage::setupActions() } if ( PartUtils::canBeReplaced( *it ) ) { - cDebug() << ".. contains replacable" << it; + cDebug() << ".. contains replaceable" << it; atLeastOneCanBeReplaced = true; } if ( (*it)->isMounted() ) From c678cd80b487527525db2452ac20ed08b50ad801 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 20 Feb 2019 05:48:15 -0500 Subject: [PATCH 29/89] [libcalamaresui] Refactor Requirements-Checking - Move the actual checking into a separate object with some lifecycle- management signals. - Right now this is still single-threaded and blocking, so no net gain. --- src/libcalamaresui/CMakeLists.txt | 1 + .../modulesystem/ModuleManager.cpp | 41 ++++------- .../modulesystem/ModuleManager.h | 2 + .../modulesystem/RequirementsChecker.cpp | 73 +++++++++++++++++++ .../modulesystem/RequirementsChecker.h | 66 +++++++++++++++++ 5 files changed, 158 insertions(+), 25 deletions(-) create mode 100644 src/libcalamaresui/modulesystem/RequirementsChecker.cpp create mode 100644 src/libcalamaresui/modulesystem/RequirementsChecker.h diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index 381909025..99531e5ff 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -6,6 +6,7 @@ set( calamaresui_SOURCES modulesystem/ModuleManager.cpp modulesystem/ProcessJobModule.cpp modulesystem/Requirement.cpp + modulesystem/RequirementsChecker.cpp modulesystem/ViewModule.cpp utils/CalamaresUtilsGui.cpp diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index c909d75cb..4133c6cae 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -21,11 +21,13 @@ #include "ExecutionViewStep.h" #include "Module.h" -#include "utils/Logger.h" -#include "utils/YamlUtils.h" +#include "RequirementsChecker.h" #include "Settings.h" #include "ViewManager.h" +#include "utils/Logger.h" +#include "utils/YamlUtils.h" + #include #include @@ -306,32 +308,21 @@ void ModuleManager::checkRequirements() { cDebug() << "Checking module requirements .."; - QTimer::singleShot( 0, this, [ this ]() + + QVector< Module* > modules( m_loadedModulesByInstanceKey.count() ); + int count = 0; + for (const auto& module : m_loadedModulesByInstanceKey ) { - bool acceptable = true; + modules[count++] = module; + } - for (const auto& module : m_loadedModulesByInstanceKey ) - { - RequirementsList l = module->checkRequirements(); - if ( l.length() > 0 ) - { - cDebug() << " .." << module->name() << "has" << l.length() << "requirements"; - emit requirementsResult( l ); - } - int count = 0; - for (const auto& r : l) - { - if ( r.mandatory && !r.satisfied ) - { - cDebug() << " .. requirement" << count << r.name << "is not satisfied."; - acceptable = false; - } - ++count; - } - } + RequirementsChecker *rq = new RequirementsChecker( modules, this ); + connect( rq, &RequirementsChecker::requirementsResult, this, &ModuleManager::requirementsResult ); + connect( rq, &RequirementsChecker::requirementsComplete, this, &ModuleManager::requirementsComplete ); + connect( rq, &RequirementsChecker::done, rq, &RequirementsChecker::deleteLater ); + connect( rq, &RequirementsChecker::requirementsProgress, this, &ModuleManager::requirementsProgress ); - emit requirementsComplete( acceptable ); - } ); + QTimer::singleShot( 0, rq, &RequirementsChecker::run ); } QStringList diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index fc88ef0b5..e235ff8f5 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -93,8 +93,10 @@ signals: void initDone(); void modulesLoaded(); /// All of the modules were loaded successfully void modulesFailed( QStringList ); /// .. or not + // Below, see RequirementsChecker documentation void requirementsComplete( bool ); void requirementsResult( RequirementsList& ); + void requirementsProgress( const QString& ); private slots: void doInit(); diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp new file mode 100644 index 000000000..2cd618b4b --- /dev/null +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -0,0 +1,73 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * 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 "RequirementsChecker.h" + +#include "Module.h" +#include "Requirement.h" + +#include "utils/Logger.h" + +#include + +namespace Calamares +{ + +RequirementsChecker::RequirementsChecker( QVector< Module* > modules, QObject* parent ) + : QObject( parent ) + , m_modules( std::move( modules ) ) +{ +} + +RequirementsChecker::~RequirementsChecker() +{ +} + +void +RequirementsChecker::run() +{ + bool acceptable = true; + + for (const auto& module : m_modules ) + { + RequirementsList l = module->checkRequirements(); + if ( l.length() > 0 ) + { + cDebug() << " .." << module->name() << "has" << l.length() << "requirements"; + emit requirementsResult( l ); + } + + int count = 0; + for (const auto& r : l) + { + if ( r.mandatory && !r.satisfied ) + { + cDebug() << " .. requirement" << count << r.name << "is not satisfied."; + acceptable = false; + } + ++count; + } + } + + emit requirementsComplete( acceptable ); + + QTimer::singleShot(0, this, &RequirementsChecker::done ); +} + + +} diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.h b/src/libcalamaresui/modulesystem/RequirementsChecker.h new file mode 100644 index 000000000..61346e750 --- /dev/null +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.h @@ -0,0 +1,66 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, Adriaan de Groot + * + * 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 CALAMARES_REQUIREMENTSCHECKER_H +#define CALAMARES_REQUIREMENTSCHECKER_H + +#include +#include + +#include "Requirement.h" + +namespace Calamares +{ + +class Module; + +/** @brief A manager-class that checks all the module requirements + * + * Asynchronously checks the requirements for each module, and + * emits progress signals as appropriate. + */ +class RequirementsChecker : public QObject +{ + Q_OBJECT + +public: + RequirementsChecker( QVector< Module* > modules, QObject* parent = nullptr ); + virtual ~RequirementsChecker() override; + +public slots: + void run(); + +signals: + /// @brief Human-readable progress message + void requirementsProgress( const QString& ); + /// @brief Requirements from a single module + void requirementsResult( RequirementsList& ); + /** @brief When all requirements are collected + * + * The argument indicates if all mandatory requirements are satisfied. + */ + void requirementsComplete( bool ); + /// @brief Emitted after requirementsComplete + void done(); + +private: + QVector< Module* > m_modules; +} ; + +} + +#endif From 3ea6c6cfbec8d303a6ebe1dba2e154091e0fd43c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 21 Feb 2019 06:40:49 -0500 Subject: [PATCH 30/89] [users] Rename badly-named variable --- src/modules/users/CreateUserJob.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/modules/users/CreateUserJob.cpp b/src/modules/users/CreateUserJob.cpp index 052af87c6..d7e356231 100644 --- a/src/modules/users/CreateUserJob.cpp +++ b/src/modules/users/CreateUserJob.cpp @@ -154,29 +154,29 @@ CreateUserJob::exec() useradd << "-c" << m_fullName; useradd << m_userName; - auto pres = CalamaresUtils::System::instance()->targetEnvCommand( useradd ); - if ( pres.getExitCode() ) + auto commandResult = CalamaresUtils::System::instance()->targetEnvCommand( useradd ); + if ( commandResult.getExitCode() ) { - cError() << "useradd failed" << pres.getExitCode(); - return pres.explainProcess( useradd, 10 /* bogus timeout */ ); + cError() << "useradd failed" << commandResult.getExitCode(); + return commandResult.explainProcess( useradd, 10 /* bogus timeout */ ); } - pres = CalamaresUtils::System::instance()->targetEnvCommand( + commandResult = CalamaresUtils::System::instance()->targetEnvCommand( { "usermod", "-aG", defaultGroups, m_userName } ); - if ( pres.getExitCode() ) + if ( commandResult.getExitCode() ) { - cError() << "usermod failed" << pres.getExitCode(); - return pres.explainProcess( "usermod", 10 ); + cError() << "usermod failed" << commandResult.getExitCode(); + return commandResult.explainProcess( "usermod", 10 ); } QString userGroup = QString( "%1:%2" ).arg( m_userName ).arg( m_userName ); QString homeDir = QString( "/home/%1" ).arg( m_userName ); - pres = CalamaresUtils::System::instance()->targetEnvCommand( + commandResult = CalamaresUtils::System::instance()->targetEnvCommand( { "chown", "-R", userGroup, homeDir } ); - if ( pres.getExitCode() ) + if ( commandResult.getExitCode() ) { - cError() << "chown failed" << pres.getExitCode(); - return pres.explainProcess( "chown", 10 ); + cError() << "chown failed" << commandResult.getExitCode(); + return commandResult.explainProcess( "chown", 10 ); } return Calamares::JobResult::ok(); From 586cb63ef5209bd532f1695bf89bc64816d6fe7f Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Fri, 22 Feb 2019 12:58:55 +0100 Subject: [PATCH 31/89] [partition] use configured default filesystem type instead of ext4 When using the default partition layout (only a `/` partition), the filesystem used was ext4, ignoring the `defaultFileSystemType` configuration option. This commit fixes this bug, so that any supported filesystem can now be used for the default partitioning scheme. Fixes #1093 Signed-off-by: Arnaud Ferraris --- .../partition/core/PartitionLayout.cpp | 22 ++++++++++++++++++- src/modules/partition/core/PartitionLayout.h | 1 + 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index c2489620f..a17e764e8 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -18,6 +18,9 @@ * along with Calamares. If not, see . */ +#include "GlobalStorage.h" +#include "JobQueue.h" + #include "core/PartitionLayout.h" #include "core/KPMHelpers.h" @@ -28,17 +31,32 @@ #include #include +static int +getDefaultFileSystemType() +{ + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + int defaultFs = FileSystem::typeForName( gs->value( "defaultFileSystemType" ).toString() ); + + if ( defaultFs == FileSystem::Unknown ) + defaultFs = FileSystem::Ext4; + + return defaultFs; +} + PartitionLayout::PartitionLayout() { + defaultFsType = getDefaultFileSystemType(); } PartitionLayout::PartitionLayout( PartitionLayout::PartitionEntry entry ) { + defaultFsType = getDefaultFileSystemType(); partLayout.append( entry ); } PartitionLayout::PartitionLayout( const PartitionLayout& layout ) : partLayout( layout.partLayout ) + , defaultFsType( layout.defaultFsType ) { } @@ -115,7 +133,7 @@ PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const PartitionLayout::PartitionEntry entry( size, min ); entry.partMountPoint = mountPoint; - entry.partFileSystem = FileSystem::Ext4; + entry.partFileSystem = defaultFsType; partLayout.append( entry ); } @@ -128,6 +146,8 @@ PartitionLayout::addEntry( const QString& label, const QString& mountPoint, cons entry.partLabel = label; entry.partMountPoint = mountPoint; entry.partFileSystem = FileSystem::typeForName( fs ); + if ( entry.partFileSystem == FileSystem::Unknown ) + entry.partFileSystem = defaultFsType; partLayout.append( entry ); } diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 5e216122c..63ea8d9ec 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -76,6 +76,7 @@ public: QList< Partition* > execute( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, PartitionNode* parent, const PartitionRole& role ); private: + int defaultFsType; QList< PartitionEntry > partLayout; }; From 79c20b8fbd6ca072c0e301d79dc36a359dac9d86 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 22 Feb 2019 07:03:38 -0500 Subject: [PATCH 32/89] [partition] Fix user-visible strings - The default window title in the designer file wasn't a good string to translate. Use one of the titles instanced from elsewhere. - The window titles set in subclasses were not translatable. FIXES #1092 --- src/modules/partition/gui/CreateVolumeGroupDialog.cpp | 2 +- src/modules/partition/gui/ResizeVolumeGroupDialog.cpp | 2 +- src/modules/partition/gui/VolumeGroupBaseDialog.ui | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/gui/CreateVolumeGroupDialog.cpp b/src/modules/partition/gui/CreateVolumeGroupDialog.cpp index fe5c40be8..a255e9902 100644 --- a/src/modules/partition/gui/CreateVolumeGroupDialog.cpp +++ b/src/modules/partition/gui/CreateVolumeGroupDialog.cpp @@ -34,7 +34,7 @@ CreateVolumeGroupDialog::CreateVolumeGroupDialog( QString& vgName, , m_selectedPVs( selectedPVs ) , m_peSize( pSize ) { - setWindowTitle( "Create Volume Group" ); + setWindowTitle( tr( "Create Volume Group" ) ); peSize()->setValue( pSize ); diff --git a/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp b/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp index b3173096d..35b6bbdf1 100644 --- a/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp +++ b/src/modules/partition/gui/ResizeVolumeGroupDialog.cpp @@ -35,7 +35,7 @@ ResizeVolumeGroupDialog::ResizeVolumeGroupDialog( LvmDevice *device, : VolumeGroupBaseDialog( device->name(), device->physicalVolumes(), parent ) , m_selectedPVs( selectedPVs ) { - setWindowTitle( "Resize Volume Group" ); + setWindowTitle( tr( "Resize Volume Group" ) ); for ( int i = 0; i < pvList()->count(); i++ ) pvList()->item(i)->setCheckState( Qt::Checked ); diff --git a/src/modules/partition/gui/VolumeGroupBaseDialog.ui b/src/modules/partition/gui/VolumeGroupBaseDialog.ui index b45d204e2..f84cf22d0 100644 --- a/src/modules/partition/gui/VolumeGroupBaseDialog.ui +++ b/src/modules/partition/gui/VolumeGroupBaseDialog.ui @@ -11,7 +11,7 @@ - VolumeGroupDialog + Create Volume Group From 5084c44b54784a03b6c9751ea1c109cff0cd161f Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Fri, 22 Feb 2019 13:08:59 +0100 Subject: [PATCH 33/89] [partition] fix naming of PartitionLayout class member variables Signed-off-by: Arnaud Ferraris --- .../partition/core/PartitionLayout.cpp | 22 +++++++++---------- src/modules/partition/core/PartitionLayout.h | 4 ++-- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index a17e764e8..f6521cea7 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -45,18 +45,18 @@ getDefaultFileSystemType() PartitionLayout::PartitionLayout() { - defaultFsType = getDefaultFileSystemType(); + m_defaultFsType = getDefaultFileSystemType(); } PartitionLayout::PartitionLayout( PartitionLayout::PartitionEntry entry ) { - defaultFsType = getDefaultFileSystemType(); - partLayout.append( entry ); + m_defaultFsType = getDefaultFileSystemType(); + m_partLayout.append( entry ); } PartitionLayout::PartitionLayout( const PartitionLayout& layout ) - : partLayout( layout.partLayout ) - , defaultFsType( layout.defaultFsType ) + : m_partLayout( layout.m_partLayout ) + , m_defaultFsType( layout.m_defaultFsType ) { } @@ -67,7 +67,7 @@ PartitionLayout::~PartitionLayout() void PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry ) { - partLayout.append( entry ); + m_partLayout.append( entry ); } static double @@ -133,9 +133,9 @@ PartitionLayout::addEntry( const QString& mountPoint, const QString& size, const PartitionLayout::PartitionEntry entry( size, min ); entry.partMountPoint = mountPoint; - entry.partFileSystem = defaultFsType; + entry.partFileSystem = m_defaultFsType; - partLayout.append( entry ); + m_partLayout.append( entry ); } void @@ -147,9 +147,9 @@ PartitionLayout::addEntry( const QString& label, const QString& mountPoint, cons entry.partMountPoint = mountPoint; entry.partFileSystem = FileSystem::typeForName( fs ); if ( entry.partFileSystem == FileSystem::Unknown ) - entry.partFileSystem = defaultFsType; + entry.partFileSystem = m_defaultFsType; - partLayout.append( entry ); + m_partLayout.append( entry ); } static qint64 @@ -195,7 +195,7 @@ PartitionLayout::execute( Device *dev, qint64 firstSector, // TODO: Refine partition sizes to make sure there is room for every partition // Use a default (200-500M ?) minimum size for partition without minSize - foreach( const PartitionLayout::PartitionEntry& part, partLayout ) + foreach( const PartitionLayout::PartitionEntry& part, m_partLayout ) { Partition *currentPartition = nullptr; diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 63ea8d9ec..f2a4cbff5 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -76,8 +76,8 @@ public: QList< Partition* > execute( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, PartitionNode* parent, const PartitionRole& role ); private: - int defaultFsType; - QList< PartitionEntry > partLayout; + int m_defaultFsType; + QList< PartitionEntry > m_partLayout; }; #endif /* PARTITIONLAYOUT_H */ From cd92b8dd5ef97bfd2f5b459987060b27d05b1618 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 22 Feb 2019 09:21:22 -0500 Subject: [PATCH 34/89] [libcalamares] Simplify logging code - log() was never called with a non-default value for toDisk, so simplify to true. Keep the if() around to indicate block scope. --- src/libcalamares/utils/Logger.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcalamares/utils/Logger.cpp b/src/libcalamares/utils/Logger.cpp index 98aa2121f..b75fb6495 100644 --- a/src/libcalamares/utils/Logger.cpp +++ b/src/libcalamares/utils/Logger.cpp @@ -2,7 +2,7 @@ * * Copyright 2010-2011, Christian Muehlhaeuser * Copyright 2014, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -68,9 +68,9 @@ logLevel() } static void -log( const char* msg, unsigned int debugLevel, bool toDisk = true ) +log( const char* msg, unsigned int debugLevel ) { - if ( toDisk || debugLevel < s_threshold ) + if ( true ) { QMutexLocker lock( &s_mutex ); From 355987bfa13343f32a5f85a52a51e0b3ad219b70 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 22 Feb 2019 10:47:20 -0500 Subject: [PATCH 35/89] CMake: QtConcurrent is required as well. SEE #1082 --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e3740c141..0aeb8a584 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -240,7 +240,7 @@ include( CMakeColors ) ### DEPENDENCIES # -find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core Gui Widgets LinguistTools Svg Quick QuickWidgets ) +find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Concurrent Core Gui Widgets LinguistTools Svg Quick QuickWidgets ) find_package( YAMLCPP ${YAMLCPP_VERSION} REQUIRED ) if( INSTALL_POLKIT ) find_package( PolkitQt5-1 REQUIRED ) From 74ead4c7bad673d6099d198f80a5524988264cde Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Fri, 22 Feb 2019 18:42:16 +0100 Subject: [PATCH 36/89] [partition] improve filesystem search operation Due to changes to the FileSsytem::typeForName() function, more processing is needed to deal with locales and different cases. This is done by refactoring the findFS() function, initially located in the PartitionViewStep class, and making it available to the whole module. Additionnally, more checks have been implemented regarding the use of global storage in the PartitionLayout class, and the filesystem types now use the correct FileSystem::Type, as requested. Signed-off-by: Arnaud Ferraris --- src/modules/partition/core/PartUtils.cpp | 50 ++++++++++++++ src/modules/partition/core/PartUtils.h | 13 ++++ .../partition/core/PartitionLayout.cpp | 21 +++--- src/modules/partition/core/PartitionLayout.h | 5 +- .../partition/gui/PartitionViewStep.cpp | 65 +++++-------------- 5 files changed, 94 insertions(+), 60 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index d61064041..d09bcd149 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -408,6 +408,56 @@ isEfiBootable( const Partition* candidate ) flags.testFlag( PartitionTable::FlagBoot ); } +QString +findFS( QString fsName, FileSystem::Type* fsType ) +{ + QStringList fsLanguage { QLatin1Literal( "C" ) }; // Required language list to turn off localization + if ( fsName.isEmpty() ) + fsName = QStringLiteral( "ext4" ); + + FileSystem::Type tmpType = FileSystem::typeForName( fsName, fsLanguage ); + if ( tmpType != FileSystem::Unknown ) + { + cDebug() << "Found filesystem" << fsName; + if ( fsType ) + *fsType = tmpType; + return fsName; + } + + // Second pass: try case-insensitive + const auto fstypes = FileSystem::types(); + for ( FileSystem::Type t : fstypes ) + { + if ( 0 == QString::compare( fsName, FileSystem::nameForType( t, fsLanguage ), Qt::CaseInsensitive ) ) + { + QString fsRealName = FileSystem::nameForType( t, fsLanguage ); + cDebug() << "Filesystem name" << fsName << "translated to" << fsRealName; + if ( fsType ) + *fsType = t; + return fsRealName; + } + } + + cDebug() << "Filesystem" << fsName << "not found, using ext4"; + fsName = QStringLiteral( "ext4" ); + // fsType can be used to check whether fsName was a valid filesystem. + if (fsType) + *fsType = FileSystem::Unknown; +#ifdef DEBUG_FILESYSTEMS + // This bit is for distro's debugging their settings, and shows + // all the strings that KPMCore is matching against for FS type. + { + Logger::CDebug d; + using TR = Logger::DebugRow< int, QString >; + const auto fstypes = FileSystem::types(); + d << "Available types (" << fstypes.count() << ')'; + for ( FileSystem::Type t : fstypes ) + d << TR( static_cast( t ), FileSystem::nameForType( t, fsLanguage ) ); + } +#endif + return fsName; +} + } // nmamespace PartUtils /* Implementation of methods for FstabEntry, from OsproberEntry.h */ diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index b94e20567..c7da86c06 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -22,6 +22,10 @@ #include "OsproberEntry.h" +// KPMcore +#include + +// Qt #include class PartitionCoreModule; @@ -73,6 +77,15 @@ bool isEfiSystem(); * the partition table layout, this may mean different flags. */ bool isEfiBootable( const Partition* candidate ); + +/** @brief translate @p fsName into a recognized name and type + * + * Makes several attempts to translate the string into a + * name that KPMCore will recognize. + * The corresponding filesystem type is stored in @p fsType, and + * its value is FileSystem::Unknown if @p fsName is not recognized. + */ +QString findFS( QString fsName, FileSystem::Type* fsType ); } #endif // PARTUTILS_H diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index f6521cea7..39341fddd 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -26,21 +26,26 @@ #include "core/KPMHelpers.h" #include "core/PartitionActions.h" #include "core/PartitionInfo.h" +#include "core/PartUtils.h" #include #include #include -static int +static FileSystem::Type getDefaultFileSystemType() { Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - int defaultFs = FileSystem::typeForName( gs->value( "defaultFileSystemType" ).toString() ); + FileSystem::Type defaultFS = FileSystem::Ext4; - if ( defaultFs == FileSystem::Unknown ) - defaultFs = FileSystem::Ext4; + if ( gs->contains( "defaultFileSystemType" ) ) + { + PartUtils::findFS( gs->value( "defaultFileSystemType" ).toString(), &defaultFS); + if ( defaultFS == FileSystem::Unknown ) + defaultFS = FileSystem::Ext4; + } - return defaultFs; + return defaultFS; } PartitionLayout::PartitionLayout() @@ -145,7 +150,7 @@ PartitionLayout::addEntry( const QString& label, const QString& mountPoint, cons entry.partLabel = label; entry.partMountPoint = mountPoint; - entry.partFileSystem = FileSystem::typeForName( fs ); + PartUtils::findFS( fs, &entry.partFileSystem ); if ( entry.partFileSystem == FileSystem::Unknown ) entry.partFileSystem = m_defaultFsType; @@ -214,7 +219,7 @@ PartitionLayout::execute( Device *dev, qint64 firstSector, parent, *dev, role, - static_cast(part.partFileSystem), + part.partFileSystem, firstSector, end, PartitionTable::FlagNone @@ -226,7 +231,7 @@ PartitionLayout::execute( Device *dev, qint64 firstSector, parent, *dev, role, - static_cast(part.partFileSystem), + part.partFileSystem, firstSector, end, luksPassphrase, diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index f2a4cbff5..999e10425 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -24,6 +24,7 @@ // KPMcore #include +#include // Qt #include @@ -48,7 +49,7 @@ public: { QString partLabel; QString partMountPoint; - int partFileSystem = 0; + FileSystem::Type partFileSystem = FileSystem::Unknown; double partSize = 0.0L; SizeUnit partSizeUnit = Percent; double partMinSize = 0.0L; @@ -76,7 +77,7 @@ public: QList< Partition* > execute( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, PartitionNode* parent, const PartitionRole& role ); private: - int m_defaultFsType; + FileSystem::Type m_defaultFsType; QList< PartitionEntry > m_partLayout; }; diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index a152db14b..3c71302e0 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -493,55 +493,6 @@ nameToChoice( QString name, bool& ok ) return names.find( name, ok ); } -/** @brief translate @p defaultFS into a recognized name - * - * Makes several attempts to translate the string into a - * name that KPMCore will recognize. - */ -static QString -findFS( QString defaultFS ) -{ - QStringList fsLanguage { QLatin1Literal( "C" ) }; // Required language list to turn off localization - if ( defaultFS.isEmpty() ) - { - cWarning() << "Partition-module setting *defaultFileSystemType* is missing, using ext4"; - defaultFS = QStringLiteral( "ext4" ); - } - if ( FileSystem::typeForName( defaultFS, fsLanguage ) != FileSystem::Unknown ) - { - cDebug() << "Partition-module setting *defaultFileSystemType*" << defaultFS; - return defaultFS; - } - - // Second pass: try case-insensitive - const auto fstypes = FileSystem::types(); - for ( FileSystem::Type t : fstypes ) - { - if ( 0 == QString::compare( defaultFS, FileSystem::nameForType( t, fsLanguage ), Qt::CaseInsensitive ) ) - { - defaultFS = FileSystem::nameForType( t, fsLanguage ); - cWarning() << "Partition-module setting *defaultFileSystemType* changed" << defaultFS; - return defaultFS; - } - } - - cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << defaultFS << ") using ext4."; - defaultFS = QStringLiteral( "ext4" ); -#ifdef DEBUG_FILESYSTEMS - // This bit is for distro's debugging their settings, and shows - // all the strings that KPMCore is matching against for FS type. - { - Logger::CDebug d; - using TR = Logger::DebugRow< int, QString >; - const auto fstypes = FileSystem::types(); - d << "Available types (" << fstypes.count() << ')'; - for ( FileSystem::Type t : fstypes ) - d << TR( static_cast( t ), FileSystem::nameForType( t, fsLanguage ) ); - } -#endif - return defaultFS; -} - void PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { @@ -630,7 +581,21 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) gs->insert( "alwaysShowPartitionLabels", CalamaresUtils::getBool( configurationMap, "alwaysShowPartitionLabels", true ) ); gs->insert( "enableLuksAutomatedPartitioning", CalamaresUtils::getBool( configurationMap, "enableLuksAutomatedPartitioning", true ) ); gs->insert( "allowManualPartitioning", CalamaresUtils::getBool( configurationMap, "allowManualPartitioning", true ) ); - gs->insert( "defaultFileSystemType", findFS( CalamaresUtils::getString( configurationMap, "defaultFileSystemType" ) ) ); + + // The defaultFileSystemType setting needs a bit more processing, + // as we want to cover various cases (such as different cases) + QString fsName = CalamaresUtils::getString( configurationMap, "defaultFileSystemType" ); + FileSystem::Type fsType; + if ( fsName.isEmpty() ) + cWarning() << "Partition-module setting *defaultFileSystemType* is missing, will use ext4"; + QString fsRealName = PartUtils::findFS( fsName, &fsType ); + if ( fsRealName == fsName ) + cDebug() << "Partition-module setting *defaultFileSystemType*" << fsRealName; + else if ( fsType != FileSystem::Unknown ) + cWarning() << "Partition-module setting *defaultFileSystemType* changed" << fsRealName; + else + cWarning() << "Partition-module setting *defaultFileSystemType* is bad (" << fsRealName << ") using ext4."; + gs->insert( "defaultFileSystemType", fsRealName ); // Now that we have the config, we load the PartitionCoreModule in the background From e366e7d83ac99f768b0bbb4c5c33966de876b388 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 22 Feb 2019 16:38:02 -0500 Subject: [PATCH 37/89] [displaymanager] It's not fatal to have no DM - If a distro provides an install-scenario that doesn't provide a DM, (e.g. via netinstall) then that should be ok; if there **is** a DM it should be configured. FIXES: #1095 --- src/modules/displaymanager/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/displaymanager/main.py b/src/modules/displaymanager/main.py index 08eeb6fdb..4413aefbb 100644 --- a/src/modules/displaymanager/main.py +++ b/src/modules/displaymanager/main.py @@ -768,11 +768,11 @@ def run(): displaymanagers.remove(dm) if not dm_impl: - return ( - _("No display managers selected for the displaymanager module."), - _("The list is empty after checking for installed display managers.") + libcalamares.utils.warning( + "No display managers selected for the displaymanager module. " + "The list is empty after checking for installed display managers." ) - + return None # Pick up remaining settings if "defaultDesktopEnvironment" in libcalamares.job.configuration: From 6090a464f899c8859efcffae0d7b0ae12a46916c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 11:12:55 -0500 Subject: [PATCH 38/89] [libcalamaresui] Switch requirementschecking to threaded mode - Use QFuture and QFutureWatcher to spawn threads that do the actual checking of the requirements; collect results and report on them as they come in. --- .../modulesystem/RequirementsChecker.cpp | 59 +++++++++++++++---- .../modulesystem/RequirementsChecker.h | 10 ++++ 2 files changed, 56 insertions(+), 13 deletions(-) diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp index 2cd618b4b..74f07e142 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -23,15 +23,32 @@ #include "utils/Logger.h" +#include + +#include +#include +#include #include + namespace Calamares { +void +check( Module * const &m, RequirementsChecker *c ) +{ + RequirementsList l = m->checkRequirements(); + if ( l.count() > 0 ) + c->addCheckedRequirements( l ); + c->requirementsProgress( QObject::tr( "Requirements checking for module %1 is complete." ).arg( m->name() ) ); +} + RequirementsChecker::RequirementsChecker( QVector< Module* > modules, QObject* parent ) : QObject( parent ) , m_modules( std::move( modules ) ) { + m_watchers.reserve( m_modules.count() ); + m_collectedRequirements.reserve( m_modules.count() ); } RequirementsChecker::~RequirementsChecker() @@ -41,19 +58,25 @@ RequirementsChecker::~RequirementsChecker() void RequirementsChecker::run() { - bool acceptable = true; - for (const auto& module : m_modules ) { - RequirementsList l = module->checkRequirements(); - if ( l.length() > 0 ) - { - cDebug() << " .." << module->name() << "has" << l.length() << "requirements"; - emit requirementsResult( l ); - } + Watcher *watcher = new Watcher( this ); + watcher->setFuture( QtConcurrent::run( check, module, this ) ); + m_watchers.append( watcher ); + connect( watcher, &Watcher::finished, this, &RequirementsChecker::finished ); + } +} +void +RequirementsChecker::finished() +{ + if ( std::all_of( m_watchers.cbegin(), m_watchers.cend(), []( const Watcher *w ) { return w && w->isFinished(); } ) ) + { + cDebug() << "All requirements have been checked."; + + bool acceptable = true; int count = 0; - for (const auto& r : l) + for ( const auto& r : m_collectedRequirements ) { if ( r.mandatory && !r.satisfied ) { @@ -62,12 +85,22 @@ RequirementsChecker::run() } ++count; } + + emit requirementsComplete( acceptable ); + QTimer::singleShot(0, this, &RequirementsChecker::done ); } - - emit requirementsComplete( acceptable ); - - QTimer::singleShot(0, this, &RequirementsChecker::done ); } +void +RequirementsChecker::addCheckedRequirements( RequirementsList l ) +{ + static QMutex addMutex; + { + QMutexLocker lock( &addMutex ); + m_collectedRequirements.append( l ); + } + cDebug() << "Added" << l.count() << "requirement results"; + emit requirementsResult( l ); +} } diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.h b/src/libcalamaresui/modulesystem/RequirementsChecker.h index 61346e750..a3f0b9c3e 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.h +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.h @@ -18,6 +18,7 @@ #ifndef CALAMARES_REQUIREMENTSCHECKER_H #define CALAMARES_REQUIREMENTSCHECKER_H +#include #include #include @@ -44,6 +45,10 @@ public: public slots: void run(); + void addCheckedRequirements( RequirementsList ); + + void finished(); + signals: /// @brief Human-readable progress message void requirementsProgress( const QString& ); @@ -59,6 +64,11 @@ signals: private: QVector< Module* > m_modules; + + using Watcher = QFutureWatcher< void >; + QVector< Watcher* > m_watchers; + + RequirementsList m_collectedRequirements; } ; } From c1cd88d5fa96fb35ddaffdf64557fac8ee1f2d81 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 12:22:08 -0500 Subject: [PATCH 39/89] [welcome] Rename files before class-rename --- .../checker/{RequirementsChecker.cpp => GeneralRequirements.cpp} | 0 .../checker/{RequirementsChecker.h => GeneralRequirements.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename src/modules/welcome/checker/{RequirementsChecker.cpp => GeneralRequirements.cpp} (100%) rename src/modules/welcome/checker/{RequirementsChecker.h => GeneralRequirements.h} (100%) diff --git a/src/modules/welcome/checker/RequirementsChecker.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp similarity index 100% rename from src/modules/welcome/checker/RequirementsChecker.cpp rename to src/modules/welcome/checker/GeneralRequirements.cpp diff --git a/src/modules/welcome/checker/RequirementsChecker.h b/src/modules/welcome/checker/GeneralRequirements.h similarity index 100% rename from src/modules/welcome/checker/RequirementsChecker.h rename to src/modules/welcome/checker/GeneralRequirements.h From a19d81e38c00abce2f61ccbc7997613c585bf4eb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 12:29:59 -0500 Subject: [PATCH 40/89] [welcome] Chase renaming of files - Rename the classes to match - Drop some unused includes --- src/modules/welcome/CMakeLists.txt | 2 +- src/modules/welcome/WelcomePage.cpp | 1 - src/modules/welcome/WelcomeViewStep.cpp | 4 +- src/modules/welcome/WelcomeViewStep.h | 4 +- src/modules/welcome/checker/CheckerWidget.h | 1 - .../welcome/checker/GeneralRequirements.cpp | 46 +++++++++---------- .../welcome/checker/GeneralRequirements.h | 8 ++-- 7 files changed, 32 insertions(+), 34 deletions(-) diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index 38fa33ca8..915f5fd2c 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -18,7 +18,7 @@ set( CHECKER_SOURCES checker/CheckerContainer.cpp checker/CheckerWidget.cpp checker/CheckItemWidget.cpp - checker/RequirementsChecker.cpp + checker/GeneralRequirements.cpp ${PARTMAN_SRC} ) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index 7af42687d..fe24b7c34 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -23,7 +23,6 @@ #include "ui_WelcomePage.h" #include "CalamaresVersion.h" #include "checker/CheckerContainer.h" -#include "checker/RequirementsChecker.h" #include "utils/Logger.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Retranslator.h" diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 003de802f..6a36dd0a1 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -20,7 +20,7 @@ #include "WelcomeViewStep.h" #include "WelcomePage.h" -#include "checker/RequirementsChecker.h" +#include "checker/GeneralRequirements.h" #include "utils/Logger.h" @@ -30,7 +30,7 @@ CALAMARES_PLUGIN_FACTORY_DEFINITION( WelcomeViewStepFactory, registerPlugin class WelcomePage; -class RequirementsChecker; +class GeneralRequirements; class PLUGINDLLEXPORT WelcomeViewStep : public Calamares::ViewStep { @@ -61,7 +61,7 @@ public: private: WelcomePage* m_widget; - RequirementsChecker* m_requirementsChecker; + GeneralRequirements* m_requirementsChecker; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( WelcomeViewStepFactory ) diff --git a/src/modules/welcome/checker/CheckerWidget.h b/src/modules/welcome/checker/CheckerWidget.h index 6f5864b1b..81eb6fef0 100644 --- a/src/modules/welcome/checker/CheckerWidget.h +++ b/src/modules/welcome/checker/CheckerWidget.h @@ -20,7 +20,6 @@ #define CHECKERWIDGET_H #include "modulesystem/Requirement.h" -#include "RequirementsChecker.h" #include #include diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 5225d1dbe..6aba2a2e9 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -18,7 +18,7 @@ * along with Calamares. If not, see . */ -#include "RequirementsChecker.h" +#include "GeneralRequirements.h" #include "CheckerContainer.h" #include "partman_devices.h" @@ -53,14 +53,14 @@ #include //geteuid -RequirementsChecker::RequirementsChecker( QObject* parent ) +GeneralRequirements::GeneralRequirements( QObject* parent ) : QObject( parent ) , m_requiredStorageGB( -1 ) , m_requiredRamGB( -1 ) { } -Calamares::RequirementsList RequirementsChecker::checkRequirements() +Calamares::RequirementsList GeneralRequirements::checkRequirements() { QSize availableSize = qApp->desktop()->availableGeometry().size(); @@ -91,7 +91,7 @@ Calamares::RequirementsList RequirementsChecker::checkRequirements() isRoot = checkIsRoot(); using TR = Logger::DebugRow; - cDebug() << "RequirementsChecker output:" + cDebug() << "GeneralRequirements output:" << TR("enoughStorage", enoughStorage) << TR("enoughRam", enoughRam) << TR("hasPower", hasPower) @@ -159,7 +159,7 @@ Calamares::RequirementsList RequirementsChecker::checkRequirements() void -RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) +GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) { bool incompleteConfiguration = false; @@ -171,7 +171,7 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) } else { - cWarning() << "RequirementsChecker entry 'check' is incomplete."; + cWarning() << "GeneralRequirements entry 'check' is incomplete."; incompleteConfiguration = true; } @@ -183,14 +183,14 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) } else { - cWarning() << "RequirementsChecker entry 'required' is incomplete."; + cWarning() << "GeneralRequirements entry 'required' is incomplete."; incompleteConfiguration = true; } // Help out with consistency, but don't fix for ( const auto& r : m_entriesToRequire ) if ( !m_entriesToCheck.contains( r ) ) - cWarning() << "RequirementsChecker requires" << r << "but does not check it."; + cWarning() << "GeneralRequirements requires" << r << "but does not check it."; if ( configurationMap.contains( "requiredStorage" ) && ( configurationMap.value( "requiredStorage" ).type() == QVariant::Double || @@ -200,7 +200,7 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) m_requiredStorageGB = configurationMap.value( "requiredStorage" ).toDouble( &ok ); if ( !ok ) { - cWarning() << "RequirementsChecker entry 'requiredStorage' is invalid."; + cWarning() << "GeneralRequirements entry 'requiredStorage' is invalid."; m_requiredStorageGB = 3.; } @@ -208,7 +208,7 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) } else { - cWarning() << "RequirementsChecker entry 'requiredStorage' is missing."; + cWarning() << "GeneralRequirements entry 'requiredStorage' is missing."; m_requiredStorageGB = 3.; incompleteConfiguration = true; } @@ -221,14 +221,14 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) m_requiredRamGB = configurationMap.value( "requiredRam" ).toDouble( &ok ); if ( !ok ) { - cWarning() << "RequirementsChecker entry 'requiredRam' is invalid."; + cWarning() << "GeneralRequirements entry 'requiredRam' is invalid."; m_requiredRamGB = 1.; incompleteConfiguration = true; } } else { - cWarning() << "RequirementsChecker entry 'requiredRam' is missing."; + cWarning() << "GeneralRequirements entry 'requiredRam' is missing."; m_requiredRamGB = 1.; incompleteConfiguration = true; } @@ -240,7 +240,7 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) if ( m_checkHasInternetUrl.isEmpty() || !QUrl( m_checkHasInternetUrl ).isValid() ) { - cWarning() << "RequirementsChecker entry 'internetCheckUrl' is invalid in welcome.conf" << m_checkHasInternetUrl + cWarning() << "GeneralRequirements entry 'internetCheckUrl' is invalid in welcome.conf" << m_checkHasInternetUrl << "reverting to default (http://example.com)."; m_checkHasInternetUrl = "http://example.com"; incompleteConfiguration = true; @@ -248,7 +248,7 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) } else { - cWarning() << "RequirementsChecker entry 'internetCheckUrl' is undefined in welcome.conf," + cWarning() << "GeneralRequirements entry 'internetCheckUrl' is undefined in welcome.conf," "reverting to default (http://example.com)."; m_checkHasInternetUrl = "http://example.com"; @@ -257,17 +257,17 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) if ( incompleteConfiguration ) { - cWarning() << "RequirementsChecker configuration map:" << Logger::DebugMap( configurationMap ); + cWarning() << "GeneralRequirements configuration map:" << Logger::DebugMap( configurationMap ); } } bool -RequirementsChecker::checkEnoughStorage( qint64 requiredSpace ) +GeneralRequirements::checkEnoughStorage( qint64 requiredSpace ) { #ifdef WITHOUT_LIBPARTED Q_UNUSED( requiredSpace ); - cWarning() << "RequirementsChecker is configured without libparted."; + cWarning() << "GeneralRequirements is configured without libparted."; return false; #else return check_big_enough( requiredSpace ); @@ -276,7 +276,7 @@ RequirementsChecker::checkEnoughStorage( qint64 requiredSpace ) bool -RequirementsChecker::checkEnoughRam( qint64 requiredRam ) +GeneralRequirements::checkEnoughRam( qint64 requiredRam ) { // Ignore the guesstimate-factor; we get an under-estimate // which is probably the usable RAM for programs. @@ -286,7 +286,7 @@ RequirementsChecker::checkEnoughRam( qint64 requiredRam ) bool -RequirementsChecker::checkBatteryExists() +GeneralRequirements::checkBatteryExists() { const QFileInfo basePath( "/sys/class/power_supply" ); @@ -312,7 +312,7 @@ RequirementsChecker::checkBatteryExists() bool -RequirementsChecker::checkHasPower() +GeneralRequirements::checkHasPower() { const QString UPOWER_SVC_NAME( "org.freedesktop.UPower" ); const QString UPOWER_INTF_NAME( "org.freedesktop.UPower" ); @@ -343,7 +343,7 @@ RequirementsChecker::checkHasPower() bool -RequirementsChecker::checkHasInternet() +GeneralRequirements::checkHasInternet() { // default to true in the QNetworkAccessManager::UnknownAccessibility case QNetworkAccessManager qnam( this ); @@ -367,14 +367,14 @@ RequirementsChecker::checkHasInternet() bool -RequirementsChecker::checkIsRoot() +GeneralRequirements::checkIsRoot() { return !geteuid(); } void -RequirementsChecker::detectFirmwareType() +GeneralRequirements::detectFirmwareType() { QString fwType = QFile::exists( "/sys/firmware/efi/efivars" ) ? "efi" : "bios"; Calamares::JobQueue::instance()->globalStorage()->insert( "firmwareType", fwType ); diff --git a/src/modules/welcome/checker/GeneralRequirements.h b/src/modules/welcome/checker/GeneralRequirements.h index 40f984c05..0e3e341b0 100644 --- a/src/modules/welcome/checker/GeneralRequirements.h +++ b/src/modules/welcome/checker/GeneralRequirements.h @@ -17,19 +17,19 @@ * along with Calamares. If not, see . */ -#ifndef REQUIREMENTSCHECKER_H -#define REQUIREMENTSCHECKER_H +#ifndef GENERALREQUIREMENTS_H +#define GENERALREQUIREMENTS_H #include #include #include "modulesystem/Requirement.h" -class RequirementsChecker : public QObject +class GeneralRequirements : public QObject { Q_OBJECT public: - explicit RequirementsChecker( QObject* parent = nullptr ); + explicit GeneralRequirements( QObject* parent = nullptr ); void setConfigurationMap( const QVariantMap& configurationMap ); From e50c2bcb44b57a77751326a6f598621ac3055311 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 16:52:10 -0500 Subject: [PATCH 41/89] [grubcfg] REVERT d775cee4cfdba4047802c9821c1d80ef69cb81b4 This is causing issue #1073 and needs further thought. --- src/modules/grubcfg/main.py | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/modules/grubcfg/main.py b/src/modules/grubcfg/main.py index d3f292281..b19ebf588 100644 --- a/src/modules/grubcfg/main.py +++ b/src/modules/grubcfg/main.py @@ -62,12 +62,6 @@ def modify_grub_default(partitions, root_mount_point, distributor): cryptdevice_params = [] - # GRUB needs to decrypt the partition that /boot is on, which may be / or /boot - boot_mountpoint = "/" - for partition in partitions: - if partition["mountPoint"] == "/boot": - boot_mountpoint = "/boot" - if have_dracut: for partition in partitions: has_luks = "luksMapperName" in partition @@ -78,7 +72,7 @@ def modify_grub_default(partitions, root_mount_point, distributor): swap_outer_uuid = partition["luksUuid"] swap_outer_mappername = partition["luksMapperName"] - if (partition["mountPoint"] == boot_mountpoint and has_luks): + if (partition["mountPoint"] == "/" and has_luks): cryptdevice_params = [ "rd.luks.uuid={!s}".format(partition["luksUuid"]) ] @@ -88,7 +82,7 @@ def modify_grub_default(partitions, root_mount_point, distributor): if partition["fs"] == "linuxswap" and not has_luks: swap_uuid = partition["uuid"] - if (partition["mountPoint"] == boot_mountpoint and has_luks): + if (partition["mountPoint"] == "/" and has_luks): cryptdevice_params = [ "cryptdevice=UUID={!s}:{!s}".format( partition["luksUuid"], partition["luksMapperName"] From 2cdfe3543015f641fc11655cee3f9b0cedfe1eca Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 17:14:52 -0500 Subject: [PATCH 42/89] [welcome] Avoid threading warnings - The NAM is being created from a method call on the GeneralRequirements object in the requirements-checking thread, while the GR object itself was created in a different thread. This cross-thread parenting produces a warning, and we don't need the parent relationship here anyway. --- src/modules/welcome/checker/GeneralRequirements.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 6aba2a2e9..0a841eca1 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -346,7 +346,7 @@ bool GeneralRequirements::checkHasInternet() { // default to true in the QNetworkAccessManager::UnknownAccessibility case - QNetworkAccessManager qnam( this ); + QNetworkAccessManager qnam; bool hasInternet = qnam.networkAccessible() == QNetworkAccessManager::Accessible; if ( !hasInternet && qnam.networkAccessible() == QNetworkAccessManager::UnknownAccessibility ) From b169281b69cd2b45b04923370f2d45732d9c4792 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 17:41:24 -0500 Subject: [PATCH 43/89] [libcalamaresui] Use convenience type --- src/libcalamaresui/modulesystem/Requirement.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/Requirement.h b/src/libcalamaresui/modulesystem/Requirement.h index 69e170c94..5688d4e14 100644 --- a/src/libcalamaresui/modulesystem/Requirement.h +++ b/src/libcalamaresui/modulesystem/Requirement.h @@ -48,7 +48,7 @@ struct RequirementEntry TextFunction enumerationText; /// @brief User-visible string to show that the requirement is not met - std::function< QString() > negatedText; + TextFunction negatedText; bool satisfied; bool mandatory; From c508e3ed4d029faa473af8fc78b51b3a50c08ac3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 24 Feb 2019 09:07:44 -0500 Subject: [PATCH 44/89] [welcome] Show progress during requirements checking --- src/modules/welcome/WelcomePage.cpp | 1 + src/modules/welcome/checker/CheckerContainer.cpp | 8 +++++++- src/modules/welcome/checker/CheckerContainer.h | 2 ++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/modules/welcome/WelcomePage.cpp b/src/modules/welcome/WelcomePage.cpp index fe24b7c34..d4ae6c47a 100644 --- a/src/modules/welcome/WelcomePage.cpp +++ b/src/modules/welcome/WelcomePage.cpp @@ -48,6 +48,7 @@ WelcomePage::WelcomePage( QWidget* parent ) { connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsResult, m_checkingWidget, &CheckerContainer::requirementsChecked ); connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, m_checkingWidget, &CheckerContainer::requirementsComplete ); + connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsProgress, m_checkingWidget, &CheckerContainer::requirementsProgress ); ui->setupUi( this ); ui->verticalLayout->insertSpacing( 1, CalamaresUtils::defaultFontHeight() * 2 ); diff --git a/src/modules/welcome/checker/CheckerContainer.cpp b/src/modules/welcome/checker/CheckerContainer.cpp index cf843f399..6f46cd094 100644 --- a/src/modules/welcome/checker/CheckerContainer.cpp +++ b/src/modules/welcome/checker/CheckerContainer.cpp @@ -54,7 +54,7 @@ void CheckerContainer::requirementsComplete( bool ok ) m_checkerWidget->init( m_requirements ); layout()->removeWidget( m_waitingWidget ); m_waitingWidget->deleteLater(); - m_waitingWidget = nullptr; // Don't delete in constructor + m_waitingWidget = nullptr; // Don't delete in destructor m_checkerWidget->setParent( this ); layout()->addWidget( m_checkerWidget ); @@ -66,6 +66,12 @@ void CheckerContainer::requirementsChecked(const Calamares::RequirementsList& l) m_requirements.append( l ); } +void CheckerContainer::requirementsProgress(const QString& message) +{ + if ( m_waitingWidget ) + m_waitingWidget->setText( message ); +} + bool CheckerContainer::verdict() const { return m_verdict; diff --git a/src/modules/welcome/checker/CheckerContainer.h b/src/modules/welcome/checker/CheckerContainer.h index 3f8f9ce92..5a8a1865e 100644 --- a/src/modules/welcome/checker/CheckerContainer.h +++ b/src/modules/welcome/checker/CheckerContainer.h @@ -51,6 +51,8 @@ public slots: /** @brief All the requirements are complete, switch to list view */ void requirementsComplete( bool ); + void requirementsProgress( const QString& message ); + protected: WaitingWidget *m_waitingWidget; CheckerWidget *m_checkerWidget; From f1aa22d9e89cf2a2c9948fe285332f0094deaf6a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 24 Feb 2019 09:08:02 -0500 Subject: [PATCH 45/89] [libcalamaresui] Sort signals chronologically --- src/libcalamaresui/modulesystem/ModuleManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 4133c6cae..d3705729c 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -319,8 +319,8 @@ ModuleManager::checkRequirements() RequirementsChecker *rq = new RequirementsChecker( modules, this ); connect( rq, &RequirementsChecker::requirementsResult, this, &ModuleManager::requirementsResult ); connect( rq, &RequirementsChecker::requirementsComplete, this, &ModuleManager::requirementsComplete ); - connect( rq, &RequirementsChecker::done, rq, &RequirementsChecker::deleteLater ); connect( rq, &RequirementsChecker::requirementsProgress, this, &ModuleManager::requirementsProgress ); + connect( rq, &RequirementsChecker::done, rq, &RequirementsChecker::deleteLater ); QTimer::singleShot( 0, rq, &RequirementsChecker::run ); } From 41fecf341b2e2ce4e9a86c65fa23d4dbf2ed46a5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 24 Feb 2019 07:32:56 -0500 Subject: [PATCH 46/89] [libcalamaresui] Avoid metatype warnings at runtime - Register the types with the Qt type system. This is needed because we're passing them as signal and slot parameters across threads. --- .../modulesystem/ModuleManager.h | 2 +- src/libcalamaresui/modulesystem/Requirement.h | 4 ++++ .../modulesystem/RequirementsChecker.cpp | 23 ++++++++++++++++++- .../modulesystem/RequirementsChecker.h | 2 +- 4 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/libcalamaresui/modulesystem/ModuleManager.h b/src/libcalamaresui/modulesystem/ModuleManager.h index e235ff8f5..689d61a77 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.h +++ b/src/libcalamaresui/modulesystem/ModuleManager.h @@ -95,7 +95,7 @@ signals: void modulesFailed( QStringList ); /// .. or not // Below, see RequirementsChecker documentation void requirementsComplete( bool ); - void requirementsResult( RequirementsList& ); + void requirementsResult( RequirementsList ); void requirementsProgress( const QString& ); private slots: diff --git a/src/libcalamaresui/modulesystem/Requirement.h b/src/libcalamaresui/modulesystem/Requirement.h index 5688d4e14..bf2157f69 100644 --- a/src/libcalamaresui/modulesystem/Requirement.h +++ b/src/libcalamaresui/modulesystem/Requirement.h @@ -19,6 +19,7 @@ #define CALAMARES_REQUIREMENT_H #include +#include #include #include @@ -57,4 +58,7 @@ struct RequirementEntry using RequirementsList = QList< RequirementEntry >; } // namespace Calamares + +Q_DECLARE_METATYPE(Calamares::RequirementEntry) + #endif diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp index 74f07e142..17bb9771c 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -34,7 +34,26 @@ namespace Calamares { -void +static void +registerMetatypes() +{ + static bool done = false; + + if ( !done ) + { + qRegisterMetaType< RequirementEntry >( "RequirementEntry" ); + // It's sensitive to the names of types in parameters; in particular + // althrough QList is the same as RequirementsList, + // because we *name* the type as RequirementsList in the parameters, + // we need to register that (as well). Here, be safe and register + // both names. + qRegisterMetaType< QList< RequirementEntry > >( "QList" ); + qRegisterMetaType< RequirementsList >( "RequirementsList" ); + done = true; + } +} + +static void check( Module * const &m, RequirementsChecker *c ) { RequirementsList l = m->checkRequirements(); @@ -49,6 +68,8 @@ RequirementsChecker::RequirementsChecker( QVector< Module* > modules, QObject* p { m_watchers.reserve( m_modules.count() ); m_collectedRequirements.reserve( m_modules.count() ); + + registerMetatypes(); } RequirementsChecker::~RequirementsChecker() diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.h b/src/libcalamaresui/modulesystem/RequirementsChecker.h index a3f0b9c3e..ce2ccce7b 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.h +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.h @@ -53,7 +53,7 @@ signals: /// @brief Human-readable progress message void requirementsProgress( const QString& ); /// @brief Requirements from a single module - void requirementsResult( RequirementsList& ); + void requirementsResult( RequirementsList ); /** @brief When all requirements are collected * * The argument indicates if all mandatory requirements are satisfied. From ac652a2bc12175afe28d8278ee5f7f7017e0d3d0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 04:19:05 -0500 Subject: [PATCH 47/89] [libcalamaresui] Report module-name in italics --- src/libcalamaresui/modulesystem/RequirementsChecker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp index 17bb9771c..9f9a88ae3 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -59,7 +59,7 @@ check( Module * const &m, RequirementsChecker *c ) RequirementsList l = m->checkRequirements(); if ( l.count() > 0 ) c->addCheckedRequirements( l ); - c->requirementsProgress( QObject::tr( "Requirements checking for module %1 is complete." ).arg( m->name() ) ); + c->requirementsProgress( QObject::tr( "Requirements checking for module %1 is complete." ).arg( m->name() ) ); } RequirementsChecker::RequirementsChecker( QVector< Module* > modules, QObject* parent ) From 2092ec3c9a0a37553fd061f423df9d29fe55ab80 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 04:36:46 -0500 Subject: [PATCH 48/89] [partition] Drop some re-parenting trickery - Can't re-parent across threads easily - If device is made by immutableDeviceCopy(), then it's still owned by the PartitionCoreModule; giving it away to the widget is not a good idea. --- src/modules/partition/gui/ChoicePage.cpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/modules/partition/gui/ChoicePage.cpp b/src/modules/partition/gui/ChoicePage.cpp index 7c980cf49..e9cd2e26b 100644 --- a/src/modules/partition/gui/ChoicePage.cpp +++ b/src/modules/partition/gui/ChoicePage.cpp @@ -882,11 +882,6 @@ ChoicePage::updateDeviceStatePreview() PartitionModel* model = new PartitionModel( m_beforePartitionBarsView ); model->init( deviceBefore, m_core->osproberEntries() ); - // The QObject parents tree is meaningful for memory management here, - // see qDeleteAll above. - deviceBefore->setParent( model ); // Can't reparent across threads - model->setParent( m_beforePartitionBarsView ); - m_beforePartitionBarsView->setModel( model ); m_beforePartitionLabelsView->setModel( model ); From 40de1bd2eb7c08ce02ed661a9697d8e315441081 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 05:12:03 -0500 Subject: [PATCH 49/89] [partition] Give requirement entry a description - The description is used in the Details dialog when the requirements fail. This one should be visible. --- src/modules/partition/gui/PartitionViewStep.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 5ec99bf92..b5a20917b 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -679,8 +679,8 @@ Calamares::RequirementsList PartitionViewStep::checkRequirements() l.append( { QLatin1Literal( "partitions" ), - []{ return QString(); }, - [this]{ return tr( "There are no partitons to install on." ); }, + []{ return tr( "has at least one disk device available." ); }, + []{ return tr( "There are no partitons to install on." ); }, m_core->deviceModel()->rowCount() > 0, // satisfied true // required } ); From 452b51304d9b1daaa9eaf75bef2f69b3185aeed5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 06:11:14 -0500 Subject: [PATCH 50/89] [welcome] Update next button when checking is complete --- src/modules/welcome/WelcomeViewStep.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 6a36dd0a1..bcded3161 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -21,8 +21,9 @@ #include "WelcomePage.h" #include "checker/GeneralRequirements.h" -#include "utils/Logger.h" +#include "modulesystem/ModuleManager.h" +#include "utils/Logger.h" #include @@ -32,6 +33,7 @@ WelcomeViewStep::WelcomeViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_requirementsChecker( new GeneralRequirements( this ) ) { + connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, this, &WelcomeViewStep::nextStatusChanged ); emit nextStatusChanged( true ); m_widget = new WelcomePage(); } From 5ddf7b980b89c614c94a94f1f0ad4eeceb469053 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 06:33:46 -0500 Subject: [PATCH 51/89] [libcalamaresui] Report progress also while waiting - Ping the progress every 1.2 seconds, so the user sees more than just the throbber. --- .../modulesystem/RequirementsChecker.cpp | 18 ++++++++++++++++++ .../modulesystem/RequirementsChecker.h | 12 +++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp index 9f9a88ae3..b6af4bcf4 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -65,6 +65,7 @@ check( Module * const &m, RequirementsChecker *c ) RequirementsChecker::RequirementsChecker( QVector< Module* > modules, QObject* parent ) : QObject( parent ) , m_modules( std::move( modules ) ) + , m_progressTimer( nullptr ) { m_watchers.reserve( m_modules.count() ); m_collectedRequirements.reserve( m_modules.count() ); @@ -79,6 +80,10 @@ RequirementsChecker::~RequirementsChecker() void RequirementsChecker::run() { + m_progressTimer = new QTimer( this ); + connect( m_progressTimer, &QTimer::timeout, this, &RequirementsChecker::reportProgress ); + m_progressTimer->start( 1200 ); // msec + for (const auto& module : m_modules ) { Watcher *watcher = new Watcher( this ); @@ -95,6 +100,9 @@ RequirementsChecker::finished() { cDebug() << "All requirements have been checked."; + if ( m_progressTimer ) + m_progressTimer->stop(); + bool acceptable = true; int count = 0; for ( const auto& r : m_collectedRequirements ) @@ -124,4 +132,14 @@ RequirementsChecker::addCheckedRequirements( RequirementsList l ) emit requirementsResult( l ); } +void +RequirementsChecker::reportProgress() +{ + auto remaining = std::count_if( m_watchers.cbegin(), m_watchers.cend(), []( const Watcher *w ) { return w && !w->isFinished(); } ); + if ( remaining > 0 ) + emit requirementsProgress( tr( "Waiting for %n module(s).", "", remaining ) ); + else + emit requirementsProgress( tr( "System-requirements checking is complete." ) ); +} + } diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.h b/src/libcalamaresui/modulesystem/RequirementsChecker.h index ce2ccce7b..af46a4ab2 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.h +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.h @@ -18,11 +18,13 @@ #ifndef CALAMARES_REQUIREMENTSCHECKER_H #define CALAMARES_REQUIREMENTSCHECKER_H +#include "Requirement.h" + #include #include +#include #include -#include "Requirement.h" namespace Calamares { @@ -43,12 +45,18 @@ public: virtual ~RequirementsChecker() override; public slots: + /// @brief Start checking all the requirements void run(); + /// @brief Called when requirements are reported by a module void addCheckedRequirements( RequirementsList ); + /// @brief Called when all requirements have been checked void finished(); + /// @brief Called periodically while requirements are being checked + void reportProgress(); + signals: /// @brief Human-readable progress message void requirementsProgress( const QString& ); @@ -69,6 +77,8 @@ private: QVector< Watcher* > m_watchers; RequirementsList m_collectedRequirements; + + QTimer *m_progressTimer; } ; } From 0ad115732e35f7bc44aa0ec57d9de790cda72e11 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 06:39:50 -0500 Subject: [PATCH 52/89] [libcalamaresui] Report elapsed time as well. - While waiting on modules, report the elapsed time in seconds based on the number of progress-ticks that have passed. --- src/libcalamaresui/modulesystem/RequirementsChecker.cpp | 9 ++++++++- src/libcalamaresui/modulesystem/RequirementsChecker.h | 1 + 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp index b6af4bcf4..68569635b 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -66,6 +66,7 @@ RequirementsChecker::RequirementsChecker( QVector< Module* > modules, QObject* p : QObject( parent ) , m_modules( std::move( modules ) ) , m_progressTimer( nullptr ) + , m_progressTimeouts( 0 ) { m_watchers.reserve( m_modules.count() ); m_collectedRequirements.reserve( m_modules.count() ); @@ -135,9 +136,15 @@ RequirementsChecker::addCheckedRequirements( RequirementsList l ) void RequirementsChecker::reportProgress() { + m_progressTimeouts++; + auto remaining = std::count_if( m_watchers.cbegin(), m_watchers.cend(), []( const Watcher *w ) { return w && !w->isFinished(); } ); if ( remaining > 0 ) - emit requirementsProgress( tr( "Waiting for %n module(s).", "", remaining ) ); + { + QString waiting = tr( "Waiting for %n module(s).", "", remaining ); + QString elapsed = tr( "(%n second(s))", "", m_progressTimeouts * m_progressTimer->interval() / 1000 ); + emit requirementsProgress( waiting + QString( " " ) + elapsed ); + } else emit requirementsProgress( tr( "System-requirements checking is complete." ) ); } diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.h b/src/libcalamaresui/modulesystem/RequirementsChecker.h index af46a4ab2..6e681971c 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.h +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.h @@ -79,6 +79,7 @@ private: RequirementsList m_collectedRequirements; QTimer *m_progressTimer; + unsigned m_progressTimeouts; } ; } From fbb513eee37d5f80e97342e52c20eafe6edade71 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 06:45:17 -0500 Subject: [PATCH 53/89] [partition] Remove artificial delay - The sleep(3) was meant as a debugging aid for the multi-threaded part of requirements checking. --- src/modules/partition/gui/PartitionViewStep.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index b5a20917b..aaa3b0138 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -668,13 +668,12 @@ PartitionViewStep::jobs() const return m_core->jobs(); } -Calamares::RequirementsList PartitionViewStep::checkRequirements() +Calamares::RequirementsList +PartitionViewStep::checkRequirements() { - if (m_future) + if ( m_future ) m_future->waitForFinished(); - sleep(3); - Calamares::RequirementsList l; l.append( { @@ -686,7 +685,6 @@ Calamares::RequirementsList PartitionViewStep::checkRequirements() } ); return l; - } From 8a8ec0138095177e15c36b243aefdf0c5d049e67 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:00:22 -0500 Subject: [PATCH 54/89] [welcome] Don't enable next early - Next was enabled early; presumably to cover the case that no requirements were checked and the requirements checker never emitted an update signal. Drop that since the module manager is now responsible for doing that checking. --- src/modules/welcome/WelcomeViewStep.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index bcded3161..bb5a9da75 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -34,7 +34,6 @@ WelcomeViewStep::WelcomeViewStep( QObject* parent ) , m_requirementsChecker( new GeneralRequirements( this ) ) { connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, this, &WelcomeViewStep::nextStatusChanged ); - emit nextStatusChanged( true ); m_widget = new WelcomePage(); } From 987cf36f51852712876cc930ed91ffdbda9aa1cb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:05:12 -0500 Subject: [PATCH 55/89] [welcome] Use convenience types --- src/modules/welcome/WelcomeViewStep.cpp | 4 ++-- src/modules/welcome/WelcomeViewStep.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index bb5a9da75..fa12db895 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -99,10 +99,10 @@ WelcomeViewStep::isAtEnd() const } -QList< Calamares::job_ptr > +Calamares::JobList WelcomeViewStep::jobs() const { - return QList< Calamares::job_ptr >(); + return Calamares::JobList(); } diff --git a/src/modules/welcome/WelcomeViewStep.h b/src/modules/welcome/WelcomeViewStep.h index 10f85f367..a6abbd341 100644 --- a/src/modules/welcome/WelcomeViewStep.h +++ b/src/modules/welcome/WelcomeViewStep.h @@ -53,7 +53,7 @@ public: bool isAtBeginning() const override; bool isAtEnd() const override; - QList< Calamares::job_ptr > jobs() const override; + Calamares::JobList jobs() const override; void setConfigurationMap( const QVariantMap& configurationMap ) override; From 40a7082bfc5019c5557072c8091282c1374a839a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:15:51 -0500 Subject: [PATCH 56/89] [libcalamaresui] Handle no-requirements-to-check case - If there's no requirements at all, none of the watchers will call finished(), so do it once extra. --- src/libcalamaresui/modulesystem/RequirementsChecker.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp index 68569635b..c7f4625eb 100644 --- a/src/libcalamaresui/modulesystem/RequirementsChecker.cpp +++ b/src/libcalamaresui/modulesystem/RequirementsChecker.cpp @@ -92,6 +92,8 @@ RequirementsChecker::run() m_watchers.append( watcher ); connect( watcher, &Watcher::finished, this, &RequirementsChecker::finished ); } + + QTimer::singleShot( 0, this, &RequirementsChecker::finished ); } void From 08565b5f179a22b0e2d53f6dae90aa5009eb354b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:34:40 -0500 Subject: [PATCH 57/89] [libcalamaresui] Remove the signal done() from ViewStep - The signal is emitted, generally from next(), but not actually used. --- src/libcalamaresui/viewpages/ViewStep.h | 1 - src/modules/finished/FinishedViewStep.cpp | 1 - .../interactiveterminal/InteractiveTerminalViewStep.cpp | 1 - src/modules/keyboard/KeyboardViewStep.cpp | 2 -- src/modules/license/LicenseViewStep.cpp | 1 - src/modules/locale/LocaleViewStep.cpp | 1 - src/modules/netinstall/NetInstallViewStep.cpp | 1 - src/modules/partition/gui/PartitionViewStep.cpp | 4 ---- src/modules/plasmalnf/PlasmaLnfViewStep.cpp | 1 - src/modules/summary/SummaryViewStep.cpp | 1 - src/modules/tracking/TrackingViewStep.cpp | 1 - src/modules/users/UsersViewStep.cpp | 1 - src/modules/webview/WebViewStep.cpp | 1 - src/modules/welcome/WelcomeViewStep.cpp | 1 - 14 files changed, 18 deletions(-) diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index f10d29b96..d6b8e1f3c 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -103,7 +103,6 @@ public: signals: void nextStatusChanged( bool status ); - void done(); /* Emitted when the viewstep thinks it needs more space than is currently * available for display. @p enlarge is the requested additional space, diff --git a/src/modules/finished/FinishedViewStep.cpp b/src/modules/finished/FinishedViewStep.cpp index 3b807f69c..818a07909 100644 --- a/src/modules/finished/FinishedViewStep.cpp +++ b/src/modules/finished/FinishedViewStep.cpp @@ -70,7 +70,6 @@ FinishedViewStep::widget() void FinishedViewStep::next() { - emit done(); } diff --git a/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp b/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp index 2559ea635..3242e47e9 100644 --- a/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp +++ b/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp @@ -56,7 +56,6 @@ InteractiveTerminalViewStep::widget() void InteractiveTerminalViewStep::next() { - emit done(); } diff --git a/src/modules/keyboard/KeyboardViewStep.cpp b/src/modules/keyboard/KeyboardViewStep.cpp index 053266059..3e846db43 100644 --- a/src/modules/keyboard/KeyboardViewStep.cpp +++ b/src/modules/keyboard/KeyboardViewStep.cpp @@ -68,8 +68,6 @@ KeyboardViewStep::widget() void KeyboardViewStep::next() { - //TODO: actually save those settings somewhere - emit done(); } diff --git a/src/modules/license/LicenseViewStep.cpp b/src/modules/license/LicenseViewStep.cpp index 41ca02a7e..a02ef36c6 100644 --- a/src/modules/license/LicenseViewStep.cpp +++ b/src/modules/license/LicenseViewStep.cpp @@ -62,7 +62,6 @@ LicenseViewStep::widget() void LicenseViewStep::next() { - emit done(); } diff --git a/src/modules/locale/LocaleViewStep.cpp b/src/modules/locale/LocaleViewStep.cpp index 4a6eb229a..4a30bc307 100644 --- a/src/modules/locale/LocaleViewStep.cpp +++ b/src/modules/locale/LocaleViewStep.cpp @@ -193,7 +193,6 @@ LocaleViewStep::widget() void LocaleViewStep::next() { - emit done(); } diff --git a/src/modules/netinstall/NetInstallViewStep.cpp b/src/modules/netinstall/NetInstallViewStep.cpp index 6dd824b32..5104390eb 100644 --- a/src/modules/netinstall/NetInstallViewStep.cpp +++ b/src/modules/netinstall/NetInstallViewStep.cpp @@ -72,7 +72,6 @@ NetInstallViewStep::widget() void NetInstallViewStep::next() { - emit done(); } diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 3c71302e0..34d9c4a81 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -294,23 +294,19 @@ PartitionViewStep::next() } else if ( m_choicePage->currentChoice() == ChoicePage::Erase ) { - emit done(); return; } else if ( m_choicePage->currentChoice() == ChoicePage::Alongside ) { - emit done(); return; } else if ( m_choicePage->currentChoice() == ChoicePage::Replace ) { - emit done(); return; } cDebug() << "Choice applied: " << m_choicePage->currentChoice(); return; } - emit done(); } diff --git a/src/modules/plasmalnf/PlasmaLnfViewStep.cpp b/src/modules/plasmalnf/PlasmaLnfViewStep.cpp index ef319bde4..6e4a3e89c 100644 --- a/src/modules/plasmalnf/PlasmaLnfViewStep.cpp +++ b/src/modules/plasmalnf/PlasmaLnfViewStep.cpp @@ -79,7 +79,6 @@ PlasmaLnfViewStep::widget() void PlasmaLnfViewStep::next() { - emit done(); } diff --git a/src/modules/summary/SummaryViewStep.cpp b/src/modules/summary/SummaryViewStep.cpp index 4f60a3c4f..2ebfa449b 100644 --- a/src/modules/summary/SummaryViewStep.cpp +++ b/src/modules/summary/SummaryViewStep.cpp @@ -54,7 +54,6 @@ SummaryViewStep::widget() void SummaryViewStep::next() { - emit done(); } diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 417e10fc0..8927c6865 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -70,7 +70,6 @@ TrackingViewStep::widget() void TrackingViewStep::next() { - emit done(); } diff --git a/src/modules/users/UsersViewStep.cpp b/src/modules/users/UsersViewStep.cpp index 8ff7b0e7b..ad0fcb118 100644 --- a/src/modules/users/UsersViewStep.cpp +++ b/src/modules/users/UsersViewStep.cpp @@ -64,7 +64,6 @@ UsersViewStep::widget() void UsersViewStep::next() { - emit done(); } diff --git a/src/modules/webview/WebViewStep.cpp b/src/modules/webview/WebViewStep.cpp index 1db7c8e41..145ff36d5 100644 --- a/src/modules/webview/WebViewStep.cpp +++ b/src/modules/webview/WebViewStep.cpp @@ -75,7 +75,6 @@ WebViewStep::widget() void WebViewStep::next() { - emit done(); } diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 86740fb3d..f3aa54532 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -63,7 +63,6 @@ WelcomeViewStep::widget() void WelcomeViewStep::next() { - emit done(); } From 6071489788010e027798d02a03c6a0da747b660c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:49:10 -0500 Subject: [PATCH 58/89] [libcalamaresui] Provide default implementations of next() and back() - These methods are used for multi-page view-steps, which are rare. For all the others, just drop the empty implementation and defer to the base class. --- src/libcalamaresui/viewpages/ViewStep.cpp | 8 ++++++++ src/libcalamaresui/viewpages/ViewStep.h | 4 ++-- src/modules/finished/FinishedViewStep.cpp | 11 ----------- src/modules/finished/FinishedViewStep.h | 3 --- .../InteractiveTerminalViewStep.cpp | 11 ----------- .../interactiveterminal/InteractiveTerminalViewStep.h | 3 --- src/modules/keyboard/KeyboardViewStep.cpp | 11 ----------- src/modules/keyboard/KeyboardViewStep.h | 3 --- src/modules/license/LicenseViewStep.cpp | 11 ----------- src/modules/license/LicenseViewStep.h | 3 --- src/modules/locale/LocaleViewStep.cpp | 11 ----------- src/modules/locale/LocaleViewStep.h | 3 --- src/modules/netinstall/NetInstallViewStep.cpp | 11 ----------- src/modules/netinstall/NetInstallViewStep.h | 3 --- src/modules/plasmalnf/PlasmaLnfViewStep.cpp | 11 ----------- src/modules/plasmalnf/PlasmaLnfViewStep.h | 3 --- src/modules/summary/SummaryViewStep.cpp | 11 ----------- src/modules/summary/SummaryViewStep.h | 3 --- src/modules/tracking/TrackingViewStep.cpp | 11 ----------- src/modules/tracking/TrackingViewStep.h | 3 --- src/modules/users/UsersViewStep.cpp | 11 ----------- src/modules/users/UsersViewStep.h | 3 --- src/modules/webview/WebViewStep.cpp | 11 ----------- src/modules/webview/WebViewStep.h | 2 -- src/modules/welcome/WelcomeViewStep.cpp | 11 ----------- src/modules/welcome/WelcomeViewStep.h | 3 --- 26 files changed, 10 insertions(+), 169 deletions(-) diff --git a/src/libcalamaresui/viewpages/ViewStep.cpp b/src/libcalamaresui/viewpages/ViewStep.cpp index c6acb5208..ec78c316f 100644 --- a/src/libcalamaresui/viewpages/ViewStep.cpp +++ b/src/libcalamaresui/viewpages/ViewStep.cpp @@ -52,6 +52,14 @@ void ViewStep::onLeave() {} +void +ViewStep::next() +{} + +void +ViewStep::back() +{} + void ViewStep::setModuleInstanceKey( const QString& instanceKey ) diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index d6b8e1f3c..775f09203 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -68,8 +68,8 @@ public: //TODO: we might want to make this a QSharedPointer virtual QWidget* widget() = 0; - virtual void next() = 0; - virtual void back() = 0; + virtual void next(); + virtual void back(); virtual bool isNextEnabled() const = 0; virtual bool isBackEnabled() const = 0; diff --git a/src/modules/finished/FinishedViewStep.cpp b/src/modules/finished/FinishedViewStep.cpp index 818a07909..8457aa4cd 100644 --- a/src/modules/finished/FinishedViewStep.cpp +++ b/src/modules/finished/FinishedViewStep.cpp @@ -67,17 +67,6 @@ FinishedViewStep::widget() } -void -FinishedViewStep::next() -{ -} - - -void -FinishedViewStep::back() -{} - - bool FinishedViewStep::isNextEnabled() const { diff --git a/src/modules/finished/FinishedViewStep.h b/src/modules/finished/FinishedViewStep.h index 393527053..b1af598c7 100644 --- a/src/modules/finished/FinishedViewStep.h +++ b/src/modules/finished/FinishedViewStep.h @@ -40,9 +40,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp b/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp index 3242e47e9..d57eb7d05 100644 --- a/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp +++ b/src/modules/interactiveterminal/InteractiveTerminalViewStep.cpp @@ -53,17 +53,6 @@ InteractiveTerminalViewStep::widget() } -void -InteractiveTerminalViewStep::next() -{ -} - - -void -InteractiveTerminalViewStep::back() -{} - - bool InteractiveTerminalViewStep::isNextEnabled() const { diff --git a/src/modules/interactiveterminal/InteractiveTerminalViewStep.h b/src/modules/interactiveterminal/InteractiveTerminalViewStep.h index 3d5862935..55486691d 100644 --- a/src/modules/interactiveterminal/InteractiveTerminalViewStep.h +++ b/src/modules/interactiveterminal/InteractiveTerminalViewStep.h @@ -41,9 +41,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/keyboard/KeyboardViewStep.cpp b/src/modules/keyboard/KeyboardViewStep.cpp index 3e846db43..40a5385a3 100644 --- a/src/modules/keyboard/KeyboardViewStep.cpp +++ b/src/modules/keyboard/KeyboardViewStep.cpp @@ -65,17 +65,6 @@ KeyboardViewStep::widget() } -void -KeyboardViewStep::next() -{ -} - - -void -KeyboardViewStep::back() -{} - - bool KeyboardViewStep::isNextEnabled() const { diff --git a/src/modules/keyboard/KeyboardViewStep.h b/src/modules/keyboard/KeyboardViewStep.h index 46a52a524..a5bdd579e 100644 --- a/src/modules/keyboard/KeyboardViewStep.h +++ b/src/modules/keyboard/KeyboardViewStep.h @@ -42,9 +42,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/license/LicenseViewStep.cpp b/src/modules/license/LicenseViewStep.cpp index a02ef36c6..96a7b8660 100644 --- a/src/modules/license/LicenseViewStep.cpp +++ b/src/modules/license/LicenseViewStep.cpp @@ -59,17 +59,6 @@ LicenseViewStep::widget() } -void -LicenseViewStep::next() -{ -} - - -void -LicenseViewStep::back() -{} - - bool LicenseViewStep::isNextEnabled() const { diff --git a/src/modules/license/LicenseViewStep.h b/src/modules/license/LicenseViewStep.h index cf7b2bc15..a4fabc8e1 100644 --- a/src/modules/license/LicenseViewStep.h +++ b/src/modules/license/LicenseViewStep.h @@ -42,9 +42,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/locale/LocaleViewStep.cpp b/src/modules/locale/LocaleViewStep.cpp index 4a30bc307..a7dc432f8 100644 --- a/src/modules/locale/LocaleViewStep.cpp +++ b/src/modules/locale/LocaleViewStep.cpp @@ -190,17 +190,6 @@ LocaleViewStep::widget() } -void -LocaleViewStep::next() -{ -} - - -void -LocaleViewStep::back() -{} - - bool LocaleViewStep::isNextEnabled() const { diff --git a/src/modules/locale/LocaleViewStep.h b/src/modules/locale/LocaleViewStep.h index 8006bc616..3f5c91621 100644 --- a/src/modules/locale/LocaleViewStep.h +++ b/src/modules/locale/LocaleViewStep.h @@ -45,9 +45,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/netinstall/NetInstallViewStep.cpp b/src/modules/netinstall/NetInstallViewStep.cpp index 5104390eb..3c4fa5e58 100644 --- a/src/modules/netinstall/NetInstallViewStep.cpp +++ b/src/modules/netinstall/NetInstallViewStep.cpp @@ -69,17 +69,6 @@ NetInstallViewStep::widget() } -void -NetInstallViewStep::next() -{ -} - - -void -NetInstallViewStep::back() -{} - - bool NetInstallViewStep::isNextEnabled() const { diff --git a/src/modules/netinstall/NetInstallViewStep.h b/src/modules/netinstall/NetInstallViewStep.h index ee53f61ce..b07d3f96d 100644 --- a/src/modules/netinstall/NetInstallViewStep.h +++ b/src/modules/netinstall/NetInstallViewStep.h @@ -42,9 +42,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/plasmalnf/PlasmaLnfViewStep.cpp b/src/modules/plasmalnf/PlasmaLnfViewStep.cpp index 6e4a3e89c..5525f36fc 100644 --- a/src/modules/plasmalnf/PlasmaLnfViewStep.cpp +++ b/src/modules/plasmalnf/PlasmaLnfViewStep.cpp @@ -76,17 +76,6 @@ PlasmaLnfViewStep::widget() } -void -PlasmaLnfViewStep::next() -{ -} - - -void -PlasmaLnfViewStep::back() -{} - - bool PlasmaLnfViewStep::isNextEnabled() const { diff --git a/src/modules/plasmalnf/PlasmaLnfViewStep.h b/src/modules/plasmalnf/PlasmaLnfViewStep.h index b9a6b72e6..01db17821 100644 --- a/src/modules/plasmalnf/PlasmaLnfViewStep.h +++ b/src/modules/plasmalnf/PlasmaLnfViewStep.h @@ -41,9 +41,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/summary/SummaryViewStep.cpp b/src/modules/summary/SummaryViewStep.cpp index 2ebfa449b..6835b2b05 100644 --- a/src/modules/summary/SummaryViewStep.cpp +++ b/src/modules/summary/SummaryViewStep.cpp @@ -51,17 +51,6 @@ SummaryViewStep::widget() } -void -SummaryViewStep::next() -{ -} - - -void -SummaryViewStep::back() -{} - - bool SummaryViewStep::isNextEnabled() const { diff --git a/src/modules/summary/SummaryViewStep.h b/src/modules/summary/SummaryViewStep.h index 9aff35cd0..88f177a4d 100644 --- a/src/modules/summary/SummaryViewStep.h +++ b/src/modules/summary/SummaryViewStep.h @@ -40,9 +40,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/tracking/TrackingViewStep.cpp b/src/modules/tracking/TrackingViewStep.cpp index 8927c6865..304e2a971 100644 --- a/src/modules/tracking/TrackingViewStep.cpp +++ b/src/modules/tracking/TrackingViewStep.cpp @@ -67,17 +67,6 @@ TrackingViewStep::widget() } -void -TrackingViewStep::next() -{ -} - - -void -TrackingViewStep::back() -{} - - bool TrackingViewStep::isNextEnabled() const { diff --git a/src/modules/tracking/TrackingViewStep.h b/src/modules/tracking/TrackingViewStep.h index dc3ae823e..aaaf3bbae 100644 --- a/src/modules/tracking/TrackingViewStep.h +++ b/src/modules/tracking/TrackingViewStep.h @@ -43,9 +43,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/users/UsersViewStep.cpp b/src/modules/users/UsersViewStep.cpp index ad0fcb118..3b1e6a5ad 100644 --- a/src/modules/users/UsersViewStep.cpp +++ b/src/modules/users/UsersViewStep.cpp @@ -61,17 +61,6 @@ UsersViewStep::widget() } -void -UsersViewStep::next() -{ -} - - -void -UsersViewStep::back() -{} - - bool UsersViewStep::isNextEnabled() const { diff --git a/src/modules/users/UsersViewStep.h b/src/modules/users/UsersViewStep.h index 81b80bced..a1995497c 100644 --- a/src/modules/users/UsersViewStep.h +++ b/src/modules/users/UsersViewStep.h @@ -43,9 +43,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; diff --git a/src/modules/webview/WebViewStep.cpp b/src/modules/webview/WebViewStep.cpp index 145ff36d5..50c270b09 100644 --- a/src/modules/webview/WebViewStep.cpp +++ b/src/modules/webview/WebViewStep.cpp @@ -72,17 +72,6 @@ WebViewStep::widget() } -void -WebViewStep::next() -{ -} - - -void -WebViewStep::back() -{} - - bool WebViewStep::isNextEnabled() const { diff --git a/src/modules/webview/WebViewStep.h b/src/modules/webview/WebViewStep.h index 6430cdcf1..c588318fa 100644 --- a/src/modules/webview/WebViewStep.h +++ b/src/modules/webview/WebViewStep.h @@ -50,8 +50,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; void onActivate() override; bool isNextEnabled() const override; diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index f3aa54532..756c5aa74 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -60,17 +60,6 @@ WelcomeViewStep::widget() } -void -WelcomeViewStep::next() -{ -} - - -void -WelcomeViewStep::back() -{} - - bool WelcomeViewStep::isNextEnabled() const { diff --git a/src/modules/welcome/WelcomeViewStep.h b/src/modules/welcome/WelcomeViewStep.h index 34b84c29f..b556b1ca1 100644 --- a/src/modules/welcome/WelcomeViewStep.h +++ b/src/modules/welcome/WelcomeViewStep.h @@ -43,9 +43,6 @@ public: QWidget* widget() override; - void next() override; - void back() override; - bool isNextEnabled() const override; bool isBackEnabled() const override; From cece01e3c5848e487bf1e448f669ea5afa27d2be Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:59:58 -0500 Subject: [PATCH 59/89] [partition] Simplify next() --- src/modules/partition/gui/PartitionViewStep.cpp | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 34d9c4a81..bee5ad965 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -292,20 +292,7 @@ PartitionViewStep::next() if ( m_core->isDirty() ) m_manualPartitionPage->onRevertClicked(); } - else if ( m_choicePage->currentChoice() == ChoicePage::Erase ) - { - return; - } - else if ( m_choicePage->currentChoice() == ChoicePage::Alongside ) - { - return; - } - else if ( m_choicePage->currentChoice() == ChoicePage::Replace ) - { - return; - } cDebug() << "Choice applied: " << m_choicePage->currentChoice(); - return; } } From 64ca9d0d5aa73701db7f1fe6f9694f76065a63c3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 08:11:03 -0500 Subject: [PATCH 60/89] [libcalamaresui] Document multi-page support. --- src/libcalamaresui/viewpages/ViewStep.h | 26 +++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index 775f09203..a1275a198 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -68,13 +68,39 @@ public: //TODO: we might want to make this a QSharedPointer virtual QWidget* widget() = 0; + /** + * @brief Multi-page support, go next + * + * Multi-page view steps need to manage the content visible in the widget + * themselves. This method is called when the user clicks the *next* + * button, and should switch to the next of the multiple-pages. It needs + * to be consistent with both isNextEnabled() and isAtEnd(). + * + * In particular: when isAtEnd() returns false, next() is called when + * the user clicks the button and a new page should be shown by this + * view step. When isAtEnd() returns true, clicking the button will + * switch to the next view step in sequence, rather than a next page + * in the current view step. + */ virtual void next(); + /// @brief Multi-page support, go back virtual void back(); + /// @brief Can the user click *next* with currently-filled-in data? virtual bool isNextEnabled() const = 0; + /// @brief Can the user click *previous* with currently-filled-in data? virtual bool isBackEnabled() const = 0; + /** + * @brief Multi-page support, switch to previous view step? + * + * For a multi-page view step, this indicates that the first (beginning) + * page is showing. Clicking *previous* when at the beginning of a view + * step, switches to the previous step, not the previous page of the + * current view step. + */ virtual bool isAtBeginning() const = 0; + /// @brief Multi-page support, switch to next view step? virtual bool isAtEnd() const = 0; /** From c3d13e345178cbc719a9e8d6e643a99e36bec7c6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:20:35 -0500 Subject: [PATCH 61/89] [libcalamaresui] Add documentation to ViewStep methods --- src/libcalamaresui/viewpages/ViewStep.h | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index ba29ccd02..2a85a1031 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -92,6 +92,12 @@ public: */ virtual void onLeave(); + /** + * @brief Jobs needed to run this viewstep + * + * When a ViewStep is listed in the exec section, its jobs are executed instead. + * This function returns that list of jobs; an empty list is ok. + */ virtual JobList jobs() const = 0; void setModuleInstanceKey( const QString& instanceKey ); @@ -102,9 +108,17 @@ public: virtual void setConfigurationMap( const QVariantMap& configurationMap ); + /** + * @brief Can this module proceed, on this machine? + * + * This is called asynchronously at startup, and returns a list of + * the requirements that the module has checked, and their status. + * See Calamares::RequirementEntry for details. + */ virtual RequirementsList checkRequirements(); signals: + /// @brief Tells the viewmanager to enable the *next* button according to @p status void nextStatusChanged( bool status ); void done(); From 9889bd6cbe7849074ca76d1058846559b9df1af5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 08:44:08 -0500 Subject: [PATCH 62/89] [welcome] Be louder when libparted is disabled --- src/modules/welcome/checker/GeneralRequirements.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 0a841eca1..7880d3c65 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -187,6 +187,18 @@ GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) incompleteConfiguration = true; } +#ifdef WITHOUT_LIBPARTED + if ( m_entriesToCheck.contains( "storage" ) ) + cWarning() << "GeneralRequirements checks 'storage' but libparted is disabled."; + if ( m_entriesToRequire.contains( "storage" ) ) + { + // Warn, but also drop the required bit because otherwise installation + // will be impossible (because the check always returns false). + cWarning() << "GeneralRequirements requires 'storage' check but libparted is disabled."; + m_entriesToRequire.removeAll( "storage" ); + } +#endif + // Help out with consistency, but don't fix for ( const auto& r : m_entriesToRequire ) if ( !m_entriesToCheck.contains( r ) ) From 33bd6c67c012a7facd20a5cc221f4f807687d64e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 10:07:21 -0500 Subject: [PATCH 63/89] [welcome] Without libparted, don't even check size available --- src/modules/welcome/checker/GeneralRequirements.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 7880d3c65..4fcd8129d 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -188,13 +188,12 @@ GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) } #ifdef WITHOUT_LIBPARTED - if ( m_entriesToCheck.contains( "storage" ) ) - cWarning() << "GeneralRequirements checks 'storage' but libparted is disabled."; - if ( m_entriesToRequire.contains( "storage" ) ) + if ( m_entriesToCheck.contains( "storage" ) || m_entriesToRequire.contains( "storage" ) ) { // Warn, but also drop the required bit because otherwise installation // will be impossible (because the check always returns false). - cWarning() << "GeneralRequirements requires 'storage' check but libparted is disabled."; + cWarning() << "GeneralRequirements checks 'storage' but libparted is disabled."; + m_entriesToCheck.removeAll( "storage" ); m_entriesToRequire.removeAll( "storage" ); } #endif From 7cfaba2d539e609544cb4d17034a25fcad790be0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 16:39:19 -0500 Subject: [PATCH 64/89] [partition] In logging, name device nicely - Provide a convenience method that names a Partition* with the best human-readable name we can find (worst-case, spit out a pointer representation which will at least help figure out the identity of the Partition*). --- src/modules/partition/core/PartUtils.cpp | 39 ++++++++++++++++++------ 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index d09bcd149..c9b46e82e 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -42,6 +42,25 @@ namespace PartUtils { +static QString +convenienceName( const Partition* const candidate ) +{ + if ( !candidate->mountPoint().isEmpty() ) + return candidate->mountPoint(); + if ( !candidate->partitionPath().isEmpty() ) + return candidate->partitionPath(); + if ( !candidate->devicePath().isEmpty() ) + return candidate->devicePath(); + if ( !candidate->deviceNode().isEmpty() ) + return candidate->devicePath(); + + QString p; + QTextStream s( &p ); + s << (void *)candidate; + + return p; +} + bool canBeReplaced( Partition* candidate ) { @@ -63,12 +82,12 @@ canBeReplaced( Partition* candidate ) << QString( "(%1GB)" ).arg( requiredStorageB / 1024 / 1024 / 1024 ); cDebug() << "Storage capacity B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << candidate->partitionPath() << " length:" << candidate->length(); + << "for" << convenienceName( candidate ) << " length:" << candidate->length(); if ( ok && availableStorageB > requiredStorageB ) { - cDebug() << "Partition" << candidate->partitionPath() << "authorized for replace install."; + cDebug() << "Partition" << convenienceName( candidate ) << "authorized for replace install."; return true; } @@ -85,7 +104,7 @@ canBeResized( Partition* candidate ) return false; } - cDebug() << "Checking if" << candidate->partitionPath() << "can be resized."; + cDebug() << "Checking if" << convenienceName( candidate ) << "can be resized."; if ( !candidate->fileSystem().supportGrow() || !candidate->fileSystem().supportShrink() ) { @@ -117,7 +136,7 @@ canBeResized( Partition* candidate ) if ( table->numPrimaries() >= table->maxPrimaries() ) { - cDebug() << " .. partition table already has" + cDebug() << " .. partition table already has" << table->maxPrimaries() << "primary partitions."; return false; } @@ -139,13 +158,13 @@ canBeResized( Partition* candidate ) << QString( "(%1GB)" ).arg( advisedStorageGB ); cDebug() << "Available storage B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << candidate->partitionPath() << " length:" << candidate->length() + << "for" << convenienceName( candidate ) << " length:" << candidate->length() << " sectorsUsed:" << candidate->sectorsUsed() << " fsType:" << candidate->fileSystem().name(); if ( ok && availableStorageB > advisedStorageB ) { - cDebug() << "Partition" << candidate->partitionPath() << "authorized for resize + autopartition install."; + cDebug() << "Partition" << convenienceName( candidate ) << "authorized for resize + autopartition install."; return true; } @@ -198,7 +217,7 @@ lookForFstabEntries( const QString& partitionPath ) mountOptions.append( "noload" ); } - cDebug() << "Checking device" << partitionPath + cDebug() << "Checking device" << partitionPath << "for fstab (fs=" << r.getOutput() << ')'; FstabEntryList fstabEntries; @@ -209,9 +228,9 @@ lookForFstabEntries( const QString& partitionPath ) if ( !exit ) // if all is well { QFile fstabFile( mountsDir.path() + "/etc/fstab" ); - + cDebug() << " .. reading" << fstabFile.fileName(); - + if ( fstabFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) { const QStringList fstabLines = QString::fromLocal8Bit( fstabFile.readAll() ) @@ -381,7 +400,7 @@ isEfiSystem() bool isEfiBootable( const Partition* candidate ) { - cDebug() << "Check EFI bootable" << candidate->partitionPath() << candidate->devicePath(); + cDebug() << "Check EFI bootable" << convenienceName( candidate ) << candidate->devicePath(); cDebug() << " .. flags" << candidate->activeFlags(); auto flags = PartitionInfo::flags( candidate ); From ba9a6981b3fcf7fbd099adbcee9f0ce7de96f6ba Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 05:05:10 -0500 Subject: [PATCH 65/89] [welcome] Fix SEGV - In the retranslate function, need to check if the waiting widget still exists. - Tighten up lifetime of the CheckerWidget. --- .../welcome/checker/CheckerContainer.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/modules/welcome/checker/CheckerContainer.cpp b/src/modules/welcome/checker/CheckerContainer.cpp index 6f46cd094..569d2e9cc 100644 --- a/src/modules/welcome/checker/CheckerContainer.cpp +++ b/src/modules/welcome/checker/CheckerContainer.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2017, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017, 2019, Adriaan de Groot * Copyright 2017, Gabriel Craciunescu * * Calamares is free software: you can redistribute it and/or modify @@ -29,10 +29,10 @@ #include "utils/Retranslator.h" #include "widgets/WaitingWidget.h" -CheckerContainer::CheckerContainer(QWidget* parent) +CheckerContainer::CheckerContainer( QWidget* parent ) : QWidget( parent ) - , m_waitingWidget( new WaitingWidget( QString() ) ) - , m_checkerWidget( new CheckerWidget() ) + , m_waitingWidget( new WaitingWidget( QString(), this ) ) + , m_checkerWidget( nullptr ) , m_verdict( false ) { QBoxLayout* mainLayout = new QHBoxLayout; @@ -40,7 +40,10 @@ CheckerContainer::CheckerContainer(QWidget* parent) CalamaresUtils::unmarginLayout( mainLayout ); mainLayout->addWidget( m_waitingWidget ); - CALAMARES_RETRANSLATE( m_waitingWidget->setText( tr( "Gathering system information..." ) ); ) + CALAMARES_RETRANSLATE( + if ( m_waitingWidget ) + m_waitingWidget->setText( tr( "Gathering system information..." ) ); + ) } CheckerContainer::~CheckerContainer() @@ -51,11 +54,13 @@ CheckerContainer::~CheckerContainer() void CheckerContainer::requirementsComplete( bool ok ) { - m_checkerWidget->init( m_requirements ); + layout()->removeWidget( m_waitingWidget ); m_waitingWidget->deleteLater(); m_waitingWidget = nullptr; // Don't delete in destructor - m_checkerWidget->setParent( this ); + + m_checkerWidget = new CheckerWidget( this ); + m_checkerWidget->init( m_requirements ); layout()->addWidget( m_checkerWidget ); m_verdict = ok; From 1240f63a39c1bde0d9142a6a3d982ca2f1003113 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 05:09:54 -0500 Subject: [PATCH 66/89] [welcome] Rename files to reflect their purpose --- .../welcome/checker/{CheckItemWidget.cpp => ResultWidget.cpp} | 0 src/modules/welcome/checker/{CheckItemWidget.h => ResultWidget.h} | 0 .../welcome/checker/{CheckerWidget.cpp => ResultsListWidget.cpp} | 0 .../welcome/checker/{CheckerWidget.h => ResultsListWidget.h} | 0 4 files changed, 0 insertions(+), 0 deletions(-) rename src/modules/welcome/checker/{CheckItemWidget.cpp => ResultWidget.cpp} (100%) rename src/modules/welcome/checker/{CheckItemWidget.h => ResultWidget.h} (100%) rename src/modules/welcome/checker/{CheckerWidget.cpp => ResultsListWidget.cpp} (100%) rename src/modules/welcome/checker/{CheckerWidget.h => ResultsListWidget.h} (100%) diff --git a/src/modules/welcome/checker/CheckItemWidget.cpp b/src/modules/welcome/checker/ResultWidget.cpp similarity index 100% rename from src/modules/welcome/checker/CheckItemWidget.cpp rename to src/modules/welcome/checker/ResultWidget.cpp diff --git a/src/modules/welcome/checker/CheckItemWidget.h b/src/modules/welcome/checker/ResultWidget.h similarity index 100% rename from src/modules/welcome/checker/CheckItemWidget.h rename to src/modules/welcome/checker/ResultWidget.h diff --git a/src/modules/welcome/checker/CheckerWidget.cpp b/src/modules/welcome/checker/ResultsListWidget.cpp similarity index 100% rename from src/modules/welcome/checker/CheckerWidget.cpp rename to src/modules/welcome/checker/ResultsListWidget.cpp diff --git a/src/modules/welcome/checker/CheckerWidget.h b/src/modules/welcome/checker/ResultsListWidget.h similarity index 100% rename from src/modules/welcome/checker/CheckerWidget.h rename to src/modules/welcome/checker/ResultsListWidget.h From bfb5a4efb9f98f3860b32a6a64a1fc973dc11be0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 06:05:34 -0500 Subject: [PATCH 67/89] [welcome] Chase file renaming - Rename classes inside - Rename include guards --- src/modules/welcome/CMakeLists.txt | 4 +-- .../welcome/checker/CheckerContainer.cpp | 4 +-- .../welcome/checker/CheckerContainer.h | 4 +-- src/modules/welcome/checker/ResultWidget.cpp | 9 +++---- src/modules/welcome/checker/ResultWidget.h | 27 ++++++++++++++----- .../welcome/checker/ResultsListWidget.cpp | 14 +++++----- .../welcome/checker/ResultsListWidget.h | 10 +++---- 7 files changed, 42 insertions(+), 30 deletions(-) diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index 915f5fd2c..f627db032 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -16,8 +16,8 @@ include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ) set( CHECKER_SOURCES checker/CheckerContainer.cpp - checker/CheckerWidget.cpp - checker/CheckItemWidget.cpp + checker/ResultWidget.cpp + checker/ResultsListWidget.cpp checker/GeneralRequirements.cpp ${PARTMAN_SRC} ) diff --git a/src/modules/welcome/checker/CheckerContainer.cpp b/src/modules/welcome/checker/CheckerContainer.cpp index 569d2e9cc..0524bddb0 100644 --- a/src/modules/welcome/checker/CheckerContainer.cpp +++ b/src/modules/welcome/checker/CheckerContainer.cpp @@ -22,7 +22,7 @@ #include "CheckerContainer.h" -#include "CheckerWidget.h" +#include "ResultsListWidget.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" @@ -59,7 +59,7 @@ void CheckerContainer::requirementsComplete( bool ok ) m_waitingWidget->deleteLater(); m_waitingWidget = nullptr; // Don't delete in destructor - m_checkerWidget = new CheckerWidget( this ); + m_checkerWidget = new ResultsListWidget( this ); m_checkerWidget->init( m_requirements ); layout()->addWidget( m_checkerWidget ); diff --git a/src/modules/welcome/checker/CheckerContainer.h b/src/modules/welcome/checker/CheckerContainer.h index 5a8a1865e..e50b362a2 100644 --- a/src/modules/welcome/checker/CheckerContainer.h +++ b/src/modules/welcome/checker/CheckerContainer.h @@ -27,7 +27,7 @@ #include "modulesystem/Requirement.h" -class CheckerWidget; +class ResultsListWidget; class WaitingWidget; /** @@ -55,7 +55,7 @@ public slots: protected: WaitingWidget *m_waitingWidget; - CheckerWidget *m_checkerWidget; + ResultsListWidget *m_checkerWidget; Calamares::RequirementsList m_requirements; bool m_verdict; diff --git a/src/modules/welcome/checker/ResultWidget.cpp b/src/modules/welcome/checker/ResultWidget.cpp index ef0905100..0a0b438e1 100644 --- a/src/modules/welcome/checker/ResultWidget.cpp +++ b/src/modules/welcome/checker/ResultWidget.cpp @@ -17,7 +17,7 @@ * along with Calamares. If not, see . */ -#include "CheckItemWidget.h" +#include "ResultWidget.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" @@ -31,7 +31,7 @@ static inline void setCondition( QLabel* label, CalamaresUtils::ImageType t ) QSize( label->height(), label->height() ) ) ); } -CheckItemWidget::CheckItemWidget( bool checked, +ResultWidget::ResultWidget( bool satisfied, bool required, QWidget* parent ) : QWidget( parent ) @@ -46,8 +46,7 @@ CheckItemWidget::CheckItemWidget( bool checked, mainLayout->addWidget( m_textLabel ); m_textLabel->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); - if ( checked ) - // Condition is satisfied + if ( satisfied ) setCondition( m_iconLabel, CalamaresUtils::StatusOk ); else if ( required ) @@ -58,7 +57,7 @@ CheckItemWidget::CheckItemWidget( bool checked, void -CheckItemWidget::setText( const QString& text ) +ResultWidget::setText( const QString& text ) { m_textLabel->setText( text ); } diff --git a/src/modules/welcome/checker/ResultWidget.h b/src/modules/welcome/checker/ResultWidget.h index d2224c694..d842339ef 100644 --- a/src/modules/welcome/checker/ResultWidget.h +++ b/src/modules/welcome/checker/ResultWidget.h @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017, 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -17,22 +17,35 @@ * along with Calamares. If not, see . */ -#ifndef CHECKITEMWIDGET_H -#define CHECKITEMWIDGET_H +#ifndef CHECKER_RESULTWIDGET_H +#define CHECKER_RESULTWIDGET_H #include -class CheckItemWidget : public QWidget +/** + * @brief Displays the results of a single check. + * + * Widget to insert into a ResultListWidget to display an iconic status + * (warning or failure when the check is not satisfied) along with + * descriptive test. + */ +class ResultWidget : public QWidget { Q_OBJECT public: - explicit CheckItemWidget( bool checked, bool required, - QWidget* parent = nullptr ); + /** + * @brief Create widget with results of a check. + * + * Use setText() to set up the text of the widget. + */ + explicit ResultWidget( bool satisfied, bool required, + QWidget* parent = nullptr ); + /// @brief Set the displayed description of the check. void setText( const QString& text ); private: QLabel* m_textLabel; QLabel* m_iconLabel; }; -#endif // CHECKITEMWIDGET_H +#endif // CHECKER_RESULTWIDGET_H diff --git a/src/modules/welcome/checker/ResultsListWidget.cpp b/src/modules/welcome/checker/ResultsListWidget.cpp index 2ad79abfd..1c566026f 100644 --- a/src/modules/welcome/checker/ResultsListWidget.cpp +++ b/src/modules/welcome/checker/ResultsListWidget.cpp @@ -17,9 +17,9 @@ * along with Calamares. If not, see . */ -#include "CheckerWidget.h" +#include "ResultsListWidget.h" -#include "CheckItemWidget.h" +#include "ResultWidget.h" #include "Branding.h" #include "utils/CalamaresUtilsGui.h" @@ -33,7 +33,7 @@ #include -CheckerWidget::CheckerWidget( QWidget* parent ) +ResultsListWidget::ResultsListWidget( QWidget* parent ) : QWidget( parent ) { setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); @@ -53,7 +53,7 @@ CheckerWidget::CheckerWidget( QWidget* parent ) void -CheckerWidget::init( const Calamares::RequirementsList& checkEntries ) +ResultsListWidget::init( const Calamares::RequirementsList& checkEntries ) { bool allChecked = true; bool requirementsSatisfied = true; @@ -62,7 +62,7 @@ CheckerWidget::init( const Calamares::RequirementsList& checkEntries ) { if ( !entry.satisfied ) { - CheckItemWidget* ciw = new CheckItemWidget( entry.satisfied, entry.mandatory ); + ResultWidget* ciw = new ResultWidget( entry.satisfied, entry.mandatory ); CALAMARES_RETRANSLATE( ciw->setText( entry.negatedText() ); ) m_entriesLayout->addWidget( ciw ); ciw->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); @@ -162,7 +162,7 @@ CheckerWidget::init( const Calamares::RequirementsList& checkEntries ) void -CheckerWidget::showDetailsDialog( const Calamares::RequirementsList& checkEntries ) +ResultsListWidget::showDetailsDialog( const Calamares::RequirementsList& checkEntries ) { QDialog* detailsDialog = new QDialog( this ); QBoxLayout* mainLayout = new QVBoxLayout; @@ -182,7 +182,7 @@ CheckerWidget::showDetailsDialog( const Calamares::RequirementsList& checkEntrie if ( entry.enumerationText().isEmpty() ) continue; - CheckItemWidget* ciw = new CheckItemWidget( entry.satisfied, entry.mandatory ); + ResultWidget* ciw = new ResultWidget( entry.satisfied, entry.mandatory ); CALAMARES_RETRANSLATE( ciw->setText( entry.enumerationText() ); ) entriesLayout->addWidget( ciw ); ciw->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred ); diff --git a/src/modules/welcome/checker/ResultsListWidget.h b/src/modules/welcome/checker/ResultsListWidget.h index 81eb6fef0..58bac0602 100644 --- a/src/modules/welcome/checker/ResultsListWidget.h +++ b/src/modules/welcome/checker/ResultsListWidget.h @@ -16,19 +16,19 @@ * along with Calamares. If not, see . */ -#ifndef CHECKERWIDGET_H -#define CHECKERWIDGET_H +#ifndef CHECKER_RESULTSLISTWIDGET_H +#define CHECKER_RESULTSLISTWIDGET_H #include "modulesystem/Requirement.h" #include #include -class CheckerWidget : public QWidget +class ResultsListWidget : public QWidget { Q_OBJECT public: - explicit CheckerWidget( QWidget* parent = nullptr ); + explicit ResultsListWidget( QWidget* parent = nullptr ); void init( const Calamares::RequirementsList& checkEntries ); @@ -40,4 +40,4 @@ private: int m_paddingSize; }; -#endif // CHECKERWIDGET_H +#endif // CHECKER_RESULTSLISTWIDGET_H From 54ba0aaf13b0bc2dc948ad88d86040daf08f4b73 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 06:20:20 -0500 Subject: [PATCH 68/89] [welcome] Use convenience function - Introduce a hasDetails() for RequirementEntry, which is just a short-cut, but makes code more readable. --- src/libcalamaresui/modulesystem/Requirement.h | 7 +++++-- src/modules/welcome/checker/ResultsListWidget.cpp | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/libcalamaresui/modulesystem/Requirement.h b/src/libcalamaresui/modulesystem/Requirement.h index bf2157f69..396fe852b 100644 --- a/src/libcalamaresui/modulesystem/Requirement.h +++ b/src/libcalamaresui/modulesystem/Requirement.h @@ -45,14 +45,17 @@ struct RequirementEntry /// @brief name of this requirement; not shown to user and used as ID QString name; - /// @brief Description of this requirement, for use in user-visible lists + /// @brief Detailed description of this requirement, for use in user-visible lists TextFunction enumerationText; - /// @brief User-visible string to show that the requirement is not met + /// @brief User-visible string to show that the requirement is not met, short form TextFunction negatedText; bool satisfied; bool mandatory; + + /// @brief Convenience to check if this entry should be shown in details dialog + bool hasDetails() const { return !enumerationText().isEmpty(); } }; using RequirementsList = QList< RequirementEntry >; diff --git a/src/modules/welcome/checker/ResultsListWidget.cpp b/src/modules/welcome/checker/ResultsListWidget.cpp index 1c566026f..ca1a9459a 100644 --- a/src/modules/welcome/checker/ResultsListWidget.cpp +++ b/src/modules/welcome/checker/ResultsListWidget.cpp @@ -179,7 +179,7 @@ ResultsListWidget::showDetailsDialog( const Calamares::RequirementsList& checkEn for ( const auto& entry : checkEntries ) { - if ( entry.enumerationText().isEmpty() ) + if ( !entry.hasDetails() ) continue; ResultWidget* ciw = new ResultWidget( entry.satisfied, entry.mandatory ); From 4d8acdf425eb3543f437ba2921ea852120df4d7a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 06:26:20 -0500 Subject: [PATCH 69/89] [welcome] Code-formatting - Update copyright headers - Apply calamaresstyle --- src/modules/welcome/checker/ResultWidget.cpp | 20 +++++++++---------- .../welcome/checker/ResultsListWidget.cpp | 20 ++++++++----------- .../welcome/checker/ResultsListWidget.h | 1 + 3 files changed, 19 insertions(+), 22 deletions(-) diff --git a/src/modules/welcome/checker/ResultWidget.cpp b/src/modules/welcome/checker/ResultWidget.cpp index 0a0b438e1..3c3af62d4 100644 --- a/src/modules/welcome/checker/ResultWidget.cpp +++ b/src/modules/welcome/checker/ResultWidget.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017, 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,14 +26,15 @@ static inline void setCondition( QLabel* label, CalamaresUtils::ImageType t ) { - label->setPixmap( CalamaresUtils::defaultPixmap( t, - CalamaresUtils::Original, - QSize( label->height(), label->height() ) ) ); + label->setPixmap( + CalamaresUtils::defaultPixmap( t, + CalamaresUtils::Original, + QSize( label->height(), label->height() ) ) ); } ResultWidget::ResultWidget( bool satisfied, - bool required, - QWidget* parent ) + bool required, + QWidget* parent ) : QWidget( parent ) { QBoxLayout* mainLayout = new QHBoxLayout; @@ -48,11 +49,10 @@ ResultWidget::ResultWidget( bool satisfied, if ( satisfied ) setCondition( m_iconLabel, CalamaresUtils::StatusOk ); + else if ( required ) + setCondition( m_iconLabel, CalamaresUtils::StatusError ); else - if ( required ) - setCondition( m_iconLabel, CalamaresUtils::StatusError ); - else - setCondition( m_iconLabel, CalamaresUtils::StatusWarning ); + setCondition( m_iconLabel, CalamaresUtils::StatusWarning ); } diff --git a/src/modules/welcome/checker/ResultsListWidget.cpp b/src/modules/welcome/checker/ResultsListWidget.cpp index ca1a9459a..5908e4bf5 100644 --- a/src/modules/welcome/checker/ResultsListWidget.cpp +++ b/src/modules/welcome/checker/ResultsListWidget.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac - * Copyright 2017, Adriaan de Groot + * Copyright 2017, 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,9 +69,7 @@ ResultsListWidget::init( const Calamares::RequirementsList& checkEntries ) allChecked = false; if ( entry.mandatory ) - { requirementsSatisfied = false; - } ciw->setAutoFillBackground( true ); QPalette pal( ciw->palette() ); pal.setColor( QPalette::Background, Qt::white ); @@ -97,7 +95,7 @@ ResultsListWidget::init( const Calamares::RequirementsList& checkEntries ) "requirements for installing %1.
" "Installation cannot continue. " "Details..." ) - .arg( *Calamares::Branding::ShortVersionedName ) ); + .arg( *Calamares::Branding::ShortVersionedName ) ); ) textLabel->setOpenExternalLinks( false ); connect( textLabel, &QLabel::linkActivated, @@ -114,7 +112,7 @@ ResultsListWidget::init( const Calamares::RequirementsList& checkEntries ) "recommended requirements for installing %1.
" "Installation can continue, but some features " "might be disabled." ) - .arg( *Calamares::Branding::ShortVersionedName ) ); + .arg( *Calamares::Branding::ShortVersionedName ) ); ) } } @@ -122,16 +120,16 @@ ResultsListWidget::init( const Calamares::RequirementsList& checkEntries ) if ( allChecked && requirementsSatisfied ) { if ( !Calamares::Branding::instance()-> - imagePath( Calamares::Branding::ProductWelcome ).isEmpty() ) + imagePath( Calamares::Branding::ProductWelcome ).isEmpty() ) { QPixmap theImage = QPixmap( Calamares::Branding::instance()-> - imagePath( Calamares::Branding::ProductWelcome ) ); + imagePath( Calamares::Branding::ProductWelcome ) ); if ( !theImage.isNull() ) { QLabel* imageLabel; if ( Calamares::Branding::instance()->welcomeExpandingLogo() ) { - FixedAspectRatioLabel *p = new FixedAspectRatioLabel; + FixedAspectRatioLabel* p = new FixedAspectRatioLabel; p->setPixmap( theImage ); imageLabel = p; } @@ -155,9 +153,7 @@ ResultsListWidget::init( const Calamares::RequirementsList& checkEntries ) ) } else - { m_mainLayout->addStretch(); - } } @@ -194,8 +190,8 @@ ResultsListWidget::showDetailsDialog( const Calamares::RequirementsList& checkEn } QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Close, - Qt::Horizontal, - this ); + Qt::Horizontal, + this ); mainLayout->addWidget( buttonBox ); detailsDialog->setModal( true ); diff --git a/src/modules/welcome/checker/ResultsListWidget.h b/src/modules/welcome/checker/ResultsListWidget.h index 58bac0602..3be02b0d0 100644 --- a/src/modules/welcome/checker/ResultsListWidget.h +++ b/src/modules/welcome/checker/ResultsListWidget.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2019, Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by From 616515cce557a6f64618268d0ae0eeb97255d21f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 06:34:56 -0500 Subject: [PATCH 70/89] Changes: document requirements-checker - Name contributors - Document changes in requirements-checking - Document libparted no-longer-needed --- CHANGES | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CHANGES b/CHANGES index b0a823883..d68a66816 100644 --- a/CHANGES +++ b/CHANGES @@ -6,16 +6,29 @@ website will have to do for older versions. # 3.2.5 (unreleased) # This release contains contributions from (alphabetically by first name): + - Arnaud Ferraris + - Dan Simmons ## Core ## + * View modules (in C++) can now perform their own requirements-checking + to see if installation makes sense. This expands upon the existing + requirements checks in the welcome module (RAM, disk space, ..). + The checks have been made asynchronous, so that responsiveness during + requirements-checking is improved and the user has better feedback. + ## Modules ## + * *Partition* module: it is now possible to build without libparted. Since + KPMCore may not need this library anymore, it is a dependency that will + be dropped as soon as it is feasible. Add `-DCMAKE_DISABLE_FIND_PACKAGE_LIBPARTED=ON` + to the CMake flags to do so. * Python modules: several modules have had translations added. This is usually only visible when the module runs as part of the *exec* step, when the module's *pretty name* is displayed. In addition, error messages are now translated. + # 3.2.4 (2019-02-12) # This release contains contributions from (alphabetically by first name): From 92d9c9491a4549eb0e7e60059a1db98bd0e17147 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 07:05:32 -0500 Subject: [PATCH 71/89] [partition] Reduce lambda-happiness - Make some methods that are called mostly as slots, actual slots, instead of going through extra lambdas. - Use QOverload<>::of for disambiguation instead of homebrew casts. --- src/modules/partition/gui/PartitionPage.cpp | 25 ++++++++------------- src/modules/partition/gui/PartitionPage.h | 10 +++++++-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index a2f2eab60..a8d58f1cd 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -90,22 +90,9 @@ PartitionPage::PartitionPage( PartitionCoreModule* core, QWidget* parent ) updateFromCurrentDevice(); - connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, - [ this ]( const QString& /* text */ ) - { - updateFromCurrentDevice(); - } ); - connect( m_ui->bootLoaderComboBox, static_cast(&QComboBox::activated), - [ this ]( const QString& /* text */ ) - { - m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); - } ); - - connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, - [ this ]( const QString& /* text */ ) - { - updateBootLoaderInstallPath(); - } ); + connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateFromCurrentDevice ); + connect( m_ui->bootLoaderComboBox, QOverload::of(&QComboBox::activated), this, &PartitionPage::updateSelectedBootLoaderIndex ); + connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateBootLoaderInstallPath ); connect( m_core, &PartitionCoreModule::isDirtyChanged, m_ui->revertButton, &QWidget::setEnabled ); @@ -512,6 +499,12 @@ PartitionPage::updateBootLoaderInstallPath() m_core->setBootLoaderInstallPath( var.toString() ); } +void +PartitionPage::updateSelectedBootLoaderIndex() +{ + m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); +} + void PartitionPage::updateFromCurrentDevice() { diff --git a/src/modules/partition/gui/PartitionPage.h b/src/modules/partition/gui/PartitionPage.h index 8289f2cdd..75d39c9dc 100644 --- a/src/modules/partition/gui/PartitionPage.h +++ b/src/modules/partition/gui/PartitionPage.h @@ -50,6 +50,14 @@ public: int selectedDeviceIndex(); void selectDeviceByIndex( int index ); +private slots: + /// @brief Update everything when the base device changes + void updateFromCurrentDevice(); + /// @brief Update when the selected device for boot loader changes + void updateBootLoaderInstallPath(); + /// @brief Explicitly selected boot loader path + void updateSelectedBootLoaderIndex(); + private: QScopedPointer< Ui_PartitionPage > m_ui; PartitionCoreModule* m_core; @@ -67,8 +75,6 @@ private: void updatePartitionToCreate( Device*, Partition* ); void editExistingPartition( Device*, Partition* ); - void updateBootLoaderInstallPath(); - void updateFromCurrentDevice(); void updateBootLoaderIndex(); /** From 943f3fb1f912600a3ee0c9aa0116c8e6c8474932 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 07:10:56 -0500 Subject: [PATCH 72/89] [partition] Improve debug-logging - Use cDebug() instead of qDebug() - Be more chatty when selecting a bootloader installation path --- src/modules/partition/gui/PartitionPage.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index a8d58f1cd..4e1e093b1 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -56,7 +56,6 @@ #include // Qt -#include #include #include #include @@ -495,7 +494,7 @@ PartitionPage::updateBootLoaderInstallPath() QVariant var = m_ui->bootLoaderComboBox->currentData( BootLoaderModel::BootLoaderPathRole ); if ( !var.isValid() ) return; - qDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); + cDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); m_core->setBootLoaderInstallPath( var.toString() ); } @@ -503,6 +502,7 @@ void PartitionPage::updateSelectedBootLoaderIndex() { m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); + cDebug() << "Selected bootloader index" << m_lastSelectedBootLoaderIndex; } void From b4cefff975138e621d9a9437891c9d1b09616b74 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 26 Feb 2019 07:21:36 -0500 Subject: [PATCH 73/89] [partition] Avoid heap-wrangling - The CreatePartitionDialog doesn't need to be on the heap, it's modal here. Avoid QPointer weirdness as well. --- src/modules/partition/gui/PartitionPage.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index 4e1e093b1..5b8f17fd0 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -362,18 +362,18 @@ PartitionPage::onCreateClicked() if ( !checkCanCreate( model->device() ) ) return; - QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( model->device(), - partition->parent(), - nullptr, - getCurrentUsedMountpoints(), - this ); - dlg->initFromFreeSpace( partition ); - if ( dlg->exec() == QDialog::Accepted ) + CreatePartitionDialog dlg( + model->device(), + partition->parent(), + nullptr, + getCurrentUsedMountpoints(), + this ); + dlg.initFromFreeSpace( partition ); + if ( dlg.exec() == QDialog::Accepted ) { - Partition* newPart = dlg->createPartition(); - m_core->createPartition( model->device(), newPart, dlg->newFlags() ); + Partition* newPart = dlg.createPartition(); + m_core->createPartition( model->device(), newPart, dlg.newFlags() ); } - delete dlg; } void From 90eb6afd528da0f7abf8c4dac3a3ea324b28d0a0 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:18:02 +0100 Subject: [PATCH 74/89] [partition] move parseSizeString() function to PartUtils In order to be able to parse partition size strings using the same functions across the partition module, the parseSizeString() function is exported to the PartUtils namespace. Signed-off-by: Arnaud Ferraris --- src/modules/partition/core/PartUtils.cpp | 59 +++++++++++++++++-- src/modules/partition/core/PartUtils.h | 17 ++++++ .../partition/core/PartitionLayout.cpp | 54 +---------------- src/modules/partition/core/PartitionLayout.h | 15 ++--- 4 files changed, 78 insertions(+), 67 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index d09bcd149..856af4799 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -2,6 +2,7 @@ * * Copyright 2015-2016, Teo Mrnjavac * Copyright 2018, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -117,7 +118,7 @@ canBeResized( Partition* candidate ) if ( table->numPrimaries() >= table->maxPrimaries() ) { - cDebug() << " .. partition table already has" + cDebug() << " .. partition table already has" << table->maxPrimaries() << "primary partitions."; return false; } @@ -198,7 +199,7 @@ lookForFstabEntries( const QString& partitionPath ) mountOptions.append( "noload" ); } - cDebug() << "Checking device" << partitionPath + cDebug() << "Checking device" << partitionPath << "for fstab (fs=" << r.getOutput() << ')'; FstabEntryList fstabEntries; @@ -209,9 +210,9 @@ lookForFstabEntries( const QString& partitionPath ) if ( !exit ) // if all is well { QFile fstabFile( mountsDir.path() + "/etc/fstab" ); - + cDebug() << " .. reading" << fstabFile.fileName(); - + if ( fstabFile.open( QIODevice::ReadOnly | QIODevice::Text ) ) { const QStringList fstabLines = QString::fromLocal8Bit( fstabFile.readAll() ) @@ -458,6 +459,56 @@ findFS( QString fsName, FileSystem::Type* fsType ) return fsName; } +double +parseSizeString( const QString& sizeString, SizeUnit* unit ) +{ + double value; + bool ok; + QString valueString; + QString unitString; + + QRegExp rx( "[KkMmGg%]" ); + int pos = rx.indexIn( sizeString ); + if (pos > 0) + { + valueString = sizeString.mid( 0, pos ); + unitString = sizeString.mid( pos ); + } + else + valueString = sizeString; + + value = valueString.toDouble( &ok ); + if ( !ok ) + { + /* + * In case the conversion fails, a size of 100% allows a few cases to pass + * anyway (e.g. when it is the last partition of the layout) + */ + *unit = SizeUnit::Percent; + return 100.0L; + } + + if ( unitString.length() > 0 ) + { + if ( unitString.at(0) == '%' ) + *unit = SizeUnit::Percent; + else if ( unitString.at(0).toUpper() == 'K' ) + *unit = SizeUnit::KiB; + else if ( unitString.at(0).toUpper() == 'M' ) + *unit = SizeUnit::MiB; + else if ( unitString.at(0).toUpper() == 'G' ) + *unit = SizeUnit::GiB; + else + *unit = SizeUnit::Byte; + } + else + { + *unit = SizeUnit::Byte; + } + + return value; +} + } // nmamespace PartUtils /* Implementation of methods for FstabEntry, from OsproberEntry.h */ diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index c7da86c06..35c78f061 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -2,6 +2,7 @@ * * Copyright 2015-2016, Teo Mrnjavac * Copyright 2018, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -33,6 +34,14 @@ class Partition; namespace PartUtils { +enum SizeUnit +{ + Percent = 0, + Byte, + KiB, + MiB, + GiB +}; /** * @brief canBeReplaced checks whether the given Partition satisfies the criteria @@ -86,6 +95,14 @@ bool isEfiBootable( const Partition* candidate ); * its value is FileSystem::Unknown if @p fsName is not recognized. */ QString findFS( QString fsName, FileSystem::Type* fsType ); + +/** + * @brief Parse a partition size string and return its value and unit used. + * @param sizeString the string to parse. + * @param unit pointer to a SizeUnit variable for storing the parsed unit. + * @return the size value, as parsed from the input string. + */ +double parseSizeString( const QString& sizeString, SizeUnit* unit ); } #endif // PARTUTILS_H diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 39341fddd..287c19e41 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -75,61 +75,11 @@ PartitionLayout::addEntry( PartitionLayout::PartitionEntry entry ) m_partLayout.append( entry ); } -static double -parseSizeString( const QString& sizeString, PartitionLayout::SizeUnit* unit ) -{ - double value; - bool ok; - QString valueString; - QString unitString; - - QRegExp rx( "[KkMmGg%]" ); - int pos = rx.indexIn( sizeString ); - if (pos > 0) - { - valueString = sizeString.mid( 0, pos ); - unitString = sizeString.mid( pos ); - } - else - valueString = sizeString; - - value = valueString.toDouble( &ok ); - if ( !ok ) - { - /* - * In case the conversion fails, a size of 100% allows a few cases to pass - * anyway (e.g. when it is the last partition of the layout) - */ - *unit = PartitionLayout::SizeUnit::Percent; - return 100; - } - - if ( unitString.length() > 0 ) - { - if ( unitString.at(0) == '%' ) - *unit = PartitionLayout::SizeUnit::Percent; - else if ( unitString.at(0).toUpper() == 'K' ) - *unit = PartitionLayout::SizeUnit::KiB; - else if ( unitString.at(0).toUpper() == 'M' ) - *unit = PartitionLayout::SizeUnit::MiB; - else if ( unitString.at(0).toUpper() == 'G' ) - *unit = PartitionLayout::SizeUnit::GiB; - else - *unit = PartitionLayout::SizeUnit::Byte; - } - else - { - *unit = PartitionLayout::SizeUnit::Byte; - } - - return value; -} - PartitionLayout::PartitionEntry::PartitionEntry(const QString& size, const QString& min) { - partSize = parseSizeString( size , &partSizeUnit ); + partSize = PartUtils::parseSizeString( size , &partSizeUnit ); if ( !min.isEmpty() ) - partMinSize = parseSizeString( min , &partMinSizeUnit ); + partMinSize = PartUtils::parseSizeString( min , &partMinSizeUnit ); } void diff --git a/src/modules/partition/core/PartitionLayout.h b/src/modules/partition/core/PartitionLayout.h index 999e10425..ab597734c 100644 --- a/src/modules/partition/core/PartitionLayout.h +++ b/src/modules/partition/core/PartitionLayout.h @@ -20,6 +20,8 @@ #ifndef PARTITIONLAYOUT_H #define PARTITIONLAYOUT_H +#include "core/PartUtils.h" + #include "Typedefs.h" // KPMcore @@ -36,24 +38,15 @@ class PartitionLayout { public: - enum SizeUnit - { - Percent = 0, - Byte, - KiB, - MiB, - GiB - }; - struct PartitionEntry { QString partLabel; QString partMountPoint; FileSystem::Type partFileSystem = FileSystem::Unknown; double partSize = 0.0L; - SizeUnit partSizeUnit = Percent; + PartUtils::SizeUnit partSizeUnit = PartUtils::SizeUnit::Percent; double partMinSize = 0.0L; - SizeUnit partMinSizeUnit = Percent; + PartUtils::SizeUnit partMinSizeUnit = PartUtils::SizeUnit::Percent; /// @brief All-zeroes PartitionEntry PartitionEntry() {}; From c3ccc0de0e910a2fe0d36b59713afaaafe593a78 Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:31:30 +0100 Subject: [PATCH 75/89] [libcalamares] Add a KiB unit This commit creates a _KiB operator for future use by the partition module. It also fixes a typo in one instance of MiBtoBytes(), requiring a couple extra fixes. Signed-off-by: Arnaud Ferraris --- src/libcalamares/utils/Units.h | 21 +++++++++++++++++-- src/modules/fsresizer/ResizeFSJob.cpp | 2 +- .../partition/tests/PartitionJobTests.cpp | 3 ++- 3 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/libcalamares/utils/Units.h b/src/libcalamares/utils/Units.h index efc100d59..34f80b17f 100644 --- a/src/libcalamares/utils/Units.h +++ b/src/libcalamares/utils/Units.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2017, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -24,10 +25,16 @@ namespace CalamaresUtils { +/** User defined literals, 1_KiB is 1 KibiByte (= 2^10 bytes) */ +constexpr qint64 operator ""_KiB( unsigned long long m ) +{ + return qint64(m) * 1024; +} + /** User defined literals, 1_MiB is 1 MibiByte (= 2^20 bytes) */ constexpr qint64 operator ""_MiB( unsigned long long m ) { - return qint64(m) * 1024 * 1024; + return operator ""_KiB(m) * 1024; } /** User defined literals, 1_GiB is 1 GibiByte (= 2^30 bytes) */ @@ -36,6 +43,11 @@ constexpr qint64 operator ""_GiB( unsigned long long m ) return operator ""_MiB(m) * 1024; } +constexpr qint64 KiBtoBytes( unsigned long long m ) +{ + return operator ""_KiB( m ); +} + constexpr qint64 MiBtoBytes( unsigned long long m ) { return operator ""_MiB( m ); @@ -46,7 +58,12 @@ constexpr qint64 GiBtoBytes( unsigned long long m ) return operator ""_GiB( m ); } -constexpr qint64 MiBToBytes( double m ) +constexpr qint64 KiBtoBytes( double m ) +{ + return qint64(m * 1024); +} + +constexpr qint64 MiBtoBytes( double m ) { return qint64(m * 1024 * 1024); } diff --git a/src/modules/fsresizer/ResizeFSJob.cpp b/src/modules/fsresizer/ResizeFSJob.cpp index 6394075ba..2ce9eba70 100644 --- a/src/modules/fsresizer/ResizeFSJob.cpp +++ b/src/modules/fsresizer/ResizeFSJob.cpp @@ -80,7 +80,7 @@ ResizeFSJob::RelativeSize::apply( qint64 totalSectors, qint64 sectorSize ) case unit_t::None: return -1; case unit_t::Absolute: - return CalamaresUtils::MiBtoBytes( value() ) / sectorSize; + return CalamaresUtils::MiBtoBytes( static_cast( value() ) ) / sectorSize; case unit_t::Percent: if ( value() == 100 ) return totalSectors; // Common-case, avoid futzing around diff --git a/src/modules/partition/tests/PartitionJobTests.cpp b/src/modules/partition/tests/PartitionJobTests.cpp index d3fd67c12..6a7e2ab72 100644 --- a/src/modules/partition/tests/PartitionJobTests.cpp +++ b/src/modules/partition/tests/PartitionJobTests.cpp @@ -349,7 +349,8 @@ PartitionJobTests::testResizePartition() // Make the test data file smaller than the full size of the partition to // accomodate for the file system overhead - const QByteArray testData = generateTestData( CalamaresUtils::MiBtoBytes( qMin( oldSizeMB, newSizeMB ) ) * 3 / 4 ); + const unsigned long long minSizeMB = qMin( oldSizeMB, newSizeMB ); + const QByteArray testData = generateTestData( CalamaresUtils::MiBtoBytes( minSizeMB ) * 3 / 4 ); const QString testName = "test.data"; // Setup: create the test partition From a5258f07a1896217af4e82e92aa5396e0d319e5a Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:36:29 +0100 Subject: [PATCH 76/89] [partition] move bytesToSectors() and sizeToSectors() to PartUtils In order to allow the use of these functions across the whole partition module and keep all partition size-related functions in the same namespace, this commit moves them to PartUtils. Signed-off-by: Arnaud Ferraris --- src/modules/partition/core/PartUtils.cpp | 34 +++++++++++++++++++ src/modules/partition/core/PartUtils.h | 28 +++++++++++++++ .../partition/core/PartitionActions.cpp | 23 ++----------- src/modules/partition/core/PartitionActions.h | 2 -- .../partition/core/PartitionLayout.cpp | 33 ++---------------- 5 files changed, 67 insertions(+), 53 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 856af4799..75a33bf94 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -459,6 +459,33 @@ findFS( QString fsName, FileSystem::Type* fsType ) return fsName; } +static qint64 +sizeToBytes( double size, SizeUnit unit, qint64 totalSize ) +{ + qint64 bytes; + + switch ( unit ) + { + case SizeUnit::Percent: + bytes = qint64( static_cast( totalSize ) * size / 100.0L ); + break; + case SizeUnit::KiB: + bytes = CalamaresUtils::KiBtoBytes(size); + break; + case SizeUnit::MiB: + bytes = CalamaresUtils::MiBtoBytes(size); + break; + case SizeUnit::GiB: + bytes = CalamaresUtils::GiBtoBytes(size); + break; + default: + bytes = size; + break; + } + + return bytes; +} + double parseSizeString( const QString& sizeString, SizeUnit* unit ) { @@ -509,6 +536,13 @@ parseSizeString( const QString& sizeString, SizeUnit* unit ) return value; } +qint64 +sizeToSectors( double size, SizeUnit unit, qint64 totalSectors, qint64 logicalSize ) +{ + qint64 bytes = sizeToBytes( size, unit, totalSectors * logicalSize ); + return bytesToSectors( static_cast( bytes ), logicalSize ); +} + } // nmamespace PartUtils /* Implementation of methods for FstabEntry, from OsproberEntry.h */ diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index 35c78f061..8b811fd6d 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -22,6 +22,7 @@ #define PARTUTILS_H #include "OsproberEntry.h" +#include "utils/Units.h" // KPMcore #include @@ -34,6 +35,8 @@ class Partition; namespace PartUtils { +using CalamaresUtils::MiBtoBytes; + enum SizeUnit { Percent = 0, @@ -103,6 +106,31 @@ QString findFS( QString fsName, FileSystem::Type* fsType ); * @return the size value, as parsed from the input string. */ double parseSizeString( const QString& sizeString, SizeUnit* unit ); + +/** + * @brief Convert a partition size to a sectors count. + * @param size the partition size. + * @param unit the partition size unit. + * @param totalSectors the total number of sectors of the selected drive. + * @param logicalSize the sector size, in bytes. + * @return the number of sectors to be used for the given partition size. + */ +qint64 sizeToSectors( double size, SizeUnit unit, qint64 totalSectors, qint64 logicalSize ); + +constexpr qint64 alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) +{ + qint64 blocks = bytes / blocksize; + + if ( blocks * blocksize != bytes ) + ++blocks; + return blocks * blocksize; +} + +constexpr qint64 bytesToSectors( qint64 bytes, qint64 blocksize ) +{ + return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize), MiBtoBytes(1ULL) ) / blocksize; +} + } #endif // PARTUTILS_H diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index a135b758f..01e794ff6 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -2,6 +2,7 @@ * * Copyright 2014-2017, Teo Mrnjavac * Copyright 2017-2018, Adriaan de Groot + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -38,8 +39,6 @@ namespace PartitionActions { -using CalamaresUtils::GiBtoBytes; -using CalamaresUtils::MiBtoBytes; using CalamaresUtils::operator""_GiB; using CalamaresUtils::operator""_MiB; @@ -82,22 +81,6 @@ swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) return suggestedSwapSizeB; } -constexpr qint64 -alignBytesToBlockSize( qint64 bytes, qint64 blocksize ) -{ - qint64 blocks = bytes / blocksize; - - if ( blocks * blocksize != bytes ) - ++blocks; - return blocks * blocksize; -} - -qint64 -bytesToSectors( qint64 bytes, qint64 blocksize ) -{ - return alignBytesToBlockSize( alignBytesToBlockSize( bytes, blocksize), MiBtoBytes(1) ) / blocksize; -} - void doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions o ) { @@ -117,11 +100,11 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO // Since sectors count from 0, if the space is 2048 sectors in size, // the first free sector has number 2048 (and there are 2048 sectors // before that one, numbered 0..2047). - qint64 firstFreeSector = bytesToSectors( empty_space_sizeB, dev->logicalSize() ); + qint64 firstFreeSector = PartUtils::bytesToSectors( empty_space_sizeB, dev->logicalSize() ); if ( isEfi ) { - qint64 efiSectorCount = bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); + qint64 efiSectorCount = PartUtils::bytesToSectors( uefisys_part_sizeB, dev->logicalSize() ); Q_ASSERT( efiSectorCount > 0 ); // Since sectors count from 0, and this partition is created starting diff --git a/src/modules/partition/core/PartitionActions.h b/src/modules/partition/core/PartitionActions.h index 179b835ab..d17852b63 100644 --- a/src/modules/partition/core/PartitionActions.h +++ b/src/modules/partition/core/PartitionActions.h @@ -75,8 +75,6 @@ namespace Choices } // namespace Choices -qint64 bytesToSectors( qint64 bytes, qint64 blocksize ); - /** * @brief doAutopartition sets up an autopartitioning operation on the given Device. * @param core a pointer to the PartitionCoreModule instance. diff --git a/src/modules/partition/core/PartitionLayout.cpp b/src/modules/partition/core/PartitionLayout.cpp index 287c19e41..4f62db7d6 100644 --- a/src/modules/partition/core/PartitionLayout.cpp +++ b/src/modules/partition/core/PartitionLayout.cpp @@ -107,35 +107,6 @@ PartitionLayout::addEntry( const QString& label, const QString& mountPoint, cons m_partLayout.append( entry ); } -static qint64 -sizeToSectors( double size, PartitionLayout::SizeUnit unit, qint64 totalSize, qint64 logicalSize ) -{ - qint64 sectors; - double tmp; - - if ( unit == PartitionLayout::SizeUnit::Percent ) - { - tmp = static_cast( totalSize ) * size / 100; - sectors = static_cast( tmp ); - } - else - { - tmp = size; - if ( unit >= PartitionLayout::SizeUnit::KiB ) - tmp *= 1024; - if ( unit >= PartitionLayout::SizeUnit::MiB ) - tmp *= 1024; - if ( unit >= PartitionLayout::SizeUnit::GiB ) - tmp *= 1024; - - sectors = PartitionActions::bytesToSectors( static_cast( tmp ), - logicalSize - ); - } - - return sectors; -} - QList< Partition* > PartitionLayout::execute( Device *dev, qint64 firstSector, qint64 lastSector, QString luksPassphrase, @@ -155,8 +126,8 @@ PartitionLayout::execute( Device *dev, qint64 firstSector, Partition *currentPartition = nullptr; // Calculate partition size - size = sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() ); - minSize = sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() ); + size = PartUtils::sizeToSectors( part.partSize, part.partSizeUnit, totalSize, dev->logicalSize() ); + minSize = PartUtils::sizeToSectors( part.partMinSize, part.partMinSizeUnit, totalSize, dev->logicalSize() ); if ( size < minSize ) size = minSize; if ( size > availableSize ) From 982840bafd234bf462f74739008c516a95b6b00a Mon Sep 17 00:00:00 2001 From: Arnaud Ferraris Date: Thu, 28 Feb 2019 13:46:25 +0100 Subject: [PATCH 77/89] [partition] Allow a configurable EFI System Partition size As requested, this commit adds a new configuration option to the partition.conf file, name `efiSystemPartitionSize`. When this option is absent, the default size of 300MiB will be used. Fixes #1090 Signed-off-by: Arnaud Ferraris --- src/modules/partition/core/PartUtils.cpp | 9 +++++++++ src/modules/partition/core/PartUtils.h | 8 ++++++++ src/modules/partition/core/PartitionActions.cpp | 14 ++++++++++++-- src/modules/partition/gui/PartitionViewStep.cpp | 8 +++++++- src/modules/partition/partition.conf | 4 ++++ 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 75a33bf94..4e8b7e8ba 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -536,6 +536,15 @@ parseSizeString( const QString& sizeString, SizeUnit* unit ) return value; } +qint64 +parseSizeString( const QString& sizeString, qint64 totalSize ) +{ + SizeUnit unit; + double value = parseSizeString( sizeString, &unit ); + + return sizeToBytes( value, unit, totalSize ); +} + qint64 sizeToSectors( double size, SizeUnit unit, qint64 totalSectors, qint64 logicalSize ) { diff --git a/src/modules/partition/core/PartUtils.h b/src/modules/partition/core/PartUtils.h index 8b811fd6d..0ad559a60 100644 --- a/src/modules/partition/core/PartUtils.h +++ b/src/modules/partition/core/PartUtils.h @@ -107,6 +107,14 @@ QString findFS( QString fsName, FileSystem::Type* fsType ); */ double parseSizeString( const QString& sizeString, SizeUnit* unit ); +/** + * @brief Parse a partition size string and return its value in bytes. + * @param sizeString the string to parse. + * @param totalSize the size of the selected drive (used when the size is expressed in %) + * @return the size value in bytes. + */ +qint64 parseSizeString( const QString& sizeString, qint64 totalSize ); + /** * @brief Convert a partition size to a sectors count. * @param size the partition size. diff --git a/src/modules/partition/core/PartitionActions.cpp b/src/modules/partition/core/PartitionActions.cpp index 01e794ff6..4172002fa 100644 --- a/src/modules/partition/core/PartitionActions.cpp +++ b/src/modules/partition/core/PartitionActions.cpp @@ -29,6 +29,7 @@ #include "utils/Units.h" #include "utils/NamedEnum.h" +#include "GlobalStorage.h" #include "JobQueue.h" #include "utils/Logger.h" @@ -84,6 +85,7 @@ swapSuggestion( const qint64 availableSpaceB, Choices::SwapChoice swap ) void doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionOptions o ) { + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); QString defaultFsType = o.defaultFsType; if ( FileSystem::typeForName( defaultFsType ) == FileSystem::Unknown ) defaultFsType = "ext4"; @@ -92,10 +94,18 @@ doAutopartition( PartitionCoreModule* core, Device* dev, Choices::AutoPartitionO // Partition sizes are expressed in MiB, should be multiples of // the logical sector size (usually 512B). EFI starts with 2MiB - // empty and a 300MiB EFI boot partition, while BIOS starts at + // empty and a EFI boot partition, while BIOS starts at // the 1MiB boundary (usually sector 2048). - int uefisys_part_sizeB = isEfi ? 300_MiB : 0_MiB; int empty_space_sizeB = isEfi ? 2_MiB : 1_MiB; + int uefisys_part_sizeB = 0_MiB; + + if ( isEfi ) + { + if ( gs->contains( "efiSystemPartitionSize" ) ) + uefisys_part_sizeB = PartUtils::parseSizeString( gs->value( "efiSystemPartitionSize" ).toString(), dev->capacity() ); + else + uefisys_part_sizeB = 300_MiB; + } // Since sectors count from 0, if the space is 2048 sectors in size, // the first free sector has number 2048 (and there are 2048 sectors diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index 6fc8b0129..ffeb8c055 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -3,7 +3,7 @@ * Copyright 2014, Aurélien Gâteau * Copyright 2014-2017, Teo Mrnjavac * Copyright 2018, Adriaan de Groot - * Copyright 2019, Collabora Ltd + * Copyright 2019, Collabora Ltd * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -489,6 +489,12 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) efiSP = QStringLiteral( "/boot/efi" ); gs->insert( "efiSystemPartition", efiSP ); + // Read and parse key efiSystemPartitionSize + if ( configurationMap.contains( "efiSystemPartitionSize" ) ) + { + gs->insert( "efiSystemPartitionSize", CalamaresUtils::getString( configurationMap, "efiSystemPartitionSize" ) ); + } + // SWAP SETTINGS // // This is a bit convoluted because there's legacy settings to handle as well diff --git a/src/modules/partition/partition.conf b/src/modules/partition/partition.conf index f812b67aa..66f40020c 100644 --- a/src/modules/partition/partition.conf +++ b/src/modules/partition/partition.conf @@ -3,6 +3,10 @@ # etc.) use just /boot. efiSystemPartition: "/boot/efi" +# This optional setting specifies the size of the EFI system partition. +# If nothing is specified, the default size of 300MiB will be used. +# efiSystemPartitionSize: 300M + # In autogenerated partitioning, allow the user to select a swap size? # If there is exactly one choice, no UI is presented, and the user # cannot make a choice -- this setting is used. If there is more than From 3e067e617e9fed5e86a39aa87f861114da61f124 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 28 Feb 2019 10:26:17 -0500 Subject: [PATCH 78/89] [partition] Add accessor and documentation to BootLoaderInstallPath --- src/modules/partition/core/PartitionCoreModule.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index c48c1562c..743f9c178 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -154,6 +154,9 @@ public: void setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags ); + /// @brief Retrieve the path where the bootloader will be installed + QString bootLoaderInstallPath() const { return m_bootLoaderInstallPath; } + /// @brief Set the path where the bootloader will be installed void setBootLoaderInstallPath( const QString& path ); void initLayout(); From 2b149fb944da8d975c05d562ab55adaa9dec25bb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 1 Mar 2019 06:56:52 -0500 Subject: [PATCH 79/89] [partition] Uncomment updateButtons() - This was commented out to combat the crash in device->type() - I believe the crash was caused by double-deletion, which was fixed in 2092ec3c9a0a37553fd061f423df9d29fe55ab80 by not re- parenting an immutable copy of something. - Restore the button-fix, since we need that to keep the *create* button in-sync with the selected partition. FIXES #1097 --- src/modules/partition/gui/PartitionPage.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index a2f2eab60..2743ec53a 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -581,7 +581,7 @@ void PartitionPage::onPartitionModelReset() { m_ui->partitionTreeView->expandAll(); - // updateButtons(); + updateButtons(); updateBootLoaderIndex(); } From ce4d0e6aea321870e171bbe910a898a9c2df8b76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 2 Mar 2019 15:51:36 +0100 Subject: [PATCH 80/89] Revert "Merge branch 'issue-1098'" This reverts commit fdb4311a70ac7a63e8ba55d00b67033e78ce8cac, reversing changes made to 6b369dc5de8a597e7a72b25259f2466b9bcebf32. --- src/modules/partition/core/PartUtils.cpp | 31 +++--------- .../partition/core/PartitionCoreModule.h | 3 -- src/modules/partition/gui/PartitionPage.cpp | 49 +++++++++++-------- src/modules/partition/gui/PartitionPage.h | 10 +--- 4 files changed, 36 insertions(+), 57 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 5cf8101f9..4e8b7e8ba 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -43,25 +43,6 @@ namespace PartUtils { -static QString -convenienceName( const Partition* const candidate ) -{ - if ( !candidate->mountPoint().isEmpty() ) - return candidate->mountPoint(); - if ( !candidate->partitionPath().isEmpty() ) - return candidate->partitionPath(); - if ( !candidate->devicePath().isEmpty() ) - return candidate->devicePath(); - if ( !candidate->deviceNode().isEmpty() ) - return candidate->devicePath(); - - QString p; - QTextStream s( &p ); - s << (void *)candidate; - - return p; -} - bool canBeReplaced( Partition* candidate ) { @@ -83,12 +64,12 @@ canBeReplaced( Partition* candidate ) << QString( "(%1GB)" ).arg( requiredStorageB / 1024 / 1024 / 1024 ); cDebug() << "Storage capacity B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << convenienceName( candidate ) << " length:" << candidate->length(); + << "for" << candidate->partitionPath() << " length:" << candidate->length(); if ( ok && availableStorageB > requiredStorageB ) { - cDebug() << "Partition" << convenienceName( candidate ) << "authorized for replace install."; + cDebug() << "Partition" << candidate->partitionPath() << "authorized for replace install."; return true; } @@ -105,7 +86,7 @@ canBeResized( Partition* candidate ) return false; } - cDebug() << "Checking if" << convenienceName( candidate ) << "can be resized."; + cDebug() << "Checking if" << candidate->partitionPath() << "can be resized."; if ( !candidate->fileSystem().supportGrow() || !candidate->fileSystem().supportShrink() ) { @@ -159,13 +140,13 @@ canBeResized( Partition* candidate ) << QString( "(%1GB)" ).arg( advisedStorageGB ); cDebug() << "Available storage B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << convenienceName( candidate ) << " length:" << candidate->length() + << "for" << candidate->partitionPath() << " length:" << candidate->length() << " sectorsUsed:" << candidate->sectorsUsed() << " fsType:" << candidate->fileSystem().name(); if ( ok && availableStorageB > advisedStorageB ) { - cDebug() << "Partition" << convenienceName( candidate ) << "authorized for resize + autopartition install."; + cDebug() << "Partition" << candidate->partitionPath() << "authorized for resize + autopartition install."; return true; } @@ -401,7 +382,7 @@ isEfiSystem() bool isEfiBootable( const Partition* candidate ) { - cDebug() << "Check EFI bootable" << convenienceName( candidate ) << candidate->devicePath(); + cDebug() << "Check EFI bootable" << candidate->partitionPath() << candidate->devicePath(); cDebug() << " .. flags" << candidate->activeFlags(); auto flags = PartitionInfo::flags( candidate ); diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index 743f9c178..c48c1562c 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -154,9 +154,6 @@ public: void setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags ); - /// @brief Retrieve the path where the bootloader will be installed - QString bootLoaderInstallPath() const { return m_bootLoaderInstallPath; } - /// @brief Set the path where the bootloader will be installed void setBootLoaderInstallPath( const QString& path ); void initLayout(); diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index ba6845020..2743ec53a 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -56,6 +56,7 @@ #include // Qt +#include #include #include #include @@ -89,9 +90,22 @@ PartitionPage::PartitionPage( PartitionCoreModule* core, QWidget* parent ) updateFromCurrentDevice(); - connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateFromCurrentDevice ); - connect( m_ui->bootLoaderComboBox, QOverload::of(&QComboBox::activated), this, &PartitionPage::updateSelectedBootLoaderIndex ); - connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateBootLoaderInstallPath ); + connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, + [ this ]( const QString& /* text */ ) + { + updateFromCurrentDevice(); + } ); + connect( m_ui->bootLoaderComboBox, static_cast(&QComboBox::activated), + [ this ]( const QString& /* text */ ) + { + m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); + } ); + + connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, + [ this ]( const QString& /* text */ ) + { + updateBootLoaderInstallPath(); + } ); connect( m_core, &PartitionCoreModule::isDirtyChanged, m_ui->revertButton, &QWidget::setEnabled ); @@ -362,18 +376,18 @@ PartitionPage::onCreateClicked() if ( !checkCanCreate( model->device() ) ) return; - CreatePartitionDialog dlg( - model->device(), - partition->parent(), - nullptr, - getCurrentUsedMountpoints(), - this ); - dlg.initFromFreeSpace( partition ); - if ( dlg.exec() == QDialog::Accepted ) + QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( model->device(), + partition->parent(), + nullptr, + getCurrentUsedMountpoints(), + this ); + dlg->initFromFreeSpace( partition ); + if ( dlg->exec() == QDialog::Accepted ) { - Partition* newPart = dlg.createPartition(); - m_core->createPartition( model->device(), newPart, dlg.newFlags() ); + Partition* newPart = dlg->createPartition(); + m_core->createPartition( model->device(), newPart, dlg->newFlags() ); } + delete dlg; } void @@ -494,17 +508,10 @@ PartitionPage::updateBootLoaderInstallPath() QVariant var = m_ui->bootLoaderComboBox->currentData( BootLoaderModel::BootLoaderPathRole ); if ( !var.isValid() ) return; - cDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); + qDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); m_core->setBootLoaderInstallPath( var.toString() ); } -void -PartitionPage::updateSelectedBootLoaderIndex() -{ - m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); - cDebug() << "Selected bootloader index" << m_lastSelectedBootLoaderIndex; -} - void PartitionPage::updateFromCurrentDevice() { diff --git a/src/modules/partition/gui/PartitionPage.h b/src/modules/partition/gui/PartitionPage.h index 75d39c9dc..8289f2cdd 100644 --- a/src/modules/partition/gui/PartitionPage.h +++ b/src/modules/partition/gui/PartitionPage.h @@ -50,14 +50,6 @@ public: int selectedDeviceIndex(); void selectDeviceByIndex( int index ); -private slots: - /// @brief Update everything when the base device changes - void updateFromCurrentDevice(); - /// @brief Update when the selected device for boot loader changes - void updateBootLoaderInstallPath(); - /// @brief Explicitly selected boot loader path - void updateSelectedBootLoaderIndex(); - private: QScopedPointer< Ui_PartitionPage > m_ui; PartitionCoreModule* m_core; @@ -75,6 +67,8 @@ private: void updatePartitionToCreate( Device*, Partition* ); void editExistingPartition( Device*, Partition* ); + void updateBootLoaderInstallPath(); + void updateFromCurrentDevice(); void updateBootLoaderIndex(); /** From 4b96a4ab242e4afc2796f3b36a0b0f789f2377d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Sat, 2 Mar 2019 17:36:59 +0100 Subject: [PATCH 81/89] Revert "Revert "Merge branch 'issue-1098'"" This reverts commit ce4d0e6aea321870e171bbe910a898a9c2df8b76. --- src/modules/partition/core/PartUtils.cpp | 31 +++++++++--- .../partition/core/PartitionCoreModule.h | 3 ++ src/modules/partition/gui/PartitionPage.cpp | 49 ++++++++----------- src/modules/partition/gui/PartitionPage.h | 10 +++- 4 files changed, 57 insertions(+), 36 deletions(-) diff --git a/src/modules/partition/core/PartUtils.cpp b/src/modules/partition/core/PartUtils.cpp index 4e8b7e8ba..5cf8101f9 100644 --- a/src/modules/partition/core/PartUtils.cpp +++ b/src/modules/partition/core/PartUtils.cpp @@ -43,6 +43,25 @@ namespace PartUtils { +static QString +convenienceName( const Partition* const candidate ) +{ + if ( !candidate->mountPoint().isEmpty() ) + return candidate->mountPoint(); + if ( !candidate->partitionPath().isEmpty() ) + return candidate->partitionPath(); + if ( !candidate->devicePath().isEmpty() ) + return candidate->devicePath(); + if ( !candidate->deviceNode().isEmpty() ) + return candidate->devicePath(); + + QString p; + QTextStream s( &p ); + s << (void *)candidate; + + return p; +} + bool canBeReplaced( Partition* candidate ) { @@ -64,12 +83,12 @@ canBeReplaced( Partition* candidate ) << QString( "(%1GB)" ).arg( requiredStorageB / 1024 / 1024 / 1024 ); cDebug() << "Storage capacity B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << candidate->partitionPath() << " length:" << candidate->length(); + << "for" << convenienceName( candidate ) << " length:" << candidate->length(); if ( ok && availableStorageB > requiredStorageB ) { - cDebug() << "Partition" << candidate->partitionPath() << "authorized for replace install."; + cDebug() << "Partition" << convenienceName( candidate ) << "authorized for replace install."; return true; } @@ -86,7 +105,7 @@ canBeResized( Partition* candidate ) return false; } - cDebug() << "Checking if" << candidate->partitionPath() << "can be resized."; + cDebug() << "Checking if" << convenienceName( candidate ) << "can be resized."; if ( !candidate->fileSystem().supportGrow() || !candidate->fileSystem().supportShrink() ) { @@ -140,13 +159,13 @@ canBeResized( Partition* candidate ) << QString( "(%1GB)" ).arg( advisedStorageGB ); cDebug() << "Available storage B:" << availableStorageB << QString( "(%1GB)" ).arg( availableStorageB / 1024 / 1024 / 1024 ) - << "for" << candidate->partitionPath() << " length:" << candidate->length() + << "for" << convenienceName( candidate ) << " length:" << candidate->length() << " sectorsUsed:" << candidate->sectorsUsed() << " fsType:" << candidate->fileSystem().name(); if ( ok && availableStorageB > advisedStorageB ) { - cDebug() << "Partition" << candidate->partitionPath() << "authorized for resize + autopartition install."; + cDebug() << "Partition" << convenienceName( candidate ) << "authorized for resize + autopartition install."; return true; } @@ -382,7 +401,7 @@ isEfiSystem() bool isEfiBootable( const Partition* candidate ) { - cDebug() << "Check EFI bootable" << candidate->partitionPath() << candidate->devicePath(); + cDebug() << "Check EFI bootable" << convenienceName( candidate ) << candidate->devicePath(); cDebug() << " .. flags" << candidate->activeFlags(); auto flags = PartitionInfo::flags( candidate ); diff --git a/src/modules/partition/core/PartitionCoreModule.h b/src/modules/partition/core/PartitionCoreModule.h index c48c1562c..743f9c178 100644 --- a/src/modules/partition/core/PartitionCoreModule.h +++ b/src/modules/partition/core/PartitionCoreModule.h @@ -154,6 +154,9 @@ public: void setPartitionFlags( Device* device, Partition* partition, PartitionTable::Flags flags ); + /// @brief Retrieve the path where the bootloader will be installed + QString bootLoaderInstallPath() const { return m_bootLoaderInstallPath; } + /// @brief Set the path where the bootloader will be installed void setBootLoaderInstallPath( const QString& path ); void initLayout(); diff --git a/src/modules/partition/gui/PartitionPage.cpp b/src/modules/partition/gui/PartitionPage.cpp index 2743ec53a..ba6845020 100644 --- a/src/modules/partition/gui/PartitionPage.cpp +++ b/src/modules/partition/gui/PartitionPage.cpp @@ -56,7 +56,6 @@ #include // Qt -#include #include #include #include @@ -90,22 +89,9 @@ PartitionPage::PartitionPage( PartitionCoreModule* core, QWidget* parent ) updateFromCurrentDevice(); - connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, - [ this ]( const QString& /* text */ ) - { - updateFromCurrentDevice(); - } ); - connect( m_ui->bootLoaderComboBox, static_cast(&QComboBox::activated), - [ this ]( const QString& /* text */ ) - { - m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); - } ); - - connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, - [ this ]( const QString& /* text */ ) - { - updateBootLoaderInstallPath(); - } ); + connect( m_ui->deviceComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateFromCurrentDevice ); + connect( m_ui->bootLoaderComboBox, QOverload::of(&QComboBox::activated), this, &PartitionPage::updateSelectedBootLoaderIndex ); + connect( m_ui->bootLoaderComboBox, &QComboBox::currentTextChanged, this, &PartitionPage::updateBootLoaderInstallPath ); connect( m_core, &PartitionCoreModule::isDirtyChanged, m_ui->revertButton, &QWidget::setEnabled ); @@ -376,18 +362,18 @@ PartitionPage::onCreateClicked() if ( !checkCanCreate( model->device() ) ) return; - QPointer< CreatePartitionDialog > dlg = new CreatePartitionDialog( model->device(), - partition->parent(), - nullptr, - getCurrentUsedMountpoints(), - this ); - dlg->initFromFreeSpace( partition ); - if ( dlg->exec() == QDialog::Accepted ) + CreatePartitionDialog dlg( + model->device(), + partition->parent(), + nullptr, + getCurrentUsedMountpoints(), + this ); + dlg.initFromFreeSpace( partition ); + if ( dlg.exec() == QDialog::Accepted ) { - Partition* newPart = dlg->createPartition(); - m_core->createPartition( model->device(), newPart, dlg->newFlags() ); + Partition* newPart = dlg.createPartition(); + m_core->createPartition( model->device(), newPart, dlg.newFlags() ); } - delete dlg; } void @@ -508,10 +494,17 @@ PartitionPage::updateBootLoaderInstallPath() QVariant var = m_ui->bootLoaderComboBox->currentData( BootLoaderModel::BootLoaderPathRole ); if ( !var.isValid() ) return; - qDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); + cDebug() << "PartitionPage::updateBootLoaderInstallPath" << var.toString(); m_core->setBootLoaderInstallPath( var.toString() ); } +void +PartitionPage::updateSelectedBootLoaderIndex() +{ + m_lastSelectedBootLoaderIndex = m_ui->bootLoaderComboBox->currentIndex(); + cDebug() << "Selected bootloader index" << m_lastSelectedBootLoaderIndex; +} + void PartitionPage::updateFromCurrentDevice() { diff --git a/src/modules/partition/gui/PartitionPage.h b/src/modules/partition/gui/PartitionPage.h index 8289f2cdd..75d39c9dc 100644 --- a/src/modules/partition/gui/PartitionPage.h +++ b/src/modules/partition/gui/PartitionPage.h @@ -50,6 +50,14 @@ public: int selectedDeviceIndex(); void selectDeviceByIndex( int index ); +private slots: + /// @brief Update everything when the base device changes + void updateFromCurrentDevice(); + /// @brief Update when the selected device for boot loader changes + void updateBootLoaderInstallPath(); + /// @brief Explicitly selected boot loader path + void updateSelectedBootLoaderIndex(); + private: QScopedPointer< Ui_PartitionPage > m_ui; PartitionCoreModule* m_core; @@ -67,8 +75,6 @@ private: void updatePartitionToCreate( Device*, Partition* ); void editExistingPartition( Device*, Partition* ); - void updateBootLoaderInstallPath(); - void updateFromCurrentDevice(); void updateBootLoaderIndex(); /** From 53fb53454f2f064f7930effa68b8c9ea61ee2bdf Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 12:10:34 -0400 Subject: [PATCH 82/89] Docs: fix up explanations, mention INSTALL_CONFIG --- src/modules/README.md | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/src/modules/README.md b/src/modules/README.md index bd6cd4e37..29fa79cff 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -18,9 +18,9 @@ There are two types of Calamares module: # Module interfaces There are three (four) interfaces for Calamares modules: -* qtplugin, +* qtplugin (viewmodules, jobmodules), * python (jobmodules only), -* pythonqt (optional), +* pythonqt (viewmodules, jobmodules, optional), * process (jobmodules only). # Module directory @@ -59,11 +59,17 @@ Module descriptors **may** have the following keys: A Calamares module **may** read a module configuration file, named `.conf`. If such a file is present in the -module's directory, it is shipped as a *default* configuration file. +module's directory, it can be shipped as a *default* configuration file. +This only happens if the CMake-time option `INSTALL_CONFIG` is on. + +The sample configuration files may work and may be suitable for +your distribution, but no guarantee is given about their stability +beyond syntactic correctness. + The module configuration file, if it exists, is a YAML 1.2 document which contains a YAML map of anything. -All default module configuration files are installed in +All sample module configuration files are installed in `$DESTDIR/share/calamares/modules` but can be overridden by files with the same name placed manually (or by the packager) in `/etc/calamares/modules`. @@ -129,7 +135,9 @@ A process jobmodule runs a (single) command. The interface is "process", while the module type must be "job" or "jobmodule". The key *command* should have a string as value, which is passed to the -shell -- remember to quote it properly. +shell -- remember to quote it properly. It is generally recommended to use +a *shellprocess* job module instead (less configuration, easier to have +multiple instances). ## Emergency Modules From eab36a098fd9d1618be8008b520568ab612d0922 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 16:52:06 -0400 Subject: [PATCH 83/89] Docs: shuffle the modules README --- src/modules/README.md | 92 +++++++++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 35 deletions(-) diff --git a/src/modules/README.md b/src/modules/README.md index 29fa79cff..2f0790863 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -8,27 +8,28 @@ Each Calamares module lives in its own directory. All modules are installed in `$DESTDIR/lib/calamares/modules`. -# Module types - -There are two types of Calamares module: +There are two **types** of Calamares module: * viewmodule, for user-visible modules. These may be in C++, or PythonQt. * jobmodule, for not-user-visible modules. These may be done in C++, Python, or as external processes. -# Module interfaces +A viewmodule exposes a UI to the user. The PythonQt-based modules +are considered experimental (and as of march 2019 may be on the +way out again as never-used-much and PythonQt is not packaged +on Debian anymore). -There are three (four) interfaces for Calamares modules: +There are three (four) **interfaces** for Calamares modules: * qtplugin (viewmodules, jobmodules), * python (jobmodules only), * pythonqt (viewmodules, jobmodules, optional), * process (jobmodules only). -# Module directory +## Module directory Each Calamares module lives in its own directory. The contents of the directory depend on the interface and type of the module. -## Module descriptor +### Module descriptor A Calamares module must have a *module descriptor file*, named `module.desc`. For C++ (qtplugin) modules using CMake as a build- @@ -55,7 +56,28 @@ Module descriptors **may** have the following keys: - *emergency* (a boolean value, set to true to mark the module as an emergency module) -## Module-specific configuration +### Emergency Modules + +Only C++ modules and job modules may be emergency modules. If, during an +*exec* step in the sequence, a module fails, installation as a whole fails +and the install is aborted. If there are emergency modules in the **same** +exec block, those will be executed before the installation is aborted. +Non-emergency modules are not executed. + +If an emergency-module fails while processing emergency-modules for +another failed module, that failure is ignored and emergency-module +processing continues. + +Use the EMERGENCY keyword in the CMake description of a C++ module +to generate a suitable `module.desc`. + +A module that is marked as an emergency module in its module.desc +must **also** set the *emergency* key to *true* in its configuration file +(see below). If it does not, the module is not considered to be an emergency +module after all (this is so that you can have modules that have several +instances, only some of which are actually needed for emergencies). + +### Module-specific configuration A Calamares module **may** read a module configuration file, named `.conf`. If such a file is present in the @@ -74,6 +96,8 @@ All sample module configuration files are installed in files with the same name placed manually (or by the packager) in `/etc/calamares/modules`. + + ## C++ modules Currently the recommended way to write a module which exposes one or more @@ -85,6 +109,8 @@ To add a Qt plugin module, put it in a subdirectory and make sure it has a `CMakeLists.txt` with a `calamares_add_plugin` call. It will be picked up automatically by our CMake magic. The `module.desc` file is optional. + + ## Python modules Modules may use one of the python interfaces, which may be present @@ -119,6 +145,17 @@ function `run()` as entry point. The function `run()` must return `None` if everything went well, or a tuple `(str,str)` with an error message and description if something went wrong. +### Python API + +**TODO:** this needs documentation + + + +## PythonQt modules + +The PythonQt modules are considered experimental and may be removed again +due to low uptake. Their documentation is also almost completely lacking. + ### PythonQt Jobmodule A PythonQt jobmodule implements the experimental Job interface by defining @@ -129,33 +166,18 @@ a subclass of something. A PythonQt viewmodule implements the experimental View interface by defining a subclass of something. +### Python API + +**TODO:** this needs documentation + + + ## Process jobmodules -A process jobmodule runs a (single) command. The interface is "process", -while the module type must be "job" or "jobmodule". +A process jobmodule runs a (single) command. The interface is *process*, +while the module type must be *job* or *jobmodule*. -The key *command* should have a string as value, which is passed to the -shell -- remember to quote it properly. It is generally recommended to use -a *shellprocess* job module instead (less configuration, easier to have -multiple instances). - -## Emergency Modules - -Only C++ modules and job modules may be emergency modules. If, during an -*exec* step in the sequence, a module fails, installation as a whole fails -and the install is aborted. If there are emergency modules in the **same** -exec block, those will be executed before the installation is aborted. -Non-emergency modules are not executed. - -If an emergency-module fails while processing emergency-modules for -another failed module, that failure is ignored and emergency-module -processing continues. - -Use the EMERGENCY keyword in the CMake description of a C++ module -to generate a suitable `module.desc`. - -A module that is marked as an emergency module in its module.desc -must **also** set the *emergency* key to *true* in its configuration file. -If it does not, the module is not considered to be an emergency module -after all (this is so that you can have modules that have several -instances, only some of which are actually needed for emergencies. +The module-descriptor key *command* should have a string as value, which is +passed to the shell -- remember to quote it properly. It is generally +recommended to use a *shellprocess* job module instead (less configuration, +easier to have multiple instances). From 2fdf799ee1969b82c122761f5892404ca7a5a758 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 16:59:00 -0400 Subject: [PATCH 84/89] Docs: document the requiredModules descriptor key --- src/modules/README.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/modules/README.md b/src/modules/README.md index 2f0790863..cb5414a6e 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -51,11 +51,20 @@ Module descriptors **must** have the following keys: refer to the kinds of modules by their interface) Module descriptors **may** have the following keys: -- *required* **unimplemented** (a list of modules which are required for this module +- *requiredModules* (a list of modules which are required for this module to operate properly) - *emergency* (a boolean value, set to true to mark the module as an emergency module) +### Required Modules + +A module may list zero (if it has no requirements) or more modules +by name. As modules are loaded from the global sequence in `settings.conf`, +each module is checked that all of the modules it requires are +already loaded before it. This ensures that if a module needs +another one to fill in globalstorage keys, that happens before +it needs those keys. + ### Emergency Modules Only C++ modules and job modules may be emergency modules. If, during an From 5513b5a6974c21488a2db689044b8b40a69ecc24 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 17:04:47 -0400 Subject: [PATCH 85/89] Docs: mention python module descriptor key --- src/modules/README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/README.md b/src/modules/README.md index cb5414a6e..7f67cfe6d 100644 --- a/src/modules/README.md +++ b/src/modules/README.md @@ -50,6 +50,9 @@ Module descriptors **must** have the following keys: - *interface* (see below for the different interfaces; generally we refer to the kinds of modules by their interface) +Module descriptors for Python and PythonQt modules **must** have the following key: +- *script* (the name of the Python script to load, nearly always `main.py`) + Module descriptors **may** have the following keys: - *requiredModules* (a list of modules which are required for this module to operate properly) @@ -131,7 +134,7 @@ or the experimental pythonqt job- and viewmodule interfaces. To add a Python or process jobmodule, put it in a subdirectory and make sure it has a `module.desc`. It will be picked up automatically by our CMake magic. For all kinds of Python jobs, the key *script* must be set to the name of -the main python file for the job. This is almost universally "main.py". +the main python file for the job. This is almost universally `main.py`. `CMakeLists.txt` is *not* used for Python and process jobmodules. From a93df6fcfb501b9bfa38063eab8924d31a509b8d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 17:07:05 -0400 Subject: [PATCH 86/89] [bootloader] Requires partition before it. --- src/modules/bootloader/module.desc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/modules/bootloader/module.desc b/src/modules/bootloader/module.desc index 94534cc98..083e1f4b5 100644 --- a/src/modules/bootloader/module.desc +++ b/src/modules/bootloader/module.desc @@ -1,5 +1,8 @@ --- type: "job" -name: "bootloader" interface: "python" +name: "bootloader" script: "main.py" +# The partition module sets up the EFI firmware type +# global key, which is used to decide how to install. +requiredModules: [ "partition" ] From bc26c3e009e10d156196da75b9022de23a369455 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 17:25:21 -0400 Subject: [PATCH 87/89] [welcome] Remove unused method - This **should** be used, though. See #1104. It should be used somewhere else. --- src/modules/welcome/checker/GeneralRequirements.cpp | 8 -------- src/modules/welcome/checker/GeneralRequirements.h | 1 - 2 files changed, 9 deletions(-) diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 4fcd8129d..07d99d707 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -382,11 +382,3 @@ GeneralRequirements::checkIsRoot() { return !geteuid(); } - - -void -GeneralRequirements::detectFirmwareType() -{ - QString fwType = QFile::exists( "/sys/firmware/efi/efivars" ) ? "efi" : "bios"; - Calamares::JobQueue::instance()->globalStorage()->insert( "firmwareType", fwType ); -} diff --git a/src/modules/welcome/checker/GeneralRequirements.h b/src/modules/welcome/checker/GeneralRequirements.h index 0e3e341b0..fe0d7a94d 100644 --- a/src/modules/welcome/checker/GeneralRequirements.h +++ b/src/modules/welcome/checker/GeneralRequirements.h @@ -45,7 +45,6 @@ private: bool checkHasPower(); bool checkHasInternet(); bool checkIsRoot(); - void detectFirmwareType(); qreal m_requiredStorageGB; qreal m_requiredRamGB; From 105f9c48617b390743aefe2e612d1761a420a7fc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 17:50:27 -0400 Subject: [PATCH 88/89] [partition] Set firmware type - This got lost in 3.2.4. - Thanks Gabriel for hunting it down; patch applied with some changes. --- src/modules/partition/gui/PartitionViewStep.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/modules/partition/gui/PartitionViewStep.cpp b/src/modules/partition/gui/PartitionViewStep.cpp index ffeb8c055..7053740c9 100644 --- a/src/modules/partition/gui/PartitionViewStep.cpp +++ b/src/modules/partition/gui/PartitionViewStep.cpp @@ -489,6 +489,11 @@ PartitionViewStep::setConfigurationMap( const QVariantMap& configurationMap ) efiSP = QStringLiteral( "/boot/efi" ); gs->insert( "efiSystemPartition", efiSP ); + // Set up firmwareType global storage entry. This is used, e.g. by the bootloader module. + QString firmwareType( PartUtils::isEfiSystem() ? QStringLiteral( "efi" ) : QStringLiteral( "bios" ) ); + cDebug() << "Setting firmwareType to" << firmwareType; + gs->insert( "firmwareType", firmwareType ); + // Read and parse key efiSystemPartitionSize if ( configurationMap.contains( "efiSystemPartitionSize" ) ) { From 919a6eb9a62a958bf77f90f2a9f0e2fdc6b67deb Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 11 Mar 2019 17:53:08 -0400 Subject: [PATCH 89/89] Changes: document bugfix FIXES #1104 --- CHANGES | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGES b/CHANGES index d68a66816..232a348ca 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ website will have to do for older versions. This release contains contributions from (alphabetically by first name): - Arnaud Ferraris - Dan Simmons + - Gabriel Craciunescu ## Core ## @@ -19,6 +20,9 @@ This release contains contributions from (alphabetically by first name): ## Modules ## + * *Bootloader* module: a serious bug introduced in 3.2.4 which prevents + succesful boot after installation on EFI machines, has been repaired. + (Thanks to Gabriel) * *Partition* module: it is now possible to build without libparted. Since KPMCore may not need this library anymore, it is a dependency that will be dropped as soon as it is feasible. Add `-DCMAKE_DISABLE_FIND_PACKAGE_LIBPARTED=ON`