From 156d78feb3d65ed158956dd9be8ba3eb9d57334d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 13 Dec 2019 11:50:12 +0100 Subject: [PATCH 02/68] [welcome] Add QML support - test application to display the QML (this will be extended with adding the locale model to it) - sample QML that does nothing useful yet (will display the locale model once it's there) --- src/modules/welcome/CMakeLists.txt | 3 ++ src/modules/welcome/qmlmain.cpp | 52 ++++++++++++++++++++++++++++++ src/modules/welcome/welcome.qml | 12 +++++++ 3 files changed, 67 insertions(+) create mode 100644 src/modules/welcome/qmlmain.cpp create mode 100644 src/modules/welcome/welcome.qml diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index e25b7f5d0..e0fbcfca1 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -40,3 +40,6 @@ calamares_add_plugin( welcome Qt5::Network SHARED_LIB ) + +add_executable( welcomeqmltest qmlmain.cpp ) +target_link_libraries( welcomeqmltest calamaresui ) diff --git a/src/modules/welcome/qmlmain.cpp b/src/modules/welcome/qmlmain.cpp new file mode 100644 index 000000000..81bf08df5 --- /dev/null +++ b/src/modules/welcome/qmlmain.cpp @@ -0,0 +1,52 @@ +/* Example executable showing a QML page and using the + * models from libcalamares for displaying a welcome. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "utils/Logger.h" + +int main(int argc, char **argv) +{ + QApplication a( argc, argv ); + + KAboutData aboutData( "calamares", + "Calamares", + "0.1", + "Calamares QML Test Application", + KAboutLicense::GPL_V3, + QString(), + QString(), + "https://calamares.io", + "https://github.com/calamares/calamares/issues" ); + KAboutData::setApplicationData( aboutData ); + a.setApplicationDisplayName( QString() ); // To avoid putting an extra "Calamares/" into the log-file + + Logger::setupLogLevel( Logger::LOGVERBOSE ); + + QMainWindow mw; + QWidget background; + QVBoxLayout vl; + QLabel l( "Hello, world", &mw ); + QQuickWidget qqw( &mw ); + vl.addWidget( &qqw ); + vl.addWidget( &l ); + background.setLayout( &vl ); + mw.setCentralWidget( &background ); + mw.resize( QSize( 400, 400 ) ); + mw.show(); + + qqw.setSource( QUrl::fromLocalFile("../src/modules/welcome/welcome.qml") ); + + return a.exec(); +} diff --git a/src/modules/welcome/welcome.qml b/src/modules/welcome/welcome.qml new file mode 100644 index 000000000..f73b66571 --- /dev/null +++ b/src/modules/welcome/welcome.qml @@ -0,0 +1,12 @@ +import QtQuick 2.0; + +Rectangle { + width: 200; + height: 200; + color: "pink"; + + Text { + anchors.centerIn: parent; + text: "Welcome to Calamares"; + } +} From c59678594bbd81c6ddb7d39b32f48b8ae9471f6a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 13 Dec 2019 12:35:42 +0100 Subject: [PATCH 03/68] [welcome] More QML support - start of a class to hold configuration information; this can later be substituted into the WelcomeViewStep and filled from setConfigurationMap() In the example application: - register the Config type --- src/modules/welcome/CMakeLists.txt | 11 ++++++-- src/modules/welcome/Config.cpp | 27 ++++++++++++++++++++ src/modules/welcome/Config.h | 40 ++++++++++++++++++++++++++++++ src/modules/welcome/qmlmain.cpp | 10 ++++++++ src/modules/welcome/welcome.qml | 1 + 5 files changed, 87 insertions(+), 2 deletions(-) create mode 100644 src/modules/welcome/Config.cpp create mode 100644 src/modules/welcome/Config.h diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index e0fbcfca1..b25bb6720 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -41,5 +41,12 @@ calamares_add_plugin( welcome SHARED_LIB ) -add_executable( welcomeqmltest qmlmain.cpp ) -target_link_libraries( welcomeqmltest calamaresui ) +add_executable( welcomeqmltest qmlmain.cpp Config.cpp ) +target_link_libraries( welcomeqmltest PRIVATE calamaresui Qt5::Core ) +set_target_properties( welcomeqmltest + PROPERTIES + ENABLE_EXPORTS TRUE + RUNTIME_OUTPUT_NAME welcomeqmltest +) +calamares_automoc( welcomeqmltest ) +calamares_autouic( welcomeqmltest ) diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp new file mode 100644 index 000000000..35ce99184 --- /dev/null +++ b/src/modules/welcome/Config.cpp @@ -0,0 +1,27 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 . + */ + +#include "Config.h" + +Config::Config() +{ +} + +Config::~Config() +{ +} diff --git a/src/modules/welcome/Config.h b/src/modules/welcome/Config.h new file mode 100644 index 000000000..91f5bec5c --- /dev/null +++ b/src/modules/welcome/Config.h @@ -0,0 +1,40 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 . + */ + +#ifndef WELCOME_CONFIG_H +#define WELCOME_CONFIG_H + +#include +#include + +class Config : public QObject +{ + Q_OBJECT + Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl ) +public: + Config(); + virtual ~Config(); + + QUrl helpUrl() const { return m_helpUrl; } + void setHelpUrl( const QUrl& url ) { m_helpUrl = url; } + +private: + QUrl m_helpUrl; +}; + +#endif diff --git a/src/modules/welcome/qmlmain.cpp b/src/modules/welcome/qmlmain.cpp index 81bf08df5..cc538747a 100644 --- a/src/modules/welcome/qmlmain.cpp +++ b/src/modules/welcome/qmlmain.cpp @@ -16,6 +16,8 @@ #include "utils/Logger.h" +#include "Config.h" + int main(int argc, char **argv) { QApplication a( argc, argv ); @@ -46,6 +48,14 @@ int main(int argc, char **argv) mw.resize( QSize( 400, 400 ) ); mw.show(); + Config cnf; + if ( argc > 1 ) + { + cnf.setHelpUrl( QUrl( argv[1] ) ); + } + + qmlRegisterType< Config >( "io.calamares.modules.welcome", 1, 0, "Config" ); + qqw.setSource( QUrl::fromLocalFile("../src/modules/welcome/welcome.qml") ); return a.exec(); diff --git a/src/modules/welcome/welcome.qml b/src/modules/welcome/welcome.qml index f73b66571..d442bfa11 100644 --- a/src/modules/welcome/welcome.qml +++ b/src/modules/welcome/welcome.qml @@ -1,4 +1,5 @@ import QtQuick 2.0; +import io.calamares.modules.welcome 1.0; Rectangle { width: 200; From d41d8df2a55c794cbb74204dcb3978c54c88de28 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 13 Dec 2019 13:19:38 +0100 Subject: [PATCH 04/68] [welcome] Put Config object into context --- src/modules/welcome/Config.cpp | 1 + src/modules/welcome/Config.h | 2 +- src/modules/welcome/qmlmain.cpp | 9 ++++++++- src/modules/welcome/welcome.qml | 10 +++++++++- 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp index 35ce99184..b46b85bf3 100644 --- a/src/modules/welcome/Config.cpp +++ b/src/modules/welcome/Config.cpp @@ -19,6 +19,7 @@ #include "Config.h" Config::Config() + : m_helpUrl( "https://www.kde.org/" ) { } diff --git a/src/modules/welcome/Config.h b/src/modules/welcome/Config.h index 91f5bec5c..7b0cfd734 100644 --- a/src/modules/welcome/Config.h +++ b/src/modules/welcome/Config.h @@ -25,7 +25,7 @@ class Config : public QObject { Q_OBJECT - Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl ) + Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl CONSTANT ) public: Config(); virtual ~Config(); diff --git a/src/modules/welcome/qmlmain.cpp b/src/modules/welcome/qmlmain.cpp index cc538747a..0aca1ddcd 100644 --- a/src/modules/welcome/qmlmain.cpp +++ b/src/modules/welcome/qmlmain.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +19,12 @@ #include "Config.h" +static Config* theConfig() +{ + static Config* cnf = new Config(); + return cnf; +} + int main(int argc, char **argv) { QApplication a( argc, argv ); @@ -54,7 +61,7 @@ int main(int argc, char **argv) cnf.setHelpUrl( QUrl( argv[1] ) ); } - qmlRegisterType< Config >( "io.calamares.modules.welcome", 1, 0, "Config" ); + qmlRegisterSingletonType< Config >( "io.calamares.modules.welcome", 1, 0, "PotatoConfig", [](QQmlEngine*, QJSEngine*) -> QObject* { return theConfig(); }); qqw.setSource( QUrl::fromLocalFile("../src/modules/welcome/welcome.qml") ); diff --git a/src/modules/welcome/welcome.qml b/src/modules/welcome/welcome.qml index d442bfa11..ba28d660b 100644 --- a/src/modules/welcome/welcome.qml +++ b/src/modules/welcome/welcome.qml @@ -1,4 +1,5 @@ import QtQuick 2.0; +import QtQuick.Controls 2.3; import io.calamares.modules.welcome 1.0; Rectangle { @@ -6,8 +7,15 @@ Rectangle { height: 200; color: "pink"; - Text { + Label { + id: label; anchors.centerIn: parent; text: "Welcome to Calamares"; } + + Button { + anchors.top: label.bottom; + text: PotatoConfig.helpUrl; + + } } From 03ed308bd93633466e7bde7852d7c21b9c3d5ed3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 13 Dec 2019 14:31:42 +0100 Subject: [PATCH 05/68] [welcome] Add QML model for translations --- src/modules/welcome/qmlmain.cpp | 4 ++++ src/modules/welcome/welcome.qml | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/modules/welcome/qmlmain.cpp b/src/modules/welcome/qmlmain.cpp index 0aca1ddcd..9c160fc1d 100644 --- a/src/modules/welcome/qmlmain.cpp +++ b/src/modules/welcome/qmlmain.cpp @@ -15,6 +15,7 @@ #include +#include "locale/LabelModel.h" #include "utils/Logger.h" #include "Config.h" @@ -61,8 +62,11 @@ int main(int argc, char **argv) cnf.setHelpUrl( QUrl( argv[1] ) ); } + // TODO: this should put the one config object in the context, rather than adding a factory function to share it everywhere qmlRegisterSingletonType< Config >( "io.calamares.modules.welcome", 1, 0, "PotatoConfig", [](QQmlEngine*, QJSEngine*) -> QObject* { return theConfig(); }); + qmlRegisterSingletonType< CalamaresUtils::Locale::LabelModel >( "io.calamares.locale", 1, 0, "LocaleModel", [](QQmlEngine*, QJSEngine*) -> QObject* { return CalamaresUtils::Locale::availableTranslations(); } ); + qqw.setSource( QUrl::fromLocalFile("../src/modules/welcome/welcome.qml") ); return a.exec(); diff --git a/src/modules/welcome/welcome.qml b/src/modules/welcome/welcome.qml index ba28d660b..bdb7c4416 100644 --- a/src/modules/welcome/welcome.qml +++ b/src/modules/welcome/welcome.qml @@ -1,6 +1,7 @@ import QtQuick 2.0; import QtQuick.Controls 2.3; import io.calamares.modules.welcome 1.0; +import io.calamares.locale 1.0; Rectangle { width: 200; @@ -14,8 +15,15 @@ Rectangle { } Button { + id: thebutton; anchors.top: label.bottom; text: PotatoConfig.helpUrl; } + + ListView { + anchors.fill: parent; + model: LocaleModel; + delegate: Label { text: display } + } } From 55f61fda3527c4072060b08d1833cd44788b4bc0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 13 Dec 2019 18:18:02 +0100 Subject: [PATCH 06/68] [welcome] Create branding and settings objects --- src/modules/welcome/qmlmain.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/welcome/qmlmain.cpp b/src/modules/welcome/qmlmain.cpp index 9c160fc1d..93017a9c7 100644 --- a/src/modules/welcome/qmlmain.cpp +++ b/src/modules/welcome/qmlmain.cpp @@ -2,6 +2,8 @@ * models from libcalamares for displaying a welcome. */ +#include + #include #include #include @@ -15,6 +17,8 @@ #include +#include "JobQueue.h" +#include "Settings.h" #include "locale/LabelModel.h" #include "utils/Logger.h" @@ -44,6 +48,9 @@ int main(int argc, char **argv) Logger::setupLogLevel( Logger::LOGVERBOSE ); + std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) ); + std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); + QMainWindow mw; QWidget background; QVBoxLayout vl; From 6c4efc1f9ce512f710cecb78a0ef1eea94ed1b17 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 13 Dec 2019 18:23:01 +0100 Subject: [PATCH 07/68] [welcome] Add Branding object to QML demo --- src/modules/welcome/qmlmain.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/welcome/qmlmain.cpp b/src/modules/welcome/qmlmain.cpp index 93017a9c7..96d9d245f 100644 --- a/src/modules/welcome/qmlmain.cpp +++ b/src/modules/welcome/qmlmain.cpp @@ -17,6 +17,7 @@ #include +#include "Branding.h" #include "JobQueue.h" #include "Settings.h" #include "locale/LabelModel.h" @@ -51,6 +52,9 @@ int main(int argc, char **argv) std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) ); std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); + Calamares::Branding defaultBrand( "src/branding/default/branding.desc" ); + cDebug() << "Branding @" << (void *)Calamares::Branding::instance(); + QMainWindow mw; QWidget background; QVBoxLayout vl; From 53b208e891d1f8e7ecc77437ad6c3a0cd54228bd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 14 Dec 2019 12:48:09 +0100 Subject: [PATCH 08/68] [welcomeq] Start new ViewStep for QML-based welcome --- src/modules/welcomeq/CMakeLists.txt | 41 ++++ src/modules/welcomeq/Config.cpp | 28 +++ src/modules/welcomeq/Config.h | 40 ++++ src/modules/welcomeq/WelcomeQmlViewStep.cpp | 243 ++++++++++++++++++++ src/modules/welcomeq/WelcomeQmlViewStep.h | 85 +++++++ 5 files changed, 437 insertions(+) create mode 100644 src/modules/welcomeq/CMakeLists.txt create mode 100644 src/modules/welcomeq/Config.cpp create mode 100644 src/modules/welcomeq/Config.h create mode 100644 src/modules/welcomeq/WelcomeQmlViewStep.cpp create mode 100644 src/modules/welcomeq/WelcomeQmlViewStep.h diff --git a/src/modules/welcomeq/CMakeLists.txt b/src/modules/welcomeq/CMakeLists.txt new file mode 100644 index 000000000..2105c77e6 --- /dev/null +++ b/src/modules/welcomeq/CMakeLists.txt @@ -0,0 +1,41 @@ +set( _welcome ${CMAKE_CURRENT_SOURCE_DIR}/../welcome ) + +include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ${_welcome} ) + +# DUPLICATED WITH WELCOME MODULE +find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) + +find_package( LIBPARTED ) +if ( LIBPARTED_FOUND ) + set( PARTMAN_SRC ${_welcome}/checker/partman_devices.c ) + set( CHECKER_LINK_LIBRARIES ${LIBPARTED_LIBRARY} ) +else() + set( PARTMAN_SRC ) + set( CHECKER_LINK_LIBRARIES ) + add_definitions( -DWITHOUT_LIBPARTED ) +endif() + +set( CHECKER_SOURCES + ${_welcome}/checker/CheckerContainer.cpp + ${_welcome}/checker/GeneralRequirements.cpp + ${_welcome}/checker/ResultWidget.cpp + ${_welcome}/checker/ResultsListWidget.cpp + ${PARTMAN_SRC} +) + +calamares_add_plugin( welcomeq + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + ${CHECKER_SOURCES} + WelcomeQmlViewStep.cpp + Config.cpp + RESOURCES + welcomeq.qrc + LINK_PRIVATE_LIBRARIES + calamaresui + ${CHECKER_LINK_LIBRARIES} + Qt5::DBus + Qt5::Network + SHARED_LIB +) diff --git a/src/modules/welcomeq/Config.cpp b/src/modules/welcomeq/Config.cpp new file mode 100644 index 000000000..b46b85bf3 --- /dev/null +++ b/src/modules/welcomeq/Config.cpp @@ -0,0 +1,28 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 . + */ + +#include "Config.h" + +Config::Config() + : m_helpUrl( "https://www.kde.org/" ) +{ +} + +Config::~Config() +{ +} diff --git a/src/modules/welcomeq/Config.h b/src/modules/welcomeq/Config.h new file mode 100644 index 000000000..7b0cfd734 --- /dev/null +++ b/src/modules/welcomeq/Config.h @@ -0,0 +1,40 @@ +/* === This file is part of Calamares - === + * + * Copyright 2019, 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 . + */ + +#ifndef WELCOME_CONFIG_H +#define WELCOME_CONFIG_H + +#include +#include + +class Config : public QObject +{ + Q_OBJECT + Q_PROPERTY( QUrl helpUrl READ helpUrl WRITE setHelpUrl CONSTANT ) +public: + Config(); + virtual ~Config(); + + QUrl helpUrl() const { return m_helpUrl; } + void setHelpUrl( const QUrl& url ) { m_helpUrl = url; } + +private: + QUrl m_helpUrl; +}; + +#endif diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp new file mode 100644 index 000000000..6a01f1ada --- /dev/null +++ b/src/modules/welcomeq/WelcomeQmlViewStep.cpp @@ -0,0 +1,243 @@ +/* === This file is part of Calamares - === + * + * Copyright 2014-2015, Teo Mrnjavac + * Copyright 2018, 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 . + */ + +#include "WelcomeQmlViewStep.h" + +#include "checker/GeneralRequirements.h" + +#include "geoip/Handler.h" +#include "locale/LabelModel.h" +#include "locale/Lookup.h" +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include "Branding.h" +#include "modulesystem/ModuleManager.h" + +#include +#include +#include + +CALAMARES_PLUGIN_FACTORY_DEFINITION( WelcomeQmlViewStepFactory, registerPlugin< WelcomeQmlViewStep >(); ) + +WelcomeQmlViewStep::WelcomeQmlViewStep( QObject* parent ) + : Calamares::ViewStep( parent ) + , m_requirementsChecker( new GeneralRequirements( this ) ) +{ + connect( Calamares::ModuleManager::instance(), + &Calamares::ModuleManager::requirementsComplete, + this, + &WelcomeQmlViewStep::nextStatusChanged ); +} + + +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 + * assume an old-style configuration, and fetch the string from + * the branding settings @p e. If it is a string, not a boolean, + * use it as-is. If not found, or a weird type, returns empty. + * + * This allows switching the showKnownIssuesUrl and similar settings + * in welcome.conf from a boolean (deferring to branding) to an + * actual string for immediate use. Empty strings, as well as + * "false" as a setting, will hide the buttons as before. + */ +static QString +jobOrBrandingSetting( Calamares::Branding::StringEntry e, const QVariantMap& map, const QString& key ) +{ + if ( !map.contains( key ) ) + { + return QString(); + } + auto v = map.value( key ); + if ( v.type() == QVariant::Bool ) + { + return v.toBool() ? ( *e ) : QString(); + } + if ( v.type() == QVariant::String ) + { + return v.toString(); + } + + return QString(); +} + +void +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 + + // TODO: figure out how the requirements (held by ModuleManager) should be accessible + // to QML as a odel. + if ( configurationMap.contains( "requirements" ) + && configurationMap.value( "requirements" ).type() == QVariant::Map ) + { + m_requirementsChecker->setConfigurationMap( configurationMap.value( "requirements" ).toMap() ); + } + else + cWarning() << "no valid requirements map found in welcome " + "module configuration."; + + bool ok = false; + QVariantMap geoip = CalamaresUtils::getSubMap( configurationMap, "geoip", ok ); + if ( ok ) + { + using FWString = QFutureWatcher< QString >; + + auto* handler = new CalamaresUtils::GeoIP::Handler( CalamaresUtils::getString( geoip, "style" ), + CalamaresUtils::getString( geoip, "url" ), + CalamaresUtils::getString( geoip, "selector" ) ); + if ( handler->type() != CalamaresUtils::GeoIP::Handler::Type::None ) + { + auto* future = new FWString(); + connect( future, &FWString::finished, [view = this, f = future, h = handler]() { + QString countryResult = f->future().result(); + cDebug() << "GeoIP result for welcome=" << countryResult; + view->setCountry( countryResult, h ); + f->deleteLater(); + delete h; + } ); + future->setFuture( handler->queryRaw() ); + } + else + { + // Would not produce useful country code anyway. + delete handler; + } + } + + QString language = CalamaresUtils::getString( configurationMap, "languageIcon" ); + if ( !language.isEmpty() ) + { + auto icon = Calamares::Branding::instance()->image( language, QSize( 48, 48 ) ); + if ( !icon.isNull() ) + { + // TODO: figure out where to set this: Config? + } + } +} + +Calamares::RequirementsList +WelcomeQmlViewStep::checkRequirements() +{ + return m_requirementsChecker->checkRequirements(); +} + +static inline void +logGeoIPHandler( CalamaresUtils::GeoIP::Handler* handler ) +{ + if ( handler ) + { + cDebug() << Logger::SubEntry << "Obtained from" << handler->url() << " (" + << static_cast< int >( handler->type() ) << handler->selector() << ')'; + } +} + +void +WelcomeQmlViewStep::setCountry( const QString& countryCode, CalamaresUtils::GeoIP::Handler* handler ) +{ + if ( countryCode.length() != 2 ) + { + cDebug() << "Unusable country code" << countryCode; + logGeoIPHandler( handler ); + return; + } + + auto c_l = CalamaresUtils::Locale::countryData( countryCode ); + if ( c_l.first == QLocale::Country::AnyCountry ) + { + cDebug() << "Unusable country code" << countryCode; + logGeoIPHandler( handler ); + return; + } + else + { + int r = CalamaresUtils::Locale::availableTranslations()->find( countryCode ); + if ( r < 0 ) + { + cDebug() << "Unusable country code" << countryCode << "(no suitable translation)"; + } + if ( ( r >= 0 ) ) + { + // TODO: update Config to point to selected language + } + } +} diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.h b/src/modules/welcomeq/WelcomeQmlViewStep.h new file mode 100644 index 000000000..162df0a7f --- /dev/null +++ b/src/modules/welcomeq/WelcomeQmlViewStep.h @@ -0,0 +1,85 @@ +/* === This file is part of Calamares - === + * + * Copyright 20195, 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 . + */ + +#ifndef WELCOME_QMLVIEWSTEP_H +#define WELCOME_QMLVIEWSTEP_H + +#include "Config.h" + +#include "modulesystem/Requirement.h" +#include "utils/PluginFactory.h" +#include "viewpages/ViewStep.h" + +#include + +#include +#include + +namespace CalamaresUtils +{ +namespace GeoIP +{ +class Handler; +} +} // namespace CalamaresUtils + +class GeneralRequirements; + +// 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 +{ + Q_OBJECT + +public: + explicit WelcomeQmlViewStep( QObject* parent = nullptr ); + virtual ~WelcomeQmlViewStep() override; + + 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. + * + * This (ideally) sets up language and locale settings that are right for + * the given 2-letter country code. Uses the handler's information (if + * given) for error reporting. + */ + void setCountry( const QString&, CalamaresUtils::GeoIP::Handler* handler ); + + Calamares::RequirementsList checkRequirements() override; + +private: + // TODO: a generic QML viewstep should return a config object from a method + Config m_config; + GeneralRequirements* m_requirementsChecker; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( WelcomeQmlViewStepFactory ) + +#endif // WELCOME_QMLVIEWSTEP_H From 8e2d257040a1da0d1d75f50f0e5004001f76dfe1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 14 Dec 2019 13:11:14 +0100 Subject: [PATCH 09/68] [welcomeq] Add QML machinery (uninitialized) --- src/modules/welcomeq/WelcomeQmlViewStep.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.h b/src/modules/welcomeq/WelcomeQmlViewStep.h index 162df0a7f..7d10e35ef 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.h +++ b/src/modules/welcomeq/WelcomeQmlViewStep.h @@ -40,6 +40,10 @@ 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 @@ -78,6 +82,12 @@ 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 56f926094e6dd0f7b2a4f5a6c62fc70090c37a1c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 9 Jan 2020 15:11:36 +0100 Subject: [PATCH 10/68] [welcomeq] Update comments - Copyright years - Purpose of this module --- src/modules/welcomeq/CMakeLists.txt | 3 +++ src/modules/welcomeq/Config.cpp | 2 +- src/modules/welcomeq/Config.h | 2 +- src/modules/welcomeq/WelcomeQmlViewStep.cpp | 2 +- src/modules/welcomeq/WelcomeQmlViewStep.h | 2 +- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/modules/welcomeq/CMakeLists.txt b/src/modules/welcomeq/CMakeLists.txt index 2105c77e6..7ee0350af 100644 --- a/src/modules/welcomeq/CMakeLists.txt +++ b/src/modules/welcomeq/CMakeLists.txt @@ -1,3 +1,6 @@ +# This is a re-write of the welcome module using QML view steps +# instead of widgets. + set( _welcome ${CMAKE_CURRENT_SOURCE_DIR}/../welcome ) include_directories( ${PROJECT_BINARY_DIR}/src/libcalamaresui ${_welcome} ) diff --git a/src/modules/welcomeq/Config.cpp b/src/modules/welcomeq/Config.cpp index b46b85bf3..6d085143c 100644 --- a/src/modules/welcomeq/Config.cpp +++ b/src/modules/welcomeq/Config.cpp @@ -1,6 +1,6 @@ /* === This file is part of Calamares - === * - * Copyright 2019, Adriaan de Groot + * Copyright 2019-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 diff --git a/src/modules/welcomeq/Config.h b/src/modules/welcomeq/Config.h index 7b0cfd734..2295d4ee2 100644 --- a/src/modules/welcomeq/Config.h +++ b/src/modules/welcomeq/Config.h @@ -1,6 +1,6 @@ /* === This file is part of Calamares - === * - * Copyright 2019, Adriaan de Groot + * Copyright 2019-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 diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp index 6a01f1ada..2a5b0f661 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.cpp +++ b/src/modules/welcomeq/WelcomeQmlViewStep.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014-2015, Teo Mrnjavac - * Copyright 2018, Adriaan de Groot + * Copyright 2018,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 diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.h b/src/modules/welcomeq/WelcomeQmlViewStep.h index 7d10e35ef..5486d8d31 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.h +++ b/src/modules/welcomeq/WelcomeQmlViewStep.h @@ -1,6 +1,6 @@ /* === This file is part of Calamares - === * - * Copyright 20195, Adriaan de Groot + * Copyright 2019-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 From 63b8de00ef55f3a16d6512347d362f46e5f48c44 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 9 Jan 2020 15:25:30 +0100 Subject: [PATCH 11/68] CI: allow plain clang-format (Tumbleweed) --- ci/calamaresstyle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/calamaresstyle b/ci/calamaresstyle index 8b13b6f31..65dc83de7 100755 --- a/ci/calamaresstyle +++ b/ci/calamaresstyle @@ -8,7 +8,7 @@ # AS=$( which astyle ) -for _cf in clang-format-7 clang-format-8 clang-format70 clang-format80 +for _cf in clang-format-7 clang-format-8 clang-format70 clang-format80 clang-format do # Not an error if this particular clang-format isn't found CF=$( which $_cf || true ) From 970702daa080446b23b9c6af4df53fb95e3d6aa8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 9 Jan 2020 21:36:43 +0100 Subject: [PATCH 12/68] [libcalamaresui] Tidy up includes --- src/libcalamaresui/viewpages/BlankViewStep.h | 7 +------ src/libcalamaresui/viewpages/ViewStep.h | 8 ++++---- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/src/libcalamaresui/viewpages/BlankViewStep.h b/src/libcalamaresui/viewpages/BlankViewStep.h index 17d323c85..ab44205ac 100644 --- a/src/libcalamaresui/viewpages/BlankViewStep.h +++ b/src/libcalamaresui/viewpages/BlankViewStep.h @@ -19,12 +19,7 @@ #ifndef BLANKVIEWSTEP_H #define BLANKVIEWSTEP_H -#include - -#include -#include - -class QWidget; +#include "viewpages/ViewStep.h" namespace Calamares { diff --git a/src/libcalamaresui/viewpages/ViewStep.h b/src/libcalamaresui/viewpages/ViewStep.h index 8c5020f83..3ae05c49f 100644 --- a/src/libcalamaresui/viewpages/ViewStep.h +++ b/src/libcalamaresui/viewpages/ViewStep.h @@ -20,15 +20,15 @@ #ifndef VIEWSTEP_H #define VIEWSTEP_H -#include -#include -#include - #include "Job.h" #include "UiDllMacro.h" #include "modulesystem/Requirement.h" +#include +#include +#include + namespace Calamares { From 16a460adff38e7043e5cdd7347c7be97616beda5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 11:56:30 +0100 Subject: [PATCH 13/68] [libcalamaresui] Move ExecutionViewStep where it belongs - viewpages/ collects the ViewStep implementations - chase header moving and tidy some #includes --- src/libcalamaresui/CMakeLists.txt | 2 +- src/libcalamaresui/ViewManager.cpp | 7 +++---- src/libcalamaresui/modulesystem/ModuleManager.cpp | 6 +++--- src/libcalamaresui/{ => viewpages}/ExecutionViewStep.cpp | 4 ++-- src/libcalamaresui/{ => viewpages}/ExecutionViewStep.h | 0 src/modules/summary/SummaryPage.cpp | 2 +- 6 files changed, 10 insertions(+), 11 deletions(-) rename src/libcalamaresui/{ => viewpages}/ExecutionViewStep.cpp (99%) rename src/libcalamaresui/{ => viewpages}/ExecutionViewStep.h (100%) diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index a9d31c2c3..c315a6b3e 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -18,6 +18,7 @@ set( calamaresui_SOURCES utils/Paste.cpp viewpages/BlankViewStep.cpp + viewpages/ExecutionViewStep.cpp viewpages/ViewStep.cpp widgets/ClickableLabel.cpp @@ -25,7 +26,6 @@ set( calamaresui_SOURCES widgets/WaitingWidget.cpp ${CMAKE_SOURCE_DIR}/3rdparty/waitingspinnerwidget.cpp - ExecutionViewStep.cpp Branding.cpp ViewManager.cpp ) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 68d918971..4721370b9 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -21,17 +21,16 @@ #include "ViewManager.h" -#include "viewpages/BlankViewStep.h" -#include "viewpages/ViewStep.h" - #include "Branding.h" -#include "ExecutionViewStep.h" #include "JobQueue.h" #include "Settings.h" #include "utils/Logger.h" #include "utils/Paste.h" #include "utils/Retranslator.h" +#include "viewpages/BlankViewStep.h" +#include "viewpages/ViewStep.h" +#include "viewpages/ExecutionViewStep.h" #include #include diff --git a/src/libcalamaresui/modulesystem/ModuleManager.cpp b/src/libcalamaresui/modulesystem/ModuleManager.cpp index 33b638e64..8591a558f 100644 --- a/src/libcalamaresui/modulesystem/ModuleManager.cpp +++ b/src/libcalamaresui/modulesystem/ModuleManager.cpp @@ -19,7 +19,6 @@ #include "ModuleManager.h" -#include "ExecutionViewStep.h" #include "Module.h" #include "RequirementsChecker.h" #include "Settings.h" @@ -27,6 +26,7 @@ #include "utils/Logger.h" #include "utils/Yaml.h" +#include "viewpages/ExecutionViewStep.h" #include #include @@ -131,9 +131,9 @@ ModuleManager::doInit() cDebug() << "ModuleManager module search path does not exist:" << path; } } - // At this point m_availableDescriptorsByModuleName is filled with + // At this point m_availableDescriptorsByModuleName is filled with // the modules that were found in the search paths. - cDebug() << "Found" + cDebug() << "Found" << m_availableDescriptorsByModuleName.count() << "modules" << m_moduleDirectoriesByModuleName.count() << "names"; emit initDone(); diff --git a/src/libcalamaresui/ExecutionViewStep.cpp b/src/libcalamaresui/viewpages/ExecutionViewStep.cpp similarity index 99% rename from src/libcalamaresui/ExecutionViewStep.cpp rename to src/libcalamaresui/viewpages/ExecutionViewStep.cpp index 501995c07..e0921910d 100644 --- a/src/libcalamaresui/ExecutionViewStep.cpp +++ b/src/libcalamaresui/viewpages/ExecutionViewStep.cpp @@ -18,16 +18,16 @@ * along with Calamares. If not, see . */ -#include +#include "ExecutionViewStep.h" #include "Branding.h" #include "Job.h" #include "JobQueue.h" #include "Settings.h" #include "ViewManager.h" + #include "modulesystem/Module.h" #include "modulesystem/ModuleManager.h" - #include "utils/CalamaresUtilsGui.h" #include "utils/Dirs.h" #include "utils/Logger.h" diff --git a/src/libcalamaresui/ExecutionViewStep.h b/src/libcalamaresui/viewpages/ExecutionViewStep.h similarity index 100% rename from src/libcalamaresui/ExecutionViewStep.h rename to src/libcalamaresui/viewpages/ExecutionViewStep.h diff --git a/src/modules/summary/SummaryPage.cpp b/src/modules/summary/SummaryPage.cpp index 61a9c2ec2..7114f27ee 100644 --- a/src/modules/summary/SummaryPage.cpp +++ b/src/modules/summary/SummaryPage.cpp @@ -23,13 +23,13 @@ #include "SummaryViewStep.h" #include "Branding.h" -#include "ExecutionViewStep.h" #include "Settings.h" #include "ViewManager.h" #include "utils/CalamaresUtilsGui.h" #include "utils/Logger.h" #include "utils/Retranslator.h" +#include "viewpages/ExecutionViewStep.h" #include #include From 492483921792c0a424bc97b717a714382702f74a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 12:13:40 +0100 Subject: [PATCH 14/68] [libcalamaresui] Start QmlViewStep --- src/libcalamaresui/CMakeLists.txt | 1 + src/libcalamaresui/viewpages/QmlViewStep.cpp | 87 ++++++++++++++++++++ src/libcalamaresui/viewpages/QmlViewStep.h | 61 ++++++++++++++ 3 files changed, 149 insertions(+) create mode 100644 src/libcalamaresui/viewpages/QmlViewStep.cpp create mode 100644 src/libcalamaresui/viewpages/QmlViewStep.h diff --git a/src/libcalamaresui/CMakeLists.txt b/src/libcalamaresui/CMakeLists.txt index c315a6b3e..061a401bb 100644 --- a/src/libcalamaresui/CMakeLists.txt +++ b/src/libcalamaresui/CMakeLists.txt @@ -19,6 +19,7 @@ set( calamaresui_SOURCES viewpages/BlankViewStep.cpp viewpages/ExecutionViewStep.cpp + viewpages/QmlViewStep.cpp viewpages/ViewStep.cpp widgets/ClickableLabel.cpp diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp new file mode 100644 index 000000000..060a4660e --- /dev/null +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -0,0 +1,87 @@ +/* === 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 . + */ + +#include "QmlViewStep.h" + +namespace Calamares +{ + +QmlViewStep::QmlViewStep( const QString& name, QObject* parent ) + : ViewStep( parent ) + , m_name( name ) +{ +} + +QmlViewStep::~QmlViewStep() {} + +QString +QmlViewStep::prettyName() const +{ + // TODO: query the QML itself + return tr( "QML Step %1" ).arg( m_name ); +} + + +} // namespace Calamares + +bool +Calamares::QmlViewStep::isAtBeginning() const +{ + return true; +} + +bool +Calamares::QmlViewStep::isAtEnd() const +{ + return true; +} +bool +Calamares::QmlViewStep::isBackEnabled() const +{ + return true; +} + +bool +Calamares::QmlViewStep::isNextEnabled() const +{ + return true; +} + +Calamares::JobList +Calamares::QmlViewStep::jobs() const +{ + return JobList(); +} + +void +Calamares::QmlViewStep::onActivate() +{ + // TODO: call into QML +} + +void +Calamares::QmlViewStep::onLeave() +{ + // TODO: call into QML +} + +QWidget* +Calamares::QmlViewStep::widget() +{ + return nullptr; +} diff --git a/src/libcalamaresui/viewpages/QmlViewStep.h b/src/libcalamaresui/viewpages/QmlViewStep.h new file mode 100644 index 000000000..53a5882d5 --- /dev/null +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -0,0 +1,61 @@ +/* === 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 . + */ + +#ifndef QMLVIEWSTEP_H +#define QMLVIEWSTEP_H + +#include "viewpages/ViewStep.h" + +namespace Calamares +{ + +/** @brief A viewstep that uses QML for the UI + * + * This is generally a **base** class for other view steps, but + * it can be used stand-alone for viewsteps that don't really have + * any functionality. + */ +class QmlViewStep : public Calamares::ViewStep +{ + Q_OBJECT + +public: + QmlViewStep( const QString& name, QObject* parent = nullptr ); + virtual ~QmlViewStep() override; + + virtual QString prettyName() const override; + + virtual QWidget* widget() override; + + virtual bool isNextEnabled() const override; + virtual bool isBackEnabled() const override; + + virtual bool isAtBeginning() const override; + virtual bool isAtEnd() const override; + + virtual void onActivate() override; + virtual void onLeave() override; + + virtual JobList jobs() const override; + +private: + QString m_name; +}; + +} // namespace Calamares +#endif From 1cc40bda83dc1245db97a6b1d54111b7faf15b28 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 12:38:46 +0100 Subject: [PATCH 15/68] [dummyqml] Stub of a QML module --- src/modules/dummyqml/CMakeLists.txt | 11 +++++++ src/modules/dummyqml/DummyQmlViewStep.cpp | 35 ++++++++++++++++++++ src/modules/dummyqml/DummyQmlViewStep.h | 40 +++++++++++++++++++++++ src/modules/dummyqml/dummyqml.qml | 12 +++++++ src/modules/dummyqml/dummyqml.qrc | 5 +++ 5 files changed, 103 insertions(+) create mode 100644 src/modules/dummyqml/CMakeLists.txt create mode 100644 src/modules/dummyqml/DummyQmlViewStep.cpp create mode 100644 src/modules/dummyqml/DummyQmlViewStep.h create mode 100644 src/modules/dummyqml/dummyqml.qml create mode 100644 src/modules/dummyqml/dummyqml.qrc diff --git a/src/modules/dummyqml/CMakeLists.txt b/src/modules/dummyqml/CMakeLists.txt new file mode 100644 index 000000000..9a7532e9e --- /dev/null +++ b/src/modules/dummyqml/CMakeLists.txt @@ -0,0 +1,11 @@ +calamares_add_plugin( dummyqml + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + DummyQmlViewStep.cpp + RESOURCES + dummyqml.qrc + LINK_PRIVATE_LIBRARIES + calamaresui + SHARED_LIB +) diff --git a/src/modules/dummyqml/DummyQmlViewStep.cpp b/src/modules/dummyqml/DummyQmlViewStep.cpp new file mode 100644 index 000000000..985d2985a --- /dev/null +++ b/src/modules/dummyqml/DummyQmlViewStep.cpp @@ -0,0 +1,35 @@ +/* === 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 . + */ + +#include "DummyQmlViewStep.h" + +DummyQmlViewStep::DummyQmlViewStep( QObject* parent ) + : Calamares::QmlViewStep( "dummyqml", parent ) +{ +} + +DummyQmlViewStep::~DummyQmlViewStep() {} + +QString +DummyQmlViewStep::prettyName() const +{ + return tr( "Example QML page" ); +} + + +CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyQmlViewStepFactory, registerPlugin< DummyQmlViewStep >(); ) diff --git a/src/modules/dummyqml/DummyQmlViewStep.h b/src/modules/dummyqml/DummyQmlViewStep.h new file mode 100644 index 000000000..ffc358fe7 --- /dev/null +++ b/src/modules/dummyqml/DummyQmlViewStep.h @@ -0,0 +1,40 @@ +/* === 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 . + */ + +#ifndef DUMMYQMLVIEWSTEP_H +#define DUMMYQMLVIEWSTEP_H + +#include "utils/PluginFactory.h" +#include "viewpages/QmlViewStep.h" + +class DummyQmlViewStep : public Calamares::QmlViewStep +{ + Q_OBJECT + +public: + DummyQmlViewStep( QObject* parent = nullptr ); + virtual ~DummyQmlViewStep() override; + + virtual QString prettyName() const override; + +private: +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( DummyQmlViewStepFactory ) + +#endif diff --git a/src/modules/dummyqml/dummyqml.qml b/src/modules/dummyqml/dummyqml.qml new file mode 100644 index 000000000..6cab24bec --- /dev/null +++ b/src/modules/dummyqml/dummyqml.qml @@ -0,0 +1,12 @@ +import QtQuick 2.3 + +Rectangle { + width: 200 + height: 100 + color: "red" + + Text { + anchors.centerIn: parent + text: "Hello, World!" + } +} diff --git a/src/modules/dummyqml/dummyqml.qrc b/src/modules/dummyqml/dummyqml.qrc new file mode 100644 index 000000000..85b1da5ca --- /dev/null +++ b/src/modules/dummyqml/dummyqml.qrc @@ -0,0 +1,5 @@ + + + dummyqml.qml + + From 60c1d40b2077df941a6d197b2d1ab0a711bc6316 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 12:56:46 +0100 Subject: [PATCH 16/68] [libcalamaresui] Log which ViewStep is broken - a ViewStep with no widget will crash the application; print out its name before doing so. --- src/libcalamaresui/ViewManager.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/src/libcalamaresui/ViewManager.cpp b/src/libcalamaresui/ViewManager.cpp index 4721370b9..7492f1f8b 100644 --- a/src/libcalamaresui/ViewManager.cpp +++ b/src/libcalamaresui/ViewManager.cpp @@ -158,13 +158,6 @@ void ViewManager::insertViewStep( int before, ViewStep* step ) { m_steps.insert( before, step ); - QLayout* layout = step->widget()->layout(); - if ( layout ) - { - layout->setContentsMargins( 0, 0, 0, 0 ); - } - m_stack->insertWidget( before, step->widget() ); - connect( step, &ViewStep::enlarge, this, &ViewManager::enlarge ); connect( step, &ViewStep::nextStatusChanged, this, [this]( bool status ) { ViewStep* vs = qobject_cast< ViewStep* >( sender() ); @@ -177,6 +170,17 @@ ViewManager::insertViewStep( int before, ViewStep* step ) } } ); + if ( !step->widget() ) + { + cError() << "ViewStep" << step->moduleInstanceKey() << "has no widget."; + } + + QLayout* layout = step->widget()->layout(); + if ( layout ) + { + layout->setContentsMargins( 0, 0, 0, 0 ); + } + m_stack->insertWidget( before, step->widget() ); m_stack->setCurrentIndex( 0 ); step->widget()->setFocus(); } From 44b250809fbed389dadefdc88b2c32ff3de5249a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 13:10:55 +0100 Subject: [PATCH 17/68] [libcalamaresui] Add spinner to QmlViewStep - view step now has a widget, doesn't load QML yet --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 11 ++++++++++- src/libcalamaresui/viewpages/QmlViewStep.h | 11 +++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 060a4660e..11637d04b 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -18,13 +18,22 @@ #include "QmlViewStep.h" +#include "widgets/WaitingWidget.h" + +#include +#include + namespace Calamares { QmlViewStep::QmlViewStep( const QString& name, QObject* parent ) : ViewStep( parent ) , m_name( name ) + , m_widget( new QWidget ) + , m_spinner( new WaitingWidget( tr( "Loading ..." ) ) ) { + QVBoxLayout* layout = new QVBoxLayout( m_widget ); + layout->addWidget( m_spinner ); } QmlViewStep::~QmlViewStep() {} @@ -83,5 +92,5 @@ Calamares::QmlViewStep::onLeave() QWidget* Calamares::QmlViewStep::widget() { - return nullptr; + return m_widget; } diff --git a/src/libcalamaresui/viewpages/QmlViewStep.h b/src/libcalamaresui/viewpages/QmlViewStep.h index 53a5882d5..d1b28af35 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.h +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -21,6 +21,11 @@ #include "viewpages/ViewStep.h" +class QQmlComponent; +class QQuickItem; +class QQuickWidget; +class WaitingWidget; + namespace Calamares { @@ -55,6 +60,12 @@ public: private: QString m_name; + + QWidget* m_widget = nullptr; + WaitingWidget* m_spinner = nullptr; + QQuickWidget* m_qmlShow = nullptr; + QQmlComponent* m_qmlComponent = nullptr; + QQuickItem* m_qmlObject = nullptr; }; } // namespace Calamares From c03c6fc8ed9e13bff8532dee983deebf9bbd06f6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 13:39:03 +0100 Subject: [PATCH 18/68] [libcalamaresui] Qml loading - this is mostly copied from ExecutionViewStep (only the V2 QML loading), which does the same kind of thing. - loading from QRC does not work yet --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 71 ++++++++++++++++++++ src/libcalamaresui/viewpages/QmlViewStep.h | 9 ++- 2 files changed, 79 insertions(+), 1 deletion(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 11637d04b..3cfcc7371 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -18,8 +18,14 @@ #include "QmlViewStep.h" +#include "utils/Dirs.h" +#include "utils/Logger.h" #include "widgets/WaitingWidget.h" +#include +#include +#include +#include #include #include @@ -31,9 +37,24 @@ QmlViewStep::QmlViewStep( const QString& name, QObject* parent ) , m_name( name ) , m_widget( new QWidget ) , m_spinner( new WaitingWidget( tr( "Loading ..." ) ) ) + , m_qmlWidget( new QQuickWidget ) { QVBoxLayout* layout = new QVBoxLayout( m_widget ); layout->addWidget( m_spinner ); + + m_qmlWidget->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding ); + m_qmlWidget->setResizeMode( QQuickWidget::SizeRootObjectToView ); + m_qmlWidget->engine()->addImportPath( CalamaresUtils::qmlModulesDir().absolutePath() ); + + // TODO: search for suitable file + QString qrcName = QStringLiteral( ":/%1.qml" ).arg( m_name ); + m_qmlFileName = qrcName; + + cDebug() << "QmlViewStep loading" << m_qmlFileName; + m_qmlComponent = new QQmlComponent( + m_qmlWidget->engine(), QUrl( m_qmlFileName ), QQmlComponent::CompilationMode::Asynchronous ); + connect( m_qmlComponent, &QQmlComponent::statusChanged, this, &QmlViewStep::loadComplete ); + cDebug() << Logger::SubEntry << "Status" << m_qmlComponent->status(); } QmlViewStep::~QmlViewStep() {} @@ -94,3 +115,53 @@ Calamares::QmlViewStep::widget() { return m_widget; } + +void +Calamares::QmlViewStep::loadComplete() +{ + cDebug() << "QML component" << m_qmlFileName << m_qmlComponent->status(); + if ( m_qmlComponent->isReady() && !m_qmlObject ) + { + cDebug() << "QML component complete" << m_qmlFileName; + // Don't do this again + disconnect( m_qmlComponent, &QQmlComponent::statusChanged, this, &QmlViewStep::loadComplete ); + + QObject* o = m_qmlComponent->create(); + m_qmlObject = qobject_cast< QQuickItem* >( o ); + if ( !m_qmlObject ) + { + cError() << Logger::SubEntry << "Could not create QML from" << m_qmlFileName; + delete o; + } + else + { + // setContent() is public API, but not documented publicly. + // 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. + m_qmlWidget->setContent( QUrl( m_qmlFileName ), m_qmlComponent, m_qmlObject ); + showQml(); + } + } +} + +void +Calamares::QmlViewStep::showQml() +{ + if ( !m_qmlWidget || !m_qmlObject ) + { + cDebug() << "showQml() called but no QML object"; + return; + } + if ( m_spinner ) + { + m_widget->layout()->removeWidget( m_spinner ); + m_widget->layout()->addWidget( m_qmlWidget ); + delete m_spinner; + m_spinner = nullptr; + } + else + { + cDebug() << "showQml() called twice"; + } +} diff --git a/src/libcalamaresui/viewpages/QmlViewStep.h b/src/libcalamaresui/viewpages/QmlViewStep.h index d1b28af35..0503f5cde 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.h +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -58,12 +58,19 @@ public: virtual JobList jobs() const override; +private Q_SLOTS: + void loadComplete(); + private: + /// @brief Swap out the spinner for the QQuickWidget + void showQml(); + QString m_name; + QString m_qmlFileName; QWidget* m_widget = nullptr; WaitingWidget* m_spinner = nullptr; - QQuickWidget* m_qmlShow = nullptr; + QQuickWidget* m_qmlWidget = nullptr; QQmlComponent* m_qmlComponent = nullptr; QQuickItem* m_qmlObject = nullptr; }; From e6713d456cfe71dbf27f81010903080a30f6bfb2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 13:44:26 +0100 Subject: [PATCH 19/68] [libcalamaresui] Need explicit qrc: scheme --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 3cfcc7371..4cee7c281 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -47,7 +47,7 @@ QmlViewStep::QmlViewStep( const QString& name, QObject* parent ) m_qmlWidget->engine()->addImportPath( CalamaresUtils::qmlModulesDir().absolutePath() ); // TODO: search for suitable file - QString qrcName = QStringLiteral( ":/%1.qml" ).arg( m_name ); + QString qrcName = QStringLiteral( "qrc:/%1.qml" ).arg( m_name ); m_qmlFileName = qrcName; cDebug() << "QmlViewStep loading" << m_qmlFileName; From e7e66497d2e583d8fb082d726af70a225ee12a9e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 17:19:15 +0100 Subject: [PATCH 20/68] [libcalamaresui] Introduce search method for QML UI modules - add a sample config and documentation in dummyqml/ --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 25 ++++++++++++++++++++ src/libcalamaresui/viewpages/QmlViewStep.h | 21 ++++++++++++++++ src/modules/dummyqml/dummyqml.conf | 19 +++++++++++++++ 3 files changed, 65 insertions(+) create mode 100644 src/modules/dummyqml/dummyqml.conf diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 4cee7c281..cf19fb2b4 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -20,6 +20,8 @@ #include "utils/Dirs.h" #include "utils/Logger.h" +#include "utils/NamedEnum.h" +#include "utils/Variant.h" #include "widgets/WaitingWidget.h" #include @@ -29,6 +31,19 @@ #include #include +static const NamedEnumTable< Calamares::QmlViewStep::QmlSearch >& +searchNames() +{ + using QmlSearch = Calamares::QmlViewStep::QmlSearch; + static NamedEnumTable< Calamares::QmlViewStep::QmlSearch > names{ + { QStringLiteral( "both" ), QmlSearch::Both }, + { QStringLiteral( "qrc" ), QmlSearch::QrcOnly }, + { QStringLiteral( "branding" ), QmlSearch::BrandingOnly } + }; + + return names; +} + namespace Calamares { @@ -165,3 +180,13 @@ Calamares::QmlViewStep::showQml() cDebug() << "showQml() called twice"; } } + +void Calamares::QmlViewStep::setConfigurationMap(const QVariantMap& configurationMap) +{ + bool ok = false; + m_searchMethod = searchNames().find( CalamaresUtils::getString( configurationMap, "search" ), ok ); + if (!ok) + { + cDebug() << "Bad QML search mode."; + } +} diff --git a/src/libcalamaresui/viewpages/QmlViewStep.h b/src/libcalamaresui/viewpages/QmlViewStep.h index 0503f5cde..38405a6a6 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.h +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -40,6 +40,20 @@ class QmlViewStep : public Calamares::ViewStep Q_OBJECT public: + enum class QmlSearch + { + QrcOnly, + BrandingOnly, + Both + }; + + /** @brief Creates a QML view step + * + * The name should not have an extension or schema or anything; + * just the plain name, which will be searched as "/.qml" in + * QRC files, or ".qml" in suitable branding paths. + * The search behavior depends on a QmlSearch value. + */ QmlViewStep( const QString& name, QObject* parent = nullptr ); virtual ~QmlViewStep() override; @@ -56,8 +70,12 @@ public: virtual void onActivate() override; virtual void onLeave() override; + /// @brief QML widgets don't produce jobs by default virtual JobList jobs() const override; + /// @brief Configure search paths; subclasses should call this as well + virtual void setConfigurationMap( const QVariantMap& configurationMap ) override; + private Q_SLOTS: void loadComplete(); @@ -65,6 +83,9 @@ private: /// @brief Swap out the spinner for the QQuickWidget void showQml(); + /// @brief Controls where m_name is searched + QmlSearch m_searchMethod; + QString m_name; QString m_qmlFileName; diff --git a/src/modules/dummyqml/dummyqml.conf b/src/modules/dummyqml/dummyqml.conf new file mode 100644 index 000000000..a861b68bd --- /dev/null +++ b/src/modules/dummyqml/dummyqml.conf @@ -0,0 +1,19 @@ +# The dummy QML module just displays a QML page. It doesn't +# have much in the way of own configuration, only where +# the QML file is searched. +# +# QML modules can search for the QML inside the Qt resources +# (QRC) which are compiled into the module, or in the branding +# setup for Calamares, (or both of them, with branding taking +# precedence). This allows the module to ship a default UI and +# branding to optionally introduce a replacement file. +# +# Generally, leave the search method set to "both" because if +# you don't want to brand the UI, just don't ship a branding +# QML file for it. +# +# To support instanced QML modules, searches in the branding +# directory look for the full module@instanceid name as well. +--- +search: both + From fed298b17963594afd601193c635e6e875d5bb71 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 17:41:20 +0100 Subject: [PATCH 21/68] [libcalamaresui] Defer QML loading - need a configuration before we can start loading (to support the variable search paths) - refactor showing a failure in the spinner widget. On failure, the spinner will never go away, so a message for the user is good. - stop clang-format from messing up the table of names. --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 60 ++++++++++++++------ src/libcalamaresui/viewpages/QmlViewStep.h | 2 + 2 files changed, 46 insertions(+), 16 deletions(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index cf19fb2b4..779a624c1 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -34,12 +34,16 @@ static const NamedEnumTable< Calamares::QmlViewStep::QmlSearch >& searchNames() { - using QmlSearch = Calamares::QmlViewStep::QmlSearch; - static NamedEnumTable< Calamares::QmlViewStep::QmlSearch > names{ - { QStringLiteral( "both" ), QmlSearch::Both }, - { QStringLiteral( "qrc" ), QmlSearch::QrcOnly }, - { QStringLiteral( "branding" ), QmlSearch::BrandingOnly } + using Search = Calamares::QmlViewStep::QmlSearch; + // *INDENT-OFF* + // clang-format off + static NamedEnumTable< Search > names { + { QStringLiteral( "both" ), Search::Both }, + { QStringLiteral( "qrc" ), Search::QrcOnly }, + { QStringLiteral( "branding" ), Search::BrandingOnly } }; + // *INDENT-ON* + // clang-format on return names; } @@ -61,15 +65,7 @@ QmlViewStep::QmlViewStep( const QString& name, QObject* parent ) m_qmlWidget->setResizeMode( QQuickWidget::SizeRootObjectToView ); m_qmlWidget->engine()->addImportPath( CalamaresUtils::qmlModulesDir().absolutePath() ); - // TODO: search for suitable file - QString qrcName = QStringLiteral( "qrc:/%1.qml" ).arg( m_name ); - m_qmlFileName = qrcName; - - cDebug() << "QmlViewStep loading" << m_qmlFileName; - m_qmlComponent = new QQmlComponent( - m_qmlWidget->engine(), QUrl( m_qmlFileName ), QQmlComponent::CompilationMode::Asynchronous ); - connect( m_qmlComponent, &QQmlComponent::statusChanged, this, &QmlViewStep::loadComplete ); - cDebug() << Logger::SubEntry << "Status" << m_qmlComponent->status(); + // QML Loading starts when the configuration for the module is set. } QmlViewStep::~QmlViewStep() {} @@ -135,6 +131,10 @@ void Calamares::QmlViewStep::loadComplete() { cDebug() << "QML component" << m_qmlFileName << m_qmlComponent->status(); + if ( m_qmlComponent->status() == QQmlComponent::Error ) + { + showFailedQml(); + } if ( m_qmlComponent->isReady() && !m_qmlObject ) { cDebug() << "QML component complete" << m_qmlFileName; @@ -181,12 +181,40 @@ Calamares::QmlViewStep::showQml() } } -void Calamares::QmlViewStep::setConfigurationMap(const QVariantMap& configurationMap) +void +Calamares::QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { bool ok = false; m_searchMethod = searchNames().find( CalamaresUtils::getString( configurationMap, "search" ), ok ); - if (!ok) + if ( !ok ) { cDebug() << "Bad QML search mode."; } + + if ( !m_qmlComponent ) + { + // TODO: search for suitable file + QString qrcName = QStringLiteral( "qrc:/X%1.qml" ).arg( m_name ); + m_qmlFileName = qrcName; + + cDebug() << "QmlViewStep" << moduleInstanceKey() << "loading" << m_qmlFileName; + m_qmlComponent = new QQmlComponent( + m_qmlWidget->engine(), QUrl( m_qmlFileName ), QQmlComponent::CompilationMode::Asynchronous ); + connect( m_qmlComponent, &QQmlComponent::statusChanged, this, &QmlViewStep::loadComplete ); + if ( m_qmlComponent->status() == QQmlComponent::Error ) + { + showFailedQml(); + } + } + else + { + cWarning() << "QML configuration set after component has loaded."; + } +} + +void +Calamares::QmlViewStep::showFailedQml() +{ + cWarning() << "QmlViewStep" << moduleInstanceKey() << "loading failed."; + m_spinner->setText( prettyName() + tr( "Loading failed." ) ); } diff --git a/src/libcalamaresui/viewpages/QmlViewStep.h b/src/libcalamaresui/viewpages/QmlViewStep.h index 38405a6a6..46ba29a53 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.h +++ b/src/libcalamaresui/viewpages/QmlViewStep.h @@ -82,6 +82,8 @@ private Q_SLOTS: private: /// @brief Swap out the spinner for the QQuickWidget void showQml(); + /// @brief Show error message in spinner. + void showFailedQml(); /// @brief Controls where m_name is searched QmlSearch m_searchMethod; From ce6d54ad9581bbb07b6818e0fb409fc57e6404fd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 17:45:09 +0100 Subject: [PATCH 22/68] [libcalamaresui] Improve failure message, unbreak loading - example loading had an X inserted in filename (to test failure) - add a space between name and failure --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 779a624c1..569eb6cd9 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -194,7 +194,7 @@ Calamares::QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap if ( !m_qmlComponent ) { // TODO: search for suitable file - QString qrcName = QStringLiteral( "qrc:/X%1.qml" ).arg( m_name ); + QString qrcName = QStringLiteral( "qrc:/%1.qml" ).arg( m_name ); m_qmlFileName = qrcName; cDebug() << "QmlViewStep" << moduleInstanceKey() << "loading" << m_qmlFileName; @@ -216,5 +216,5 @@ void Calamares::QmlViewStep::showFailedQml() { cWarning() << "QmlViewStep" << moduleInstanceKey() << "loading failed."; - m_spinner->setText( prettyName() + tr( "Loading failed." ) ); + m_spinner->setText( prettyName() + ' ' + tr( "Loading failed." ) ); } From 04615b251c652e765503f11d0b9c9f813f9588ef Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 10 Jan 2020 17:47:02 +0100 Subject: [PATCH 23/68] [dummyqml] Make prettyName() return a sentence with . --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 2 +- src/modules/dummyqml/DummyQmlViewStep.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 569eb6cd9..e26b02430 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -74,7 +74,7 @@ QString QmlViewStep::prettyName() const { // TODO: query the QML itself - return tr( "QML Step %1" ).arg( m_name ); + return tr( "QML Step %1." ).arg( m_name ); } diff --git a/src/modules/dummyqml/DummyQmlViewStep.cpp b/src/modules/dummyqml/DummyQmlViewStep.cpp index 985d2985a..32c1c60d0 100644 --- a/src/modules/dummyqml/DummyQmlViewStep.cpp +++ b/src/modules/dummyqml/DummyQmlViewStep.cpp @@ -28,7 +28,7 @@ DummyQmlViewStep::~DummyQmlViewStep() {} QString DummyQmlViewStep::prettyName() const { - return tr( "Example QML page" ); + return tr( "Example QML page." ); } From 7f8a31007a8e07dcd0e430b9f7443777a9b8bc9a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 13 Jan 2020 22:04:27 +0100 Subject: [PATCH 24/68] [dummyqml] Search for files - start implementation of searching-for-qml - add a *filename* configuration item, so that the filename can be set per-instance (via the config file) --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 45 ++++++++++++++++++-- src/modules/dummyqml/dummyqml.conf | 3 ++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index e26b02430..8fcc75a9b 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -181,6 +181,40 @@ Calamares::QmlViewStep::showQml() } } + +/** @brief Find a suitable QML file, given the search method and name hints + * + * Returns QString() if nothing is found (which would mean the module + * is badly configured). + */ +QString +searchQmlFile( Calamares::QmlViewStep::QmlSearch method, const QString& configuredName, const QString& moduleName ) +{ + cDebug() << "Looking for QML for" << moduleName; + for ( const QString& candidate : + QStringList { configuredName.isEmpty() ? QString() : QStringLiteral( ":/%1.qml" ).arg( configuredName ), + moduleName.isEmpty() ? QString() : QStringLiteral( ":/%1.qml" ).arg( moduleName ) } ) + { + if ( candidate.isEmpty() ) + { + continue; + } + cDebug() << Logger::SubEntry << "Looking at QML file" << candidate; + if ( QFile::exists( candidate ) ) + { + if ( candidate.startsWith( ':' ) ) + { + // Inconsistency: QFile only sees the file with :, + // but QML needs an explicit scheme (of qrc:) + return QStringLiteral( "qrc" ) + candidate; + } + return candidate; + } + } + cDebug() << Logger::SubEntry << "None found."; + return QString(); +} + void Calamares::QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { @@ -191,11 +225,14 @@ Calamares::QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap cDebug() << "Bad QML search mode."; } - if ( !m_qmlComponent ) + QString qmlFile = CalamaresUtils::getString( configurationMap, "filename" ); + if ( qmlFile.isEmpty() ) { - // TODO: search for suitable file - QString qrcName = QStringLiteral( "qrc:/%1.qml" ).arg( m_name ); - m_qmlFileName = qrcName; + cWarning() << "No QML file for module" << m_name; + } + else if ( !m_qmlComponent ) + { + m_qmlFileName = searchQmlFile( m_searchMethod, qmlFile, m_name ); cDebug() << "QmlViewStep" << moduleInstanceKey() << "loading" << m_qmlFileName; m_qmlComponent = new QQmlComponent( diff --git a/src/modules/dummyqml/dummyqml.conf b/src/modules/dummyqml/dummyqml.conf index a861b68bd..e62d35383 100644 --- a/src/modules/dummyqml/dummyqml.conf +++ b/src/modules/dummyqml/dummyqml.conf @@ -15,5 +15,8 @@ # To support instanced QML modules, searches in the branding # directory look for the full module@instanceid name as well. --- +# Search mode. Valid values are "both", "qrc" and "branding" search: both +# Name of the QML file. If not set, uses the name of the module. +filename: dummyqml From 750465153f4d6a329b97b2ed9786423b618411d9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Mon, 13 Jan 2020 22:28:21 +0100 Subject: [PATCH 25/68] [dummyqml] Improve QML searching - if the filename is an absolute path, use that - support searching in branding directory --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 25 +++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 8fcc75a9b..44edba97d 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -18,6 +18,8 @@ #include "QmlViewStep.h" +#include "Branding.h" + #include "utils/Dirs.h" #include "utils/Logger.h" #include "utils/NamedEnum.h" @@ -190,10 +192,27 @@ Calamares::QmlViewStep::showQml() QString searchQmlFile( Calamares::QmlViewStep::QmlSearch method, const QString& configuredName, const QString& moduleName ) { + using QmlSearch = Calamares::QmlViewStep::QmlSearch; + cDebug() << "Looking for QML for" << moduleName; - for ( const QString& candidate : - QStringList { configuredName.isEmpty() ? QString() : QStringLiteral( ":/%1.qml" ).arg( configuredName ), - moduleName.isEmpty() ? QString() : QStringLiteral( ":/%1.qml" ).arg( moduleName ) } ) + QStringList candidates; + if ( configuredName.startsWith( '/' ) ) + { + candidates << configuredName; + } + if ( ( method == QmlSearch::Both ) || ( method == QmlSearch::BrandingOnly ) ) + { + QString brandDir = Calamares::Branding::instance()->componentDirectory(); + candidates << ( configuredName.isEmpty() ? QString() + : QStringLiteral( "%1/%2.qml" ).arg( brandDir, configuredName ) ) + << ( moduleName.isEmpty() ? QString() : QStringLiteral( "%1/%2.qml" ).arg( brandDir, moduleName ) ); + } + if ( ( method == QmlSearch::Both ) || ( method == QmlSearch::QrcOnly ) ) + { + candidates << ( configuredName.isEmpty() ? QString() : QStringLiteral( ":/%1.qml" ).arg( configuredName ) ) + << ( moduleName.isEmpty() ? QString() : QStringLiteral( ":/%1.qml" ).arg( moduleName ) ); + } + for ( const QString& candidate : candidates ) { if ( candidate.isEmpty() ) { From f2e68ddcf4dc62c38d0ffcdbbb504b7dae13cd11 Mon Sep 17 00:00:00 2001 From: demmm Date: Tue, 14 Jan 2020 12:30:22 +0100 Subject: [PATCH 26/68] adding configure option dummyqml sidebar entry can be configured and translated adding a more elaborate qml example keeping this in dummyqml for now, another commit will follow with continuation of dummyqml in a more aptly named module --- src/modules/dummyqml/DummyQmlViewStep.cpp | 20 +++++- src/modules/dummyqml/DummyQmlViewStep.h | 12 +++- src/modules/dummyqml/dummyqml.conf | 7 +++ src/modules/dummyqml/dummyqml.qml | 77 ++++++++++++++++++++--- 4 files changed, 105 insertions(+), 11 deletions(-) diff --git a/src/modules/dummyqml/DummyQmlViewStep.cpp b/src/modules/dummyqml/DummyQmlViewStep.cpp index 32c1c60d0..6bf0b4a60 100644 --- a/src/modules/dummyqml/DummyQmlViewStep.cpp +++ b/src/modules/dummyqml/DummyQmlViewStep.cpp @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2020, Adriaan de Groot + * Copyright 2020, Anke Boersma * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,6 +19,8 @@ #include "DummyQmlViewStep.h" +#include + DummyQmlViewStep::DummyQmlViewStep( QObject* parent ) : Calamares::QmlViewStep( "dummyqml", parent ) { @@ -28,8 +31,23 @@ DummyQmlViewStep::~DummyQmlViewStep() {} QString DummyQmlViewStep::prettyName() const { - return tr( "Example QML page." ); + return m_notesName ? m_notesName->get() : tr( "Notes" ); } +void +DummyQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ + Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation + + bool qmlLabel_ok = false; + auto qmlLabel = CalamaresUtils::getSubMap( configurationMap, "qmlLabel", qmlLabel_ok ); + if ( qmlLabel_ok ) + { + if ( qmlLabel.contains( "notes" ) ) + { + m_notesName = new CalamaresUtils::Locale::TranslatedString( qmlLabel, "notes" ); + } + } +} CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyQmlViewStepFactory, registerPlugin< DummyQmlViewStep >(); ) diff --git a/src/modules/dummyqml/DummyQmlViewStep.h b/src/modules/dummyqml/DummyQmlViewStep.h index ffc358fe7..6eb0d768e 100644 --- a/src/modules/dummyqml/DummyQmlViewStep.h +++ b/src/modules/dummyqml/DummyQmlViewStep.h @@ -1,6 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2020, Adriaan de Groot + * Copyright 2020, Anke Boersma * * Calamares is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -19,10 +20,14 @@ #ifndef DUMMYQMLVIEWSTEP_H #define DUMMYQMLVIEWSTEP_H +#include +#include "locale/TranslatableConfiguration.h" +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Variant.h" #include "utils/PluginFactory.h" #include "viewpages/QmlViewStep.h" -class DummyQmlViewStep : public Calamares::QmlViewStep +class PLUGINDLLEXPORT DummyQmlViewStep : public Calamares::QmlViewStep { Q_OBJECT @@ -30,9 +35,12 @@ public: DummyQmlViewStep( QObject* parent = nullptr ); virtual ~DummyQmlViewStep() override; - virtual QString prettyName() const override; + QString prettyName() const override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; private: + CalamaresUtils::Locale::TranslatedString* m_notesName; // As it appears in the sidebar }; CALAMARES_PLUGIN_FACTORY_DECLARATION( DummyQmlViewStepFactory ) diff --git a/src/modules/dummyqml/dummyqml.conf b/src/modules/dummyqml/dummyqml.conf index e62d35383..c3581911f 100644 --- a/src/modules/dummyqml/dummyqml.conf +++ b/src/modules/dummyqml/dummyqml.conf @@ -20,3 +20,10 @@ search: both # Name of the QML file. If not set, uses the name of the module. filename: dummyqml + +# Name of the QML file. If not set, uses the name of the module. +filename: notes + +qmlLabel: + notes: "Release Notes" + notes[nl]: "Opmerkingen" diff --git a/src/modules/dummyqml/dummyqml.qml b/src/modules/dummyqml/dummyqml.qml index 6cab24bec..3cbfa65fc 100644 --- a/src/modules/dummyqml/dummyqml.qml +++ b/src/modules/dummyqml/dummyqml.qml @@ -1,12 +1,73 @@ -import QtQuick 2.3 +/* === This file is part of Calamares - === + * + * Copyright 2020, Anke Boersma + * + * 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 . + */ -Rectangle { - width: 200 - height: 100 - color: "red" +import QtQuick 2.7 +import QtQuick.Controls 2.2 +import QtQuick.Window 2.2 +import QtQuick.Layouts 1.3 +import QtQuick.Controls.Material 2.1 - Text { - anchors.centerIn: parent - text: "Hello, World!" +Item { + width: 740 + height: 420 + + Flickable { + id: flick + anchors.fill: parent + contentHeight: 800 + + ScrollBar.vertical: ScrollBar { + width: 10 + policy: ScrollBar.AlwaysOn + } + + TextArea { + id: intro + x: 1 + y: 0 + width: 720 + font.pointSize: 14 + textFormat: Text.RichText + antialiasing: true + activeFocusOnPress: false + wrapMode: Text.WordWrap + + text: qsTr("

