diff --git a/src/libcalamaresui/Branding.h b/src/libcalamaresui/Branding.h index f1b26fbb5..3dfcd0586 100644 --- a/src/libcalamaresui/Branding.h +++ b/src/libcalamaresui/Branding.h @@ -146,9 +146,6 @@ public: QString slideshowPath() const { return m_slideshowPath; } int slideshowAPI() const { return m_slideshowAPI; } - QString string( Branding::StringEntry stringEntry ) const; - QString styleString( Branding::StyleEntry styleEntry ) const; - QString imagePath( Branding::ImageEntry imageEntry ) const; QPixmap image( Branding::ImageEntry imageEntry, const QSize& size ) const; /** @brief Look up an image in the branding directory or as an icon @@ -185,6 +182,11 @@ public: */ void setGlobals( GlobalStorage* globalStorage ) const; +public slots: + QString string( StringEntry stringEntry ) const; + QString styleString( StyleEntry styleEntry ) const; + QString imagePath( ImageEntry imageEntry ) const; + private: static Branding* s_instance; diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 2bfc72757..e13e022d8 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -29,12 +29,14 @@ #include "widgets/WaitingWidget.h" #include +#include #include #include #include #include #include + static const NamedEnumTable< Calamares::QmlViewStep::QmlSearch >& searchNames() { @@ -82,6 +84,20 @@ changeQMLState( QMLAction action, QQuickItem* item ) } } +static void +registerCalamaresModels() +{ + static bool done = false; + if ( !done ) + { + done = true; + qmlRegisterSingletonType< Calamares::Branding >( + "calamares.ui", 1, 0, "Branding", []( QQmlEngine*, QJSEngine* ) -> QObject* { + return Calamares::Branding::instance(); + } ); + } +} + namespace Calamares { @@ -92,6 +108,8 @@ QmlViewStep::QmlViewStep( const QString& name, QObject* parent ) , m_spinner( new WaitingWidget( tr( "Loading ..." ) ) ) , m_qmlWidget( new QQuickWidget ) { + registerCalamaresModels(); + QVBoxLayout* layout = new QVBoxLayout( m_widget ); layout->addWidget( m_spinner ); @@ -297,6 +315,12 @@ QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { m_qmlFileName = searchQmlFile( m_searchMethod, qmlFile, m_name ); + QObject* config = this->getConfig(); + if ( config ) + { + m_qmlWidget->engine()->rootContext()->setContextProperty( "config", config ); + } + cDebug() << "QmlViewStep" << moduleInstanceKey() << "loading" << m_qmlFileName; m_qmlComponent = new QQmlComponent( m_qmlWidget->engine(), QUrl( m_qmlFileName ), QQmlComponent::CompilationMode::Asynchronous ); @@ -316,7 +340,17 @@ void QmlViewStep::showFailedQml() { cWarning() << "QmlViewStep" << moduleInstanceKey() << "loading failed."; + if ( m_qmlComponent ) + { + cDebug() << Logger::SubEntry << "QML error:" << m_qmlComponent->errorString(); + } m_spinner->setText( prettyName() + ' ' + tr( "Loading failed." ) ); } +QObject* +QmlViewStep::getConfig() +{ + return nullptr; +} + } // namespace Calamares diff --git a/src/libcalamaresui/viewpages/QmlViewStep.h b/src/libcalamaresui/viewpages/QmlViewStep.h index 46ba29a53..b54dc2fb7 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.h +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -73,9 +73,21 @@ public: /// @brief QML widgets don't produce jobs by default virtual JobList jobs() const override; - /// @brief Configure search paths; subclasses should call this as well + /// @brief Configure search paths; subclasses should call this at the **end** of their own implementation virtual void setConfigurationMap( const QVariantMap& configurationMap ) override; +protected: + /** @brief Gets a pointer to the Config of this view step + * + * Parts of the configuration of the viewstep can be passed to QML + * by placing them in a QObject (as properties). The default + * implementation returns nullptr, for no-config. + * + * Ownership of the config object remains with the ViewStep; it is possible + * to return a pointer to a member variable. + */ + virtual QObject* getConfig(); + private Q_SLOTS: void loadComplete(); diff --git a/src/modules/notesqml/NotesQmlViewStep.cpp b/src/modules/notesqml/NotesQmlViewStep.cpp index e729c2df7..79c2e39f2 100644 --- a/src/modules/notesqml/NotesQmlViewStep.cpp +++ b/src/modules/notesqml/NotesQmlViewStep.cpp @@ -36,9 +36,7 @@ NotesQmlViewStep::prettyName() const void NotesQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) -{ - Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation - +{ bool qmlLabel_ok = false; auto qmlLabel = CalamaresUtils::getSubMap( configurationMap, "qmlLabel", qmlLabel_ok ); @@ -46,7 +44,8 @@ NotesQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { m_notesName = new CalamaresUtils::Locale::TranslatedString( qmlLabel, "notes" ); } - + + Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last } CALAMARES_PLUGIN_FACTORY_DEFINITION( NotesQmlViewStepFactory, registerPlugin< NotesQmlViewStep >(); ) diff --git a/src/modules/notesqml/notesqml.qml b/src/modules/notesqml/notesqml.qml index d1ff4f1b5..a41fa98fd 100644 --- a/src/modules/notesqml/notesqml.qml +++ b/src/modules/notesqml/notesqml.qml @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2020, Anke Boersma + * Copyright 2020, 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 @@ -16,6 +17,14 @@ * along with Calamares. If not, see . */ +/* Some Calamares internals are available to all QML modules. + * They live in the calamares.ui namespace (filled programmatically + * by Calamares). One of the internals that is exposed is the + * Branding object, which can be used to retrieve strings and paths + * and colors. + */ +import calamares.ui 1.0 + import QtQuick 2.7 import QtQuick.Controls 2.2 import QtQuick.Window 2.2 @@ -30,9 +39,9 @@ Item { id: flick anchors.fill: parent contentHeight: 800 - + ScrollBar.vertical: ScrollBar { - id: fscrollbar + id: fscrollbar width: 10 policy: ScrollBar.AlwaysOn } @@ -48,27 +57,27 @@ Item { activeFocusOnPress: false wrapMode: Text.WordWrap - text: qsTr("

