diff --git a/src/libcalamares/modulesystem/RequirementsModel.cpp b/src/libcalamares/modulesystem/RequirementsModel.cpp index 6f9fc1e7b..41a5616c1 100644 --- a/src/libcalamares/modulesystem/RequirementsModel.cpp +++ b/src/libcalamares/modulesystem/RequirementsModel.cpp @@ -1,5 +1,5 @@ /* === This file is part of Calamares - === - * + * * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot * * Calamares is free software: you can redistribute it and/or modify @@ -96,13 +96,16 @@ RequirementsModel::roleNames() const void RequirementsModel::describe() const { + cDebug() << "Requirements model has" << m_requirements.count() << "items"; bool acceptable = true; int count = 0; for ( const auto& r : m_requirements ) { + cDebug() << Logger::SubEntry << "requirement" << count << r.name + << "satisfied?" << r.satisfied + << "mandatory?" << r.mandatory; if ( r.mandatory && !r.satisfied ) { - cDebug() << Logger::SubEntry << "requirement" << count << r.name << "is not satisfied."; acceptable = false; } ++count; diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp index c842e2451..2bf418ff1 100644 --- a/src/modules/welcome/Config.cpp +++ b/src/modules/welcome/Config.cpp @@ -32,6 +32,7 @@ Config::Config( QObject* parent ) : QObject( parent ) , m_languages( CalamaresUtils::Locale::availableTranslations() ) + , m_filtermodel( std::make_unique< QSortFilterProxyModel >() ) { initLanguages(); @@ -97,6 +98,18 @@ Config::requirementsModel() const return Calamares::ModuleManager::instance()->requirementsModel(); } +QAbstractItemModel* +Config::unsatisfiedRequirements() const +{ + if ( !m_filtermodel->sourceModel() ) + { + m_filtermodel->setFilterRole( Calamares::RequirementsModel::Roles::Satisfied ); + m_filtermodel->setFilterFixedString( QStringLiteral( "false" ) ); + m_filtermodel->setSourceModel( requirementsModel() ); + } + return m_filtermodel.get(); +} + QString Config::languageIcon() const @@ -336,7 +349,7 @@ setCountry( Config* config, const QString& countryCode, CalamaresUtils::GeoIP::H } static inline void -setGeoIP( Config* c, const QVariantMap& configurationMap ) +setGeoIP( Config* config, const QVariantMap& configurationMap ) { bool ok = false; QVariantMap geoip = CalamaresUtils::getSubMap( configurationMap, "geoip", ok ); @@ -350,12 +363,12 @@ setGeoIP( Config* c, const QVariantMap& configurationMap ) if ( handler->type() != CalamaresUtils::GeoIP::Handler::Type::None ) { auto* future = new FWString(); - QObject::connect( future, &FWString::finished, [config = c, f = future, h = handler]() { - QString countryResult = f->future().result(); + QObject::connect( future, &FWString::finished, [config, future, handler]() { + QString countryResult = future->future().result(); cDebug() << "GeoIP result for welcome=" << countryResult; - ::setCountry( config, countryResult, h ); - f->deleteLater(); - delete h; + ::setCountry( config, countryResult, handler ); + future->deleteLater(); + delete handler; } ); future->setFuture( handler->queryRaw() ); } diff --git a/src/modules/welcome/Config.h b/src/modules/welcome/Config.h index 7fe6fa04e..6d14097c5 100644 --- a/src/modules/welcome/Config.h +++ b/src/modules/welcome/Config.h @@ -23,13 +23,37 @@ #include "modulesystem/RequirementsModel.h" #include +#include #include +#include + class Config : public QObject { Q_OBJECT + /** @brief The languages available in Calamares. + * + * This is a list-model, with names and descriptions for the translations + * available to Calamares. + */ Q_PROPERTY( CalamaresUtils::Locale::LabelModel* languagesModel READ languagesModel CONSTANT FINAL ) + /** @brief The requirements (from modules) and their checked-status + * + * The model grows rows over time as each module is checked and its + * requirements are taken into account. The model **as a whole** + * has properties *satisfiedRequirements* and *satisfiedMandatory* + * to say if all of the requirements held in the model have been + * satisfied. See the model documentation for details. + */ Q_PROPERTY( Calamares::RequirementsModel* requirementsModel READ requirementsModel CONSTANT FINAL ) + /** @brief The requirements (from modules) that are **unsatisfied** + * + * This is the same as requirementsModel(), except filtered so + * that only those requirements that are not satisfied are exposed. + * Note that the type is different, so you should still use the + * requirementsModel() for overall status like *satisfiedMandatory*. + */ + Q_PROPERTY( QAbstractItemModel* unsatisfiedRequirements READ unsatisfiedRequirements CONSTANT FINAL ) Q_PROPERTY( QString languageIcon READ languageIcon CONSTANT FINAL ) @@ -83,6 +107,8 @@ public slots: ///@brief The **global** requirements model, from ModuleManager Calamares::RequirementsModel* requirementsModel() const; + QAbstractItemModel* unsatisfiedRequirements() const; + signals: void countryCodeChanged( QString countryCode ); void localeIndexChanged( int localeIndex ); @@ -99,7 +125,8 @@ signals: private: void initLanguages(); - CalamaresUtils::Locale::LabelModel* m_languages; + CalamaresUtils::Locale::LabelModel* m_languages = nullptr; + std::unique_ptr< QSortFilterProxyModel > m_filtermodel; QString m_languageIcon; QString m_countryCode; diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index d8da60d19..45cb654a2 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -67,6 +67,14 @@ requirements: # Also, note the analogous feature in `src/modules/locale/locale.conf`, # which is where you will find complete documentation. # +# For testing, the *style* may be set to `fixed`, any URL that +# returns data (e.g. `http://example.com`) and then *selector* +# sets the data that is actually returned (e.g. "DE" to simulate +# the machine being in Germany). +# +# NOTE: the *selector* must pick the country code from the GeoIP +# data. Timezone, city, or other data will not be recognized. +# geoip: style: "none" url: "https://geoip.kde.org/v1/ubiquity" # extended XML format diff --git a/src/modules/welcomeq/Recommended.qml b/src/modules/welcomeq/Recommended.qml index 636311b11..5a6c1316d 100644 --- a/src/modules/welcomeq/Recommended.qml +++ b/src/modules/welcomeq/Recommended.qml @@ -17,6 +17,8 @@ * along with Calamares. If not, see . */ +/* THIS COMPONENT IS UNUSED -- from the default welcomeq.qml at least */ + import io.calamares.core 1.0 import io.calamares.ui 1.0 diff --git a/src/modules/welcomeq/Requirements.qml b/src/modules/welcomeq/Requirements.qml index e81d0a2e6..e7835d868 100644 --- a/src/modules/welcomeq/Requirements.qml +++ b/src/modules/welcomeq/Requirements.qml @@ -44,8 +44,12 @@ Rectangle { activeFocusOnPress: false wrapMode: Text.WordWrap - text: qsTr("

