From bd27dda4746074c55e3e18c03371ca08eb619e14 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 2 Dec 2017 09:56:03 -0500 Subject: [PATCH] [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