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/37] 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/37] [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/37] [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/37] [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/37] [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/37] [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/37] [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/37] [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/37] [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/37] [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/37] [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 d33752c66ce5de240884b926b68368aa97d9669a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 15 Feb 2019 20:53:55 +0100 Subject: [PATCH 12/37] [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 5aa4e52452c5a9c647a9db3bf33abe2d1a10dcdf Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 18 Feb 2019 09:09:37 -0500 Subject: [PATCH 13/37] [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 14/37] [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 15/37] [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 16/37] [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 c678cd80b487527525db2452ac20ed08b50ad801 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 20 Feb 2019 05:48:15 -0500 Subject: [PATCH 17/37] [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 6090a464f899c8859efcffae0d7b0ae12a46916c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 11:12:55 -0500 Subject: [PATCH 18/37] [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 19/37] [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 20/37] [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 2cdfe3543015f641fc11655cee3f9b0cedfe1eca Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 23 Feb 2019 17:14:52 -0500 Subject: [PATCH 21/37] [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 22/37] [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 23/37] [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 24/37] [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 25/37] [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 26/37] [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 27/37] [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 28/37] [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 29/37] [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 30/37] [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 31/37] [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 32/37] [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 33/37] [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 34/37] [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 35/37] [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 c3d13e345178cbc719a9e8d6e643a99e36bec7c6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 25 Feb 2019 07:20:35 -0500 Subject: [PATCH 36/37] [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 37/37] [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 ) )