Merge remote-tracking branch 'origin/welcome-q'

- Updates QmlViewStep with slightly neater API
- Introduces Config object for QML pages
- Updates notesqml and welcomeq to use that API
This commit is contained in:
Adriaan de Groot 2020-02-19 12:56:04 +01:00
commit bff07ded25
12 changed files with 269 additions and 108 deletions

View file

@ -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;

View file

@ -29,12 +29,14 @@
#include "widgets/WaitingWidget.h"
#include <QQmlComponent>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQuickItem>
#include <QQuickWidget>
#include <QVBoxLayout>
#include <QWidget>
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

View file

@ -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();

View file

@ -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 >(); )

View file

@ -1,6 +1,7 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2020, Anke Boersma <demm@kaosx.us>
* Copyright 2020, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/* 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("<h3>Generic GNU/Linux 2020.2 LTS <quote>Turgid Tuba</quote></h3>
text: qsTr("<h3>%1</h3>
<p>This an example QML file, showing options in RichText with Flickable content.</p>
<p>QML with RichText can use HTML tags, Flickable content is useful for touchscreens.</p>
<p><b>This is bold text</b></p>
<p><i>This is italic text</i></p>
<p><u>This is underlined text</u></p>
<p><center>This text will be center-aligned.</center></p>
<p><s>This is strikethrough</s></p>
<p>Code example:
<code>ls -l /home</code></p>
<p><b>Lists:</b></p>
<ul>
<li>Intel CPU systems</li>
<li>AMD CPU systems</li>
</ul>
<p>The vertical scrollbar is adjustable, current width set to 10.</p>")
<p>The vertical scrollbar is adjustable, current width set to 10.</p>").arg(Branding.string(Branding.VersionedName))
}
}

View file

@ -18,11 +18,6 @@
#include "Config.h"
Config::Config()
: m_helpUrl( "https://www.kde.org/" )
{
}
Config::Config() {}
Config::~Config()
{
}
Config::~Config() {}

View file

@ -16,8 +16,8 @@
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef WELCOME_CONFIG_H
#define WELCOME_CONFIG_H
#ifndef WELCOMEQ_CONFIG_H
#define WELCOMEQ_CONFIG_H
#include <QObject>
#include <QUrl>
@ -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

View file

@ -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;
}

View file

@ -21,11 +21,10 @@
#include "Config.h"
#include "DllMacro.h"
#include "modulesystem/Requirement.h"
#include "utils/PluginFactory.h"
#include "viewpages/ViewStep.h"
#include <DllMacro.h>
#include "viewpages/QmlViewStep.h"
#include <QObject>
#include <QVariantMap>
@ -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 )

View file

@ -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/

View file

@ -0,0 +1,129 @@
/* === This file is part of Calamares - <https://github.com/calamares> ===
*
* Copyright 2020, Adriaan de Groot <groot@kde.org>
*
* 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 <http://www.gnu.org/licenses/>.
*/
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("<h3>%1 <quote>%2</quote></h3>").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)
}
}
}
}

View file

@ -0,0 +1,5 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file alias="welcomeq.qml">welcomeq.qml</file>
</qresource>
</RCC>