Generic GNU/Linux 2020.2 LTS Turgid Tuba

+ text: qsTr("

%1

This an example QML file, showing options in RichText with Flickable content.

- +

QML with RichText can use HTML tags, Flickable content is useful for touchscreens.

- +

This is bold text

This is italic text

This is underlined text

This text will be center-aligned.

This is strikethrough

- +

Code example: ls -l /home

- +

Lists:

  • Intel CPU systems
  • AMD CPU systems
- -

The vertical scrollbar is adjustable, current width set to 10.

") + +

The vertical scrollbar is adjustable, current width set to 10.

").arg(Branding.string(Branding.VersionedName)) } } diff --git a/src/modules/welcomeq/Config.cpp b/src/modules/welcomeq/Config.cpp index 6d085143c..cfa6336e2 100644 --- a/src/modules/welcomeq/Config.cpp +++ b/src/modules/welcomeq/Config.cpp @@ -18,11 +18,6 @@ #include "Config.h" -Config::Config() - : m_helpUrl( "https://www.kde.org/" ) -{ -} +Config::Config() {} -Config::~Config() -{ -} +Config::~Config() {} diff --git a/src/modules/welcomeq/Config.h b/src/modules/welcomeq/Config.h index 2295d4ee2..50c3e387b 100644 --- a/src/modules/welcomeq/Config.h +++ b/src/modules/welcomeq/Config.h @@ -16,8 +16,8 @@ * along with Calamares. If not, see . */ -#ifndef WELCOME_CONFIG_H -#define WELCOME_CONFIG_H +#ifndef WELCOMEQ_CONFIG_H +#define WELCOMEQ_CONFIG_H #include #include @@ -25,16 +25,27 @@ class Config : public QObject { Q_OBJECT - Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl CONSTANT ) + Q_PROPERTY( QUrl helpUrl READ helpUrl CONSTANT FINAL ) + Q_PROPERTY( QUrl issuesUrl READ issuesUrl CONSTANT FINAL ) + Q_PROPERTY( QUrl notesUrl READ notesUrl CONSTANT FINAL ) + Q_PROPERTY( QUrl donateUrl READ donateUrl CONSTANT FINAL ) public: Config(); virtual ~Config(); - QUrl helpUrl() const { return m_helpUrl; } void setHelpUrl( const QUrl& url ) { m_helpUrl = url; } + void setIssuesUrl( const QUrl& url ) { m_issuesUrl = url; } + void setNotesUrl( const QUrl& url ) { m_notesUrl = url; } + void setDonateUrl( const QUrl& url ) { m_donateUrl = url; } + +public slots: + QUrl helpUrl() const { return m_helpUrl; } + QUrl issuesUrl() const { return m_issuesUrl; } + QUrl notesUrl() const { return m_notesUrl; } + QUrl donateUrl() const { return m_donateUrl; } private: - QUrl m_helpUrl; + QUrl m_helpUrl, m_issuesUrl, m_notesUrl, m_donateUrl; }; #endif diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp index 2a5b0f661..382e0b4d1 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.cpp +++ b/src/modules/welcomeq/WelcomeQmlViewStep.cpp @@ -37,7 +37,7 @@ CALAMARES_PLUGIN_FACTORY_DEFINITION( WelcomeQmlViewStepFactory, registerPlugin< WelcomeQmlViewStep >(); ) WelcomeQmlViewStep::WelcomeQmlViewStep( QObject* parent ) - : Calamares::ViewStep( parent ) + : Calamares::QmlViewStep( QStringLiteral( "welcomeq" ), parent ) , m_requirementsChecker( new GeneralRequirements( this ) ) { connect( Calamares::ModuleManager::instance(), @@ -47,10 +47,7 @@ WelcomeQmlViewStep::WelcomeQmlViewStep( QObject* parent ) } -WelcomeQmlViewStep::~WelcomeQmlViewStep() -{ -} - +WelcomeQmlViewStep::~WelcomeQmlViewStep() {} QString WelcomeQmlViewStep::prettyName() const @@ -58,53 +55,6 @@ WelcomeQmlViewStep::prettyName() const return tr( "Welcome" ); } - -QWidget* -WelcomeQmlViewStep::widget() -{ - return nullptr; -} - - -bool -WelcomeQmlViewStep::isNextEnabled() const -{ - // TODO: should return true - return false; -} - - -bool -WelcomeQmlViewStep::isBackEnabled() const -{ - // TODO: should return true (it's weird that you are not allowed to have welcome *after* anything - return false; -} - - -bool -WelcomeQmlViewStep::isAtBeginning() const -{ - // TODO: adjust to "pages" in the QML - return true; -} - - -bool -WelcomeQmlViewStep::isAtEnd() const -{ - // TODO: adjust to "pages" in the QML - return true; -} - - -Calamares::JobList -WelcomeQmlViewStep::jobs() const -{ - return Calamares::JobList(); -} - - /** @brief Look up a URL for a button * * Looks up @p key in @p map; if it is a *boolean* value, then @@ -143,7 +93,9 @@ WelcomeQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) using Calamares::Branding; m_config.setHelpUrl( jobOrBrandingSetting( Branding::SupportUrl, configurationMap, "showSupportUrl" ) ); - // TODO: expand Config class and set the remaining fields + m_config.setIssuesUrl( jobOrBrandingSetting( Branding::KnownIssuesUrl, configurationMap, "showKnownIssuesUrl" ) ); + m_config.setNotesUrl( jobOrBrandingSetting( Branding::ReleaseNotesUrl, configurationMap, "showReleaseNotesUrl" ) ); + m_config.setDonateUrl( CalamaresUtils::getString( configurationMap, "showDonateUrl" ) ); // TODO: figure out how the requirements (held by ModuleManager) should be accessible // to QML as a odel. @@ -193,6 +145,8 @@ WelcomeQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) // TODO: figure out where to set this: Config? } } + + QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last } Calamares::RequirementsList @@ -241,3 +195,9 @@ WelcomeQmlViewStep::setCountry( const QString& countryCode, CalamaresUtils::GeoI } } } + +QObject* +WelcomeQmlViewStep::getConfig() +{ + return &m_config; +} diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.h b/src/modules/welcomeq/WelcomeQmlViewStep.h index 468dd7621..064be0455 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.h +++ b/src/modules/welcomeq/WelcomeQmlViewStep.h @@ -21,11 +21,10 @@ #include "Config.h" +#include "DllMacro.h" #include "modulesystem/Requirement.h" #include "utils/PluginFactory.h" -#include "viewpages/ViewStep.h" - -#include +#include "viewpages/QmlViewStep.h" #include #include @@ -40,13 +39,7 @@ class Handler; class GeneralRequirements; -class QQmlComponent; -class QQuickItem; -class QQuickWidget; - -// TODO: Needs a generic Calamares::QmlViewStep as base class -// TODO: refactor and move what makes sense to base class -class PLUGINDLLEXPORT WelcomeQmlViewStep : public Calamares::ViewStep +class PLUGINDLLEXPORT WelcomeQmlViewStep : public Calamares::QmlViewStep { Q_OBJECT @@ -56,16 +49,6 @@ public: QString prettyName() const override; - QWidget* widget() override; - - bool isNextEnabled() const override; - bool isBackEnabled() const override; - - bool isAtBeginning() const override; - bool isAtEnd() const override; - - Calamares::JobList jobs() const override; - void setConfigurationMap( const QVariantMap& configurationMap ) override; /** @brief Sets the country that Calamares is running in. @@ -78,16 +61,13 @@ public: Calamares::RequirementsList checkRequirements() override; +protected: + QObject* getConfig() override; + private: // TODO: a generic QML viewstep should return a config object from a method Config m_config; GeneralRequirements* m_requirementsChecker; - - // TODO: these need to be in the base class (also a base class of ExecutionViewStep) - QQuickWidget* m_qmlWidget; - QQmlComponent* m_qmlComponent; - QQuickItem* m_qmlItem; - }; CALAMARES_PLUGIN_FACTORY_DECLARATION( WelcomeQmlViewStepFactory ) diff --git a/src/modules/welcomeq/welcomeq.conf b/src/modules/welcomeq/welcomeq.conf new file mode 100644 index 000000000..0068ebe5c --- /dev/null +++ b/src/modules/welcomeq/welcomeq.conf @@ -0,0 +1,25 @@ +# 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. +# 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. +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/ diff --git a/src/modules/welcomeq/welcomeq.qml b/src/modules/welcomeq/welcomeq.qml new file mode 100644 index 000000000..b40ec4813 --- /dev/null +++ b/src/modules/welcomeq/welcomeq.qml @@ -0,0 +1,129 @@ +/* === This file is part of Calamares - === + * + * Copyright 2020, 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 . + */ +import calamares.ui 1.0 + +import QtQuick 2.10 +import QtQuick.Controls 2.10 +import QtQuick.Layouts 1.3 +import org.kde.kirigami 2.7 as Kirigami +import QtGraphicalEffects 1.0 +import QtQuick.Window 2.3 + +Page +{ + id: welcome + + header: Item + { + width: parent.width + height: 150 + + Text + { + id: welcomeTopText + anchors.horizontalCenter: parent.horizontalCenter + anchors.top: parent.top + // In QML, QString::arg() only takes one argument + text: qsTr("

%1 %2

").arg(Branding.string(Branding.ProductName)).arg(Branding.string(Branding.Version)) + } + Image + { + id: welcomeImage + anchors.centerIn: parent + // imagePath() returns a full pathname, so make it refer to the filesystem + // .. otherwise the path is interpreted relative to the "call site", which + // .. might be the QRC file. + source: "file:/" + Branding.imagePath(Branding.ProductWelcome) + height: Math.min(100, parent.height) + width: height + sourceSize.width: width + sourceSize.height: height + } + + RowLayout + { + id: buttonBar + width: parent.width + height: 64 + + anchors.bottom: parent.bottom + + spacing: Kirigami.Units.largeSpacing* 2 + +/* Traditionally Calamares has had an "About" button that talks about + * Calamares itself, which just isn't a very useful thing in someone + * else's installation ISO. + */ + Button + { + Layout.fillWidth: true + text: qsTr("About") + icon.name: "documentinfo" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + + visible: false + onClicked: { } // TODO: show an about-Calamares window + } + Button + { + Layout.fillWidth: true + text: qsTr("Support") + icon.name: "documentinfo" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + + visible: config.helpUrl.isValid + onClicked: Qt.openUrlExternally(config.helpUrl) + } + Button + { + Layout.fillWidth: true + text: qsTr("Known issues") + icon.name: "documentinfo" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + + visible: config.issuesUrl.isValid + onClicked: Qt.openUrlExternally(config.issuesUrl) + } + Button + { + Layout.fillWidth: true + text: qsTr("Release notes") + icon.name: "documentinfo" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + + visible: config.notesUrl.isValid + onClicked: Qt.openUrlExternally(config.notesUrl) + } + Button + { + Layout.fillWidth: true + text: qsTr("Donate") + icon.name: "documentinfo" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + + visible: config.donateUrl.isValid + onClicked: Qt.openUrlExternally(config.donateUrl) + } + } + } +} diff --git a/src/modules/welcomeq/welcomeq.qrc b/src/modules/welcomeq/welcomeq.qrc new file mode 100644 index 000000000..772bf7e88 --- /dev/null +++ b/src/modules/welcomeq/welcomeq.qrc @@ -0,0 +1,5 @@ + + + welcomeq.qml + +