Generic GNU/Linux 2017.8 LTS Soapy Sousaphone

+

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 is strikethrough

+ +

Code example: + ls -l /home

+ +

Lists:

+
    +
  • Intel CPU systems
  • +
  • AMD CPU systems
  • +
+ +

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

") + + } } } From 32eee827440da46ef8b644a607b19a6760bbd8c8 Mon Sep 17 00:00:00 2001 From: demmm Date: Tue, 14 Jan 2020 13:08:54 +0100 Subject: [PATCH 27/68] clean-up dummyqml.conf --- src/modules/dummyqml/dummyqml.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/modules/dummyqml/dummyqml.conf b/src/modules/dummyqml/dummyqml.conf index c3581911f..48bbbc150 100644 --- a/src/modules/dummyqml/dummyqml.conf +++ b/src/modules/dummyqml/dummyqml.conf @@ -21,9 +21,6 @@ search: both # Name of the QML file. If not set, uses the name of the module. filename: dummyqml -# Name of the QML file. If not set, uses the name of the module. -filename: notes - qmlLabel: notes: "Release Notes" notes[nl]: "Opmerkingen" From 9f55cf4cf4d313cc87134e1561e78c3be14c109e Mon Sep 17 00:00:00 2001 From: demmm Date: Fri, 24 Jan 2020 15:12:10 +0100 Subject: [PATCH 28/68] part of the changes requested others fail to build, or no idea how to fix --- src/modules/dummyqml/DummyQmlViewStep.cpp | 3 +++ src/modules/dummyqml/DummyQmlViewStep.h | 4 +--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/modules/dummyqml/DummyQmlViewStep.cpp b/src/modules/dummyqml/DummyQmlViewStep.cpp index 6bf0b4a60..39c95e993 100644 --- a/src/modules/dummyqml/DummyQmlViewStep.cpp +++ b/src/modules/dummyqml/DummyQmlViewStep.cpp @@ -19,6 +19,9 @@ #include "DummyQmlViewStep.h" +#include "utils/PluginFactory.h" +#include "viewpages/QmlViewStep.h" + #include DummyQmlViewStep::DummyQmlViewStep( QObject* parent ) diff --git a/src/modules/dummyqml/DummyQmlViewStep.h b/src/modules/dummyqml/DummyQmlViewStep.h index 6eb0d768e..adcd294fa 100644 --- a/src/modules/dummyqml/DummyQmlViewStep.h +++ b/src/modules/dummyqml/DummyQmlViewStep.h @@ -20,12 +20,10 @@ #ifndef DUMMYQMLVIEWSTEP_H #define DUMMYQMLVIEWSTEP_H -#include +#include "PluginDllMacro.h" #include "locale/TranslatableConfiguration.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Variant.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" class PLUGINDLLEXPORT DummyQmlViewStep : public Calamares::QmlViewStep { From 538d8d5497f8f77ed8644244717b44c2d02b8e0a Mon Sep 17 00:00:00 2001 From: demmm Date: Fri, 24 Jan 2020 15:14:51 +0100 Subject: [PATCH 29/68] address qmlLabel changes too --- src/modules/dummyqml/DummyQmlViewStep.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/modules/dummyqml/DummyQmlViewStep.cpp b/src/modules/dummyqml/DummyQmlViewStep.cpp index 39c95e993..030779f7f 100644 --- a/src/modules/dummyqml/DummyQmlViewStep.cpp +++ b/src/modules/dummyqml/DummyQmlViewStep.cpp @@ -19,9 +19,6 @@ #include "DummyQmlViewStep.h" -#include "utils/PluginFactory.h" -#include "viewpages/QmlViewStep.h" - #include DummyQmlViewStep::DummyQmlViewStep( QObject* parent ) @@ -44,13 +41,12 @@ DummyQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) bool qmlLabel_ok = false; auto qmlLabel = CalamaresUtils::getSubMap( configurationMap, "qmlLabel", qmlLabel_ok ); - if ( qmlLabel_ok ) + + if ( qmlLabel.contains( "notes" ) ) { - if ( qmlLabel.contains( "notes" ) ) - { - m_notesName = new CalamaresUtils::Locale::TranslatedString( qmlLabel, "notes" ); - } + m_notesName = new CalamaresUtils::Locale::TranslatedString( qmlLabel, "notes" ); } + } CALAMARES_PLUGIN_FACTORY_DEFINITION( DummyQmlViewStepFactory, registerPlugin< DummyQmlViewStep >(); ) From b20a957c6ef9a22d4e9e8e158a4c1678d87a26b3 Mon Sep 17 00:00:00 2001 From: demmm Date: Fri, 24 Jan 2020 15:52:59 +0100 Subject: [PATCH 30/68] restore includes in header file to amke it build --- src/modules/dummyqml/DummyQmlViewStep.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/modules/dummyqml/DummyQmlViewStep.h b/src/modules/dummyqml/DummyQmlViewStep.h index adcd294fa..cf49436b0 100644 --- a/src/modules/dummyqml/DummyQmlViewStep.h +++ b/src/modules/dummyqml/DummyQmlViewStep.h @@ -24,6 +24,8 @@ #include "locale/TranslatableConfiguration.h" #include "utils/CalamaresUtilsSystem.h" #include "utils/Variant.h" +#include "utils/PluginFactory.h" +#include "viewpages/QmlViewStep.h" class PLUGINDLLEXPORT DummyQmlViewStep : public Calamares::QmlViewStep { From abdeb07bd332c454a8937685552a3de34183f23c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 24 Jan 2020 17:14:45 +0100 Subject: [PATCH 31/68] [dummyqml] Minor polishing in Qml module - document the default filename better - mark TODO actually loading the instance-id file --- src/libcalamaresui/viewpages/QmlViewStep.cpp | 5 +++-- src/modules/dummyqml/dummyqml.conf | 9 ++++++--- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/libcalamaresui/viewpages/QmlViewStep.cpp b/src/libcalamaresui/viewpages/QmlViewStep.cpp index 44edba97d..b009d1626 100644 --- a/src/libcalamaresui/viewpages/QmlViewStep.cpp +++ b/src/libcalamaresui/viewpages/QmlViewStep.cpp @@ -247,9 +247,10 @@ Calamares::QmlViewStep::setConfigurationMap( const QVariantMap& configurationMap QString qmlFile = CalamaresUtils::getString( configurationMap, "filename" ); if ( qmlFile.isEmpty() ) { - cWarning() << "No QML file for module" << m_name; + // TODO use the module instance } - else if ( !m_qmlComponent ) + + if ( !m_qmlComponent ) { m_qmlFileName = searchQmlFile( m_searchMethod, qmlFile, m_name ); diff --git a/src/modules/dummyqml/dummyqml.conf b/src/modules/dummyqml/dummyqml.conf index 48bbbc150..9e7a83fdd 100644 --- a/src/modules/dummyqml/dummyqml.conf +++ b/src/modules/dummyqml/dummyqml.conf @@ -18,9 +18,12 @@ # Search mode. Valid values are "both", "qrc" and "branding" search: both -# Name of the QML file. If not set, uses the name of the module. -filename: dummyqml +# Name of the QML file. If not set, uses the name of the instance +# of the module (e.g. if you list this module in `settings.conf` +# in the *instances* section, you get *id*, otherwise it would +# normally be "dummyqml"). +# filename: dummyqml -qmlLabel: +qmlLabel: notes: "Release Notes" notes[nl]: "Opmerkingen" From 91625c8ba8cf68228f785a45479e02ea1db3a3a1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 13:35:26 +0100 Subject: [PATCH 32/68] [libcalamares] Tidy up boolean options in Settings - The const getters for a single boolean value have moved to the header, for inlining. - Document the getters and what their settings mean. --- src/libcalamares/Settings.cpp | 33 --------------------------------- src/libcalamares/Settings.h | 30 +++++++++++++++++++++++++----- 2 files changed, 25 insertions(+), 38 deletions(-) diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 456956430..668868812 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -265,37 +265,4 @@ Settings::brandingComponentName() const return m_brandingComponentName; } - -bool -Settings::showPromptBeforeExecution() const -{ - return m_promptInstall; -} - - -bool -Settings::debugMode() const -{ - return m_debug; -} - -bool -Settings::doChroot() const -{ - return m_doChroot; -} - -bool -Settings::disableCancel() const -{ - return m_disableCancel; -} - -bool -Settings::disableCancelDuringExec() const -{ - return m_disableCancelDuringExec; -} - - } // namespace Calamares diff --git a/src/libcalamares/Settings.h b/src/libcalamares/Settings.h index 4c2f2ed9d..bd980caaa 100644 --- a/src/libcalamares/Settings.h +++ b/src/libcalamares/Settings.h @@ -51,11 +51,31 @@ public: QString brandingComponentName() const; - bool showPromptBeforeExecution() const; + /** @brief Is this a debugging run? + * + * Returns true if Calamares is in debug mode. In debug mode, + * modules and settings are loaded from more locations, to help + * development and debugging. + */ + bool debugMode() const { return m_debug; } - bool debugMode() const; + /** @brief Distinguish "install" from "OEM" modes. + * + * Returns true in "install" mode, which is where actions happen + * in a chroot -- the target system, which exists separately from + * the source system. In "OEM" mode, returns false and most actions + * apply to the *current* (host) system. + */ + bool doChroot() const { return m_doChroot; } - bool doChroot() const; + /** @brief Global setting of prompt-before-install. + * + * Returns true when the configuration is such that the user + * should be prompted one-last-time before any action is taken + * that really affects the machine. + */ + bool showPromptBeforeExecution() const { return m_promptInstall; } + /** @brief Distinguish between "install" and "setup" modes. * * This influences user-visible strings, for instance using the @@ -64,9 +84,9 @@ public: bool isSetupMode() const { return m_isSetupMode; } /** @brief Global setting of disable-cancel: can't cancel ever. */ - bool disableCancel() const; + bool disableCancel() const { return m_disableCancel; } /** @brief Temporary setting of disable-cancel: can't cancel during exec. */ - bool disableCancelDuringExec() const; + bool disableCancelDuringExec() const { return m_disableCancelDuringExec; } private: static Settings* s_instance; From af862336a862717dad0ee8e65dc9a0041ffde3b2 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 13:49:44 +0100 Subject: [PATCH 33/68] [calamares] Initialize settings before QML --- src/calamares/CalamaresApplication.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index 1584b11fa..e435dd6ef 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -75,13 +75,13 @@ CalamaresApplication::init() setQuitOnLastWindowClosed( false ); - initQmlPath(); initSettings(); + initQmlPath(); initBranding(); setWindowIcon( QIcon( Calamares::Branding::instance()->imagePath( Calamares::Branding::ProductIcon ) ) ); - cDebug() << "STARTUP: initQmlPath, initSettings, initBranding done"; + cDebug() << "STARTUP: initSettings, initQmlPath, initBranding done"; initModuleManager(); //also shows main window From ea8adc3de71a4bd38f7f4cf1eab9a83fa7269f2d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 14:04:52 +0100 Subject: [PATCH 34/68] [calamares] Simplify return from main --- src/calamares/main.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index caf1f6cfd..2a49b4806 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -116,11 +116,10 @@ main( int argc, char* argv[] ) handle_args( a ); KDSingleApplicationGuard guard( KDSingleApplicationGuard::AutoKillOtherInstances ); - int returnCode = 0; if ( guard.isPrimaryInstance() ) { a.init(); - returnCode = a.exec(); + return a.exec(); } else { @@ -135,7 +134,6 @@ main( int argc, char* argv[] ) { qDebug() << " " << i.isValid() << i.pid() << i.arguments(); } + return 69; // EX_UNAVAILABLE on FreeBSD } - - return returnCode; } From f233cac7a17d39038839a12d8223db85c4808f90 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 14:23:55 +0100 Subject: [PATCH 35/68] [calamares] Refactor debug-logging settings --- src/calamares/main.cpp | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index 2a49b4806..e451cf8cc 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -35,6 +35,21 @@ #include #include +static unsigned int +debug_level( QCommandLineParser& parser, QCommandLineOption& levelOption ) +{ + bool ok = true; + int l = parser.value( levelOption ).toInt( &ok ); + if ( !ok || ( l < 0 ) ) + { + return Logger::LOGVERBOSE; + } + else + { + return static_cast< unsigned int >( l ); // l >= 0 + } +} + static void handle_args( CalamaresApplication& a ) { @@ -59,25 +74,7 @@ handle_args( CalamaresApplication& a ) parser.process( a ); a.setDebug( parser.isSet( debugOption ) ); - if ( parser.isSet( debugOption ) ) - { - Logger::setupLogLevel( Logger::LOGVERBOSE ); - } - else if ( parser.isSet( debugLevelOption ) ) - { - bool ok = true; - int l = parser.value( debugLevelOption ).toInt( &ok ); - unsigned int dlevel = 0; - if ( !ok || ( l < 0 ) ) - { - dlevel = Logger::LOGVERBOSE; - } - else - { - dlevel = static_cast< unsigned int >( l ); // l >= 0 - } - Logger::setupLogLevel( dlevel ); - } + Logger::setupLogLevel( a.isDebug() ? Logger::LOGVERBOSE : debug_level( parser, debugLevelOption ) ); if ( parser.isSet( configOption ) ) { CalamaresUtils::setAppDataDir( QDir( parser.value( configOption ) ) ); @@ -115,7 +112,6 @@ main( int argc, char* argv[] ) handle_args( a ); KDSingleApplicationGuard guard( KDSingleApplicationGuard::AutoKillOtherInstances ); - if ( guard.isPrimaryInstance() ) { a.init(); From 50b6801d35abf01d63534f8baf9b52c98089d533 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 14:33:42 +0100 Subject: [PATCH 36/68] [calamares] Install translator after loading settings - means that also the *initial* translation can take settings into account, like -d loading local translations. --- src/calamares/CalamaresApplication.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index e435dd6ef..a1daa4df2 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -59,8 +59,6 @@ CalamaresApplication::CalamaresApplication( int& argc, char* argv[] ) setApplicationName( QStringLiteral( CALAMARES_APPLICATION_NAME ) ); setApplicationVersion( QStringLiteral( CALAMARES_VERSION ) ); - CalamaresUtils::installTranslator( QLocale::system(), QString(), this ); - QFont f = font(); CalamaresUtils::setDefaultFontSize( f.pointSize() ); } @@ -73,12 +71,13 @@ CalamaresApplication::init() cDebug() << "Calamares version:" << CALAMARES_VERSION; cDebug() << " languages:" << QString( CALAMARES_TRANSLATION_LANGUAGES ).replace( ";", ", " ); - setQuitOnLastWindowClosed( false ); - initSettings(); initQmlPath(); initBranding(); + CalamaresUtils::installTranslator( QLocale::system(), QString(), this ); + + setQuitOnLastWindowClosed( false ); setWindowIcon( QIcon( Calamares::Branding::instance()->imagePath( Calamares::Branding::ProductIcon ) ) ); cDebug() << "STARTUP: initSettings, initQmlPath, initBranding done"; From db80a34aca14fdb710588a6cc1ccb3c4d5aad2d6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 16:09:35 +0100 Subject: [PATCH 37/68] [calamares] Remove intermediate debug-settings - There's a multi-stage setup for debug-mode, where the application object also knows that debugging is set. Remove it. - Break debug mode (because now the settings don't get debug-mode set). - Refactor so that parameter handing is only done if this Calamares is the unique (first) Calamares. --- src/calamares/CalamaresApplication.cpp | 21 ++++++--------------- src/calamares/CalamaresApplication.h | 12 ------------ src/calamares/main.cpp | 8 ++++---- 3 files changed, 10 insertions(+), 31 deletions(-) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index a1daa4df2..1ce8f5eaa 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -42,12 +42,17 @@ #include #include +/// @brief Convenience for "are the settings in debug mode" +static bool +isDebug() +{ + return Calamares::Settings::instance() && Calamares::Settings::instance()->debugMode(); +} CalamaresApplication::CalamaresApplication( int& argc, char* argv[] ) : QApplication( argc, argv ) , m_mainwindow( nullptr ) , m_moduleManager( nullptr ) - , m_debugMode( false ) { // Setting the organization name makes the default cache // directory -- where Calamares stores logs, for instance -- @@ -102,20 +107,6 @@ CalamaresApplication::instance() } -void -CalamaresApplication::setDebug( bool enabled ) -{ - m_debugMode = enabled; -} - - -bool -CalamaresApplication::isDebug() -{ - return m_debugMode; -} - - CalamaresWindow* CalamaresApplication::mainWindow() { diff --git a/src/calamares/CalamaresApplication.h b/src/calamares/CalamaresApplication.h index 634f4cdb2..091361602 100644 --- a/src/calamares/CalamaresApplication.h +++ b/src/calamares/CalamaresApplication.h @@ -49,16 +49,6 @@ public: void init(); static CalamaresApplication* instance(); - /** - * @brief setDebug controls whether debug mode is enabled - */ - void setDebug( bool enabled ); - - /** - * @brief isDebug returns true if running in debug mode, otherwise false. - */ - bool isDebug(); - /** * @brief mainWindow returns the Calamares application main window. */ @@ -78,8 +68,6 @@ private: CalamaresWindow* m_mainwindow; Calamares::ModuleManager* m_moduleManager; - - bool m_debugMode; }; #endif // CALAMARESAPPLICATION_H diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index e451cf8cc..e2f5c0fd9 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -73,8 +73,7 @@ handle_args( CalamaresApplication& a ) parser.process( a ); - a.setDebug( parser.isSet( debugOption ) ); - Logger::setupLogLevel( a.isDebug() ? Logger::LOGVERBOSE : debug_level( parser, debugLevelOption ) ); + Logger::setupLogLevel( parser.isSet( debugOption ) ? Logger::LOGVERBOSE : debug_level( parser, debugLevelOption ) ); if ( parser.isSet( configOption ) ) { CalamaresUtils::setAppDataDir( QDir( parser.value( configOption ) ) ); @@ -83,6 +82,8 @@ handle_args( CalamaresApplication& a ) { CalamaresUtils::setXdgDirs(); } + + a.init(); } int @@ -110,11 +111,10 @@ main( int argc, char* argv[] ) // TODO: umount anything in /tmp/calamares-... as an emergency save function #endif - handle_args( a ); KDSingleApplicationGuard guard( KDSingleApplicationGuard::AutoKillOtherInstances ); if ( guard.isPrimaryInstance() ) { - a.init(); + handle_args( a ); return a.exec(); } else From 68e8b0695d0439b9f5cd0f08e676d53e411717d6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 16:14:56 +0100 Subject: [PATCH 38/68] [calamares] Make declaration order match calling order --- src/calamares/CalamaresApplication.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/calamares/CalamaresApplication.h b/src/calamares/CalamaresApplication.h index 091361602..23239d79e 100644 --- a/src/calamares/CalamaresApplication.h +++ b/src/calamares/CalamaresApplication.h @@ -60,8 +60,9 @@ private slots: void initFailed( const QStringList& l ); private: - void initQmlPath(); + // Initialization steps happen in this order void initSettings(); + void initQmlPath(); void initBranding(); void initModuleManager(); void initJobQueue(); From 4525060c26860917a0adeb09384b80a4a17bad0e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 16:48:49 +0100 Subject: [PATCH 39/68] [calamares] Refactor Settings initialization - add a Settings::init() to do actual work - remove the same kind of code from CalamaresApplication - make constructor of Settings private - initialize settings before the application --- src/calamares/CalamaresApplication.cpp | 78 ++------------------- src/calamares/CalamaresApplication.h | 1 - src/calamares/main.cpp | 3 +- src/calamares/testmain.cpp | 2 +- src/libcalamares/Settings.cpp | 94 +++++++++++++++++++++++++- src/libcalamares/Settings.h | 9 ++- src/modules/shellprocess/Tests.cpp | 2 +- 7 files changed, 107 insertions(+), 82 deletions(-) diff --git a/src/calamares/CalamaresApplication.cpp b/src/calamares/CalamaresApplication.cpp index 1ce8f5eaa..48e54b76e 100644 --- a/src/calamares/CalamaresApplication.cpp +++ b/src/calamares/CalamaresApplication.cpp @@ -76,7 +76,11 @@ CalamaresApplication::init() cDebug() << "Calamares version:" << CALAMARES_VERSION; cDebug() << " languages:" << QString( CALAMARES_TRANSLATION_LANGUAGES ).replace( ";", ", " ); - initSettings(); + if ( !Calamares::Settings::instance() ) + { + cError() << "Must create Calamares::Settings before the application."; + ::exit( 1 ); + } initQmlPath(); initBranding(); @@ -142,35 +146,6 @@ qmlDirCandidates( bool assumeBuilddir ) } -static QStringList -settingsFileCandidates( bool assumeBuilddir ) -{ - static const char settings[] = "settings.conf"; - - QStringList settingsPaths; - if ( CalamaresUtils::isAppDataDirOverridden() ) - { - settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings ); - } - else - { - if ( assumeBuilddir ) - { - settingsPaths << QDir::current().absoluteFilePath( settings ); - } - if ( CalamaresUtils::haveExtraDirs() ) - for ( auto s : CalamaresUtils::extraConfigDirs() ) - { - settingsPaths << ( s + settings ); - } - settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat - settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings ); - } - - return settingsPaths; -} - - static QStringList brandingFileCandidates( bool assumeBuilddir, const QString& brandingFilename ) { @@ -236,49 +211,6 @@ CalamaresApplication::initQmlPath() } -void -CalamaresApplication::initSettings() -{ - QStringList settingsFileCandidatesByPriority = settingsFileCandidates( isDebug() ); - - QFileInfo settingsFile; - bool found = false; - - foreach ( const QString& path, settingsFileCandidatesByPriority ) - { - QFileInfo pathFi( path ); - if ( pathFi.exists() && pathFi.isReadable() ) - { - settingsFile = pathFi; - found = true; - break; - } - } - - if ( !found || !settingsFile.exists() || !settingsFile.isReadable() ) - { - cError() << "Cowardly refusing to continue startup without settings." - << Logger::DebugList( settingsFileCandidatesByPriority ); - if ( CalamaresUtils::isAppDataDirOverridden() ) - { - cError() << "FATAL: explicitly configured application data directory is missing settings.conf"; - } - else - { - cError() << "FATAL: none of the expected configuration file paths exist."; - } - ::exit( EXIT_FAILURE ); - } - - auto* settings = new Calamares::Settings( settingsFile.absoluteFilePath(), isDebug(), this ); // Creates singleton - if ( settings->modulesSequence().count() < 1 ) - { - cError() << "FATAL: no sequence set."; - ::exit( EXIT_FAILURE ); - } -} - - void CalamaresApplication::initBranding() { diff --git a/src/calamares/CalamaresApplication.h b/src/calamares/CalamaresApplication.h index 23239d79e..f42c21b56 100644 --- a/src/calamares/CalamaresApplication.h +++ b/src/calamares/CalamaresApplication.h @@ -61,7 +61,6 @@ private slots: private: // Initialization steps happen in this order - void initSettings(); void initQmlPath(); void initBranding(); void initModuleManager(); diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index e2f5c0fd9..9369d59e5 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -20,7 +20,7 @@ #include "CalamaresApplication.h" -#include "CalamaresConfig.h" +#include "Settings.h" #include "utils/Dirs.h" #include "utils/Logger.h" @@ -83,6 +83,7 @@ handle_args( CalamaresApplication& a ) CalamaresUtils::setXdgDirs(); } + Calamares::Settings::init( parser.isSet( debugOption ) ); a.init(); } diff --git a/src/calamares/testmain.cpp b/src/calamares/testmain.cpp index 885915041..0845218eb 100644 --- a/src/calamares/testmain.cpp +++ b/src/calamares/testmain.cpp @@ -225,7 +225,7 @@ main( int argc, char* argv[] ) return 1; } - std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) ); + std::unique_ptr< Calamares::Settings > settings_p( Calamares::Settings::init( QString() ) ); std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); QMainWindow* mw = nullptr; diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 668868812..48f8c606d 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -21,6 +21,7 @@ #include "Settings.h" +#include "CalamaresConfig.h" #include "utils/Dirs.h" #include "utils/Logger.h" #include "utils/Yaml.h" @@ -193,8 +194,8 @@ interpretSequence( const YAML::Node& node, Settings::ModuleSequence& moduleSeque } } -Settings::Settings( const QString& settingsFilePath, bool debugMode, QObject* parent ) - : QObject( parent ) +Settings::Settings( const QString& settingsFilePath, bool debugMode ) + : QObject() , m_debug( debugMode ) , m_doChroot( true ) , m_promptInstall( false ) @@ -265,4 +266,93 @@ Settings::brandingComponentName() const return m_brandingComponentName; } +static QStringList +settingsFileCandidates( bool assumeBuilddir ) +{ + static const char settings[] = "settings.conf"; + + QStringList settingsPaths; + if ( CalamaresUtils::isAppDataDirOverridden() ) + { + settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings ); + } + else + { + if ( assumeBuilddir ) + { + settingsPaths << QDir::current().absoluteFilePath( settings ); + } + if ( CalamaresUtils::haveExtraDirs() ) + for ( auto s : CalamaresUtils::extraConfigDirs() ) + { + settingsPaths << ( s + settings ); + } + settingsPaths << CMAKE_INSTALL_FULL_SYSCONFDIR "/calamares/settings.conf"; // String concat + settingsPaths << CalamaresUtils::appDataDir().absoluteFilePath( settings ); + } + + return settingsPaths; +} + +Settings* +Settings::init( bool debugMode ) +{ + if ( s_instance ) + { + cWarning() << "Calamares::Settings already created"; + return s_instance; + } + + QStringList settingsFileCandidatesByPriority = settingsFileCandidates( debugMode ); + + QFileInfo settingsFile; + bool found = false; + + foreach ( const QString& path, settingsFileCandidatesByPriority ) + { + QFileInfo pathFi( path ); + if ( pathFi.exists() && pathFi.isReadable() ) + { + settingsFile = pathFi; + found = true; + break; + } + } + + if ( !found || !settingsFile.exists() || !settingsFile.isReadable() ) + { + cError() << "Cowardly refusing to continue startup without settings." + << Logger::DebugList( settingsFileCandidatesByPriority ); + if ( CalamaresUtils::isAppDataDirOverridden() ) + { + cError() << "FATAL: explicitly configured application data directory is missing settings.conf"; + } + else + { + cError() << "FATAL: none of the expected configuration file paths exist."; + } + ::exit( EXIT_FAILURE ); + } + + auto* settings = new Calamares::Settings( settingsFile.absoluteFilePath(), debugMode ); // Creates singleton + if ( settings->modulesSequence().count() < 1 ) + { + cError() << "FATAL: no sequence set."; + ::exit( EXIT_FAILURE ); + } + + return settings; +} + +Settings* +Settings::init( const QString& path ) +{ + if ( s_instance ) + { + cWarning() << "Calamares::Settings already created"; + return s_instance; + } + return new Calamares::Settings( path, true ); +} + } // namespace Calamares diff --git a/src/libcalamares/Settings.h b/src/libcalamares/Settings.h index bd980caaa..26990f027 100644 --- a/src/libcalamares/Settings.h +++ b/src/libcalamares/Settings.h @@ -35,11 +35,14 @@ namespace Calamares class DLLEXPORT Settings : public QObject { Q_OBJECT + explicit Settings( const QString& settingsFilePath, bool debugMode ); public: - explicit Settings( const QString& settingsFilePath, bool debugMode, QObject* parent = nullptr ); - static Settings* instance(); - + /// @brief Find a settings.conf, following @p debugMode + static Settings* init( bool debugMode ); + /// @brief Explicif filename, debug is always true (for testing) + static Settings* init( const QString& filename ); + QStringList modulesSearchPaths() const; using InstanceDescription = QMap< QString, QString >; diff --git a/src/modules/shellprocess/Tests.cpp b/src/modules/shellprocess/Tests.cpp index 943a70957..e991973db 100644 --- a/src/modules/shellprocess/Tests.cpp +++ b/src/modules/shellprocess/Tests.cpp @@ -176,7 +176,7 @@ script: if ( !Calamares::JobQueue::instance() ) (void)new Calamares::JobQueue( nullptr ); if ( !Calamares::Settings::instance() ) - (void)new Calamares::Settings( QString(), true ); + (void)Calamares::Settings::init( QString() ); Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); QVERIFY( gs != nullptr ); From 24c2c435a0865df2c22f7b84264d8eafa5c35184 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 17:08:47 +0100 Subject: [PATCH 40/68] [libcalamares] Try repairing tests - Fail on FreeBSD with an instant timeout --- src/libcalamares/network/Tests.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/network/Tests.cpp b/src/libcalamares/network/Tests.cpp index 559a955fe..3a15b3c59 100644 --- a/src/libcalamares/network/Tests.cpp +++ b/src/libcalamares/network/Tests.cpp @@ -19,6 +19,7 @@ #include "Tests.h" #include "Manager.h" +#include "utils/Logger.h" #include @@ -43,6 +44,9 @@ NetworkTests::testInstance() void NetworkTests::testPing() { - auto& nam = CalamaresUtils::Network::Manager::instance(); - QVERIFY( nam.synchronousPing( QUrl( "https://www.kde.org" ) ) ); + using namespace CalamaresUtils::Network; + Logger::setupLogLevel( Logger::LOGVERBOSE ); + auto& nam = Manager::instance(); + auto r = nam.synchronousPing( QUrl( "https://www.kde.org" ), RequestOptions( RequestOptions::FollowRedirect ) ); + QVERIFY( r ); } From 4b3f7eb2090815727247446a0441308e70100800 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 17:48:39 +0100 Subject: [PATCH 41/68] [calamares] Local translations can be a separate setting - Don't stick this in Settings, though, it becomes overly complicated. --- src/calamares/main.cpp | 7 ++++++- src/libcalamares/utils/Retranslator.cpp | 15 ++++++++++++--- src/libcalamares/utils/Retranslator.h | 9 +++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/calamares/main.cpp b/src/calamares/main.cpp index 9369d59e5..670b7a654 100644 --- a/src/calamares/main.cpp +++ b/src/calamares/main.cpp @@ -23,6 +23,7 @@ #include "Settings.h" #include "utils/Dirs.h" #include "utils/Logger.h" +#include "utils/Retranslator.h" #include "3rdparty/kdsingleapplicationguard/kdsingleapplicationguard.h" @@ -57,6 +58,9 @@ handle_args( CalamaresApplication& a ) "Also look in current directory for configuration. Implies -D8." ); QCommandLineOption debugLevelOption( QStringLiteral( "D" ), "Verbose output for debugging purposes (0-8).", "level" ); + QCommandLineOption debugTxOption( QStringList { "T", "debug-translation" }, + "Also look in the current directory for translation." ); + QCommandLineOption configOption( QStringList { "c", "config" }, "Configuration directory to use, for testing purposes.", "config" ); QCommandLineOption xdgOption( QStringList { "X", "xdg-config" }, "Use XDG_{CONFIG,DATA}_DIRS as well." ); @@ -70,6 +74,7 @@ handle_args( CalamaresApplication& a ) parser.addOption( debugLevelOption ); parser.addOption( configOption ); parser.addOption( xdgOption ); + parser.addOption( debugTxOption ); parser.process( a ); @@ -82,7 +87,7 @@ handle_args( CalamaresApplication& a ) { CalamaresUtils::setXdgDirs(); } - + CalamaresUtils::setAllowLocalTranslation( parser.isSet( debugOption ) || parser.isSet( debugTxOption ) ); Calamares::Settings::init( parser.isSet( debugOption ) ); a.init(); } diff --git a/src/libcalamares/utils/Retranslator.cpp b/src/libcalamares/utils/Retranslator.cpp index 85dfb62b6..767d0581e 100644 --- a/src/libcalamares/utils/Retranslator.cpp +++ b/src/libcalamares/utils/Retranslator.cpp @@ -27,6 +27,8 @@ #include #include +static bool s_allowLocalTranslations = false; + /** @brief Helper class for loading translations * * This is used by the loadSingletonTranslator() function to hand off @@ -131,7 +133,7 @@ static bool tryLoad( QTranslator* translator, const QString& prefix, const QString& localeName ) { // In debug-mode, try loading from the current directory - if ( Calamares::Settings::instance() && Calamares::Settings::instance()->debugMode() && translator->load( prefix + localeName ) ) + if ( s_allowLocalTranslations && translator->load( prefix + localeName ) ) { cDebug() << Logger::SubEntry << "Loaded local translation" << prefix << localeName; return true; @@ -139,14 +141,15 @@ tryLoad( QTranslator* translator, const QString& prefix, const QString& localeNa // Or load from appDataDir -- often /usr/share/calamares -- subdirectory land/ QDir localeData( CalamaresUtils::appDataDir() ); - if ( localeData.exists() && translator->load( localeData.absolutePath() + QStringLiteral("/lang/") + prefix + localeName) ) + if ( localeData.exists() + && translator->load( localeData.absolutePath() + QStringLiteral( "/lang/" ) + prefix + localeName ) ) { cDebug() << Logger::SubEntry << "Loaded appdata translation" << prefix << localeName; return true; } // Or from QRC (most common) - if ( translator->load( QStringLiteral( ":/lang/") + prefix + localeName ) ) + if ( translator->load( QStringLiteral( ":/lang/" ) + prefix + localeName ) ) { cDebug() << Logger::SubEntry << "Loaded QRC translation" << prefix << localeName; return true; @@ -260,5 +263,11 @@ Retranslator::eventFilter( QObject* obj, QEvent* e ) return QObject::eventFilter( obj, e ); } +void +setAllowLocalTranslation( bool allow ) +{ + s_allowLocalTranslations = allow; +} + } // namespace CalamaresUtils diff --git a/src/libcalamares/utils/Retranslator.h b/src/libcalamares/utils/Retranslator.h index 58c60b761..af322e5b5 100644 --- a/src/libcalamares/utils/Retranslator.h +++ b/src/libcalamares/utils/Retranslator.h @@ -42,6 +42,15 @@ DLLEXPORT void installTranslator( const QLocale& locale, const QString& branding DLLEXPORT QString translatorLocaleName(); +/** @brief Set @p allow to true to load translations from current dir. + * + * If false, (or never called) the translations are loaded only from + * system locations (the AppData dir) and from QRC (compiled in). + * Enable local translations to test translations stored in the + * current directory. + */ +DLLEXPORT void setAllowLocalTranslation( bool allow ); + class Retranslator : public QObject { Q_OBJECT From 53b6113c7509572ceef98009aa7a477ff96bc456 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Wed, 5 Feb 2020 18:38:46 +0100 Subject: [PATCH 42/68] [welcome] Fix QML tests --- src/modules/welcome/qmlmain.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/welcome/qmlmain.cpp b/src/modules/welcome/qmlmain.cpp index 96d9d245f..a9dd1875d 100644 --- a/src/modules/welcome/qmlmain.cpp +++ b/src/modules/welcome/qmlmain.cpp @@ -49,7 +49,7 @@ int main(int argc, char **argv) Logger::setupLogLevel( Logger::LOGVERBOSE ); - std::unique_ptr< Calamares::Settings > settings_p( new Calamares::Settings( QString(), true ) ); + std::unique_ptr< Calamares::Settings > settings_p( Calamares::Settings::init( QString() ) ); std::unique_ptr< Calamares::JobQueue > jobqueue_p( new Calamares::JobQueue( nullptr ) ); Calamares::Branding defaultBrand( "src/branding/default/branding.desc" ); From b8505dc6215770ae7b09584e2d8e7a7101f32c6f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 6 Feb 2020 12:45:40 +0100 Subject: [PATCH 43/68] CI: tidy up txcheck.sh - Add license header with SPDX info - Add usage header - Support --help - Document internals a little more --- ci/txcheck.sh | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/ci/txcheck.sh b/ci/txcheck.sh index a2130c9d5..61fdd7030 100644 --- a/ci/txcheck.sh +++ b/ci/txcheck.sh @@ -1,5 +1,18 @@ #! /bin/sh +### LICENSE +# === This file is part of Calamares - === +# +# This file is Free Software: you can redistribute it and/or modify +# it under the terms of the 2-clause BSD License. +# https://spdx.org/licenses/BSD-2-Clause.html +# +# SPDX-License-Identifier: BSD-2-Clause +# SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot +### END LICENSE + +### USAGE +# # Does the translation tag (from a previous txpush) exist? # This assumes that the release host has also locally done # a translations push, which works for the current development @@ -7,6 +20,13 @@ # the typical txpush log messages instead of the tag. # # Use --cleanup as an argument to clean things up. +# +# Normal use: +# $ sh ci/txcheck.sh +# If there are differences, fix them and then clean up: +# $ sh ci/txcheck.sh --cleanup +# +### END USAGE # The files that are translated; should match the contents of .tx/config TX_FILE_LIST="lang/calamares_en.ts lang/python.pot src/modules/dummypythonqt/lang/dummypythonqt.pot calamares.desktop" @@ -27,6 +47,9 @@ if test "x$1" = "x--cleanup" ; then tx_cleanup exit 0 fi +if test "x$1" = "x--help" ; then + sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" +fi test -z "$1" || { echo "! Usage: txcheck.sh [--cleanup]" ; exit 1 ; } @@ -67,6 +90,8 @@ fi if test `git describe` = `git describe --dirty` ; then : else + # Don't want any local changes, since those won't be + # reflected in the worktrees and we might miss a string change. echo "! There are local changes." exit 1 fi @@ -75,13 +100,20 @@ DATE_PREV=$( git log -1 translation --date=unix | sed -e '/^Date:/s+.*:++p' -e d DATE_HEAD=$( last_week ) test "$DATE_PREV" -le "$DATE_HEAD" || { echo "! Translation tag has not aged enough." ; git log -1 translation ; exit 1 ; } -# Tag is good, do real work of checking strings: collect names of relevant files +# Tag is good, check that necessary files exist. The list of +# files is hard-coded, but should match what is in the Transifex config. test -f ".tx/config" || { echo "! No Transifex configuration is present." ; exit 1 ; } for f in $TX_FILE_LIST ; do test -f $f || { echo "! Translation file '$f' does not exist." ; exit 1 ; } done -# The state of translations +### COMPARE TRANSLATIONS +# +# + +# The state of translations; assume that sha256 is enough +# to distinguish changed translations when we cat all the +# string sources together. tx_sum() { CURDIR=`pwd` From 44489d3d7b01efdbf97f1d93fb76799c92c36162 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 6 Feb 2020 12:51:06 +0100 Subject: [PATCH 44/68] CI: tidy up license header in txcheck.sh --- ci/txcheck.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ci/txcheck.sh b/ci/txcheck.sh index 61fdd7030..8eef04571 100644 --- a/ci/txcheck.sh +++ b/ci/txcheck.sh @@ -3,12 +3,12 @@ ### LICENSE # === This file is part of Calamares - === # -# This file is Free Software: you can redistribute it and/or modify -# it under the terms of the 2-clause BSD License. -# https://spdx.org/licenses/BSD-2-Clause.html -# # SPDX-License-Identifier: BSD-2-Clause # SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot +# +# This file is Free Software: you can redistribute it and/or modify +# it under the terms of the 2-clause BSD License. +# ### END LICENSE ### USAGE From 0d2425ca78a4e733c21066c4a5b79290dbc28144 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 6 Feb 2020 13:01:55 +0100 Subject: [PATCH 45/68] CI: make shell-scripts tab-indented by default --- .editorconfig | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.editorconfig b/.editorconfig index b2ae0dd2b..d282d6273 100644 --- a/.editorconfig +++ b/.editorconfig @@ -11,3 +11,8 @@ trim_trailing_whitespace = true indent_style = space indent_size = 4 insert_final_newline = true + +[*.sh] +indent_style = tab +insert_final_newline = true + From dec30d70fd971b8e7a5d58a72757a82d1c88b24a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Thu, 6 Feb 2020 13:11:23 +0100 Subject: [PATCH 46/68] CI: tidy up scripts - Add SPDX headers - Indent consistently (tabs, not a mix of 2-space, 4-space, and tabs) The scripts were originally added without a license header. Since they are simple, and re-usable, and not particularly interesting, I've made the license explicitly 2-clause BSD. This is unlike the rest of Calamares, which is GPLv3+; the build system and support scripts are not the software itself. --- ci/txcheck.sh | 26 ++++++------- ci/txpull.sh | 64 ++++++++++++++++++------------ ci/txpush.sh | 106 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 116 insertions(+), 80 deletions(-) diff --git a/ci/txcheck.sh b/ci/txcheck.sh index 8eef04571..9ce8f0c30 100644 --- a/ci/txcheck.sh +++ b/ci/txcheck.sh @@ -37,18 +37,18 @@ TX_FILE_LIST="lang/calamares_en.ts lang/python.pot src/modules/dummypythonqt/lan # normally used much later in the script. tx_cleanup() { - # Cleanup artifacs of checking - git worktree remove --force build-txcheck-head - git worktree remove --force build-txcheck-prev - git branch -D build-txcheck-head > /dev/null 2>&1 + # Cleanup artifacs of checking + git worktree remove --force build-txcheck-head + git worktree remove --force build-txcheck-prev + git branch -D build-txcheck-head > /dev/null 2>&1 } if test "x$1" = "x--cleanup" ; then - tx_cleanup - exit 0 + tx_cleanup + exit 0 fi if test "x$1" = "x--help" ; then - sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" + sed -e '1,/USAGE/d' -e '/END.USAGE/,$d' < "$0" fi test -z "$1" || { echo "! Usage: txcheck.sh [--cleanup]" ; exit 1 ; } @@ -59,22 +59,22 @@ test -z "$1" || { echo "! Usage: txcheck.sh [--cleanup]" ; exit 1 ; } XMLLINT="" for _xmllint in xmllint do - $_xmllint --version > /dev/null 2>&1 && XMLLINT=$_xmllint - test -n "$XMLLINT" && break + $_xmllint --version > /dev/null 2>&1 && XMLLINT=$_xmllint + test -n "$XMLLINT" && break done # Distinguish GNU date from BSD date if date +%s -d "1 week ago" > /dev/null 2>&1 ; then - last_week() { date +%s -d "1 week ago" ; } + last_week() { date +%s -d "1 week ago" ; } else - last_week() { date -v1w +%s; } + last_week() { date -v1w +%s; } fi # Distinguish GNU SHA executables from BSD ones if which sha256sum > /dev/null 2>&1 ; then - SHA256=sha256sum + SHA256=sha256sum else - SHA256=sha256 + SHA256=sha256 fi ### CHECK WORKING DIRECTORY diff --git a/ci/txpull.sh b/ci/txpull.sh index b320da300..734a689b5 100755 --- a/ci/txpull.sh +++ b/ci/txpull.sh @@ -1,4 +1,18 @@ #!/bin/sh + +### LICENSE +# === This file is part of Calamares - === +# +# SPDX-License-Identifier: BSD-2-Clause +# SPDX-FileCopyrightText: 2017-2020 Adriaan de Groot +# SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac +# +# This file is Free Software: you can redistribute it and/or modify +# it under the terms of the 2-clause BSD License. +# +### END LICENSE + +### USAGE # # Fetch the Transifex translations for Calamares and incorporate them # into the source tree, adding commits of the different files. @@ -6,6 +20,8 @@ # Run this (occasionally) at the top-level directory to get # new translations. See also CMakeLists.txt and ci/txstats.py # for update instructions. +# +### END USAGE ### INITIAL SETUP # @@ -32,8 +48,8 @@ test -f "calamares.desktop" || { echo "! Not at Calamares top-level" ; exit 1 ; XMLLINT="" for _xmllint in xmllint do - $_xmllint --version > /dev/null 2>&1 && XMLLINT=$_xmllint - test -n "$XMLLINT" && break + $_xmllint --version > /dev/null 2>&1 && XMLLINT=$_xmllint + test -n "$XMLLINT" && break done # XMLLINT is optional @@ -53,9 +69,9 @@ tx pull --force --source --all # so clean them up after pulling. # drop_language() { - rm -rf lang/python/"$1" src/modules/dummypythonqt/lang/"$1" lang/calamares_"$1".ts - grep -v "\\[$1]" calamares.desktop > calamares.desktop.new - mv calamares.desktop.new calamares.desktop + rm -rf lang/python/"$1" src/modules/dummypythonqt/lang/"$1" lang/calamares_"$1".ts + grep -v "\\[$1]" calamares.desktop > calamares.desktop.new + mv calamares.desktop.new calamares.desktop } drop_language es_ES @@ -68,10 +84,10 @@ mv calamares.desktop.new calamares.desktop # And fixup the XML files like in txpush.sh if test -n "$XMLLINT" ; then - for TS_FILE in lang/calamares_*.ts - do - $XMLLINT --c14n11 "$TS_FILE" | { echo "" ; cat - ; } | $XMLLINT --format --encode utf-8 -o "$TS_FILE".new - && mv "$TS_FILE".new "$TS_FILE" - done + for TS_FILE in lang/calamares_*.ts + do + $XMLLINT --c14n11 "$TS_FILE" | { echo "" ; cat - ; } | $XMLLINT --format --encode utf-8 -o "$TS_FILE".new - && mv "$TS_FILE".new "$TS_FILE" + done fi @@ -108,24 +124,24 @@ git diff --numstat src/modules | awk '($1==1 && $2==1){print $3}' | xargs git ch # Go through the Python modules; those with a lang/ subdir have their # own complete gettext-based setup. for MODULE_DIR in $(find src/modules -maxdepth 1 -mindepth 1 -type d) ; do - FILES=$(find "$MODULE_DIR" -name "*.py" -a -type f) - if test -n "$FILES" ; then - MODULE_NAME=$(basename ${MODULE_DIR}) - if [ -d ${MODULE_DIR}/lang ]; then - # Convert PO files to MO files - for POFILE in $(find ${MODULE_DIR} -name "*.po") ; do - sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' $POFILE - msgfmt -o ${POFILE%.po}.mo $POFILE - done - git add --verbose ${MODULE_DIR}/lang/* - git commit "$AUTHOR" --message="i18n: [${MODULE_NAME}] $BOILERPLATE" | true - fi - fi + FILES=$(find "$MODULE_DIR" -name "*.py" -a -type f) + if test -n "$FILES" ; then + MODULE_NAME=$(basename ${MODULE_DIR}) + if [ -d ${MODULE_DIR}/lang ]; then + # Convert PO files to MO files + for POFILE in $(find ${MODULE_DIR} -name "*.po") ; do + sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' $POFILE + msgfmt -o ${POFILE%.po}.mo $POFILE + done + git add --verbose ${MODULE_DIR}/lang/* + git commit "$AUTHOR" --message="i18n: [${MODULE_NAME}] $BOILERPLATE" | true + fi + fi done for POFILE in $(find lang -name "python.po") ; do - sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' $POFILE - msgfmt -o ${POFILE%.po}.mo $POFILE + sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' $POFILE + msgfmt -o ${POFILE%.po}.mo $POFILE done git add --verbose lang/python* git commit "$AUTHOR" --message="i18n: [python] $BOILERPLATE" | true diff --git a/ci/txpush.sh b/ci/txpush.sh index 6882fa523..3195f42b4 100755 --- a/ci/txpush.sh +++ b/ci/txpush.sh @@ -1,13 +1,33 @@ #!/bin/sh + +### LICENSE +# === This file is part of Calamares - === +# +# SPDX-License-Identifier: BSD-2-Clause +# SPDX-FileCopyrightText: 2017-2020 Adriaan de Groot +# SPDX-FileCopyrightText: 2015-2016 Teo Mrnjavac +# +# This file is Free Software: you can redistribute it and/or modify +# it under the terms of the 2-clause BSD License. +# +### END LICENSE + +### USAGE # # Extract translations from Calamares source and send them -# to Transifex. +# to Transifex. Also (forcibly) updates the git "translation" +# tag to document that source texts were updated and sent; +# this is used by txcheck.sh to ensure that there's enough +# time between updates and releases, and that strings don't +# change between updates and releases. # # Run this at the top-level. # # Use the --no-tx option to do the extraction, but not the # pushing-to-Transifex part. This can be useful to check for # new strings or when testing the tools themselves. +# +### END USAGE ### INITIAL SETUP # @@ -28,21 +48,21 @@ test -f ".tx/config" || { echo "! Not at Calamares top-level" ; exit 1 ; } test -f "calamares.desktop" || { echo "! Not at Calamares top-level" ; exit 1 ; } if test "x$1" = "x--no-tx" ; then - # tx is the transifex command -- eat its arguments and do nothing - tx() { - echo "Skipped tx $*" - } - # txtag is used to tag in git to measure changes -- skip it too - txtag() { - echo "Skipped tx tagging." - } + # tx is the transifex command -- eat its arguments and do nothing + tx() { + echo "Skipped tx $*" + } + # txtag is used to tag in git to measure changes -- skip it too + txtag() { + echo "Skipped tx tagging." + } else - # tx is the regular transifex command - # txtag is used to tag in git to measure changes - txtag() { - git tag -f translation - git push --force origin translation - } + # tx is the regular transifex command + # txtag is used to tag in git to measure changes + txtag() { + git tag -f translation + git push --force origin translation + } fi @@ -52,18 +72,18 @@ fi LUPDATE="" for _lupdate in lupdate-qt5 lupdate do - export QT_SELECT=5 - $_lupdate -version > /dev/null 2>&1 || export QT_SELECT=qt5 - $_lupdate -version > /dev/null 2>&1 && LUPDATE=$_lupdate - test -n "$LUPDATE" && break + export QT_SELECT=5 + $_lupdate -version > /dev/null 2>&1 || export QT_SELECT=qt5 + $_lupdate -version > /dev/null 2>&1 && LUPDATE=$_lupdate + test -n "$LUPDATE" && break done test -n "$LUPDATE" || { echo "! No working lupdate" ; lupdate -version ; exit 1 ; } XMLLINT="" for _xmllint in xmllint do - $_xmllint --version > /dev/null 2>&1 && XMLLINT=$_xmllint - test -n "$XMLLINT" && break + $_xmllint --version > /dev/null 2>&1 && XMLLINT=$_xmllint + test -n "$XMLLINT" && break done # XMLLINT is optional @@ -82,8 +102,8 @@ $LUPDATE -no-obsolete $_srcdirs -ts lang/calamares_en.ts # $LUPDATE -no-obsolete -extensions cxxtr src/libcalamares/locale -ts lang/tz_en.ts if test -n "$XMLLINT" ; then - TS_FILE="lang/calamares_en.ts" - $XMLLINT --c14n11 "$TS_FILE" | { echo "" ; cat - ; } | $XMLLINT --format --encode utf-8 -o "$TS_FILE".new - && mv "$TS_FILE".new "$TS_FILE" + TS_FILE="lang/calamares_en.ts" + $XMLLINT --c14n11 "$TS_FILE" | { echo "" ; cat - ; } | $XMLLINT --format --encode utf-8 -o "$TS_FILE".new - && mv "$TS_FILE".new "$TS_FILE" fi tx push --source --no-interactive -r calamares.calamares-master @@ -103,29 +123,29 @@ PYGETTEXT="xgettext --keyword=_n:1,2 -L python" SHARED_PYTHON="" for MODULE_DIR in $(find src/modules -maxdepth 1 -mindepth 1 -type d) ; do - FILES=$(find "$MODULE_DIR" -name "*.py" -a -type f) - if test -n "$FILES" ; then - MODULE_NAME=$(basename ${MODULE_DIR}) - if [ -d ${MODULE_DIR}/lang ]; then - ${PYGETTEXT} -p ${MODULE_DIR}/lang -d ${MODULE_NAME} -o ${MODULE_NAME}.pot ${MODULE_DIR}/*.py - POTFILE="${MODULE_DIR}/lang/${MODULE_NAME}.pot" - if [ -f "$POTFILE" ]; then - sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' "$POTFILE" - tx set -r calamares.${MODULE_NAME} --source -l en "$POTFILE" - tx push --source --no-interactive -r calamares.${MODULE_NAME} - fi - else - SHARED_PYTHON="$SHARED_PYTHON $FILES" - fi - fi + FILES=$(find "$MODULE_DIR" -name "*.py" -a -type f) + if test -n "$FILES" ; then + MODULE_NAME=$(basename ${MODULE_DIR}) + if [ -d ${MODULE_DIR}/lang ]; then + ${PYGETTEXT} -p ${MODULE_DIR}/lang -d ${MODULE_NAME} -o ${MODULE_NAME}.pot ${MODULE_DIR}/*.py + POTFILE="${MODULE_DIR}/lang/${MODULE_NAME}.pot" + if [ -f "$POTFILE" ]; then + sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' "$POTFILE" + tx set -r calamares.${MODULE_NAME} --source -l en "$POTFILE" + tx push --source --no-interactive -r calamares.${MODULE_NAME} + fi + else + SHARED_PYTHON="$SHARED_PYTHON $FILES" + fi + fi done if test -n "$SHARED_PYTHON" ; then - ${PYGETTEXT} -p lang -d python -o python.pot $SHARED_PYTHON - POTFILE="lang/python.pot" - sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' "$POTFILE" - tx set -r calamares.python --source -l en "$POTFILE" - tx push --source --no-interactive -r calamares.python + ${PYGETTEXT} -p lang -d python -o python.pot $SHARED_PYTHON + POTFILE="lang/python.pot" + sed -i'' '/^"Content-Type/s/CHARSET/UTF-8/' "$POTFILE" + tx set -r calamares.python --source -l en "$POTFILE" + tx push --source --no-interactive -r calamares.python fi txtag From c766a0f10f44b90cfe7bee8fb2f7b7f040c98936 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Fri, 7 Feb 2020 10:26:36 +0100 Subject: [PATCH 47/68] [machineid] create dbus var-lib folder when not existing See also #1314 --- src/modules/machineid/main.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/machineid/main.py b/src/modules/machineid/main.py index cde47cfd9..61f8c891e 100644 --- a/src/modules/machineid/main.py +++ b/src/modules/machineid/main.py @@ -4,7 +4,7 @@ # === This file is part of Calamares - === # # Copyright 2014, Kevin Kofler -# Copyright 2016, Philip Müller +# Copyright 2016,2020 Philip Müller # Copyright 2017, Alf Gaida # Copyright 2019, Adriaan de Groot # @@ -54,6 +54,10 @@ def run(): enable_symlink = libcalamares.job.configuration["symlink"] target_systemd_machineid_file = root_mount_point + "/etc/machine-id" target_dbus_machineid_file = root_mount_point + "/var/lib/dbus/machine-id" + target_dbus_folder = root_mount_point + "/var/lib/dbus" + + if not os.path.exists(target_dbus_folder): + os.mkdir(target_dbus_folder, 0644) if os.path.exists(target_dbus_machineid_file): os.remove(target_dbus_machineid_file) From 72d742e2f4a339929f0e8c0e9ae79704112bf741 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Fri, 7 Feb 2020 10:34:01 +0100 Subject: [PATCH 48/68] [machineid] Use same approach as we do in Manjaro - See also https://gitlab.manjaro.org/applications/calamares/commit/da8f45ae - Fixes #1314 --- src/modules/machineid/main.py | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/modules/machineid/main.py b/src/modules/machineid/main.py index 61f8c891e..384193ed6 100644 --- a/src/modules/machineid/main.py +++ b/src/modules/machineid/main.py @@ -54,10 +54,6 @@ def run(): enable_symlink = libcalamares.job.configuration["symlink"] target_systemd_machineid_file = root_mount_point + "/etc/machine-id" target_dbus_machineid_file = root_mount_point + "/var/lib/dbus/machine-id" - target_dbus_folder = root_mount_point + "/var/lib/dbus" - - if not os.path.exists(target_dbus_folder): - os.mkdir(target_dbus_folder, 0644) if os.path.exists(target_dbus_machineid_file): os.remove(target_dbus_machineid_file) @@ -69,7 +65,7 @@ def run(): if enable_dbus: if enable_symlink and os.path.exists(target_systemd_machineid_file): - check_target_env_call(["ln", "-s", "/etc/machine-id", + check_target_env_call(["ln", "-sf", "/etc/machine-id", "/var/lib/dbus/machine-id"]) else: check_target_env_call(["dbus-uuidgen", "--ensure"]) From 97ddd30af48013b10034380f2654cb188062bf0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Philip=20M=C3=BCller?= Date: Fri, 7 Feb 2020 10:46:26 +0100 Subject: [PATCH 49/68] [machineid] folder needs to be created when not exists - See #1314 --- src/modules/machineid/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/machineid/main.py b/src/modules/machineid/main.py index 384193ed6..3c83ecf1a 100644 --- a/src/modules/machineid/main.py +++ b/src/modules/machineid/main.py @@ -54,6 +54,10 @@ def run(): enable_symlink = libcalamares.job.configuration["symlink"] target_systemd_machineid_file = root_mount_point + "/etc/machine-id" target_dbus_machineid_file = root_mount_point + "/var/lib/dbus/machine-id" + target_dbus_folder = root_mount_point + "/var/lib/dbus" + + if not os.path.exists(target_dbus_folder): + os.mkdir(target_dbus_folder, 0644) if os.path.exists(target_dbus_machineid_file): os.remove(target_dbus_machineid_file) From 9ef04192dbc621dbc2864c856d12b94eb139d4ce Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 11:03:40 +0100 Subject: [PATCH 50/68] [libcalamares] Simplify returns in targetPath() --- src/libcalamares/utils/CalamaresUtilsSystem.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index ea8f507bd..5d4b61a2f 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -266,8 +266,6 @@ System::runCommand( System::RunLocation location, QString System::targetPath( const QString& path ) const { - QString completePath; - if ( doChroot() ) { Calamares::GlobalStorage* gs @@ -279,14 +277,12 @@ System::targetPath( const QString& path ) const return QString(); } - completePath = gs->value( "rootMountPoint" ).toString() + '/' + path; + return gs->value( "rootMountPoint" ).toString() + '/' + path; } else { - completePath = QStringLiteral( "/" ) + path; + return QStringLiteral( "/" ) + path; } - - return completePath; } QString From bf882cec1d8ce7669645268d2ef4a2e5c49d9ecd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 11:14:57 +0100 Subject: [PATCH 51/68] [machineid] Migrate removeFile() to libcalamares - Becomes removeTargetFile() --- .../utils/CalamaresUtilsSystem.cpp | 20 ++++++++++++++++++- src/libcalamares/utils/CalamaresUtilsSystem.h | 11 +++++++++- src/modules/machineid/MachineIdJob.cpp | 10 ++++++---- src/modules/machineid/Workers.cpp | 11 ---------- src/modules/machineid/Workers.h | 3 --- 5 files changed, 35 insertions(+), 20 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 5d4b61a2f..ede96305a 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2018, 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 @@ -285,6 +285,13 @@ System::targetPath( const QString& path ) const } } +/// @brief Cheap check if a path is absolute. +static inline bool +isAbsolutePath( const QString& path ) +{ + return path.startsWith( '/' ); +} + QString System::createTargetFile( const QString& path, const QByteArray& contents ) const { @@ -323,6 +330,17 @@ System::createTargetFile( const QString& path, const QByteArray& contents ) cons return QFileInfo( f ).canonicalFilePath(); } +void +System::removeTargetFile( const QString& path ) const +{ + if ( !isAbsolutePath( path ) ) + { + cWarning() << "Will not remove non-absolute path" << path; + return; + } + QFile::remove( targetPath( path ) ); +} + QPair< quint64, float > System::getTotalMemoryB() const diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index 8265f0fdb..5c5e04eb2 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -1,7 +1,7 @@ /* === This file is part of Calamares - === * * Copyright 2014, Teo Mrnjavac - * Copyright 2017-2018, Adriaan de Groot + * Copyright 2017-2018, 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 @@ -246,6 +246,15 @@ public: */ DLLEXPORT QString createTargetFile( const QString& path, const QByteArray& contents ) const; + /** @brief Remove a file from the target system. + * + * @param path Path to the file; this is interpreted from the root + * of the target system (@see targetPath()). + * + * Does no error checking to see if the target file was really removed. + */ + DLLEXPORT void removeTargetFile( const QString& path ) const; + /** * @brief getTotalMemoryB returns the total main memory, in bytes. * diff --git a/src/modules/machineid/MachineIdJob.cpp b/src/modules/machineid/MachineIdJob.cpp index 393950ded..af3a68d90 100644 --- a/src/modules/machineid/MachineIdJob.cpp +++ b/src/modules/machineid/MachineIdJob.cpp @@ -3,7 +3,7 @@ * Copyright 2014, Kevin Kofler * Copyright 2016, Philip Müller * Copyright 2017, Alf Gaida - * Copyright 2019, Adriaan de Groot + * Copyright 2019-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 @@ -68,18 +68,20 @@ MachineIdJob::exec() QString target_dbus_machineid_file = QStringLiteral( "/var/lib/dbus/machine-id" ); QString target_entropy_file = QStringLiteral( "/var/lib/urandom/random-seed" ); + const auto* system = CalamaresUtils::System::instance(); + // Clear existing files if ( m_entropy ) { - MachineId::removeFile( root, target_entropy_file ); + system->removeTargetFile( target_entropy_file ); } if ( m_dbus ) { - MachineId::removeFile( root, target_dbus_machineid_file ); + system->removeTargetFile( target_dbus_machineid_file ); } if ( m_systemd ) { - MachineId::removeFile( root, target_systemd_machineid_file ); + system->removeTargetFile( target_systemd_machineid_file ); } //Create new files diff --git a/src/modules/machineid/Workers.cpp b/src/modules/machineid/Workers.cpp index fefaf24b9..f1f7bb369 100644 --- a/src/modules/machineid/Workers.cpp +++ b/src/modules/machineid/Workers.cpp @@ -36,17 +36,6 @@ isAbsolutePath( const QString& fileName ) return fileName.startsWith( '/' ); } -// might need to use a helper to remove the file -void -removeFile( const QString& rootMountPoint, const QString& fileName ) -{ - if ( isAbsolutePath( fileName ) ) - { - QFile::remove( rootMountPoint + fileName ); - } - // Otherwise, do nothing -} - Calamares::JobResult copyFile( const QString& rootMountPoint, const QString& fileName ) { diff --git a/src/modules/machineid/Workers.h b/src/modules/machineid/Workers.h index 5cf6270d9..31561af1b 100644 --- a/src/modules/machineid/Workers.h +++ b/src/modules/machineid/Workers.h @@ -30,9 +30,6 @@ namespace MachineId * for moving files around in the target system. */ -/// @brief Remove @p fileName from the target system at @p rootMountPoint -void removeFile( const QString& rootMountPoint, const QString& fileName ); - /// @brief Copy @p fileName from host into target system at @p rootMountPoint Calamares::JobResult copyFile( const QString& rootMountPoint, const QString& fileName ); From 4af68365c9bd955ee66001ad54b5d8bb71ef8cf5 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 11:16:40 +0100 Subject: [PATCH 52/68] [machineid] Remove obsolete implementation --- src/modules/machineid/main.py | 73 ----------------------------------- 1 file changed, 73 deletions(-) delete mode 100644 src/modules/machineid/main.py diff --git a/src/modules/machineid/main.py b/src/modules/machineid/main.py deleted file mode 100644 index 384193ed6..000000000 --- a/src/modules/machineid/main.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# === This file is part of Calamares - === -# -# Copyright 2014, Kevin Kofler -# Copyright 2016,2020 Philip Müller -# Copyright 2017, Alf Gaida -# Copyright 2019, 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 libcalamares -import os -from libcalamares.utils import check_target_env_call, debug - -import gettext -_ = gettext.translation("calamares-python", - localedir=libcalamares.utils.gettext_path(), - languages=libcalamares.utils.gettext_languages(), - fallback=True).gettext - - -def pretty_name(): - return _("Generate machine-id.") - - -def run(): - """ - Generate machine-id using dbus and systemd. - - :return: - """ - root_mount_point = libcalamares.globalstorage.value("rootMountPoint") - - if root_mount_point is None: - libcalamares.utils.warning("rootMountPoint is empty, {!s}".format(root_mount_point)) - return (_("Configuration Error"), - _("No root mount point is given for
{!s}
to use." ).format("machineid")) - - enable_systemd = libcalamares.job.configuration["systemd"] - enable_dbus = libcalamares.job.configuration["dbus"] - enable_symlink = libcalamares.job.configuration["symlink"] - target_systemd_machineid_file = root_mount_point + "/etc/machine-id" - target_dbus_machineid_file = root_mount_point + "/var/lib/dbus/machine-id" - - if os.path.exists(target_dbus_machineid_file): - os.remove(target_dbus_machineid_file) - - if enable_systemd: - if os.path.exists(target_systemd_machineid_file): - os.remove(target_systemd_machineid_file) - check_target_env_call("systemd-machine-id-setup") - - if enable_dbus: - if enable_symlink and os.path.exists(target_systemd_machineid_file): - check_target_env_call(["ln", "-sf", "/etc/machine-id", - "/var/lib/dbus/machine-id"]) - else: - check_target_env_call(["dbus-uuidgen", "--ensure"]) - - return None From 95936549e2be8e8f8c1aa343bf4b794d9c14204a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 11:30:37 +0100 Subject: [PATCH 53/68] [libcalamares] Add a createTargetBasedirs() - Used to ensure that the directories leading up to a given path exist. Implementation is incomplete and broken for now. - While here, avoid removing an empty pathname in removeTargetFile() (the empty pathname indicates a broken configuration). --- .../utils/CalamaresUtilsSystem.cpp | 30 ++++++++++++++++++- src/libcalamares/utils/CalamaresUtilsSystem.h | 11 +++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index ede96305a..3b36a7ccf 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -338,7 +338,35 @@ System::removeTargetFile( const QString& path ) const cWarning() << "Will not remove non-absolute path" << path; return; } - QFile::remove( targetPath( path ) ); + QString target = targetPath( path ); + if ( !target.isEmpty() ) + { + QFile::remove( target ); + } + // If it was empty, a warning was already printed +} + +int +System::createTargetBasedirs(const QString& path) const +{ + if ( !isAbsolutePath( path ) ) + { + cWarning() << "Will not create basedirs for non-absolute path" << path; + return -1; + } + + QString target = targetPath( path ); + if ( target.isEmpty() ) + { + // If it was empty, a warning was already printed + return -1; + } + + QString base( "/" ); + QStringList parts = target.split( '/', QString::SplitBehavior::SkipEmptyParts ); + + cDebug() << parts; + return -1; } diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index 5c5e04eb2..09a606e2c 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -255,6 +255,17 @@ public: */ DLLEXPORT void removeTargetFile( const QString& path ) const; + /** @brief Ensure that the directories above @p path exist + * + * @param path a full pathname to a desired file. + * + * All the directory components before the last path component are + * created, as needed, with 0755 permissions. Returns the number + * of components that needed to be created; 0 if they all already + * existed, and < 0 on failure. + */ + DLLEXPORT int createTargetBasedirs( const QString& path ) const; + /** * @brief getTotalMemoryB returns the total main memory, in bytes. * From 15bca702c1adefa0ab71ea2ee2181601544858d0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 11:51:13 +0100 Subject: [PATCH 54/68] [libcalamares] Add tests for path functions (part 1) --- src/libcalamares/utils/Tests.cpp | 27 +++++++++++++++++++++++++++ src/libcalamares/utils/Tests.h | 3 +++ 2 files changed, 30 insertions(+) diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 16faec9a1..7f9f7f2bf 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -24,6 +24,9 @@ #include "UMask.h" #include "Yaml.h" +#include "GlobalStorage.h" +#include "JobQueue.h" + #include #include @@ -221,3 +224,27 @@ LibCalamaresTests::testPrintableEntropy() QVERIFY( c.cell() < 127 ); } } + +void +LibCalamaresTests::testTargetPath() +{ + // Ensure we have a system object, expect it to be a "bogus" one + const CalamaresUtils::System* system = CalamaresUtils::System::instance(); + QVERIFY( system ); + QVERIFY( system->doChroot() ); + + // Ensure we have a system-wide GlobalStorage with /tmp as root + if ( !Calamares::JobQueue::instance() ) + { + (void)new Calamares::JobQueue(); + } + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + QVERIFY( gs ); + gs->insert( "rootMountPoint", "/tmp" ); + + // Paths mapped normally + QCOMPARE( system->targetPath( "/etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); + QCOMPARE( system->targetPath( "//etc//calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); // extra / + QCOMPARE( system->targetPath( "etc/calamares" ), QString() ); // NOT ABSOLUTE +} diff --git a/src/libcalamares/utils/Tests.h b/src/libcalamares/utils/Tests.h index d369ed4cb..8ea9aa0ce 100644 --- a/src/libcalamares/utils/Tests.h +++ b/src/libcalamares/utils/Tests.h @@ -43,6 +43,9 @@ private Q_SLOTS: /** @brief Tests the entropy functions. */ void testEntropy(); void testPrintableEntropy(); + + /** @brief Tests file creation and removal. */ + void testTargetPath(); }; #endif From 31878dd43b0f6adb879585228d4ce61ed1e8a7b1 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 13:29:35 +0100 Subject: [PATCH 55/68] [libcalamares] Avoid double / between root and path in targetPath() --- .../utils/CalamaresUtilsSystem.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 3b36a7ccf..b5293c252 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -263,6 +263,13 @@ System::runCommand( System::RunLocation location, return ProcessResult( r, output ); } +/// @brief Cheap check if a path is absolute. +static inline bool +isAbsolutePath( const QString& path ) +{ + return path.startsWith( '/' ); +} + QString System::targetPath( const QString& path ) const { @@ -277,21 +284,15 @@ System::targetPath( const QString& path ) const return QString(); } - return gs->value( "rootMountPoint" ).toString() + '/' + path; + QString root = gs->value( "rootMountPoint" ).toString(); + return isAbsolutePath( path ) ? ( root + path ) : ( root + '/' + path ); } else { - return QStringLiteral( "/" ) + path; + return isAbsolutePath( path ) ? path : ( QStringLiteral( "/" ) + path ); } } -/// @brief Cheap check if a path is absolute. -static inline bool -isAbsolutePath( const QString& path ) -{ - return path.startsWith( '/' ); -} - QString System::createTargetFile( const QString& path, const QByteArray& contents ) const { @@ -347,7 +348,7 @@ System::removeTargetFile( const QString& path ) const } int -System::createTargetBasedirs(const QString& path) const +System::createTargetBasedirs( const QString& path ) const { if ( !isAbsolutePath( path ) ) { From daa5b804b3e7b78a6f0431f43cf270a85d2e0951 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 13:49:06 +0100 Subject: [PATCH 56/68] [libcalamares] Split paths-tests into own test executable - Since these tests all want a system object, and a GS with a sensible setup, give them one with its own initTestCase(). This could have been done with one executable, running tests from multiple classes, but there's not much overall benefit there. --- src/libcalamares/CMakeLists.txt | 12 ++++ src/libcalamares/utils/TestPaths.cpp | 89 ++++++++++++++++++++++++++++ src/libcalamares/utils/Tests.cpp | 24 -------- src/libcalamares/utils/Tests.h | 3 - 4 files changed, 101 insertions(+), 27 deletions(-) create mode 100644 src/libcalamares/utils/TestPaths.cpp diff --git a/src/libcalamares/CMakeLists.txt b/src/libcalamares/CMakeLists.txt index 0e7f7c6e7..cad7e7a6e 100644 --- a/src/libcalamares/CMakeLists.txt +++ b/src/libcalamares/CMakeLists.txt @@ -171,6 +171,18 @@ if ( ECM_FOUND AND BUILD_TESTING ) ) calamares_automoc( libcalamarestest ) + ecm_add_test( + utils/TestPaths.cpp + TEST_NAME + libcalamarestestpaths + LINK_LIBRARIES + calamares + Qt5::Core + Qt5::Test + ) + calamares_automoc( libcalamarestestpaths ) + + ecm_add_test( geoip/GeoIPTests.cpp ${geoip_src} diff --git a/src/libcalamares/utils/TestPaths.cpp b/src/libcalamares/utils/TestPaths.cpp new file mode 100644 index 000000000..5071b1289 --- /dev/null +++ b/src/libcalamares/utils/TestPaths.cpp @@ -0,0 +1,89 @@ +/* === This file is part of Calamares - === + * + * Copyright 2018, 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 . + */ + +#include "CalamaresUtilsSystem.h" +#include "Entropy.h" +#include "Logger.h" +#include "UMask.h" +#include "Yaml.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" + +#include + +#include + +#include +#include +#include + +class TestPaths : public QObject +{ + Q_OBJECT +public: + TestPaths() {}; + virtual ~TestPaths() {}; + +private Q_SLOTS: + void initTestCase(); + + void testTargetPath(); + +private: + CalamaresUtils::System* m_system; // Points to singleton instance, not owned +}; + +void +TestPaths::initTestCase() +{ + Logger::setupLogLevel( Logger::LOGDEBUG ); + + // Ensure we have a system object, expect it to be a "bogus" one + CalamaresUtils::System* system = CalamaresUtils::System::instance(); + QVERIFY( system ); + QVERIFY( system->doChroot() ); + + // Ensure we have a system-wide GlobalStorage with /tmp as root + if ( !Calamares::JobQueue::instance() ) + { + (void)new Calamares::JobQueue(); + } + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + QVERIFY( gs ); + gs->insert( "rootMountPoint", "/tmp" ); + + m_system = system; +} + + +void +TestPaths::testTargetPath() +{ + // Paths mapped normally + QCOMPARE( m_system->targetPath( "/etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); + QCOMPARE( m_system->targetPath( "//etc//calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); // extra / + QCOMPARE( m_system->targetPath( "etc/calamares" ), QString() ); // NOT ABSOLUTE +} + +QTEST_GUILESS_MAIN( TestPaths ) + +#include "utils/moc-warnings.h" + +#include "TestPaths.moc" diff --git a/src/libcalamares/utils/Tests.cpp b/src/libcalamares/utils/Tests.cpp index 7f9f7f2bf..e39d182ea 100644 --- a/src/libcalamares/utils/Tests.cpp +++ b/src/libcalamares/utils/Tests.cpp @@ -224,27 +224,3 @@ LibCalamaresTests::testPrintableEntropy() QVERIFY( c.cell() < 127 ); } } - -void -LibCalamaresTests::testTargetPath() -{ - // Ensure we have a system object, expect it to be a "bogus" one - const CalamaresUtils::System* system = CalamaresUtils::System::instance(); - QVERIFY( system ); - QVERIFY( system->doChroot() ); - - // Ensure we have a system-wide GlobalStorage with /tmp as root - if ( !Calamares::JobQueue::instance() ) - { - (void)new Calamares::JobQueue(); - } - Calamares::GlobalStorage* gs - = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; - QVERIFY( gs ); - gs->insert( "rootMountPoint", "/tmp" ); - - // Paths mapped normally - QCOMPARE( system->targetPath( "/etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); - QCOMPARE( system->targetPath( "//etc//calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); // extra / - QCOMPARE( system->targetPath( "etc/calamares" ), QString() ); // NOT ABSOLUTE -} diff --git a/src/libcalamares/utils/Tests.h b/src/libcalamares/utils/Tests.h index 8ea9aa0ce..d369ed4cb 100644 --- a/src/libcalamares/utils/Tests.h +++ b/src/libcalamares/utils/Tests.h @@ -43,9 +43,6 @@ private Q_SLOTS: /** @brief Tests the entropy functions. */ void testEntropy(); void testPrintableEntropy(); - - /** @brief Tests file creation and removal. */ - void testTargetPath(); }; #endif From 8d23e665ea82e4aa75bfab3060e2f8298bea7f82 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 13:53:49 +0100 Subject: [PATCH 57/68] [libcalamares] Fix targetPath() tests - there is less simplification done than you might think --- src/libcalamares/utils/TestPaths.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/TestPaths.cpp b/src/libcalamares/utils/TestPaths.cpp index 5071b1289..2232ca084 100644 --- a/src/libcalamares/utils/TestPaths.cpp +++ b/src/libcalamares/utils/TestPaths.cpp @@ -78,8 +78,8 @@ TestPaths::testTargetPath() { // Paths mapped normally QCOMPARE( m_system->targetPath( "/etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); - QCOMPARE( m_system->targetPath( "//etc//calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); // extra / - QCOMPARE( m_system->targetPath( "etc/calamares" ), QString() ); // NOT ABSOLUTE + QCOMPARE( m_system->targetPath( "//etc//calamares" ), QStringLiteral( "/tmp//etc//calamares" ) ); // extra / are not cleaned up + QCOMPARE( m_system->targetPath( "etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); // relative to root } QTEST_GUILESS_MAIN( TestPaths ) From 394eee395414b844ad27ac15b002d069883a3827 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 13:57:14 +0100 Subject: [PATCH 58/68] [libcalamares] Test more targetPath() scenario's --- src/libcalamares/utils/TestPaths.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/libcalamares/utils/TestPaths.cpp b/src/libcalamares/utils/TestPaths.cpp index 2232ca084..7411dc5bb 100644 --- a/src/libcalamares/utils/TestPaths.cpp +++ b/src/libcalamares/utils/TestPaths.cpp @@ -80,6 +80,13 @@ TestPaths::testTargetPath() QCOMPARE( m_system->targetPath( "/etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); QCOMPARE( m_system->targetPath( "//etc//calamares" ), QStringLiteral( "/tmp//etc//calamares" ) ); // extra / are not cleaned up QCOMPARE( m_system->targetPath( "etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); // relative to root + + // Weird Paths + QCOMPARE( m_system->targetPath( QString() ), QStringLiteral( "/tmp/" ) ); + + // Now break GS + Calamares::JobQueue::instance()->globalStorage()->remove( "rootMountPoint" ); + QCOMPARE( m_system->targetPath( QString() ), QString() ); // Without root, no path } QTEST_GUILESS_MAIN( TestPaths ) From b502d78984e9b5406600f9eeea93ebc26171344f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 13:58:44 +0100 Subject: [PATCH 59/68] [libcalamares] Fix warning message - "create" was when this function was used elsewhere --- src/libcalamares/utils/CalamaresUtilsSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index b5293c252..0c21034af 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -280,7 +280,7 @@ System::targetPath( const QString& path ) const if ( !gs || !gs->contains( "rootMountPoint" ) ) { - cWarning() << "No rootMountPoint in global storage, cannot create target file" << path; + cWarning() << "No rootMountPoint in global storage, cannot name target file" << path; return QString(); } From 8b8ecf7b7bcdf42adff3e8c5082a4d67c3dd827e Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 15:23:02 +0100 Subject: [PATCH 60/68] [libcalamars] Improve test init and cleanup - Test createTargetFile and removeTargetFile - Clean up afterwards - Ensure /tmp is the RMP for each test --- src/libcalamares/utils/TestPaths.cpp | 45 +++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 4 deletions(-) diff --git a/src/libcalamares/utils/TestPaths.cpp b/src/libcalamares/utils/TestPaths.cpp index 7411dc5bb..5de8ae4fc 100644 --- a/src/libcalamares/utils/TestPaths.cpp +++ b/src/libcalamares/utils/TestPaths.cpp @@ -42,13 +42,20 @@ public: private Q_SLOTS: void initTestCase(); + void init(); + void cleanupTestCase(); void testTargetPath(); + void testCreateTarget(); private: - CalamaresUtils::System* m_system; // Points to singleton instance, not owned + CalamaresUtils::System* m_system = nullptr; // Points to singleton instance, not owned + Calamares::GlobalStorage* m_gs = nullptr; }; +static const char testFile[] = "/calamares-testcreate"; +static const char absFile[] = "/tmp/calamares-testcreate"; // With rootMountPoint prepended + void TestPaths::initTestCase() { @@ -62,14 +69,28 @@ TestPaths::initTestCase() // Ensure we have a system-wide GlobalStorage with /tmp as root if ( !Calamares::JobQueue::instance() ) { + cDebug() << "Creating new JobQueue"; (void)new Calamares::JobQueue(); } Calamares::GlobalStorage* gs = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; QVERIFY( gs ); - gs->insert( "rootMountPoint", "/tmp" ); m_system = system; + m_gs = gs; +} + +void +TestPaths::cleanupTestCase() +{ + QFile::remove( absFile ); +} + +void +TestPaths::init() +{ + cDebug() << "Setting rootMountPoint"; + m_gs->insert( "rootMountPoint", "/tmp" ); } @@ -78,17 +99,33 @@ TestPaths::testTargetPath() { // Paths mapped normally QCOMPARE( m_system->targetPath( "/etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); - QCOMPARE( m_system->targetPath( "//etc//calamares" ), QStringLiteral( "/tmp//etc//calamares" ) ); // extra / are not cleaned up + QCOMPARE( m_system->targetPath( "//etc//calamares" ), + QStringLiteral( "/tmp//etc//calamares" ) ); // extra / are not cleaned up QCOMPARE( m_system->targetPath( "etc/calamares" ), QStringLiteral( "/tmp/etc/calamares" ) ); // relative to root // Weird Paths QCOMPARE( m_system->targetPath( QString() ), QStringLiteral( "/tmp/" ) ); // Now break GS - Calamares::JobQueue::instance()->globalStorage()->remove( "rootMountPoint" ); + m_gs->remove( "rootMountPoint" ); QCOMPARE( m_system->targetPath( QString() ), QString() ); // Without root, no path } + +void +TestPaths::testCreateTarget() +{ + QCOMPARE( m_system->createTargetFile( testFile, "Hello" ), QString( absFile ) ); // Success + + QFileInfo fi( absFile ); + QVERIFY( fi.exists() ); + QCOMPARE( fi.size(), 5 ); + + m_system->removeTargetFile( testFile ); + QFileInfo fi2( absFile ); // fi caches information + QVERIFY( !fi2.exists() ); +} + QTEST_GUILESS_MAIN( TestPaths ) #include "utils/moc-warnings.h" From e65969d5871e79b4a4fdaf46eab3af4b0baba7b8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 15:51:46 +0100 Subject: [PATCH 61/68] [libcalamares] Re-do createTargetDirs() - Drop the basedirs idea, replace return with just bool - Use QDir::mkpath, with some extra validation - Test it a bit --- .../utils/CalamaresUtilsSystem.cpp | 24 ++++++++---- src/libcalamares/utils/CalamaresUtilsSystem.h | 12 +++--- src/libcalamares/utils/TestPaths.cpp | 37 +++++++++++++++++-- 3 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 0c21034af..7e6ef99d6 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -347,27 +347,35 @@ System::removeTargetFile( const QString& path ) const // If it was empty, a warning was already printed } -int -System::createTargetBasedirs( const QString& path ) const +bool +System::createTargetDirs( const QString& path ) const { if ( !isAbsolutePath( path ) ) { cWarning() << "Will not create basedirs for non-absolute path" << path; - return -1; + return false; } QString target = targetPath( path ); if ( target.isEmpty() ) { // If it was empty, a warning was already printed - return -1; + return false; } - QString base( "/" ); - QStringList parts = target.split( '/', QString::SplitBehavior::SkipEmptyParts ); + QString root = Calamares::JobQueue::instance()->globalStorage()->value( "rootMountPoint" ).toString(); + if ( root.isEmpty() ) + { + return false; + } - cDebug() << parts; - return -1; + QDir d( root ); + if ( !d.exists() ) + { + cWarning() << "Root mountpoint" << root << "does not exist."; + return false; + } + return d.mkpath( target ); // This re-does everything starting from the **host** / } diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index 09a606e2c..e95d5731e 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -257,14 +257,14 @@ public: /** @brief Ensure that the directories above @p path exist * - * @param path a full pathname to a desired file. + * @param path a full pathname to a desired directory. * - * All the directory components before the last path component are - * created, as needed, with 0755 permissions. Returns the number - * of components that needed to be created; 0 if they all already - * existed, and < 0 on failure. + * All the directory components including the last path component are + * created, as needed, with 0755 permissions. Returns true on success. + * + * @see QDir::mkpath */ - DLLEXPORT int createTargetBasedirs( const QString& path ) const; + DLLEXPORT bool createTargetDirs( const QString& path ) const; /** * @brief getTotalMemoryB returns the total main memory, in bytes. diff --git a/src/libcalamares/utils/TestPaths.cpp b/src/libcalamares/utils/TestPaths.cpp index 5de8ae4fc..36e8afe5e 100644 --- a/src/libcalamares/utils/TestPaths.cpp +++ b/src/libcalamares/utils/TestPaths.cpp @@ -25,13 +25,14 @@ #include "GlobalStorage.h" #include "JobQueue.h" -#include +#include +// #include #include -#include -#include -#include +// #include +// #include +// #include class TestPaths : public QObject { @@ -47,6 +48,7 @@ private Q_SLOTS: void testTargetPath(); void testCreateTarget(); + void testCreateTargetBasedirs(); private: CalamaresUtils::System* m_system = nullptr; // Points to singleton instance, not owned @@ -126,6 +128,33 @@ TestPaths::testCreateTarget() QVERIFY( !fi2.exists() ); } +struct DirRemover +{ + DirRemover( const QString& base, const QString& dir ) + : m_base( base ) + , m_dir( dir ) + { + } + ~DirRemover() { QDir( m_base ).rmpath( m_dir ); } + + bool exists() const { return QDir( m_base ).exists( m_dir ); } + + QString m_base, m_dir; +}; + +void +TestPaths::testCreateTargetBasedirs() +{ + { + DirRemover dirrm( "/tmp", "var/lib/dbus" ); + QVERIFY( m_system->createTargetDirs( "/" ) ); + QVERIFY( m_system->createTargetDirs( "/var/lib/dbus" ) ); + QVERIFY( QFile( "/tmp/var/lib/dbus" ).exists() ); + QVERIFY( dirrm.exists() ); + } + QVERIFY( !QFile( "/tmp/var/lib/dbus" ).exists() ); +} + QTEST_GUILESS_MAIN( TestPaths ) #include "utils/moc-warnings.h" From 6ede9f2c7ce40859275fead6882f49679932d7a8 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 16:08:38 +0100 Subject: [PATCH 62/68] [libcalamares] Test QFileInfo::dir() for completeness --- src/libcalamares/utils/TestPaths.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcalamares/utils/TestPaths.cpp b/src/libcalamares/utils/TestPaths.cpp index 36e8afe5e..2f9f4e657 100644 --- a/src/libcalamares/utils/TestPaths.cpp +++ b/src/libcalamares/utils/TestPaths.cpp @@ -153,6 +153,9 @@ TestPaths::testCreateTargetBasedirs() QVERIFY( dirrm.exists() ); } QVERIFY( !QFile( "/tmp/var/lib/dbus" ).exists() ); + + // QFileInfo.dir() behaves even when things don't exist + QCOMPARE( QFileInfo( "/tmp/var/lib/dbus/bogus" ).dir().path(), QStringLiteral( "/tmp/var/lib/dbus" ) ); } QTEST_GUILESS_MAIN( TestPaths ) From 240fe2a56481d59c2f4b92aa927f02900fee2f96 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 16:09:02 +0100 Subject: [PATCH 63/68] [libcalamares] Add convenience createTargetParentDirs() --- src/libcalamares/utils/CalamaresUtilsSystem.cpp | 6 ++++++ src/libcalamares/utils/CalamaresUtilsSystem.h | 11 +++++++++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 7e6ef99d6..61e05976a 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -378,6 +378,12 @@ System::createTargetDirs( const QString& path ) const return d.mkpath( target ); // This re-does everything starting from the **host** / } +bool +System::createTargetParentDirs( const QString& filePath ) const +{ + return createTargetDirs( QFileInfo( filePath ).dir().path() ); +} + QPair< quint64, float > System::getTotalMemoryB() const diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index e95d5731e..ca8e0d797 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -255,17 +255,24 @@ public: */ DLLEXPORT void removeTargetFile( const QString& path ) const; - /** @brief Ensure that the directories above @p path exist + /** @brief Ensure that the directory @p path exists * * @param path a full pathname to a desired directory. * * All the directory components including the last path component are - * created, as needed, with 0755 permissions. Returns true on success. + * created, as needed. Returns true on success. * * @see QDir::mkpath */ DLLEXPORT bool createTargetDirs( const QString& path ) const; + /** @brief Convenience to create parent directories of a file path. + * + * Creates all the parent directories until the last + * component of @p filePath . @see createTargetDirs() + */ + DLLEXPORT bool createTargetParentDirs( const QString& filePath ) const; + /** * @brief getTotalMemoryB returns the total main memory, in bytes. * From b62004aae9039b44fd9d2c8e6eb9d74f5c88d863 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 16:10:13 +0100 Subject: [PATCH 64/68] [machineid] Create the DBus data directory - before running dbus-uuidgen or linking to systemd's UUID, create /var/lib/dbus; some distro's don't create that beforehand. FIXES #1314 --- src/modules/machineid/MachineIdJob.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/modules/machineid/MachineIdJob.cpp b/src/modules/machineid/MachineIdJob.cpp index af3a68d90..fc535e356 100644 --- a/src/modules/machineid/MachineIdJob.cpp +++ b/src/modules/machineid/MachineIdJob.cpp @@ -68,7 +68,7 @@ MachineIdJob::exec() QString target_dbus_machineid_file = QStringLiteral( "/var/lib/dbus/machine-id" ); QString target_entropy_file = QStringLiteral( "/var/lib/urandom/random-seed" ); - const auto* system = CalamaresUtils::System::instance(); + const CalamaresUtils::System* system = CalamaresUtils::System::instance(); // Clear existing files if ( m_entropy ) @@ -106,6 +106,10 @@ MachineIdJob::exec() } if ( m_dbus ) { + if ( !system->createTargetParentDirs( target_dbus_machineid_file ) ) + { + cWarning() << "Could not create DBus data-directory."; + } if ( m_dbus_symlink && QFile::exists( root + target_systemd_machineid_file ) ) { auto r = MachineId::createDBusLink( root, target_dbus_machineid_file, target_systemd_machineid_file ); From 4cdcb48de6f0dd79264df56dbaf6ad961098931a Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 16:12:17 +0100 Subject: [PATCH 65/68] [machineid] Functionality moved to libcalamares --- src/modules/machineid/Tests.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/modules/machineid/Tests.cpp b/src/modules/machineid/Tests.cpp index 273645e22..87853af82 100644 --- a/src/modules/machineid/Tests.cpp +++ b/src/modules/machineid/Tests.cpp @@ -35,7 +35,6 @@ public: private Q_SLOTS: void initTestCase(); - void testRemoveFile(); void testCopyFile(); void testPoolSize(); @@ -84,11 +83,6 @@ MachineIdTests::testCopyFile() } } -void -MachineIdTests::testRemoveFile() -{ -} - void MachineIdTests::testPoolSize() { From 110a84344bd8e88a6da156c0323de26d057890cd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 20:29:42 +0100 Subject: [PATCH 66/68] [machineid] Test job function - Create a job and ask it to create dbus files -- either directly, or as a symlink. Since the target chroot isn't viable, this will fail but we can at least see that directories are created, etc. --- src/modules/machineid/CMakeLists.txt | 1 + src/modules/machineid/Tests.cpp | 63 +++++++++++++++++++++++++++- 2 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/modules/machineid/CMakeLists.txt b/src/modules/machineid/CMakeLists.txt index efb6454e8..a57d5163d 100644 --- a/src/modules/machineid/CMakeLists.txt +++ b/src/modules/machineid/CMakeLists.txt @@ -12,6 +12,7 @@ calamares_add_plugin( machineid if ( ECM_FOUND AND BUILD_TESTING ) ecm_add_test( Tests.cpp + MachineIdJob.cpp Workers.cpp TEST_NAME machineidtest diff --git a/src/modules/machineid/Tests.cpp b/src/modules/machineid/Tests.cpp index 87853af82..53abd0482 100644 --- a/src/modules/machineid/Tests.cpp +++ b/src/modules/machineid/Tests.cpp @@ -16,11 +16,14 @@ * along with Calamares. If not, see . */ +#include "MachineIdJob.h" #include "Workers.h" +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "utils/CalamaresUtilsSystem.h" #include "utils/Logger.h" - #include #include #include @@ -38,6 +41,8 @@ private Q_SLOTS: void testCopyFile(); void testPoolSize(); + + void testJob(); }; void @@ -95,6 +100,62 @@ MachineIdTests::testPoolSize() #endif } +void +MachineIdTests::testJob() +{ + Logger::setupLogLevel( Logger::LOGDEBUG ); + + // Ensure we have a system object, expect it to be a "bogus" one + CalamaresUtils::System* system = CalamaresUtils::System::instance(); + QVERIFY( system ); + QVERIFY( system->doChroot() ); + + // Ensure we have a system-wide GlobalStorage with /tmp as root + if ( !Calamares::JobQueue::instance() ) + { + cDebug() << "Creating new JobQueue"; + (void)new Calamares::JobQueue(); + } + Calamares::GlobalStorage* gs + = Calamares::JobQueue::instance() ? Calamares::JobQueue::instance()->globalStorage() : nullptr; + QVERIFY( gs ); + gs->insert( "rootMountPoint", "/tmp" ); + + // Prepare part of the target filesystem + QVERIFY( system->createTargetDirs("/etc") ); + QVERIFY( !(system->createTargetFile( "/etc/machine-id", "Hello" ).isEmpty() ) ); + + MachineIdJob job( nullptr ); + QVERIFY( !job.prettyName().isEmpty() ); + + QVariantMap config; + config.insert( "dbus", true ); + job.setConfigurationMap( config ); + + { + auto r = job.exec(); + QVERIFY( !r ); // It's supposed to fail, because no dbus-uuidgen executable exists + QVERIFY( QFile::exists( "/tmp/var/lib/dbus" ) ); // but the target dir exists + } + + config.insert( "dbus-symlink", true ); + job.setConfigurationMap( config ); + { + auto r = job.exec(); + QVERIFY( !r ); // It's supposed to fail, because no dbus-uuidgen executable exists + QVERIFY( QFile::exists( "/tmp/var/lib/dbus" ) ); // but the target dir exists + + // These all (would) fail, because the chroot isn't viable +#if 0 + QVERIFY( QFile::exists( "/tmp/var/lib/dbus/machine-id" ) ); + + QFileInfo fi( "/tmp/var/lib/dbus/machine-id" ); + QVERIFY( fi.exists() ); + QVERIFY( fi.isSymLink() ); + QCOMPARE( fi.size(), 5); +#endif + } +} QTEST_GUILESS_MAIN( MachineIdTests ) From 3e2908ea166e3726e1cdd5bd0e961413ab2f5f38 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 20:31:15 +0100 Subject: [PATCH 67/68] [machineid] Follow Manjaro flags - add -f to ln(1) flags --- src/modules/machineid/Workers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/machineid/Workers.cpp b/src/modules/machineid/Workers.cpp index f1f7bb369..39acdfbf2 100644 --- a/src/modules/machineid/Workers.cpp +++ b/src/modules/machineid/Workers.cpp @@ -181,7 +181,7 @@ Calamares::JobResult createDBusLink( const QString& rootMountPoint, const QString& fileName, const QString& systemdFileName ) { Q_UNUSED( rootMountPoint ) - return runCmd( QStringList { QStringLiteral( "ln" ), QStringLiteral( "-s" ), systemdFileName, fileName } ); + return runCmd( QStringList { QStringLiteral( "ln" ), QStringLiteral( "-sf" ), systemdFileName, fileName } ); } } // namespace MachineId From 229d09927e6cc5ae8129fb547ab53168b2d2ad78 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 7 Feb 2020 10:54:18 +0100 Subject: [PATCH 68/68] Changes: for 2020, new fake Linux distro name --- src/branding/default/branding.desc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/branding/default/branding.desc b/src/branding/default/branding.desc index f70715aea..af1d39ca4 100644 --- a/src/branding/default/branding.desc +++ b/src/branding/default/branding.desc @@ -69,11 +69,11 @@ windowPlacement: center strings: productName: "@{NAME}" shortProductName: Generic - version: 2017.8 LTS - shortVersion: 2017.8 - versionedName: Generic GNU/Linux 2017.8 LTS "Soapy Sousaphone" - shortVersionedName: Generic 2017.8 - bootloaderEntryName: Generic + version: 2020.2 LTS + shortVersion: 2020.2 + versionedName: Fancy GNU/Linux 2020.2 LTS "Turgid Tuba" + shortVersionedName: FancyGL 2020.2 + bootloaderEntryName: FancyGL productUrl: https://calamares.io/ supportUrl: https://github.com/calamares/calamares/issues knownIssuesUrl: https://calamares.io/about/