This computer does not satisfy the minimum requirements for installing %1.
+ property var requirementsText: qsTr("

This computer does not satisfy the minimum requirements for installing %1.
Installation cannot continue.

").arg(Branding.string(Branding.VersionedName)) + property var recommendationsText: qsTr("

This computer does not satisfy some of the recommended requirements for setting up %1.
+ Setup can continue, but some features might be disabled.

").arg(Branding.string(Branding.VersionedName)) + + text: config.requirementsModel.satisfiedMandatory ? recommendationsText : requirementsText } Rectangle { @@ -61,6 +65,7 @@ Rectangle { Item { width: 640 height: 35 + visible: true Column { anchors.centerIn: parent @@ -68,18 +73,22 @@ Rectangle { Rectangle { implicitWidth: 640 implicitHeight: 35 - border.color: mandatory ? "#228b22" : "#ff0000" - color: mandatory ? "#f0fff0" : "#ffc0cb" + // Colors and images based on the two satisfied-bools: + // - if satisfied, then green / ok + // - otherwise if mandatory, then red / stop + // - otherwise, then yellow / warning + border.color: satisfied ? "#228b22" : (mandatory ? "#ff0000" : "#ffa411") + color: satisfied ? "#f0fff0" : (mandatory ? "#ffc0cb" : "#ffefd5") Image { anchors.verticalCenter: parent.verticalCenter anchors.right: parent.right anchors.margins: 20 - source: mandatory ? "qrc:/data/images/yes.svgz" : "qrc:/data/images/no.svgz" + source: satisfied ? "qrc:/data/images/yes.svgz" : (mandatory ? "qrc:/data/images/no.svgz" : "qrc:/data/images/information.svgz") } Text { - text: mandatory ? details : negatedText + text: satisfied ? details : negatedText anchors.centerIn: parent font.pointSize: 11 } @@ -89,9 +98,13 @@ Rectangle { } ListView { + id: requirementsList anchors.fill: parent spacing: 5 - model: config.requirementsModel + // This uses the filtered model, so that only unsatisfied + // requirements are ever shown. You could use *requirementsModel* + // to get all of them. + model: config.unsatisfiedRequirements delegate: requirementsDelegate } } diff --git a/src/modules/welcomeq/welcomeq.conf b/src/modules/welcomeq/welcomeq.conf index 6c2cf9557..6c131742e 100644 --- a/src/modules/welcomeq/welcomeq.conf +++ b/src/modules/welcomeq/welcomeq.conf @@ -1,52 +1,23 @@ -# 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. +# Configuration for the welcomeq module. # -# In addition to displaying the welcome page, this module -# can check requirements for installation. +# The configuration for welcomeq is exactly the same +# as the welcome module, with the one exception of +# *qmlSearch* which governs QML loading. +# +# No documentation is given here: look in the welcome module. --- -# Setting for QML loading +# Setting for QML loading: use QRC, branding, or both sources of files qmlSearch: both -# Display settings for various buttons on the welcome page. -# The URLs themselves come from branding.desc is the setting -# here is "true". If the setting is false, the button is hidden. -# The setting can also be a full URL which will then be used -# instead of the one from the branding file, or empty or not-set -# which will hide the button. + +# Everythin below here is documented in `welcome.conf` showSupportUrl: true showKnownIssuesUrl: true showReleaseNotesUrl: true -# If this Url is set to something non-empty, a "donate" -# button is added to the welcome page alongside the -# others (see settings, above). Clicking the button opens -# the corresponding link. (This button has no corresponding -# branding.desc string) -# -# showDonateUrl: https://kde.org/community/donations/ - -# 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 GiB. 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 GiB. 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 known. check: - storage - ram @@ -54,28 +25,9 @@ requirements: - internet - root - screen - # 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. required: - # - storage - ram - # - root -# GeoIP checking -# -# This can be used to pre-select a language based on the country -# the user is currently in. It *assumes* that there's internet -# connectivity, though. Configuration is like in the locale module, -# but remember to use a URL that returns full data **and** to -# use a selector that will pick the country, not the timezone. -# -# To disable GeoIP checking, either comment-out the entire geoip section, -# or set the *style* key to an unsupported format (e.g. `none`). -# Also, note the analogous feature in `src/modules/locale/locale.conf`, -# which is where you will find complete documentation. -# geoip: style: "none" url: "https://geoip.kde.org/v1/ubiquity" # extended XML format diff --git a/src/modules/welcomeq/welcomeq.qml b/src/modules/welcomeq/welcomeq.qml index b92ff9628..ffa480f4a 100644 --- a/src/modules/welcomeq/welcomeq.qml +++ b/src/modules/welcomeq/welcomeq.qml @@ -56,12 +56,8 @@ Page fillMode: Image.PreserveAspectFit } - Recommended { - visible: !config.requirementsModel.satisfiedRequirements - } - Requirements { - visible: !config.requirementsModel.satisfiedMandatory + visible: !config.requirementsModel.satisfiedRequirements } RowLayout {