From adb312bdd271614251d03c709cd906ad8d4e1a3a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 14:19:33 +0100 Subject: [PATCH 01/14] [welcomeq] Coding style - a R/W property isn't CONSTANT - apply calamaresstyle --- src/modules/welcomeq/Config.cpp | 4 +--- src/modules/welcomeq/Config.h | 6 +++--- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/modules/welcomeq/Config.cpp b/src/modules/welcomeq/Config.cpp index 6d085143c..e69f9f2dd 100644 --- a/src/modules/welcomeq/Config.cpp +++ b/src/modules/welcomeq/Config.cpp @@ -23,6 +23,4 @@ Config::Config() { } -Config::~Config() -{ -} +Config::~Config() {} diff --git a/src/modules/welcomeq/Config.h b/src/modules/welcomeq/Config.h index 2295d4ee2..59d90e31d 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,7 +25,7 @@ class Config : public QObject { Q_OBJECT - Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl CONSTANT ) + Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl ) public: Config(); virtual ~Config(); From 7bf0fded1b7b917ca8e1555f7654d91f2dd89891 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 14:25:30 +0100 Subject: [PATCH 02/14] [welcomeq] Port to newer QmlViewStep --- src/modules/welcomeq/WelcomeQmlViewStep.cpp | 51 +-------------------- src/modules/welcomeq/WelcomeQmlViewStep.h | 29 ++---------- 2 files changed, 5 insertions(+), 75 deletions(-) diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp index 2a5b0f661..e43bddc54 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(), @@ -51,60 +51,12 @@ WelcomeQmlViewStep::~WelcomeQmlViewStep() { } - QString 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 @@ -140,6 +92,7 @@ jobOrBrandingSetting( Calamares::Branding::StringEntry e, const QVariantMap& map void WelcomeQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { + QmlViewStep::setConfigurationMap( configurationMap ); using Calamares::Branding; m_config.setHelpUrl( jobOrBrandingSetting( Branding::SupportUrl, configurationMap, "showSupportUrl" ) ); diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.h b/src/modules/welcomeq/WelcomeQmlViewStep.h index 5486d8d31..2bfe448a3 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.h +++ b/src/modules/welcomeq/WelcomeQmlViewStep.h @@ -21,11 +21,10 @@ #include "Config.h" +#include "PluginDllMacro.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. @@ -82,12 +65,6 @@ 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 ) From b5e17b7ea5486dff912fa1f09bcc8da882f9058f Mon Sep 17 00:00:00 2001 From: Camilo Higuita Date: Sat, 14 Dec 2019 18:14:35 +0100 Subject: [PATCH 03/14] [welcomeq] Add full-featured QML for welcome page This is a merge of several commits by Camilo. --- src/modules/welcomeq/welcomeq.qml | 226 ++++++++++++++++++++++++++++++ 1 file changed, 226 insertions(+) create mode 100644 src/modules/welcomeq/welcomeq.qml diff --git a/src/modules/welcomeq/welcomeq.qml b/src/modules/welcomeq/welcomeq.qml new file mode 100644 index 000000000..051430e0e --- /dev/null +++ b/src/modules/welcomeq/welcomeq.qml @@ -0,0 +1,226 @@ +import io.calamares.modules 1.0 as Modules +import io.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 org.kde.mauikit 1.0 as Maui +import QtGraphicalEffects 1.0 +import QtQuick.Window 2.3 + +ResponsiveBase +{ + id: control + + Modules.Welcome + { + id: _welcome + } + + nextButton.enabled: _welcome.Config.isNextEnabled + onNextClicked: + { + if (stackView.depth === 2) + return + + stackView.push(_langComponent) + } + + title: stackView.currentItem.title + subtitle: stackView.currentItem.subtitle + message: stackView.currentItem.message + + header: Item + { + width: parent.width + height: 150 + + Image + { + anchors.centerIn: parent + source: Branding.imagePath(Branding.ProductWelcome) + height: Math.min(100, parent.height) + width: height + sourceSize.width: width + sourceSize.height: height + } + } + + stackView.initialItem: Item + { + property string title: "Welcome to " + Branding.string(Branding.ProductName) + " " + Branding.string(Branding.Version) + property string subtitle: _welcome.Config.genericWelcomeMessage + property string message: _welcome.Config.warningMessage + + ListView + { + id: _requirementsList + anchors.centerIn: parent + implicitWidth: Math.min(parent.width, 500) + implicitHeight: Math.min(contentHeight, 500) + + Rectangle + { + z: parent.z - 1 + anchors.fill: parent + color: Kirigami.Theme.backgroundColor + radius: 5 + opacity: 0.5 + } + + model: _welcome.Config.requirementsModel + + delegate: ItemDelegate + { + id: _delegate + + background: Rectangle + { + color: model.satisfied ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.negativeTextColor + opacity: 0.2 + } + + width: parent.width + height: 48 + + contentItem: RowLayout + { + width: parent.width + height: parent.height + + Item + { + Layout.fillHeight: true + Layout.preferredWidth: height + + Kirigami.Icon + { + source: model.satisfied ? "checkmark" : (model.mandatory ? "error" : "dialog-warning-symbolic") + height: 32 + width: height + anchors.centerIn: parent + color: background.color + } + } + + ColumnLayout + { + Layout.fillWidth: true + Layout.fillHeight: true + + spacing: 0 + + Label + { + Layout.fillWidth: true + Layout.fillHeight: true + horizontalAlignment: Qt.AlignLeft + text: model.name + } + + Label + { + Layout.fillWidth: true + Layout.fillHeight: true + horizontalAlignment: Qt.AlignLeft + text: !model.satisfied ? model.negatedText : model.details + opacity: isCurrentItem ? 1 : 0.7 + font.weight: Font.Light + } + } + } + } + + footer: RowLayout + { + + width: parent.width + height: 64 + + spacing: Kirigami.Units.largeSpacing* 2 + + Button + { + Layout.fillWidth: true + text: "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: Branding.string(Branding.ProductUrl).length + onClicked: Qt.openUrlExternally(Branding.string(Branding.ProductUrl)) + } + + Button + { + Layout.fillWidth: true + text: qsTr("Support") + icon.name: "help-contents" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + visible: Branding.string(Branding.SupportUrl).length + onClicked: Qt.openUrlExternally(Branding.string(Branding.SupportUrl)) + } + + Button + { + Layout.fillWidth: true + text: qsTr("Known issues") + icon.name: "tools-report-bug" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + visible: Branding.string(Branding.KnownIssuesUrl).length + onClicked: Qt.openUrlExternally(Branding.string(Branding.KnownIssuesUrl)) + } + + Button + { + Layout.fillWidth: true + text: qsTr("Release notes") + icon.name: "answer" + Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) + Kirigami.Theme.textColor: "#fff" + visible: Branding.string(Branding.ReleaseNotesUrl).length + onClicked: Qt.openUrlExternally(Branding.string(Branding.ReleaseNotesUrl)) + } + + } + } + } + + + + + Component + { + id: _langComponent + + Item + { + property string title : qsTr("Language") + property string subtitle: qsTr("Select your preferred language to continue with the installation") + + ListViewTemplate + { + id: _langList + anchors.centerIn: parent + implicitWidth: Math.min(parent.width, 500) + implicitHeight: Math.min(contentHeight, 500) + + currentIndex: _welcome.Config.localeIndex + + model: _welcome.Config.languagesModel + + delegate: ListItemDelegate + { + id: _delegate + label1.text: model.label + label2.text: model.englishLabel + } + } + } + + } + +} From 152c3352c2b42cd28329a3c32189ea4850a26c65 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 15:08:18 +0100 Subject: [PATCH 04/14] [welcomeq] Compile the QML into the module - Default implementation is in the QRC - Register Branding for QML modules (just once) --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 17 ++ src/modules/welcomeq/welcomeq.qml | 203 +------------------ src/modules/welcomeq/welcomeq.qrc | 5 + 3 files changed, 25 insertions(+), 200 deletions(-) create mode 100644 src/modules/welcomeq/welcomeq.qrc diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 2bfc72757..582389a5e 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -35,6 +35,7 @@ #include #include + static const NamedEnumTable< Calamares::QmlViewStep::QmlSearch >& searchNames() { @@ -82,6 +83,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 +107,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 ); diff --git a/src/modules/welcomeq/welcomeq.qml b/src/modules/welcomeq/welcomeq.qml index 051430e0e..604a90f66 100644 --- a/src/modules/welcomeq/welcomeq.qml +++ b/src/modules/welcomeq/welcomeq.qml @@ -1,35 +1,15 @@ -import io.calamares.modules 1.0 as Modules -import io.calamares.ui 1.0 +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 org.kde.mauikit 1.0 as Maui import QtGraphicalEffects 1.0 import QtQuick.Window 2.3 -ResponsiveBase +Page { - id: control - - Modules.Welcome - { - id: _welcome - } - - nextButton.enabled: _welcome.Config.isNextEnabled - onNextClicked: - { - if (stackView.depth === 2) - return - - stackView.push(_langComponent) - } - - title: stackView.currentItem.title - subtitle: stackView.currentItem.subtitle - message: stackView.currentItem.message + id: welcome header: Item { @@ -46,181 +26,4 @@ ResponsiveBase sourceSize.height: height } } - - stackView.initialItem: Item - { - property string title: "Welcome to " + Branding.string(Branding.ProductName) + " " + Branding.string(Branding.Version) - property string subtitle: _welcome.Config.genericWelcomeMessage - property string message: _welcome.Config.warningMessage - - ListView - { - id: _requirementsList - anchors.centerIn: parent - implicitWidth: Math.min(parent.width, 500) - implicitHeight: Math.min(contentHeight, 500) - - Rectangle - { - z: parent.z - 1 - anchors.fill: parent - color: Kirigami.Theme.backgroundColor - radius: 5 - opacity: 0.5 - } - - model: _welcome.Config.requirementsModel - - delegate: ItemDelegate - { - id: _delegate - - background: Rectangle - { - color: model.satisfied ? Kirigami.Theme.positiveTextColor : Kirigami.Theme.negativeTextColor - opacity: 0.2 - } - - width: parent.width - height: 48 - - contentItem: RowLayout - { - width: parent.width - height: parent.height - - Item - { - Layout.fillHeight: true - Layout.preferredWidth: height - - Kirigami.Icon - { - source: model.satisfied ? "checkmark" : (model.mandatory ? "error" : "dialog-warning-symbolic") - height: 32 - width: height - anchors.centerIn: parent - color: background.color - } - } - - ColumnLayout - { - Layout.fillWidth: true - Layout.fillHeight: true - - spacing: 0 - - Label - { - Layout.fillWidth: true - Layout.fillHeight: true - horizontalAlignment: Qt.AlignLeft - text: model.name - } - - Label - { - Layout.fillWidth: true - Layout.fillHeight: true - horizontalAlignment: Qt.AlignLeft - text: !model.satisfied ? model.negatedText : model.details - opacity: isCurrentItem ? 1 : 0.7 - font.weight: Font.Light - } - } - } - } - - footer: RowLayout - { - - width: parent.width - height: 64 - - spacing: Kirigami.Units.largeSpacing* 2 - - Button - { - Layout.fillWidth: true - text: "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: Branding.string(Branding.ProductUrl).length - onClicked: Qt.openUrlExternally(Branding.string(Branding.ProductUrl)) - } - - Button - { - Layout.fillWidth: true - text: qsTr("Support") - icon.name: "help-contents" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: "#fff" - visible: Branding.string(Branding.SupportUrl).length - onClicked: Qt.openUrlExternally(Branding.string(Branding.SupportUrl)) - } - - Button - { - Layout.fillWidth: true - text: qsTr("Known issues") - icon.name: "tools-report-bug" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: "#fff" - visible: Branding.string(Branding.KnownIssuesUrl).length - onClicked: Qt.openUrlExternally(Branding.string(Branding.KnownIssuesUrl)) - } - - Button - { - Layout.fillWidth: true - text: qsTr("Release notes") - icon.name: "answer" - Kirigami.Theme.backgroundColor: Qt.rgba(Kirigami.Theme.backgroundColor.r, Kirigami.Theme.backgroundColor.g, Kirigami.Theme.backgroundColor.b, 0.4) - Kirigami.Theme.textColor: "#fff" - visible: Branding.string(Branding.ReleaseNotesUrl).length - onClicked: Qt.openUrlExternally(Branding.string(Branding.ReleaseNotesUrl)) - } - - } - } - } - - - - - Component - { - id: _langComponent - - Item - { - property string title : qsTr("Language") - property string subtitle: qsTr("Select your preferred language to continue with the installation") - - ListViewTemplate - { - id: _langList - anchors.centerIn: parent - implicitWidth: Math.min(parent.width, 500) - implicitHeight: Math.min(contentHeight, 500) - - currentIndex: _welcome.Config.localeIndex - - model: _welcome.Config.languagesModel - - delegate: ListItemDelegate - { - id: _delegate - label1.text: model.label - label2.text: model.englishLabel - } - } - } - - } - } 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 + + From 15d850372646586f5a935d1978c67c707d8b4e85 Mon Sep 17 00:00:00 2001 From: Camilo Higuita Date: Fri, 13 Dec 2019 22:09:27 +0100 Subject: [PATCH 05/14] [libcalamaresui] Expose the branding strings & urls to qml --- src/libcalamaresui/Branding.h | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/libcalamaresui/Branding.h b/src/libcalamaresui/Branding.h index e3952881e..619847d71 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( Branding::StringEntry stringEntry ) const; + QString styleString( Branding::StyleEntry styleEntry ) const; + QString imagePath( Branding::ImageEntry imageEntry ) const; + private: static Branding* s_instance; From 18942f835f200d6e6b6e9c969c37104bafa73ada Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 15:35:11 +0100 Subject: [PATCH 06/14] [libcalamares] Remove confusing name-qualifiers - Using Branding::ImageEntry, when ImageEntry is an enum class defined *in* Branding, is superfluous, and it also confuses moc; the enum type isn't recognized from QML. --- src/libcalamaresui/Branding.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/libcalamaresui/Branding.h b/src/libcalamaresui/Branding.h index 619847d71..0912ff89f 100644 --- a/src/libcalamaresui/Branding.h +++ b/src/libcalamaresui/Branding.h @@ -183,9 +183,9 @@ public: void setGlobals( GlobalStorage* globalStorage ) const; public slots: - QString string( Branding::StringEntry stringEntry ) const; - QString styleString( Branding::StyleEntry styleEntry ) const; - QString imagePath( Branding::ImageEntry imageEntry ) const; + QString string( StringEntry stringEntry ) const; + QString styleString( StyleEntry styleEntry ) const; + QString imagePath( ImageEntry imageEntry ) const; private: static Branding* s_instance; From ae35256177a6b6a2680ece86d77743cccd79784d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 16:03:19 +0100 Subject: [PATCH 07/14] [welcomeq] Add top-text - Fix QML indentation to the canonical 4-spaces - Add a header at the top of the page - Force the image to load from the filesystem --- src/modules/welcomeq/welcomeq.qml | 59 +++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 15 deletions(-) diff --git a/src/modules/welcomeq/welcomeq.qml b/src/modules/welcomeq/welcomeq.qml index 604a90f66..d6ce9342b 100644 --- a/src/modules/welcomeq/welcomeq.qml +++ b/src/modules/welcomeq/welcomeq.qml @@ -1,3 +1,20 @@ +/* === 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 @@ -9,21 +26,33 @@ import QtQuick.Window 2.3 Page { - id: welcome + id: welcome - header: Item - { - width: parent.width - height: 150 + header: Item + { + width: parent.width + height: 150 - Image - { - anchors.centerIn: parent - source: Branding.imagePath(Branding.ProductWelcome) - height: Math.min(100, parent.height) - width: height - sourceSize.width: width - sourceSize.height: height - } - } + 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 + } + } } From 86bf9287ab1341820db08606fc910476a9f577ae Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 16:21:13 +0100 Subject: [PATCH 08/14] [notesqml] Use Branding strings --- src/modules/notesqml/notesqml.qml | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) 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)) } } From f0134aab71b507ac200b41ebd5b72dcc27bbebd4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 17:31:32 +0100 Subject: [PATCH 09/14] [welcomeq] Add more fields to Config - getters as slots, for later access from QML --- src/modules/welcomeq/Config.cpp | 5 +---- src/modules/welcomeq/Config.h | 17 ++++++++++++++--- src/modules/welcomeq/WelcomeQmlViewStep.cpp | 8 ++++---- 3 files changed, 19 insertions(+), 11 deletions(-) diff --git a/src/modules/welcomeq/Config.cpp b/src/modules/welcomeq/Config.cpp index e69f9f2dd..cfa6336e2 100644 --- a/src/modules/welcomeq/Config.cpp +++ b/src/modules/welcomeq/Config.cpp @@ -18,9 +18,6 @@ #include "Config.h" -Config::Config() - : m_helpUrl( "https://www.kde.org/" ) -{ -} +Config::Config() {} Config::~Config() {} diff --git a/src/modules/welcomeq/Config.h b/src/modules/welcomeq/Config.h index 59d90e31d..01c841068 100644 --- a/src/modules/welcomeq/Config.h +++ b/src/modules/welcomeq/Config.h @@ -25,16 +25,27 @@ class Config : public QObject { Q_OBJECT - Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl ) + Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl FINAL ) + Q_PROPERTY( QUrl issuesUrl READ issuesUrl WRITE setIssuesUrl FINAL ) + Q_PROPERTY( QUrl notesUrl READ notesUrl WRITE setNotesUrl FINAL ) + Q_PROPERTY( QUrl donateUrl READ donateUrl WRITE setDonateUrl 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 e43bddc54..fbed4c382 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.cpp +++ b/src/modules/welcomeq/WelcomeQmlViewStep.cpp @@ -47,9 +47,7 @@ WelcomeQmlViewStep::WelcomeQmlViewStep( QObject* parent ) } -WelcomeQmlViewStep::~WelcomeQmlViewStep() -{ -} +WelcomeQmlViewStep::~WelcomeQmlViewStep() {} QString WelcomeQmlViewStep::prettyName() const @@ -96,7 +94,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. From 49ed97cb7792053b45dc5721c20766df77ab56f3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 17:51:10 +0100 Subject: [PATCH 10/14] [libcalamares] Allow QML ViewSteps to expose a config object --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 12 ++++++++++++ src/libcalamaresui/viewpages/QmlViewStep.h | 12 ++++++++++++ src/modules/welcomeq/WelcomeQmlViewStep.cpp | 6 ++++++ src/modules/welcomeq/WelcomeQmlViewStep.h | 3 +++ 4 files changed, 33 insertions(+) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 582389a5e..7a38fb588 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -29,6 +29,7 @@ #include "widgets/WaitingWidget.h" #include +#include #include #include #include @@ -209,6 +210,11 @@ QmlViewStep::loadComplete() // It is marked \internal in the Qt sources, but does exactly // what is needed: sets up visual parent by replacing the root // item, and handling resizes. + QObject* config = this->getConfig(); + if ( config ) + { + m_qmlWidget->engine()->rootContext()->setContextProperty( "config", config ); + } m_qmlWidget->setContent( QUrl( m_qmlFileName ), m_qmlComponent, m_qmlObject ); showQml(); } @@ -336,4 +342,10 @@ QmlViewStep::showFailedQml() 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..038569927 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.h +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -76,6 +76,18 @@ public: /// @brief Configure search paths; subclasses should call this as well 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/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp index fbed4c382..580b183d1 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.cpp +++ b/src/modules/welcomeq/WelcomeQmlViewStep.cpp @@ -194,3 +194,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 2bfe448a3..a497f4c40 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.h +++ b/src/modules/welcomeq/WelcomeQmlViewStep.h @@ -61,6 +61,9 @@ 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; From 85b873a1a286230c7dd5f03a0ce3345505ec3735 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 17:58:21 +0100 Subject: [PATCH 11/14] [libcalamaresui] Log QML error message - When loading fails, log a useful error message from the QML engine (to help debug the QML) --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 7a38fb588..4ae640eee 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -339,6 +339,10 @@ 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." ) ); } From 7e0cc7af419b1934e88ddaab2beaa17e4a97722f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 18:24:07 +0100 Subject: [PATCH 12/14] [welcomeq] Add configuration file - copy the buttons-config part from welcome.conf - create buttons in the QML part --- src/modules/welcomeq/welcomeq.conf | 25 +++++++++++ src/modules/welcomeq/welcomeq.qml | 71 ++++++++++++++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 src/modules/welcomeq/welcomeq.conf 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 index d6ce9342b..b40ec4813 100644 --- a/src/modules/welcomeq/welcomeq.qml +++ b/src/modules/welcomeq/welcomeq.qml @@ -54,5 +54,76 @@ Page 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) + } + } } } From f094cb543bf9b430cb6ffff75f5c8f9acbae2988 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 22:33:49 +0100 Subject: [PATCH 13/14] [libcalamaresui] Set config object earlier - The config context object should be set earlier, otherwise QML code will try binding to a non-existent config already - Document that QMLViewStep::setConfigurationMap() parent implementation should be called **last**, at the end of the subclass implementation. --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 11 ++++++----- src/libcalamaresui/viewpages/QmlViewStep.h | 2 +- src/modules/notesqml/NotesQmlViewStep.cpp | 7 +++---- src/modules/welcomeq/WelcomeQmlViewStep.cpp | 3 ++- 4 files changed, 12 insertions(+), 11 deletions(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 4ae640eee..e13e022d8 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -210,11 +210,6 @@ QmlViewStep::loadComplete() // It is marked \internal in the Qt sources, but does exactly // what is needed: sets up visual parent by replacing the root // item, and handling resizes. - QObject* config = this->getConfig(); - if ( config ) - { - m_qmlWidget->engine()->rootContext()->setContextProperty( "config", config ); - } m_qmlWidget->setContent( QUrl( m_qmlFileName ), m_qmlComponent, m_qmlObject ); showQml(); } @@ -320,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 ); diff --git a/src/libcalamaresui/viewpages/QmlViewStep.h b/src/libcalamaresui/viewpages/QmlViewStep.h index 038569927..b54dc2fb7 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.h +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -73,7 +73,7 @@ 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: 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/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp index 580b183d1..382e0b4d1 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.cpp +++ b/src/modules/welcomeq/WelcomeQmlViewStep.cpp @@ -90,7 +90,6 @@ jobOrBrandingSetting( Calamares::Branding::StringEntry e, const QVariantMap& map void WelcomeQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { - QmlViewStep::setConfigurationMap( configurationMap ); using Calamares::Branding; m_config.setHelpUrl( jobOrBrandingSetting( Branding::SupportUrl, configurationMap, "showSupportUrl" ) ); @@ -146,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 From aa0a7994928940b24de2b5ee8b99325af4eaf5c8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 12 Feb 2020 22:47:11 +0100 Subject: [PATCH 14/14] [welcomeq] QML warnings-- The config bits are all constant, so avoid NOTIFY warnings. --- src/modules/welcomeq/Config.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/modules/welcomeq/Config.h b/src/modules/welcomeq/Config.h index 01c841068..50c3e387b 100644 --- a/src/modules/welcomeq/Config.h +++ b/src/modules/welcomeq/Config.h @@ -25,10 +25,10 @@ class Config : public QObject { Q_OBJECT - Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl FINAL ) - Q_PROPERTY( QUrl issuesUrl READ issuesUrl WRITE setIssuesUrl FINAL ) - Q_PROPERTY( QUrl notesUrl READ notesUrl WRITE setNotesUrl FINAL ) - Q_PROPERTY( QUrl donateUrl READ donateUrl WRITE setDonateUrl FINAL ) + 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();