diff --git a/CMakeLists.txt b/CMakeLists.txt index 960f9a734..53e989975 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -114,6 +114,16 @@ find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED Core Gui Widgets LinguistTools S find_package( YAMLCPP 0.5.1 REQUIRED ) find_package( PolkitQt5-1 REQUIRED ) +# Find ECM once, and add it to the module search path; Calamares +# modules that need ECM can do +# find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE), +# no need to mess with the module path after. +set( ECM_VERSION 5.10.0 ) +find_package(ECM ${ECM_VERSION} NO_MODULE) +if( ECM_FOUND ) + set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) +endif() + option( INSTALL_CONFIG "Install configuration files" ON ) option( WITH_PYTHON "Enable Python modules API (requires Boost.Python)." ON ) option( WITH_PYTHONQT "Enable next generation Python modules API (experimental, requires PythonQt)." OFF ) diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 656a57c10..1f910230d 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -256,5 +256,10 @@ System::getTotalMemoryB() #endif } - +bool +System::doChroot() const +{ + return m_doChroot; } + +} // namespace diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.h b/src/libcalamares/utils/CalamaresUtilsSystem.h index 1ccdfb516..8eeff4ef9 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.h +++ b/src/libcalamares/utils/CalamaresUtilsSystem.h @@ -114,6 +114,8 @@ public: */ DLLEXPORT QPair getTotalMemoryB(); + DLLEXPORT bool doChroot() const; + private: static System* s_instance; diff --git a/src/modules/interactiveterminal/CMakeLists.txt b/src/modules/interactiveterminal/CMakeLists.txt index 7b35fae0d..71f6bae14 100644 --- a/src/modules/interactiveterminal/CMakeLists.txt +++ b/src/modules/interactiveterminal/CMakeLists.txt @@ -1,5 +1,4 @@ -find_package(ECM 5.10.0 REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) +find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE) include(KDEInstallDirs) include(GenerateExportHeader) diff --git a/src/modules/partition/CMakeLists.txt b/src/modules/partition/CMakeLists.txt index ee96c4275..c58eb1d69 100644 --- a/src/modules/partition/CMakeLists.txt +++ b/src/modules/partition/CMakeLists.txt @@ -1,5 +1,4 @@ -find_package(ECM 5.10.0 REQUIRED NO_MODULE) -set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) +find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE) include(KDEInstallDirs) include(GenerateExportHeader) diff --git a/src/modules/plasmalnf/CMakeLists.txt b/src/modules/plasmalnf/CMakeLists.txt new file mode 100644 index 000000000..8148a80e9 --- /dev/null +++ b/src/modules/plasmalnf/CMakeLists.txt @@ -0,0 +1,22 @@ +find_package(ECM ${ECM_VERSION} REQUIRED NO_MODULE) + +find_package( KF5 5.29 REQUIRED CoreAddons Plasma Package ) + +calamares_add_plugin( plasmalnf + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + PlasmaLnfViewStep.cpp + PlasmaLnfPage.cpp + PlasmaLnfJob.cpp + ThemeWidget.cpp + RESOURCES + page_plasmalnf.qrc + UI + page_plasmalnf.ui + LINK_PRIVATE_LIBRARIES + calamaresui + KF5::Package + KF5::Plasma + SHARED_LIB +) diff --git a/src/modules/plasmalnf/PlasmaLnfJob.cpp b/src/modules/plasmalnf/PlasmaLnfJob.cpp new file mode 100644 index 000000000..82d55f609 --- /dev/null +++ b/src/modules/plasmalnf/PlasmaLnfJob.cpp @@ -0,0 +1,78 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 "PlasmaLnfJob.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" + +PlasmaLnfJob::PlasmaLnfJob( const QString& lnfPath, const QString& id ) + : m_lnfPath( lnfPath ) + , m_id( id ) +{ +} + + +PlasmaLnfJob::~PlasmaLnfJob() +{ +} + + +QString +PlasmaLnfJob::prettyName() const +{ + return tr( "Plasma Look-and-Feel Job" ); +} + +QString +PlasmaLnfJob::prettyDescription() const +{ + return prettyName(); +} + +QString PlasmaLnfJob::prettyStatusMessage() const +{ + return prettyName(); +} + + +Calamares::JobResult +PlasmaLnfJob::exec() +{ + cDebug() << "Plasma Look-and-Feel Job"; + + auto system = CalamaresUtils::System::instance(); + Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); + + QStringList command( + { + "sudo", "-E", "-H", "-u", gs->value( "username" ).toString(), + m_lnfPath, "-platform", "minimal", "--resetLayout", "--apply", m_id + } ); + + int r = system->targetEnvCall( command ); + if ( r ) + return Calamares::JobResult::error( + tr( "Could not select KDE Plasma Look-and-Feel package" ), + tr( "Could not select KDE Plasma Look-and-Feel package" ) ); + + return Calamares::JobResult::ok(); +} + diff --git a/src/modules/plasmalnf/PlasmaLnfJob.h b/src/modules/plasmalnf/PlasmaLnfJob.h new file mode 100644 index 000000000..c7a7726ed --- /dev/null +++ b/src/modules/plasmalnf/PlasmaLnfJob.h @@ -0,0 +1,46 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 PLASMALNFJOB_H +#define PLASMALNFJOB_H + +#include +#include + +#include + +class PlasmaLnfJob : public Calamares::Job +{ + Q_OBJECT + +public: + explicit PlasmaLnfJob( const QString& lnfPath, const QString& id ); + virtual ~PlasmaLnfJob() override; + + QString prettyName() const override; + QString prettyDescription() const override; + QString prettyStatusMessage() const override; + + Calamares::JobResult exec() override; + +private: + QString m_lnfPath; + QString m_id; +}; + +#endif // PLASMALNFJOB_H diff --git a/src/modules/plasmalnf/PlasmaLnfPage.cpp b/src/modules/plasmalnf/PlasmaLnfPage.cpp new file mode 100644 index 000000000..2b171cc40 --- /dev/null +++ b/src/modules/plasmalnf/PlasmaLnfPage.cpp @@ -0,0 +1,167 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 "PlasmaLnfPage.h" + +#include "ui_page_plasmalnf.h" + +#include "utils/Logger.h" +#include "utils/Retranslator.h" + +#include +#include + +ThemeInfo::ThemeInfo( const KPluginMetaData& data ) + : id( data.pluginId() ) + , name( data.name() ) + , description( data.description() ) + , widget( nullptr ) +{ +} + +static ThemeInfoList plasma_themes() +{ + ThemeInfoList packages; + + QList pkgs = KPackage::PackageLoader::self()->listPackages( "Plasma/LookAndFeel" ); + + for ( const KPluginMetaData& data : pkgs ) + { + if ( data.isValid() && !data.isHidden() && !data.name().isEmpty() ) + { + packages << ThemeInfo{ data }; + } + } + + return packages; +} + + +PlasmaLnfPage::PlasmaLnfPage( QWidget* parent ) + : QWidget( parent ) + , ui( new Ui::PlasmaLnfPage ) + , m_buttonGroup( nullptr ) +{ + ui->setupUi( this ); + CALAMARES_RETRANSLATE( + { + ui->retranslateUi( this ); + ui->generalExplanation->setText( tr( "Please choose a look-and-feel for the KDE Plasma Desktop. You can also skip this step and configure the look-and-feel once the system is installed." ) ); + updateThemeNames(); + fillUi(); + } + ) +} + +void +PlasmaLnfPage::setLnfPath( const QString& path ) +{ + m_lnfPath = path; +} + +void +PlasmaLnfPage::setEnabledThemes(const ThemeInfoList& themes) +{ + m_enabledThemes = themes; + + updateThemeNames(); + winnowThemes(); + fillUi(); +} + +void +PlasmaLnfPage::setEnabledThemesAll() +{ + setEnabledThemes( plasma_themes() ); +} + + +void PlasmaLnfPage::updateThemeNames() +{ + auto plasmaThemes = plasma_themes(); + for ( auto& enabled_theme : m_enabledThemes ) + { + ThemeInfo* t = plasmaThemes.findById( enabled_theme.id ); + if ( t != nullptr ) + { + enabled_theme.name = t->name; + enabled_theme.description = t->description; + } + } +} + +void PlasmaLnfPage::winnowThemes() +{ + auto plasmaThemes = plasma_themes(); + bool winnowed = true; + int winnow_index = 0; + while ( winnowed ) + { + winnowed = false; + winnow_index = 0; + + for ( auto& enabled_theme : m_enabledThemes ) + { + ThemeInfo* t = plasmaThemes.findById( enabled_theme.id ); + if ( t == nullptr ) + { + cDebug() << "Removing" << enabled_theme.id; + winnowed = true; + break; + } + ++winnow_index; + } + + if ( winnowed ) + { + m_enabledThemes.removeAt( winnow_index ); + } + } +} + +void PlasmaLnfPage::fillUi() +{ + if ( m_enabledThemes.isEmpty() ) + { + return; + } + + if ( !m_buttonGroup ) + { + m_buttonGroup = new QButtonGroup( this ); + m_buttonGroup->setExclusive( true ); + } + + int c = 1; // After the general explanation + for ( auto& theme : m_enabledThemes ) + { + if ( !theme.widget ) + { + ThemeWidget* w = new ThemeWidget( theme ); + m_buttonGroup->addButton( w->button() ); + ui->verticalLayout->insertWidget( c, w ); + connect( w, &ThemeWidget::themeSelected, this, &PlasmaLnfPage::plasmaThemeSelected); + theme.widget = w; + } + else + { + theme.widget->updateThemeName( theme ); + } + ++c; + } +} diff --git a/src/modules/plasmalnf/PlasmaLnfPage.h b/src/modules/plasmalnf/PlasmaLnfPage.h new file mode 100644 index 000000000..e489e99a7 --- /dev/null +++ b/src/modules/plasmalnf/PlasmaLnfPage.h @@ -0,0 +1,73 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 PLASMALNFPAGE_H +#define PLASMALNFPAGE_H + +#include +#include +#include +#include +#include + +#include "ThemeInfo.h" +#include "ThemeWidget.h" + +namespace Ui +{ +class PlasmaLnfPage; +} + +/** @brief Page for selecting a Plasma Look-and-Feel theme. + * + * You must call setEnabledThemes -- either overload -- once + * to get the selection widgets. Note that calling that with + * an empty list will result in zero (0) selectable themes. + */ +class PlasmaLnfPage : public QWidget +{ + Q_OBJECT +public: + explicit PlasmaLnfPage( QWidget* parent = nullptr ); + + void setLnfPath( const QString& path ); + /** @brief enable only the listed themes. */ + void setEnabledThemes( const ThemeInfoList& themes ); + /** @brief enable all installed plasma themes. */ + void setEnabledThemesAll(); + +signals: + void plasmaThemeSelected( const QString& id ); + +private: + /** @brief Intersect the list of enabled themes with the installed ones. */ + void winnowThemes(); + /** @brief Get the translated names for all enabled themes. */ + void updateThemeNames(); + /** @brief show enabled themes in the UI. */ + void fillUi(); + + Ui::PlasmaLnfPage* ui; + QString m_lnfPath; + ThemeInfoList m_enabledThemes; + + QButtonGroup *m_buttonGroup; + QList< ThemeWidget* > m_widgets; +}; + +#endif //PLASMALNFPAGE_H diff --git a/src/modules/plasmalnf/PlasmaLnfViewStep.cpp b/src/modules/plasmalnf/PlasmaLnfViewStep.cpp new file mode 100644 index 000000000..db8529d56 --- /dev/null +++ b/src/modules/plasmalnf/PlasmaLnfViewStep.cpp @@ -0,0 +1,196 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 "PlasmaLnfViewStep.h" + +#include "PlasmaLnfJob.h" +#include "PlasmaLnfPage.h" +#include "ThemeInfo.h" + +#include "utils/Logger.h" + +#include +#include + +CALAMARES_PLUGIN_FACTORY_DEFINITION( PlasmaLnfViewStepFactory, registerPlugin(); ) + +PlasmaLnfViewStep::PlasmaLnfViewStep( QObject* parent ) + : Calamares::ViewStep( parent ) + , m_widget( new PlasmaLnfPage ) +{ + connect( m_widget, &PlasmaLnfPage::plasmaThemeSelected, this, &PlasmaLnfViewStep::themeSelected ); + emit nextStatusChanged( false ); +} + + +PlasmaLnfViewStep::~PlasmaLnfViewStep() +{ + if ( m_widget && m_widget->parent() == nullptr ) + m_widget->deleteLater(); +} + + +QString +PlasmaLnfViewStep::prettyName() const +{ + return tr( "Look-and-Feel" ); +} + + +QWidget* +PlasmaLnfViewStep::widget() +{ + return m_widget; +} + + +void +PlasmaLnfViewStep::next() +{ + emit done(); +} + + +void +PlasmaLnfViewStep::back() +{} + + +bool +PlasmaLnfViewStep::isNextEnabled() const +{ + return true; +} + + +bool +PlasmaLnfViewStep::isBackEnabled() const +{ + return true; +} + + +bool +PlasmaLnfViewStep::isAtBeginning() const +{ + return true; +} + + +bool +PlasmaLnfViewStep::isAtEnd() const +{ + return true; +} + + +void PlasmaLnfViewStep::onLeave() +{ +} + + +QList +PlasmaLnfViewStep::jobs() const +{ + QList l; + + cDebug() << "Creating Plasma LNF jobs .."; + if ( !m_themeId.isEmpty() ) + { + if ( !m_lnfPath.isEmpty() ) + l.append( Calamares::job_ptr( new PlasmaLnfJob( m_lnfPath, m_themeId ) ) ); + else + cDebug() << "WARNING: no lnftool given for plasmalnf module."; + } + return l; +} + + +void +PlasmaLnfViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ + QString lnfPath; + if ( configurationMap.contains( "lnftool" ) && configurationMap.value( "lnftool" ).type() == QVariant::String ) + lnfPath = configurationMap.value( "lnftool" ).toString(); + m_lnfPath = lnfPath; + m_widget->setLnfPath( m_lnfPath ); + + if ( m_lnfPath.isEmpty() ) + cDebug() << "WARNING: no lnftool given for plasmalnf module."; + + QString liveUser; + if ( configurationMap.contains( "liveuser" ) && configurationMap.value( "liveuser" ).type() == QVariant::String ) + liveUser = configurationMap.value( "liveuser" ).toString(); + m_liveUser = liveUser; + + if ( configurationMap.contains( "themes" ) && + configurationMap.value( "themes" ).type() == QVariant::List ) + { + ThemeInfoList allThemes; + auto themeList = configurationMap.value( "themes" ).toList(); + // Create the ThemInfo objects for the listed themes; information + // about the themes from Plasma (e.g. human-readable name and description) + // are filled in by update_names() in PlasmaLnfPage. + for ( const auto& i : themeList ) + if ( i.type() == QVariant::Map ) + { + auto iv = i.toMap(); + allThemes.append( ThemeInfo( iv.value( "theme" ).toString(), iv.value( "image" ).toString() ) ); + } + else if ( i.type() == QVariant::String ) + allThemes.append( ThemeInfo( i.toString() ) ); + + if ( allThemes.length() == 1 ) + cDebug() << "WARNING: only one theme enabled in plasmalnf"; + m_widget->setEnabledThemes( allThemes ); + } + else + m_widget->setEnabledThemesAll(); // All of them +} + +void +PlasmaLnfViewStep::themeSelected( const QString& id ) +{ + m_themeId = id; + if ( m_lnfPath.isEmpty() ) + { + cDebug() << "WARNING: no lnftool given for plasmalnf module."; + return; + } + + QProcess lnftool; + if ( !m_liveUser.isEmpty() ) + lnftool.start( "sudo", {"-E", "-H", "-u", m_liveUser, m_lnfPath, "--resetLayout", "--apply", id} ); + else + lnftool.start( m_lnfPath, {"--resetLayout", "--apply", id} ); + + if ( !lnftool.waitForStarted( 1000 ) ) + { + cDebug() << "WARNING: could not start look-and-feel" << m_lnfPath; + return; + } + if ( !lnftool.waitForFinished() ) + { + cDebug() << "WARNING:" << m_lnfPath << "timed out."; + return; + } + + if ( ( lnftool.exitCode() == 0 ) && ( lnftool.exitStatus() == QProcess::NormalExit ) ) + cDebug() << "Plasma look-and-feel applied" << id; + else + cDebug() << "WARNING: could not apply look-and-feel" << id; +} diff --git a/src/modules/plasmalnf/PlasmaLnfViewStep.h b/src/modules/plasmalnf/PlasmaLnfViewStep.h new file mode 100644 index 000000000..7fcfc50cc --- /dev/null +++ b/src/modules/plasmalnf/PlasmaLnfViewStep.h @@ -0,0 +1,71 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 PLASMALNFVIEWSTEP_H +#define PLASMALNFVIEWSTEP_H + +#include +#include +#include + +#include +#include +#include + +class PlasmaLnfPage; + +class PLUGINDLLEXPORT PlasmaLnfViewStep : public Calamares::ViewStep +{ + Q_OBJECT + +public: + explicit PlasmaLnfViewStep( QObject* parent = nullptr ); + virtual ~PlasmaLnfViewStep() override; + + QString prettyName() const override; + + QWidget* widget() override; + + void next() override; + void back() override; + + bool isNextEnabled() const override; + bool isBackEnabled() const override; + + bool isAtBeginning() const override; + bool isAtEnd() const override; + + void onLeave() override; + + QList jobs() const override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +public slots: + void themeSelected( const QString& id ); + +private: + PlasmaLnfPage* m_widget; + QString m_lnfPath; + QString m_themeId; + QString m_liveUser; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( PlasmaLnfViewStepFactory ) + +#endif // PLASMALNFVIEWSTEP_H diff --git a/src/modules/plasmalnf/ThemeInfo.h b/src/modules/plasmalnf/ThemeInfo.h new file mode 100644 index 000000000..b186b9be1 --- /dev/null +++ b/src/modules/plasmalnf/ThemeInfo.h @@ -0,0 +1,97 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 PLASMALNF_THEMEINFO_H +#define PLASMALNF_THEMEINFO_H + +#include +#include + +class KPluginMetaData; +class ThemeWidget; + +/** @brief describes a single plasma LnF theme. + * + * A theme description has an id, which is really the name of the desktop + * file (e.g. org.kde.breeze.desktop), a name which is human-readable and + * translated, and an optional image Page, which points to a local screenshot + * of that theme. + */ +struct ThemeInfo +{ + QString id; + QString name; + QString description; + QString imagePath; + ThemeWidget* widget; + + ThemeInfo() + : widget( nullptr ) + {} + + explicit ThemeInfo( const QString& _id ) + : id( _id ) + , widget( nullptr ) + { + } + + explicit ThemeInfo( const QString& _id, const QString& image ) + : id( _id ) + , imagePath( image ) + , widget( nullptr ) + {} + + // Defined in PlasmaLnfPage.cpp + explicit ThemeInfo( const KPluginMetaData& ); + + bool isValid() const { return !id.isEmpty(); } +} ; + +class ThemeInfoList : public QList< ThemeInfo > +{ +public: + /** @brief Looks for a given @p id in the list of themes, returns nullptr if not found. */ + ThemeInfo* findById( const QString& id ) + { + for ( ThemeInfo& i : *this ) + { + if ( i.id == id ) + return &i; + } + return nullptr; + } + + /** @brief Looks for a given @p id in the list of themes, returns nullptr if not found. */ + const ThemeInfo* findById( const QString& id ) const + { + for ( const ThemeInfo& i : *this ) + { + if ( i.id == id ) + return &i; + } + return nullptr; + } + + /** @brief Checks if a given @p id is in the list of themes. */ + bool contains( const QString& id ) const + { + return findById( id ) != nullptr; + } +} ; + +#endif diff --git a/src/modules/plasmalnf/ThemeWidget.cpp b/src/modules/plasmalnf/ThemeWidget.cpp new file mode 100644 index 000000000..28e01c2ff --- /dev/null +++ b/src/modules/plasmalnf/ThemeWidget.cpp @@ -0,0 +1,85 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 "ThemeWidget.h" + +#include "ThemeInfo.h" + +#include "utils/Logger.h" + +#include +#include +#include + +ThemeWidget::ThemeWidget(const ThemeInfo& info, QWidget* parent) + : QWidget( parent ) + , m_check( new QRadioButton( info.name.isEmpty() ? info.id : info.name, parent ) ) + , m_description( new QLabel( info.description, parent ) ) + , m_id( info.id ) +{ + QHBoxLayout* layout = new QHBoxLayout( this ); + this->setLayout( layout ); + + layout->addWidget( m_check, 1 ); + + constexpr QSize image_size{120, 80}; + + QPixmap image( info.imagePath ); + if ( info.imagePath.isEmpty() ) + { + // Image can't possibly be valid + image = QPixmap( ":/view-preview.png" ); + } + else if ( image.isNull() ) + { + // Not found or not specified, so convert the name into some (horrible, likely) + // color instead. + image = QPixmap( image_size ); + uint hash_color = qHash( info.imagePath.isEmpty() ? info.id : info.imagePath ); + cDebug() << "Theme image" << info.imagePath << "not found, hash" << hash_color; + image.fill( QColor( QRgb( hash_color ) ) ); + } + else + image.scaled( image_size ); + + QLabel* image_label = new QLabel( this ); + image_label->setPixmap( image ); + layout->addWidget( image_label, 1 ); + layout->addWidget( m_description, 3 ); + + connect( m_check, &QRadioButton::clicked, this, &ThemeWidget::clicked ); +} + +void +ThemeWidget::clicked( bool checked ) +{ + if ( checked ) + emit themeSelected( m_id ); +} + +QAbstractButton* +ThemeWidget::button() const +{ + return m_check; +} + +void ThemeWidget::updateThemeName(const ThemeInfo& info) +{ + m_check->setText( info.name ); + m_description->setText( info.description ); +} diff --git a/src/modules/plasmalnf/ThemeWidget.h b/src/modules/plasmalnf/ThemeWidget.h new file mode 100644 index 000000000..a6716ce72 --- /dev/null +++ b/src/modules/plasmalnf/ThemeWidget.h @@ -0,0 +1,53 @@ +/* === This file is part of Calamares - === + * + * Copyright 2017, 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 PLASMALNF_THEMEWIDGET_H +#define PLASMALNF_THEMEWIDGET_H + +#include + +class QAbstractButton; +class QLabel; +class QRadioButton; + +struct ThemeInfo; + +class ThemeWidget : public QWidget +{ + Q_OBJECT +public: + explicit ThemeWidget( const ThemeInfo& info, QWidget* parent = nullptr ); + + QAbstractButton* button() const; + + void updateThemeName( const ThemeInfo& info ); + +signals: + void themeSelected( const QString& id ); + +public slots: + void clicked( bool ); + +private: + QString m_id; + QRadioButton* m_check; + QLabel* m_description; +} ; + +#endif + diff --git a/src/modules/plasmalnf/page_plasmalnf.qrc b/src/modules/plasmalnf/page_plasmalnf.qrc new file mode 100644 index 000000000..c63ecc03b --- /dev/null +++ b/src/modules/plasmalnf/page_plasmalnf.qrc @@ -0,0 +1,5 @@ + + + view-preview.png + + diff --git a/src/modules/plasmalnf/page_plasmalnf.ui b/src/modules/plasmalnf/page_plasmalnf.ui new file mode 100644 index 000000000..6da6647fd --- /dev/null +++ b/src/modules/plasmalnf/page_plasmalnf.ui @@ -0,0 +1,46 @@ + + + PlasmaLnfPage + + + + 0 + 0 + 799 + 400 + + + + Form + + + + + + Placeholder + + + true + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + diff --git a/src/modules/plasmalnf/plasmalnf.conf b/src/modules/plasmalnf/plasmalnf.conf new file mode 100644 index 000000000..aa9865117 --- /dev/null +++ b/src/modules/plasmalnf/plasmalnf.conf @@ -0,0 +1,29 @@ +--- +# Full path to the Plasma look-and-feel tool (CLI program +# for querying and applying Plasma themes). If this is not +# set, no LNF setting will happen. +lnftool: "/usr/bin/lookandfeeltool" + +# For systems where the user Calamares runs as (usually root, +# via either sudo or pkexec) has a clean environment, set this +# to the originating username; the lnftool will be run through +# "sudo -H -u " instead of directly. +# +# liveuser: "live" + +# You can limit the list of Plasma look-and-feel themes by listing ids +# here. If this key is not present, all of the installed themes are listed. +# If the key is present, only installed themes that are *also* included +# in the list are shown (could be none!). +# +# Themes may be listed by id, (e.g. fluffy-bunny, below) or as a theme +# and an image (e.g. breeze) which will be used to show a screenshot. +# Themes with no image get a "missing screenshot" image; if the +# image file is not found, they get a color swatch based on the image name. +themes: + - org.kde.fuzzy-pig.desktop + - theme: org.kde.breeze.desktop + image: "breeze.png" + - theme: org.kde.breezedark.desktop + image: "breeze-dark.png" + - org.kde.fluffy-bunny.desktop diff --git a/src/modules/plasmalnf/view-preview.png b/src/modules/plasmalnf/view-preview.png new file mode 100644 index 000000000..8e5f07ba9 Binary files /dev/null and b/src/modules/plasmalnf/view-preview.png differ diff --git a/src/modules/plasmalnf/view-preview.svg b/src/modules/plasmalnf/view-preview.svg new file mode 100644 index 000000000..90e5beec5 --- /dev/null +++ b/src/modules/plasmalnf/view-preview.svg @@ -0,0 +1,13 @@ + + + + + + diff --git a/src/modules/users/CMakeLists.txt b/src/modules/users/CMakeLists.txt index 074118d54..ebff9df8c 100644 --- a/src/modules/users/CMakeLists.txt +++ b/src/modules/users/CMakeLists.txt @@ -1,6 +1,5 @@ -find_package(ECM 5.10.0 NO_MODULE) +find_package(ECM ${ECM_VERSION} NO_MODULE) if( ECM_FOUND ) - set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) include( ECMAddTests ) endif() diff --git a/src/modules/welcome/checker/RequirementsChecker.cpp b/src/modules/welcome/checker/RequirementsChecker.cpp index 3d4e394c4..e56e88a4c 100644 --- a/src/modules/welcome/checker/RequirementsChecker.cpp +++ b/src/modules/welcome/checker/RequirementsChecker.cpp @@ -213,12 +213,16 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) bool ok = false; m_requiredStorageGB = configurationMap.value( "requiredStorage" ).toDouble( &ok ); if ( !ok ) + { + cDebug() << "WARNING: RequirementsChecker entry 'requiredStorage' is invalid."; m_requiredStorageGB = 3.; + } Calamares::JobQueue::instance()->globalStorage()->insert( "requiredStorageGB", m_requiredStorageGB ); } else { + cDebug() << "WARNING: RequirementsChecker entry 'requiredStorage' is missing."; m_requiredStorageGB = 3.; incompleteConfiguration = true; } @@ -231,12 +235,14 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) m_requiredRamGB = configurationMap.value( "requiredRam" ).toDouble( &ok ); if ( !ok ) { + cDebug() << "WARNING: RequirementsChecker entry 'requiredRam' is invalid."; m_requiredRamGB = 1.; incompleteConfiguration = true; } } else { + cDebug() << "WARNING: RequirementsChecker entry 'requiredRam' is missing."; m_requiredRamGB = 1.; incompleteConfiguration = true; } @@ -248,7 +254,7 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) if ( m_checkHasInternetUrl.isEmpty() || !QUrl( m_checkHasInternetUrl ).isValid() ) { - cDebug() << "Invalid internetCheckUrl in welcome.conf" << m_checkHasInternetUrl + cDebug() << "WARNING: RequirementsChecker entry 'internetCheckUrl' is invalid in welcome.conf" << m_checkHasInternetUrl << "reverting to default (http://example.com)."; m_checkHasInternetUrl = "http://example.com"; incompleteConfiguration = true; @@ -256,8 +262,9 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) } else { - cDebug() << "internetCheckUrl is undefined in welcome.conf, " + cDebug() << "WARNING: RequirementsChecker entry 'internetCheckUrl' is undefined in welcome.conf," "reverting to default (http://example.com)."; + m_checkHasInternetUrl = "http://example.com"; incompleteConfiguration = true; } @@ -269,7 +276,10 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) m_entriesToCheck.append( configurationMap.value( "check" ).toStringList() ); } else + { + cDebug() << "WARNING: RequirementsChecker entry 'check' is incomplete."; incompleteConfiguration = true; + } if ( configurationMap.contains( "required" ) && configurationMap.value( "required" ).type() == QVariant::List ) @@ -278,18 +288,13 @@ RequirementsChecker::setConfigurationMap( const QVariantMap& configurationMap ) m_entriesToRequire.append( configurationMap.value( "required" ).toStringList() ); } else + { + cDebug() << "WARNING: RequirementsChecker entry 'required' is incomplete."; incompleteConfiguration = true; + } if ( incompleteConfiguration ) - { - cDebug() << "WARNING: The RequirementsChecker configuration map provided by " - "the welcome module configuration file is incomplete or " - "incorrect.\n" - "Startup will continue for debugging purposes, but one or " - "more checks might not function correctly.\n" - "RequirementsChecker configuration map:\n" - << configurationMap; - } + cDebug() << "WARNING: RequirementsChecker configuration map:\n" << configurationMap; }