From 735d5d2683454cc84cd77f57f0f92e7f517f9e6b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 10:57:12 +0200 Subject: [PATCH 01/44] [packagechooser] Add stub of module Package chooser is a **low density** package selector -- unlike netinstall which offers a high density tree view -- for picking zero, one, or more items from a small collection of packages. This can be used, e.g., for "pick exactly one desktop environment", "pick zero or more text editors" which can then be installed by another module. The UI is big and shiny (rather than netinstall's text-based tree view) and isn't suitable for more than a dozen or so items. --- src/modules/packagechooser/CMakeLists.txt | 27 +++++ .../packagechooser/PackageChooserPage.cpp | 33 +++++ .../packagechooser/PackageChooserPage.h | 39 ++++++ .../packagechooser/PackageChooserViewStep.cpp | 113 ++++++++++++++++++ .../packagechooser/PackageChooserViewStep.h | 60 ++++++++++ src/modules/packagechooser/Tests.cpp | 38 ++++++ src/modules/packagechooser/Tests.h | 36 ++++++ src/modules/packagechooser/page_package.ui | 59 +++++++++ 8 files changed, 405 insertions(+) create mode 100644 src/modules/packagechooser/CMakeLists.txt create mode 100644 src/modules/packagechooser/PackageChooserPage.cpp create mode 100644 src/modules/packagechooser/PackageChooserPage.h create mode 100644 src/modules/packagechooser/PackageChooserViewStep.cpp create mode 100644 src/modules/packagechooser/PackageChooserViewStep.h create mode 100644 src/modules/packagechooser/Tests.cpp create mode 100644 src/modules/packagechooser/Tests.h create mode 100644 src/modules/packagechooser/page_package.ui diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt new file mode 100644 index 000000000..0c739012a --- /dev/null +++ b/src/modules/packagechooser/CMakeLists.txt @@ -0,0 +1,27 @@ +find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) + +calamares_add_plugin( packagechooser + TYPE viewmodule + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + PackageChooserPage.cpp + PackageChooserViewStep.cpp + UI + page_package.ui + LINK_PRIVATE_LIBRARIES + calamaresui + SHARED_LIB +) + +if( ECM_FOUND AND BUILD_TESTING ) + ecm_add_test( + Tests.cpp + TEST_NAME + packagechooosertest + LINK_LIBRARIES + ${CALAMARES_LIBRARIES} + Qt5::Core + Qt5::Test + ) + calamares_automoc( packagechooosertest) +endif() diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp new file mode 100644 index 000000000..2f83e6728 --- /dev/null +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -0,0 +1,33 @@ +/* === 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 "PackageChooserPage.h" + +#include "ui_page_package.h" + +#include "utils/Logger.h" +#include "utils/Retranslator.h" + +#include + +PackageChooserPage::PackageChooserPage( QWidget* parent ) + : QWidget( parent ) + , ui( new Ui::PackageChooserPage ) +{ + ui->setupUi( this ); +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h new file mode 100644 index 000000000..1bc46bef3 --- /dev/null +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -0,0 +1,39 @@ +/* === 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 PACKAGECHOOSERPAGE_H +#define PACKAGECHOOSERPAGE_H + +#include + +namespace Ui +{ +class PackageChooserPage; +} + +class PackageChooserPage : public QWidget +{ + Q_OBJECT +public: + explicit PackageChooserPage( QWidget* parent = nullptr ); + +private: + Ui::PackageChooserPage* ui; +}; + +#endif // PACKAGECHOOSERPAGE_H diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp new file mode 100644 index 000000000..db45bea0b --- /dev/null +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -0,0 +1,113 @@ +/* === 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 "PackageChooserViewStep.h" + +#include "PackageChooserPage.h" + +#include "GlobalStorage.h" +#include "JobQueue.h" + +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" +#include "utils/Variant.h" + +#include +#include + +CALAMARES_PLUGIN_FACTORY_DEFINITION( PackageChooserViewStepFactory, registerPlugin< PackageChooserViewStep >(); ) + +PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) + : Calamares::ViewStep( parent ) + , m_widget( nullptr ) +{ + emit nextStatusChanged( false ); +} + + +PackageChooserViewStep::~PackageChooserViewStep() +{ + if ( m_widget && m_widget->parent() == nullptr ) + { + m_widget->deleteLater(); + } +} + + +QString +PackageChooserViewStep::prettyName() const +{ + return tr( "Packages" ); +} + + +QWidget* +PackageChooserViewStep::widget() +{ + if ( !m_widget ) + { + m_widget = new PackageChooserPage( nullptr ); + } + return m_widget; +} + + +bool +PackageChooserViewStep::isNextEnabled() const +{ + return true; +} + + +bool +PackageChooserViewStep::isBackEnabled() const +{ + return true; +} + + +bool +PackageChooserViewStep::isAtBeginning() const +{ + return true; +} + + +bool +PackageChooserViewStep::isAtEnd() const +{ + return true; +} + + +void +PackageChooserViewStep::onLeave() +{ +} + +Calamares::JobList +PackageChooserViewStep::jobs() const +{ + Calamares::JobList l; + return l; +} + +void +PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) +{ +} diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h new file mode 100644 index 000000000..a32d4caab --- /dev/null +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -0,0 +1,60 @@ +/* === 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 PACKAGECHOOSERVIEWSTEP_H +#define PACKAGECHOOSERVIEWSTEP_H + +#include +#include +#include + +#include +#include +#include + +class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep +{ + Q_OBJECT + +public: + explicit PackageChooserViewStep( QObject* parent = nullptr ); + virtual ~PackageChooserViewStep() override; + + QString prettyName() const override; + + QWidget* widget() override; + + bool isNextEnabled() const override; + bool isBackEnabled() const override; + + bool isAtBeginning() const override; + bool isAtEnd() const override; + + void onLeave() override; + + Calamares::JobList jobs() const override; + + void setConfigurationMap( const QVariantMap& configurationMap ) override; + +private: + QWidget* m_widget; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) + +#endif // PACKAGECHOOSERVIEWSTEP_H diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp new file mode 100644 index 000000000..c016f1808 --- /dev/null +++ b/src/modules/packagechooser/Tests.cpp @@ -0,0 +1,38 @@ +/* === 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 "Tests.h" + +#include + +QTEST_GUILESS_MAIN( PackageChooserTests ) + +PackageChooserTests::PackageChooserTests() {} + +PackageChooserTests::~PackageChooserTests() {} + +void +PackageChooserTests::initTestCase() +{ +} + +void +PackageChooserTests::testBogus() +{ + QVERIFY( true ); +} diff --git a/src/modules/packagechooser/Tests.h b/src/modules/packagechooser/Tests.h new file mode 100644 index 000000000..bc257f5a5 --- /dev/null +++ b/src/modules/packagechooser/Tests.h @@ -0,0 +1,36 @@ +/* === 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 PACKAGECHOOSERTESTS_H +#define PACKAGECHOOSERTESTS_H + +#include + +class PackageChooserTests : public QObject +{ + Q_OBJECT +public: + PackageChooserTests(); + ~PackageChooserTests() override; + +private Q_SLOTS: + void initTestCase(); + void testBogus(); +}; + +#endif diff --git a/src/modules/packagechooser/page_package.ui b/src/modules/packagechooser/page_package.ui new file mode 100644 index 000000000..18c2f81fd --- /dev/null +++ b/src/modules/packagechooser/page_package.ui @@ -0,0 +1,59 @@ + + + PackageChooserPage + + + + 0 + 0 + 400 + 300 + + + + Form + + + + + 9 + 19 + 341 + 261 + + + + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + + + From 727290f75e9286e6819122295f5955c117f8406b Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 11:09:12 +0200 Subject: [PATCH 02/44] [packagechooser] Handle translation events (stub) --- src/modules/packagechooser/PackageChooserPage.cpp | 11 +++++++++++ src/modules/packagechooser/PackageChooserPage.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 2f83e6728..5524bd103 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -30,4 +30,15 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) , ui( new Ui::PackageChooserPage ) { ui->setupUi( this ); + CALAMARES_RETRANSLATE( + updateLabels(); + ) +} + +void +PackageChooserPage::updateLabels() +{ + ui->productName->setText( QString() ); + ui->productScreenshot->hide(); + ui->productDescription->setText( tr( "Please pick a product from the list." ) ); } diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 1bc46bef3..02c46fc3e 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -32,6 +32,9 @@ class PackageChooserPage : public QWidget public: explicit PackageChooserPage( QWidget* parent = nullptr ); +public slots: + void updateLabels(); + private: Ui::PackageChooserPage* ui; }; From d1a85ba5ca5f333e1564d3a5f7a8e29127ccf8ff Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 13:05:46 +0200 Subject: [PATCH 03/44] [packagechooser] Add a model for the list to use - Model contents currently hard-coded --- src/modules/packagechooser/CMakeLists.txt | 1 + .../packagechooser/PackageChooserPage.cpp | 18 +++- .../packagechooser/PackageChooserPage.h | 4 + .../packagechooser/PackageChooserViewStep.cpp | 35 +++++++ .../packagechooser/PackageChooserViewStep.h | 14 ++- src/modules/packagechooser/PackageModel.cpp | 93 +++++++++++++++++++ src/modules/packagechooser/PackageModel.h | 62 +++++++++++++ 7 files changed, 220 insertions(+), 7 deletions(-) create mode 100644 src/modules/packagechooser/PackageModel.cpp create mode 100644 src/modules/packagechooser/PackageModel.h diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 0c739012a..525921602 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -6,6 +6,7 @@ calamares_add_plugin( packagechooser SOURCES PackageChooserPage.cpp PackageChooserViewStep.cpp + PackageModel.cpp UI page_package.ui LINK_PRIVATE_LIBRARIES diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 5524bd103..215adeeef 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -30,9 +30,7 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) , ui( new Ui::PackageChooserPage ) { ui->setupUi( this ); - CALAMARES_RETRANSLATE( - updateLabels(); - ) + CALAMARES_RETRANSLATE( updateLabels(); ) } void @@ -42,3 +40,17 @@ PackageChooserPage::updateLabels() ui->productScreenshot->hide(); ui->productDescription->setText( tr( "Please pick a product from the list." ) ); } + +void +PackageChooserPage::setModel( QAbstractItemModel* model ) +{ + ui->products->setModel( model ); +} + +void +PackageChooserPage::currentChanged( const QModelIndex& current ) +{ + updateLabels(); + cDebug() << "Current updated to" << current.row(); + cDebug() << ui->products->model()->data( current, Qt::DisplayRole ); +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 02c46fc3e..db5540312 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -19,6 +19,7 @@ #ifndef PACKAGECHOOSERPAGE_H #define PACKAGECHOOSERPAGE_H +#include #include namespace Ui @@ -32,8 +33,11 @@ class PackageChooserPage : public QWidget public: explicit PackageChooserPage( QWidget* parent = nullptr ); + void setModel( QAbstractItemModel* model ); + public slots: void updateLabels(); + void currentChanged( const QModelIndex& current ); private: Ui::PackageChooserPage* ui; diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index db45bea0b..3ff2ac636 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -19,6 +19,7 @@ #include "PackageChooserViewStep.h" #include "PackageChooserPage.h" +#include "PackageModel.h" #include "GlobalStorage.h" #include "JobQueue.h" @@ -35,6 +36,7 @@ CALAMARES_PLUGIN_FACTORY_DEFINITION( PackageChooserViewStepFactory, registerPlug PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) + , m_model( nullptr ) { emit nextStatusChanged( false ); } @@ -46,6 +48,7 @@ PackageChooserViewStep::~PackageChooserViewStep() { m_widget->deleteLater(); } + delete m_model; } @@ -62,6 +65,10 @@ PackageChooserViewStep::widget() if ( !m_widget ) { m_widget = new PackageChooserPage( nullptr ); + if ( m_model ) + { + hookupModel(); + } } return m_widget; } @@ -110,4 +117,32 @@ PackageChooserViewStep::jobs() const void PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { + // TODO: use the configurationMap + + if ( !m_model ) + { + + m_model = new PackageListModel( nullptr ); + m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop" } ); + m_model->addPackage( + PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop" } ); + + + if ( m_widget ) + { + hookupModel(); + } + } +} + +void +PackageChooserViewStep::hookupModel() +{ + if ( !m_model || !m_widget ) + { + cError() << "Can't hook up model until widget and model both exist."; + return; + } + + m_widget->setModel( m_model ); } diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index a32d4caab..56fbf5d3a 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -19,14 +19,17 @@ #ifndef PACKAGECHOOSERVIEWSTEP_H #define PACKAGECHOOSERVIEWSTEP_H -#include -#include -#include +#include "PluginDllMacro.h" +#include "utils/PluginFactory.h" +#include "viewpages/ViewStep.h" #include #include #include +class PackageChooserPage; +class PackageListModel; + class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep { Q_OBJECT @@ -52,7 +55,10 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: - QWidget* m_widget; + void hookupModel(); + + PackageChooserPage* m_widget; + PackageListModel* m_model; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp new file mode 100644 index 000000000..1f6346666 --- /dev/null +++ b/src/modules/packagechooser/PackageModel.cpp @@ -0,0 +1,93 @@ +/* === 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 "PackageModel.h" + +#include "utils/Logger.h" + +PackageItem +PackageItem::fromAppStream( const QString& filename ) +{ + // TODO: implement this + return PackageItem {}; +} + +PackageItem::PackageItem() {} + +PackageItem::PackageItem( const QString& a_id, + const QString& a_package, + const QString& a_name, + const QString& a_description ) + : id( a_id ) + , package( a_package ) + , name( a_name ) + , description( a_description ) +{ +} + + +PackageListModel::PackageListModel( QObject* parent ) + : QAbstractListModel( parent ) +{ +} + +PackageListModel::PackageListModel( PackageList&& items, QObject* parent ) + : QAbstractListModel( parent ) + , m_packages( std::move( items ) ) +{ +} + +PackageListModel::~PackageListModel() {} + +void +PackageListModel::addPackage( PackageItem&& p ) +{ + int c = m_packages.count(); + beginInsertRows( QModelIndex(), c, c ); + m_packages.append( p ); + endInsertRows(); +} + +int +PackageListModel::rowCount( const QModelIndex& index ) const +{ + // For lists, valid indexes have zero children; only the root index has them + return index.isValid() ? 0 : m_packages.count(); +} + +QVariant +PackageListModel::data( const QModelIndex& index, int role ) const +{ + cDebug() << "Data" << m_packages.count() << index.isValid() << ( index.isValid() ? index.row() : -1 ); + if ( !index.isValid() ) + { + return QVariant(); + } + int row = index.row(); + if ( row >= m_packages.count() || row < 0 ) + { + return QVariant(); + } + + if ( role == Qt::DisplayRole ) + { + return m_packages[ row ].name; + } + + return QVariant(); +} diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h new file mode 100644 index 000000000..c00e55c0a --- /dev/null +++ b/src/modules/packagechooser/PackageModel.h @@ -0,0 +1,62 @@ +/* === 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 PACKAGEMODEL_H +#define PACKAGEMODEL_H + +#include +#include +#include + +struct PackageItem +{ + QString id; + // TODO: may need more than one + QString package; + // TODO: name and description are localized + QString name; + QString description; + // TODO: may be more than one + // QPixmap screenshot; + + PackageItem(); + PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + + // TODO: implement this + PackageItem fromAppStream( const QString& filename ); +}; + +using PackageList = QVector< PackageItem >; + +class PackageListModel : public QAbstractListModel +{ +public: + PackageListModel( PackageList&& items, QObject* parent ); + PackageListModel( QObject* parent ); + virtual ~PackageListModel(); + + void addPackage( PackageItem&& p ); + + int rowCount( const QModelIndex& index ) const override; + QVariant data( const QModelIndex& index, int role ) const override; + +private: + PackageList m_packages; +}; + +#endif From f8d159dfa49dbd820ed3a3945e0d46da4e953a61 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 15:32:14 +0200 Subject: [PATCH 04/44] [packagechooser] Massage layout a bit --- src/modules/packagechooser/page_package.ui | 91 ++++++++++++---------- 1 file changed, 49 insertions(+), 42 deletions(-) diff --git a/src/modules/packagechooser/page_package.ui b/src/modules/packagechooser/page_package.ui index 18c2f81fd..1ba032ed2 100644 --- a/src/modules/packagechooser/page_package.ui +++ b/src/modules/packagechooser/page_package.ui @@ -1,58 +1,65 @@ PackageChooserPage - + 0 0 400 - 300 + 500 + + + 0 + 1 + + Form - - - - 9 - 19 - 341 - 261 - - - - - - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - TextLabel - - - - - - - + + + + + + + + 0 + 1 + + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + From dc5cdbb38cad5206b03893beba169506529f507c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:07:47 +0200 Subject: [PATCH 05/44] [packagechooser] Update other parts of the window on selection --- .../packagechooser/PackageChooserPage.cpp | 42 ++++++++++++++----- .../packagechooser/PackageChooserPage.h | 5 ++- src/modules/packagechooser/PackageModel.cpp | 1 - src/modules/packagechooser/PackageModel.h | 9 +++- 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 215adeeef..a474e7536 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -28,29 +28,51 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) : QWidget( parent ) , ui( new Ui::PackageChooserPage ) + , m_introduction( QString(), + QString(), + tr( "Package Selection" ), + tr( "Please pick a product from the list. The selected product will be installed." ) ) { ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) } void -PackageChooserPage::updateLabels() +PackageChooserPage::currentChanged( const QModelIndex& index ) { - ui->productName->setText( QString() ); - ui->productScreenshot->hide(); - ui->productDescription->setText( tr( "Please pick a product from the list." ) ); + if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() ) + { + ui->productName->setText( m_introduction.name ); + ui->productScreenshot->setPixmap( m_introduction.screenshot ); + ui->productDescription->setText( m_introduction.description ); + } + else + { + ui->productName->setText( QString::number( index.row() ) ); + ui->productScreenshot->hide(); + ui->productDescription->setText( "derp" ); + } } void -PackageChooserPage::setModel( QAbstractItemModel* model ) +PackageChooserPage::updateLabels() { - ui->products->setModel( model ); + if ( ui && ui->products && ui->products->selectionModel() ) + { + currentChanged( ui->products->selectionModel()->currentIndex() ); + } + else + { + currentChanged( QModelIndex() ); + } } void -PackageChooserPage::currentChanged( const QModelIndex& current ) +PackageChooserPage::setModel( QAbstractItemModel* model ) { - updateLabels(); - cDebug() << "Current updated to" << current.row(); - cDebug() << ui->products->model()->data( current, Qt::DisplayRole ); + ui->products->setModel( model ); + connect( ui->products->selectionModel(), + &QItemSelectionModel::selectionChanged, + this, + &PackageChooserPage::updateLabels ); } diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index db5540312..031abad69 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -19,6 +19,8 @@ #ifndef PACKAGECHOOSERPAGE_H #define PACKAGECHOOSERPAGE_H +#include "PackageModel.h" + #include #include @@ -36,11 +38,12 @@ public: void setModel( QAbstractItemModel* model ); public slots: + void currentChanged( const QModelIndex& index ); void updateLabels(); - void currentChanged( const QModelIndex& current ); private: Ui::PackageChooserPage* ui; + PackageItem m_introduction; }; #endif // PACKAGECHOOSERPAGE_H diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 1f6346666..86e18aa88 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -73,7 +73,6 @@ PackageListModel::rowCount( const QModelIndex& index ) const QVariant PackageListModel::data( const QModelIndex& index, int role ) const { - cDebug() << "Data" << m_packages.count() << index.isValid() << ( index.isValid() ? index.row() : -1 ); if ( !index.isValid() ) { return QVariant(); diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index c00e55c0a..67715e197 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -21,6 +21,7 @@ #include #include +#include #include struct PackageItem @@ -32,9 +33,15 @@ struct PackageItem QString name; QString description; // TODO: may be more than one - // QPixmap screenshot; + QPixmap screenshot; + /// @brief Create blank PackageItem PackageItem(); + /** @brief Creates a PackageItem from given strings + * + * This constructor sets all the text members, + * but leaves the screenshot blank. Set that separately. + */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); // TODO: implement this From a32dcdad869d1544e46d6e7651d2768967e2983d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:25:26 +0200 Subject: [PATCH 06/44] [packagechooser] Support multiple selection modes --- .../packagechooser/PackageChooserPage.cpp | 12 ++++++- .../packagechooser/PackageChooserPage.h | 2 +- .../packagechooser/PackageChooserViewStep.cpp | 32 +++++++++++++++++-- .../packagechooser/PackageChooserViewStep.h | 3 ++ src/modules/packagechooser/PackageModel.h | 8 +++++ 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index a474e7536..307b1b861 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -25,7 +25,7 @@ #include -PackageChooserPage::PackageChooserPage( QWidget* parent ) +PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent ) : QWidget( parent ) , ui( new Ui::PackageChooserPage ) , m_introduction( QString(), @@ -35,6 +35,16 @@ PackageChooserPage::PackageChooserPage( QWidget* parent ) { ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) + + switch( mode ) + { + case PackageChooserMode::Optional: + case PackageChooserMode::Exclusive: + ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + case PackageChooserMode::Multiple: + case PackageChooserMode::RequiredMultiple: + ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); + } } void diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 031abad69..483fd5d0a 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -33,7 +33,7 @@ class PackageChooserPage : public QWidget { Q_OBJECT public: - explicit PackageChooserPage( QWidget* parent = nullptr ); + explicit PackageChooserPage( PackageChooserMode mode, QWidget* parent = nullptr ); void setModel( QAbstractItemModel* model ); diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 3ff2ac636..2a5cc8073 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -37,6 +37,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) , m_model( nullptr ) + , m_mode( PackageChooserMode::Optional ) { emit nextStatusChanged( false ); } @@ -64,7 +65,7 @@ PackageChooserViewStep::widget() { if ( !m_widget ) { - m_widget = new PackageChooserPage( nullptr ); + m_widget = new PackageChooserPage( m_mode, nullptr ); if ( m_model ) { hookupModel(); @@ -77,7 +78,34 @@ PackageChooserViewStep::widget() bool PackageChooserViewStep::isNextEnabled() const { - return true; + if ( !m_model ) + { + return false; + } + + if ( !m_widget ) + { + // No way to have changed anything + return true; + } + + switch( m_mode ) + { + case PackageChooserMode::Optional: + // zero or one + return false; + case PackageChooserMode::Exclusive: + // exactly one + return false; + case PackageChooserMode::Multiple: + // zero or more + return true; + case PackageChooserMode::RequiredMultiple: + // one or more + return false; + } + + NOTREACHED return true; } diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 56fbf5d3a..ed33c3e46 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -23,6 +23,8 @@ #include "utils/PluginFactory.h" #include "viewpages/ViewStep.h" +#include "PackageModel.h" + #include #include #include @@ -59,6 +61,7 @@ private: PackageChooserPage* m_widget; PackageListModel* m_model; + PackageChooserMode m_mode; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 67715e197..6d150802f 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -24,6 +24,14 @@ #include #include +enum class PackageChooserMode +{ + Optional, // zero or one + Exclusive, // exactly one + Multiple, // zero or more + RequiredMultiple // one or more +}; + struct PackageItem { QString id; From 86e2e6242f999c79650d60d7d9cddffe5f666ec9 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:26:10 +0200 Subject: [PATCH 07/44] [packagechooser] Warn about weird calling orders --- src/modules/packagechooser/PackageChooserViewStep.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 2a5cc8073..705958849 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -70,6 +70,10 @@ PackageChooserViewStep::widget() { hookupModel(); } + else + { + cWarning() << "PackageChooser Widget created before model."; + } } return m_widget; } From 2272d2ab430d866e21c4cd6291a212fbea56a2ed Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 16:43:10 +0200 Subject: [PATCH 08/44] [packagechooser] Add selection modes - Introduce different selection modes (most don't work yet) - Use model data in the main widget --- .../packagechooser/PackageChooserPage.cpp | 22 +++++++++------- .../packagechooser/PackageChooserViewStep.cpp | 26 +++++++++---------- src/modules/packagechooser/PackageModel.cpp | 10 ++++++- src/modules/packagechooser/PackageModel.h | 9 ++++++- 4 files changed, 42 insertions(+), 25 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 307b1b861..174f7efe1 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -36,14 +36,14 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) - switch( mode ) + switch ( mode ) { - case PackageChooserMode::Optional: - case PackageChooserMode::Exclusive: - ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); - case PackageChooserMode::Multiple: - case PackageChooserMode::RequiredMultiple: - ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); + case PackageChooserMode::Optional: + case PackageChooserMode::Exclusive: + ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + case PackageChooserMode::Multiple: + case PackageChooserMode::RequiredMultiple: + ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } } @@ -58,9 +58,11 @@ PackageChooserPage::currentChanged( const QModelIndex& index ) } else { - ui->productName->setText( QString::number( index.row() ) ); - ui->productScreenshot->hide(); - ui->productDescription->setText( "derp" ); + const auto* model = ui->products->model(); + + ui->productName->setText( model->data( index, PackageListModel::NameRole ).toString() ); + ui->productScreenshot->setPixmap( model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >() ); + ui->productDescription->setText( model->data( index, PackageListModel::DescriptionRole ).toString() ); } } diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 705958849..e125cdba4 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -93,20 +93,20 @@ PackageChooserViewStep::isNextEnabled() const return true; } - switch( m_mode ) + switch ( m_mode ) { - case PackageChooserMode::Optional: - // zero or one - return false; - case PackageChooserMode::Exclusive: - // exactly one - return false; - case PackageChooserMode::Multiple: - // zero or more - return true; - case PackageChooserMode::RequiredMultiple: - // one or more - return false; + case PackageChooserMode::Optional: + // zero or one + return false; + case PackageChooserMode::Exclusive: + // exactly one + return false; + case PackageChooserMode::Multiple: + // zero or more + return true; + case PackageChooserMode::RequiredMultiple: + // one or more + return false; } NOTREACHED return true; diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 86e18aa88..fc19fda47 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -83,10 +83,18 @@ PackageListModel::data( const QModelIndex& index, int role ) const return QVariant(); } - if ( role == Qt::DisplayRole ) + if ( role == Qt::DisplayRole /* Also PackageNameRole */ ) { return m_packages[ row ].name; } + else if ( role == DescriptionRole ) + { + return m_packages[ row ].description; + } + else if ( role == ScreenshotRole ) + { + return m_packages[ row ].screenshot; + } return QVariant(); } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 6d150802f..61e2864a9 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -27,7 +27,7 @@ enum class PackageChooserMode { Optional, // zero or one - Exclusive, // exactly one + Exclusive, // exactly one Multiple, // zero or more RequiredMultiple // one or more }; @@ -70,6 +70,13 @@ public: int rowCount( const QModelIndex& index ) const override; QVariant data( const QModelIndex& index, int role ) const override; + enum Roles : int + { + NameRole = Qt::DisplayRole, + DescriptionRole = Qt::UserRole, + ScreenshotRole + }; + private: PackageList m_packages; }; From 7609546d8bebd96d037a1e8eb77c0dc779ca746d Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 17:02:02 +0200 Subject: [PATCH 09/44] [packagechooser] Add screenshots for example --- src/modules/packagechooser/CMakeLists.txt | 2 ++ .../packagechooser/PackageChooserPage.cpp | 3 +++ src/modules/packagechooser/images/gnome.png | Bin 0 -> 5739 bytes src/modules/packagechooser/images/kde.png | Bin 0 -> 4678 bytes .../packagechooser/images/no-selection.png | Bin 0 -> 4618 bytes src/modules/packagechooser/packagechooser.qrc | 7 +++++++ 6 files changed, 12 insertions(+) create mode 100644 src/modules/packagechooser/images/gnome.png create mode 100644 src/modules/packagechooser/images/kde.png create mode 100644 src/modules/packagechooser/images/no-selection.png create mode 100644 src/modules/packagechooser/packagechooser.qrc diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 525921602..483092800 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -7,6 +7,8 @@ calamares_add_plugin( packagechooser PackageChooserPage.cpp PackageChooserViewStep.cpp PackageModel.cpp + RESOURCES + packagechooser.qrc UI page_package.ui LINK_PRIVATE_LIBRARIES diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 174f7efe1..23d3b837b 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -33,6 +33,9 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent tr( "Package Selection" ), tr( "Please pick a product from the list. The selected product will be installed." ) ) { + m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); + cDebug() << m_introduction.screenshot; + ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) diff --git a/src/modules/packagechooser/images/gnome.png b/src/modules/packagechooser/images/gnome.png new file mode 100644 index 0000000000000000000000000000000000000000..f9f3901e14aeafc94babdf08bb5ffeb99af836a7 GIT binary patch literal 5739 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 J3*eT){{=a!jIsa# literal 0 HcmV?d00001 diff --git a/src/modules/packagechooser/images/kde.png b/src/modules/packagechooser/images/kde.png new file mode 100644 index 0000000000000000000000000000000000000000..02f3e70ea21282afa79d367f05d602c33cb5ddd3 GIT binary patch literal 4678 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 literal 0 HcmV?d00001 diff --git a/src/modules/packagechooser/images/no-selection.png b/src/modules/packagechooser/images/no-selection.png new file mode 100644 index 0000000000000000000000000000000000000000..f9dbbbac45d0b03667f66be54664fdc5dce71983 GIT binary patch literal 4618 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 literal 0 HcmV?d00001 diff --git a/src/modules/packagechooser/packagechooser.qrc b/src/modules/packagechooser/packagechooser.qrc new file mode 100644 index 000000000..9212c2f93 --- /dev/null +++ b/src/modules/packagechooser/packagechooser.qrc @@ -0,0 +1,7 @@ + + + images/no-selection.png + images/kde.png + images/gnome.png + + From 86d8db6bbf92e77981532d9409a685b953711fe3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 17:06:03 +0200 Subject: [PATCH 10/44] [packagechooser] Enforce selection mode on the next-button --- .../packagechooser/PackageChooserPage.cpp | 7 +++++++ .../packagechooser/PackageChooserPage.h | 5 +++++ .../packagechooser/PackageChooserViewStep.cpp | 18 +++++++++--------- 3 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 23d3b837b..f0f7cb04c 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -80,6 +80,7 @@ PackageChooserPage::updateLabels() { currentChanged( QModelIndex() ); } + emit selectionChanged(); } void @@ -91,3 +92,9 @@ PackageChooserPage::setModel( QAbstractItemModel* model ) this, &PackageChooserPage::updateLabels ); } + +bool +PackageChooserPage::hasSelection() const +{ + return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection(); +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 483fd5d0a..8f9fde11f 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -37,10 +37,15 @@ public: void setModel( QAbstractItemModel* model ); + bool hasSelection() const; + public slots: void currentChanged( const QModelIndex& index ); void updateLabels(); +signals: + void selectionChanged(); + private: Ui::PackageChooserPage* ui; PackageItem m_introduction; diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index e125cdba4..1379f5dd6 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -37,7 +37,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) , m_model( nullptr ) - , m_mode( PackageChooserMode::Optional ) + , m_mode( PackageChooserMode::Exclusive ) { emit nextStatusChanged( false ); } @@ -66,6 +66,10 @@ PackageChooserViewStep::widget() if ( !m_widget ) { m_widget = new PackageChooserPage( m_mode, nullptr ); + connect( m_widget, &PackageChooserPage::selectionChanged, [=]() { + emit nextStatusChanged( this->isNextEnabled() ); + } ); + if ( m_model ) { hookupModel(); @@ -96,17 +100,13 @@ PackageChooserViewStep::isNextEnabled() const switch ( m_mode ) { case PackageChooserMode::Optional: - // zero or one - return false; - case PackageChooserMode::Exclusive: - // exactly one - return false; case PackageChooserMode::Multiple: - // zero or more + // zero or one OR zero or more return true; + case PackageChooserMode::Exclusive: case PackageChooserMode::RequiredMultiple: - // one or more - return false; + // exactly one OR one or more + return m_widget->hasSelection(); } NOTREACHED return true; From ab7374628b9eed73650c0b6260b155499e6fe2cd Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 17:17:53 +0200 Subject: [PATCH 11/44] [packagechooser] Use sample screenshots --- .../packagechooser/PackageChooserViewStep.cpp | 4 ++-- src/modules/packagechooser/PackageModel.cpp | 13 +++++++++++++ src/modules/packagechooser/PackageModel.h | 6 ++++++ 3 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 1379f5dd6..9b3c174da 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -155,9 +155,9 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_model = new PackageListModel( nullptr ); - m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop" } ); + m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); m_model->addPackage( - PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop" } ); + PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); if ( m_widget ) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index fc19fda47..7798b33bd 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -40,6 +40,19 @@ PackageItem::PackageItem( const QString& a_id, { } +PackageItem::PackageItem( const QString& a_id, + const QString& a_package, + const QString& a_name, + const QString& a_description, + const QString& screenshotPath ) + : id( a_id ) + , package( a_package ) + , name( a_name ) + , description( a_description ) + , screenshot( screenshotPath ) +{ +} + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 61e2864a9..7db668df4 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -52,6 +52,12 @@ struct PackageItem */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + PackageItem( const QString& id, + const QString& package, + const QString& name, + const QString& description, + const QString& screenshotPath ); + // TODO: implement this PackageItem fromAppStream( const QString& filename ); }; From 9d026862a87748d3caeeabd88be92c8c981e10e6 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 23:20:45 +0200 Subject: [PATCH 12/44] [packagechooser] Provide names for selection mode --- src/modules/packagechooser/PackageModel.cpp | 20 ++++++++++++++++++++ src/modules/packagechooser/PackageModel.h | 4 ++++ 2 files changed, 24 insertions(+) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 7798b33bd..3546d9e42 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -20,6 +20,26 @@ #include "utils/Logger.h" +const NamedEnumTable< PackageChooserMode >& +roleNames() +{ + static const NamedEnumTable< PackageChooserMode > names { + { "optional", PackageChooserMode::Optional }, + { "exclusive", PackageChooserMode::Exclusive }, + { "multiple", PackageChooserMode::Multiple }, + { "requiredmultiple", + PackageChooserMode::RequiredMultiple }, + // and a bunch of aliases + { "zero-or-one", PackageChooserMode::Optional }, + { "radio", PackageChooserMode::Exclusive }, + { "one", PackageChooserMode::Exclusive }, + { "set", PackageChooserMode::Multiple }, + { "zero-or-more", PackageChooserMode::Multiple }, + { "required", PackageChooserMode::RequiredMultiple }, + { "one-or-more", PackageChooserMode::RequiredMultiple } }; + return names; +} + PackageItem PackageItem::fromAppStream( const QString& filename ) { diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 7db668df4..ed5ac4b24 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -19,6 +19,8 @@ #ifndef PACKAGEMODEL_H #define PACKAGEMODEL_H +#include "utils/NamedEnum.h" + #include #include #include @@ -32,6 +34,8 @@ enum class PackageChooserMode RequiredMultiple // one or more }; +const NamedEnumTable< PackageChooserMode >& roleNames(); + struct PackageItem { QString id; From fb3204262c596343a1bea200fc7af0d8555c3b44 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Fri, 2 Aug 2019 23:24:35 +0200 Subject: [PATCH 13/44] [packagechooser] Remove unneeded forward declaration --- src/modules/packagechooser/PackageChooserViewStep.h | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index ed33c3e46..3947298ba 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -30,7 +30,6 @@ #include class PackageChooserPage; -class PackageListModel; class PLUGINDLLEXPORT PackageChooserViewStep : public Calamares::ViewStep { From 76077743afdd838739cdf80cacf4c2ce26c3f54c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 15:45:00 +0200 Subject: [PATCH 14/44] [packagechooser] Add configuration setting for selection mode - Add a *mode* key to the configuration file - Change some names around to be more consistent (not user-visible) --- .../packagechooser/PackageChooserViewStep.cpp | 10 ++++++++++ src/modules/packagechooser/PackageModel.cpp | 17 ++++++++--------- src/modules/packagechooser/PackageModel.h | 4 ++-- src/modules/packagechooser/packagechooser.conf | 9 +++++++++ 4 files changed, 29 insertions(+), 11 deletions(-) create mode 100644 src/modules/packagechooser/packagechooser.conf diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 9b3c174da..09fa488aa 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -150,6 +150,16 @@ void PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { // TODO: use the configurationMap + QString mode = CalamaresUtils::getString( configurationMap, "mode" ); + bool ok = false; + if ( !mode.isEmpty() ) + { + m_mode = roleNames().find( mode, ok ); + } + if ( !ok ) + { + m_mode = PackageChooserMode::Required; + } if ( !m_model ) { diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 3546d9e42..484b4de3b 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -25,17 +25,16 @@ roleNames() { static const NamedEnumTable< PackageChooserMode > names { { "optional", PackageChooserMode::Optional }, - { "exclusive", PackageChooserMode::Exclusive }, - { "multiple", PackageChooserMode::Multiple }, - { "requiredmultiple", - PackageChooserMode::RequiredMultiple }, + { "required", PackageChooserMode::Required }, + { "optionalmultiple", PackageChooserMode::OptionalMultiple }, + { "requiredmultiple", PackageChooserMode::RequiredMultiple }, // and a bunch of aliases { "zero-or-one", PackageChooserMode::Optional }, - { "radio", PackageChooserMode::Exclusive }, - { "one", PackageChooserMode::Exclusive }, - { "set", PackageChooserMode::Multiple }, - { "zero-or-more", PackageChooserMode::Multiple }, - { "required", PackageChooserMode::RequiredMultiple }, + { "radio", PackageChooserMode::Required }, + { "one", PackageChooserMode::Required }, + { "set", PackageChooserMode::OptionalMultiple }, + { "zero-or-more", PackageChooserMode::OptionalMultiple }, + { "multiple", PackageChooserMode::RequiredMultiple }, { "one-or-more", PackageChooserMode::RequiredMultiple } }; return names; } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index ed5ac4b24..76e43ef44 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -29,8 +29,8 @@ enum class PackageChooserMode { Optional, // zero or one - Exclusive, // exactly one - Multiple, // zero or more + Required, // exactly one + OptionalMultiple, // zero or more RequiredMultiple // one or more }; diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf new file mode 100644 index 000000000..f08d07895 --- /dev/null +++ b/src/modules/packagechooser/packagechooser.conf @@ -0,0 +1,9 @@ +# Configuration for the low-density software chooser +--- +# Software selection mode, to set whether the software packages +# can be chosen singly, or multiply. +# +# Possible modes are "optional", "required" (for zero or one) +# or "optionalmultiple", "requiredmultiple" (for zero-or-more +# or one-or-more). +mode: required From 87d7b2a5c072966422f19985a450449420ecdd31 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:24:30 +0200 Subject: [PATCH 15/44] [packagechooser] Allow setting an ID for the module's GS key --- src/modules/packagechooser/PackageChooserViewStep.cpp | 6 ++++-- src/modules/packagechooser/PackageChooserViewStep.h | 3 +++ src/modules/packagechooser/packagechooser.conf | 9 +++++++++ 3 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 09fa488aa..a8dd0e8d0 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -149,7 +149,6 @@ PackageChooserViewStep::jobs() const void PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { - // TODO: use the configurationMap QString mode = CalamaresUtils::getString( configurationMap, "mode" ); bool ok = false; if ( !mode.isEmpty() ) @@ -160,7 +159,10 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_mode = PackageChooserMode::Required; } - + + m_id = CalamaresUtils::getString( configurationMap, "id" ); + + // TODO: replace this hard-coded model if ( !m_model ) { diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 3947298ba..e410e547b 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -60,7 +60,10 @@ private: PackageChooserPage* m_widget; PackageListModel* m_model; + + // Configuration PackageChooserMode m_mode; + QString m_id; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageChooserViewStepFactory ) diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index f08d07895..fd100ab27 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -1,5 +1,14 @@ # Configuration for the low-density software chooser --- +# The packagechooser writes a GlobalStorage value for the choice that +# has been made. The key is *packagechooser_*. If *id* is set here, +# it is substituted into the key name. If it is not set, the module's +# instance name is used; see the *instances* section of `settings.conf`. +# If there is just one packagechooser module, and no *id* is set, +# resulting GS key is probably *packagechooser_packagechooser*. +# +# id: "" + # Software selection mode, to set whether the software packages # can be chosen singly, or multiply. # From b711c791bdb9cc4f660a0cd3546391c4dd16eba0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:28:55 +0200 Subject: [PATCH 16/44] [packagechooser] Fix build, tidy code --- src/modules/packagechooser/PackageChooserPage.cpp | 4 ++-- .../packagechooser/PackageChooserViewStep.cpp | 14 +++++++------- .../packagechooser/PackageChooserViewStep.h | 2 +- src/modules/packagechooser/PackageModel.cpp | 3 ++- src/modules/packagechooser/PackageModel.h | 2 +- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index f0f7cb04c..d267e4885 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -42,9 +42,9 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent switch ( mode ) { case PackageChooserMode::Optional: - case PackageChooserMode::Exclusive: + case PackageChooserMode::Required: ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); - case PackageChooserMode::Multiple: + case PackageChooserMode::OptionalMultiple: case PackageChooserMode::RequiredMultiple: ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index a8dd0e8d0..47b6f84d0 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -37,7 +37,7 @@ PackageChooserViewStep::PackageChooserViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_widget( nullptr ) , m_model( nullptr ) - , m_mode( PackageChooserMode::Exclusive ) + , m_mode( PackageChooserMode::Required ) { emit nextStatusChanged( false ); } @@ -100,10 +100,10 @@ PackageChooserViewStep::isNextEnabled() const switch ( m_mode ) { case PackageChooserMode::Optional: - case PackageChooserMode::Multiple: + case PackageChooserMode::OptionalMultiple: // zero or one OR zero or more return true; - case PackageChooserMode::Exclusive: + case PackageChooserMode::Required: case PackageChooserMode::RequiredMultiple: // exactly one OR one or more return m_widget->hasSelection(); @@ -159,17 +159,17 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap { m_mode = PackageChooserMode::Required; } - + m_id = CalamaresUtils::getString( configurationMap, "id" ); - + // TODO: replace this hard-coded model if ( !m_model ) { m_model = new PackageListModel( nullptr ); m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); - m_model->addPackage( - PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); + m_model->addPackage( PackageItem { + "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); if ( m_widget ) diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index e410e547b..55ed2d4d5 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -60,7 +60,7 @@ private: PackageChooserPage* m_widget; PackageListModel* m_model; - + // Configuration PackageChooserMode m_mode; QString m_id; diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 484b4de3b..eb783259b 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -35,7 +35,8 @@ roleNames() { "set", PackageChooserMode::OptionalMultiple }, { "zero-or-more", PackageChooserMode::OptionalMultiple }, { "multiple", PackageChooserMode::RequiredMultiple }, - { "one-or-more", PackageChooserMode::RequiredMultiple } }; + { "one-or-more", PackageChooserMode::RequiredMultiple } + }; return names; } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 76e43ef44..dfb922e59 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -73,7 +73,7 @@ class PackageListModel : public QAbstractListModel public: PackageListModel( PackageList&& items, QObject* parent ); PackageListModel( QObject* parent ); - virtual ~PackageListModel(); + virtual ~PackageListModel() override; void addPackage( PackageItem&& p ); From c59ffc77652231f67bc0ba93240532927b1b321c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:33:34 +0200 Subject: [PATCH 17/44] [packagechooser] Set default ID as documented --- src/modules/packagechooser/PackageChooserViewStep.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 47b6f84d0..9edfa9416 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -161,6 +161,12 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap } m_id = CalamaresUtils::getString( configurationMap, "id" ); + if ( m_id.isEmpty() ) + { + // Not set, so use the instance id + // TODO: use a stronger type than QString for structured IDs + m_id = moduleInstanceKey().split( '@' ).last(); + } // TODO: replace this hard-coded model if ( !m_model ) From 140c0db7a48b89af9e7a6b4c36a7a0ee0ae9467c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:51:00 +0200 Subject: [PATCH 18/44] [packagechooser] Set GlobalStorage packagechooser_ --- .../packagechooser/PackageChooserPage.cpp | 21 +++++++++++++++++++ .../packagechooser/PackageChooserPage.h | 6 ++++++ .../packagechooser/PackageChooserViewStep.cpp | 9 ++++++++ src/modules/packagechooser/PackageModel.cpp | 4 ++++ src/modules/packagechooser/PackageModel.h | 3 ++- .../packagechooser/packagechooser.conf | 3 +++ 6 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index d267e4885..265ce3b53 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -98,3 +98,24 @@ PackageChooserPage::hasSelection() const { return ui && ui->products && ui->products->selectionModel() && ui->products->selectionModel()->hasSelection(); } + +QStringList +PackageChooserPage::selectedPackageIds() const +{ + if ( !( ui && ui->products && ui->products->selectionModel() ) ) + { + return QStringList(); + } + + const auto* model = ui->products->model(); + QStringList ids; + for ( const auto& index : ui->products->selectionModel()->selectedIndexes() ) + { + QString pid = model->data( index, PackageListModel::IdRole ).toString(); + if ( !pid.isEmpty() ) + { + ids.append( pid ); + } + } + return ids; +} diff --git a/src/modules/packagechooser/PackageChooserPage.h b/src/modules/packagechooser/PackageChooserPage.h index 8f9fde11f..401de903b 100644 --- a/src/modules/packagechooser/PackageChooserPage.h +++ b/src/modules/packagechooser/PackageChooserPage.h @@ -37,7 +37,13 @@ public: void setModel( QAbstractItemModel* model ); + /// @brief Is anything selected? bool hasSelection() const; + /** @brief Get the list of selected ids + * + * This list may be empty (if none is selected). + */ + QStringList selectedPackageIds() const; public slots: void currentChanged( const QModelIndex& index ); diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 9edfa9416..9d32884c7 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -137,6 +137,15 @@ PackageChooserViewStep::isAtEnd() const void PackageChooserViewStep::onLeave() { + QString key = QStringLiteral( "packagechooser_%1" ).arg( m_id ); + QString value; + if ( m_widget->hasSelection() ) + { + value = m_widget->selectedPackageIds().join( ',' ); + } + Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); + + cDebug() << "PackageChooser" << key << "selected" << value; } Calamares::JobList diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index eb783259b..aa8dd39fc 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -128,6 +128,10 @@ PackageListModel::data( const QModelIndex& index, int role ) const { return m_packages[ row ].screenshot; } + else if ( role == IdRole ) + { + return m_packages[ row ].id; + } return QVariant(); } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index dfb922e59..7f8fff8ec 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -84,7 +84,8 @@ public: { NameRole = Qt::DisplayRole, DescriptionRole = Qt::UserRole, - ScreenshotRole + ScreenshotRole, + IdRole }; private: diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index fd100ab27..b4e48c995 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -7,6 +7,9 @@ # If there is just one packagechooser module, and no *id* is set, # resulting GS key is probably *packagechooser_packagechooser*. # +# The GS value is a comma-separated list of the IDs of the selected +# packages, or an empty string if none is selected. +# # id: "" # Software selection mode, to set whether the software packages From 047a300a5181a03dd11c1a3b6862f3301236f301 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sat, 3 Aug 2019 23:55:29 +0200 Subject: [PATCH 19/44] [packagechooser] Remove unneeded debug --- src/modules/packagechooser/PackageChooserPage.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 265ce3b53..63307d095 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -34,7 +34,6 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent tr( "Please pick a product from the list. The selected product will be installed." ) ) { m_introduction.screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); - cDebug() << m_introduction.screenshot; ui->setupUi( this ); CALAMARES_RETRANSLATE( updateLabels(); ) From d5275d5e10cac56db5f3f573a5ecf54b681850e4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 00:08:41 +0200 Subject: [PATCH 20/44] [packagechooser] Allow the model to set the introductory text --- .../packagechooser/PackageChooserPage.cpp | 20 +++++++++++++++++++ .../packagechooser/PackageChooserViewStep.cpp | 11 ++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 63307d095..60becf64f 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -86,6 +86,26 @@ void PackageChooserPage::setModel( QAbstractItemModel* model ) { ui->products->setModel( model ); + + // Check if any of the items in the model is the "none" option. + // If so, copy its values into the introduction / none item. + for ( int r = 0; r < model->rowCount(); ++r ) + { + auto index = model->index( r, 0 ); + if ( index.isValid() ) + { + QVariant v = model->data( index, PackageListModel::IdRole ); + if ( v.isValid() && v.toString().isEmpty() ) + { + m_introduction.name = model->data( index, PackageListModel::NameRole ).toString(); + m_introduction.description = model->data( index, PackageListModel::DescriptionRole ).toString(); + m_introduction.screenshot = model->data( index, PackageListModel::ScreenshotRole ).value< QPixmap >(); + currentChanged( QModelIndex() ); + break; + } + } + } + connect( ui->products->selectionModel(), &QItemSelectionModel::selectionChanged, this, diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 9d32884c7..8515d03a9 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -144,7 +144,7 @@ PackageChooserViewStep::onLeave() value = m_widget->selectedPackageIds().join( ',' ); } Calamares::JobQueue::instance()->globalStorage()->insert( key, value ); - + cDebug() << "PackageChooser" << key << "selected" << value; } @@ -180,8 +180,15 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap // TODO: replace this hard-coded model if ( !m_model ) { - m_model = new PackageListModel( nullptr ); + m_model->addPackage( PackageItem { QString(), + QString(), + "No Desktop", + "Please pick a desktop environment from the list. " + "If you don't want to install a desktop, that's fine, " + "your system will start up in text-only mode and you can " + "install a desktop environment later.", + ":/images/no-selection.png" } ); m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); m_model->addPackage( PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); From adb939b2e82617003b16a81d0622d1bd45192843 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 00:11:50 +0200 Subject: [PATCH 21/44] [packagechooser] Word-wrap package descriptions --- src/modules/packagechooser/page_package.ui | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/modules/packagechooser/page_package.ui b/src/modules/packagechooser/page_package.ui index 1ba032ed2..17a960549 100644 --- a/src/modules/packagechooser/page_package.ui +++ b/src/modules/packagechooser/page_package.ui @@ -53,6 +53,12 @@ TextLabel + + true + + + true + From 791f9cbccbef3fcbf5433329a313e7b4c28bbaab Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 16:00:55 +0200 Subject: [PATCH 22/44] [packagechooser] Read packages model from config - add key *items* which will be used to fill up the model for software products. TODO: needs translation support --- .../packagechooser/PackageChooserViewStep.cpp | 55 ++++++++++++++++++- .../packagechooser/PackageChooserViewStep.h | 1 + .../packagechooser/packagechooser.conf | 35 ++++++++++++ 3 files changed, 89 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 8515d03a9..4d9ab4f5f 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -177,6 +177,15 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_id = moduleInstanceKey().split( '@' ).last(); } + bool first_time = !m_model; + + ok = false; + QVariantMap items = CalamaresUtils::getSubMap( configurationMap, "items", ok ); + if ( ok ) + { + fillModel( items ); + } + // TODO: replace this hard-coded model if ( !m_model ) { @@ -192,12 +201,54 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap m_model->addPackage( PackageItem { "kde", "kde", "Plasma", "Plasma Desktop", ":/images/kde.png" } ); m_model->addPackage( PackageItem { "gnome", "gnome", "GNOME", "GNU Networked Object Modeling Environment Desktop", ":/images/gnome.png" } ); + } + + if ( first_time && m_widget && m_model ) + { + hookupModel(); + } +} + +void +PackageChooserViewStep::fillModel( const QVariantMap& items ) +{ + if ( !m_model ) + { + m_model = new PackageListModel( nullptr ); + } + cDebug() << "Loading PackageChooser model items from config"; + for ( auto item_it = items.constKeyValueBegin(); item_it != items.constKeyValueEnd(); ++item_it ) + { + QString id = ( *item_it ).first; - if ( m_widget ) + QVariantMap item_map = ( *item_it ).second.toMap(); + if ( item_map.isEmpty() ) { - hookupModel(); + cWarning() << "PackageChooser item" << id << "is not valid."; + continue; } + + QString package = CalamaresUtils::getString( item_map, "package" ); + QString name = CalamaresUtils::getString( item_map, "name" ); + QString description = CalamaresUtils::getString( item_map, "description" ); + QString screenshot = CalamaresUtils::getString( item_map, "screenshot" ); + + if ( name.isEmpty() ) + { + cWarning() << "PackageChooser item" << id << "has an empty name."; + continue; + } + if ( description.isEmpty() ) + { + description = tr( "No description provided." ); + } + if ( screenshot.isEmpty() ) + { + screenshot = QStringLiteral( ":/images/no-selection.png" ); + } + + m_model->addPackage( PackageItem { id, package, name, description, screenshot } ); } } diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 55ed2d4d5..4d5cc346f 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -56,6 +56,7 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: + void fillModel( const QVariantMap& items ); void hookupModel(); PackageChooserPage* m_widget; diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index b4e48c995..f4bab476c 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -19,3 +19,38 @@ # or "optionalmultiple", "requiredmultiple" (for zero-or-more # or one-or-more). mode: required + +# Items to display in the chooser. In general, this should be a +# pretty short list to avoid overwhelming the UI. +# +# Each item has a key, which is used as its ID (used in setting +# the value of *packagechooser_*). The following fields +# are mandatory: +# +# - *package* Package name for the product. While mandatory, this is +# not actually used anywhere. +# - *name* Human-readable, but untranslated, name of the product. +# - *description* Human-readable, but untranslated, description. +# - *screenshot* Path to a single screenshot of the product. May be +# a filesystem path or a QRC path (e.g. ":/images/no-selection.png"). +# +# Use the empty string "" as ID / key for the "no selection" item if +# you want to customize the display of that item as well. +items: + "": + package: "" + name: "No Desktop" + description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." + screenshot: ":/images/no-selection.png" + kde: + package: kde + name: Plasma Desktop + description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." + screenshot: ":/images/kde.png" + gnome: + package: gnome + name: GNOME + description: GNU Networked Object Modeling Environment Desktop + screenshot: ":/images/gnome.png" + + From 9a52430e74d8b8b9b763725e01f150d97b378c87 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 20:04:32 +0200 Subject: [PATCH 23/44] [packagechooser] Too many 'o's in test name --- src/modules/packagechooser/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 483092800..4663ccce7 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -20,11 +20,11 @@ if( ECM_FOUND AND BUILD_TESTING ) ecm_add_test( Tests.cpp TEST_NAME - packagechooosertest + packagechoosertest LINK_LIBRARIES ${CALAMARES_LIBRARIES} Qt5::Core Qt5::Test ) - calamares_automoc( packagechooosertest) + calamares_automoc( packagechoosertest) endif() From b16354133da0f5873f7eee25d1e1aeec297d2483 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Sun, 4 Aug 2019 20:19:56 +0200 Subject: [PATCH 24/44] [packagechooser] Switch to a list form - Using id's as keys in a map orders them indeterminately -- in practice, alphabetically by key. Switch to a list form so that the products stick to the order they have in the config file (which means distro's can list "preferred" versions at top). --- .../packagechooser/PackageChooserViewStep.cpp | 32 +++++++++------ .../packagechooser/PackageChooserViewStep.h | 2 +- .../packagechooser/packagechooser.conf | 40 ++++++++++--------- 3 files changed, 43 insertions(+), 31 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 4d9ab4f5f..4476eb9e6 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -178,12 +178,9 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap } bool first_time = !m_model; - - ok = false; - QVariantMap items = CalamaresUtils::getSubMap( configurationMap, "items", ok ); - if ( ok ) + if ( configurationMap.contains( "items" ) ) { - fillModel( items ); + fillModel( configurationMap.value( "items" ).toList() ); } // TODO: replace this hard-coded model @@ -210,31 +207,42 @@ PackageChooserViewStep::setConfigurationMap( const QVariantMap& configurationMap } void -PackageChooserViewStep::fillModel( const QVariantMap& items ) +PackageChooserViewStep::fillModel( const QVariantList& items ) { if ( !m_model ) { m_model = new PackageListModel( nullptr ); } - cDebug() << "Loading PackageChooser model items from config"; - for ( auto item_it = items.constKeyValueBegin(); item_it != items.constKeyValueEnd(); ++item_it ) + if ( items.isEmpty() ) { - QString id = ( *item_it ).first; + cWarning() << "No *items* for PackageChooser module."; + return; + } - QVariantMap item_map = ( *item_it ).second.toMap(); + cDebug() << "Loading PackageChooser model items from config"; + int item_index = 0; + for ( const auto& item_it : items ) + { + ++item_index; + QVariantMap item_map = item_it.toMap(); if ( item_map.isEmpty() ) { - cWarning() << "PackageChooser item" << id << "is not valid."; + cWarning() << "PackageChooser entry" << item_index << "is not valid."; continue; } + QString id = CalamaresUtils::getString( item_map, "id" ); QString package = CalamaresUtils::getString( item_map, "package" ); QString name = CalamaresUtils::getString( item_map, "name" ); QString description = CalamaresUtils::getString( item_map, "description" ); QString screenshot = CalamaresUtils::getString( item_map, "screenshot" ); - if ( name.isEmpty() ) + if ( name.isEmpty() && id.isEmpty() ) + { + name = tr( "No product" ); + } + else if ( name.isEmpty() ) { cWarning() << "PackageChooser item" << id << "has an empty name."; continue; diff --git a/src/modules/packagechooser/PackageChooserViewStep.h b/src/modules/packagechooser/PackageChooserViewStep.h index 4d5cc346f..e3ffc1d5b 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.h +++ b/src/modules/packagechooser/PackageChooserViewStep.h @@ -56,7 +56,7 @@ public: void setConfigurationMap( const QVariantMap& configurationMap ) override; private: - void fillModel( const QVariantMap& items ); + void fillModel( const QVariantList& items ); void hookupModel(); PackageChooserPage* m_widget; diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index f4bab476c..391e1f325 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -21,12 +21,16 @@ mode: required # Items to display in the chooser. In general, this should be a -# pretty short list to avoid overwhelming the UI. +# pretty short list to avoid overwhelming the UI. This is a list +# of objects, and the items are displayed in list order. # -# Each item has a key, which is used as its ID (used in setting -# the value of *packagechooser_*). The following fields +# Each item has an id, which is used in setting # the value of +# *packagechooser_*). The following fields # are mandatory: # +# - *id* ID for the product. The ID "" is special, and is used for +# "no package selected". Only include this if the mode allows +# selecting none. # - *package* Package name for the product. While mandatory, this is # not actually used anywhere. # - *name* Human-readable, but untranslated, name of the product. @@ -37,20 +41,20 @@ mode: required # Use the empty string "" as ID / key for the "no selection" item if # you want to customize the display of that item as well. items: - "": - package: "" - name: "No Desktop" - description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." - screenshot: ":/images/no-selection.png" - kde: - package: kde - name: Plasma Desktop - description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." - screenshot: ":/images/kde.png" - gnome: - package: gnome - name: GNOME - description: GNU Networked Object Modeling Environment Desktop - screenshot: ":/images/gnome.png" + - id: "" + package: "" + name: "No Desktop" + description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." + screenshot: ":/images/no-selection.png" + - id: kde + package: kde + name: Plasma Desktop + description: "KDE Plasma Desktop, DERP" + screenshot: ":/images/kde.png" + - id: gnome + package: gnome + name: GNOME + description: GNU Networked Object Modeling Environment Desktop + screenshot: ":/images/gnome.png" From fd75b3378418efd3106d8b6b874b3fef96447454 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:17:30 +0200 Subject: [PATCH 25/44] [libcalamares] Add default constructor to TranslatedString --- src/libcalamares/locale/TranslatableConfiguration.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index 0735a2274..b2f598069 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -44,6 +44,9 @@ public: /** @brief Not-actually-translated string. */ TranslatedString( const QString& string ); + /// @brief Empty string + TranslatedString() + : TranslatedString( QString() ) {} int count() const { return m_strings.count(); } From 56db9e93412c897bc86be85b2c99ab5379617360 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:17:50 +0200 Subject: [PATCH 26/44] [packagechooser] Use translated strings --- src/modules/packagechooser/PackageChooserPage.cpp | 4 ++-- src/modules/packagechooser/PackageModel.cpp | 4 ++-- src/modules/packagechooser/PackageModel.h | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 60becf64f..0587af190 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -54,9 +54,9 @@ PackageChooserPage::currentChanged( const QModelIndex& index ) { if ( !index.isValid() || !ui->products->selectionModel()->hasSelection() ) { - ui->productName->setText( m_introduction.name ); + ui->productName->setText( m_introduction.name.get() ); ui->productScreenshot->setPixmap( m_introduction.screenshot ); - ui->productDescription->setText( m_introduction.description ); + ui->productDescription->setText( m_introduction.description.get() ); } else { diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index aa8dd39fc..f133f4fbd 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -118,11 +118,11 @@ PackageListModel::data( const QModelIndex& index, int role ) const if ( role == Qt::DisplayRole /* Also PackageNameRole */ ) { - return m_packages[ row ].name; + return m_packages[ row ].name.get(); } else if ( role == DescriptionRole ) { - return m_packages[ row ].description; + return m_packages[ row ].description.get(); } else if ( role == ScreenshotRole ) { diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 7f8fff8ec..68e19a25d 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -19,6 +19,7 @@ #ifndef PACKAGEMODEL_H #define PACKAGEMODEL_H +#include "locale/TranslatableConfiguration.h" #include "utils/NamedEnum.h" #include @@ -41,9 +42,8 @@ struct PackageItem QString id; // TODO: may need more than one QString package; - // TODO: name and description are localized - QString name; - QString description; + CalamaresUtils::Locale::TranslatedString name; + CalamaresUtils::Locale::TranslatedString description; // TODO: may be more than one QPixmap screenshot; From fee2297e67639cdcd0a10f4889fec87cc747237c Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:24:53 +0200 Subject: [PATCH 27/44] [packagechooser] Fix fallthrough situation - Add a FALLTHRU macro to annotate fallthrough situations in both Clang and GCC, - Annotate intentional fallthroughs. - Add missing break which meant that the selection mode was always multiple-selection. --- CMakeLists.txt | 4 ++-- src/modules/packagechooser/PackageChooserPage.cpp | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e38c1db9b..e28d28f38 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -198,7 +198,7 @@ if( CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) ) string( APPEND CMAKE_CXX_FLAGS " ${CLANG_WARNINGS}" ) endforeach() - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='//'" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='//' -DFALLTHRU='[[clang::fallthrough]]'") # Third-party code where we don't care so much about compiler warnings # (because it's uncomfortable to patch) get different flags; use @@ -225,7 +225,7 @@ else() set( SUPPRESS_3RDPARTY_WARNINGS "" ) set( SUPPRESS_BOOST_WARNINGS "" ) - set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='__builtin_unreachable();'" ) + set( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DNOTREACHED='__builtin_unreachable();' -DFALLTHRU='/* */'" ) endif() # Use mark_thirdparty_code() to reduce warnings from the compiler diff --git a/src/modules/packagechooser/PackageChooserPage.cpp b/src/modules/packagechooser/PackageChooserPage.cpp index 0587af190..6f565c914 100644 --- a/src/modules/packagechooser/PackageChooserPage.cpp +++ b/src/modules/packagechooser/PackageChooserPage.cpp @@ -41,9 +41,12 @@ PackageChooserPage::PackageChooserPage( PackageChooserMode mode, QWidget* parent switch ( mode ) { case PackageChooserMode::Optional: + FALLTHRU; case PackageChooserMode::Required: ui->products->setSelectionMode( QAbstractItemView::SingleSelection ); + break; case PackageChooserMode::OptionalMultiple: + FALLTHRU; case PackageChooserMode::RequiredMultiple: ui->products->setSelectionMode( QAbstractItemView::ExtendedSelection ); } From 6a8e10837d044dc892804a5120ae4b462556f625 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:26:04 +0200 Subject: [PATCH 28/44] [libcalamares] Drop unneeded debugging --- src/libcalamares/locale/TranslatableConfiguration.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index 82923a5fa..b3b5259c9 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -79,7 +79,6 @@ TranslatedString::get( const QLocale& locale ) const localeName = QStringLiteral( "sr@latin" ); } - cDebug() << "Getting locale" << localeName; if ( m_strings.contains( localeName ) ) { return m_strings[ localeName ]; From 8d3546f0b3a4c1b8ceeb4467f8e80a2b9f8ea503 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 00:31:05 +0200 Subject: [PATCH 29/44] [packagechooser] Expand the example config with translated entries --- src/modules/packagechooser/packagechooser.conf | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index 391e1f325..7d60b50a4 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -44,12 +44,14 @@ items: - id: "" package: "" name: "No Desktop" + name[nl]: "Geen desktop" description: "Please pick a desktop environment from the list. If you don't want to install a desktop, that's fine, your system will start up in text-only mode and you can install a desktop environment later." + description[nl]: "Kies eventueel een desktop-omgeving uit deze lijst. Als u geen desktop-omgeving wenst te gebruiken, kies er dan geen. In dat geval start het systeem straks op in tekst-modus en kunt u later alsnog een desktop-omgeving installeren." screenshot: ":/images/no-selection.png" - id: kde package: kde name: Plasma Desktop - description: "KDE Plasma Desktop, DERP" + description: "KDE Plasma Desktop, simple by default, a clean work area for real-world usage which intends to stay out of your way. Plasma is powerful when needed, enabling the user to create the workflow that makes them more effective to complete their tasks." screenshot: ":/images/kde.png" - id: gnome package: gnome From 4febe477cf82e1cf27f0c27a7a07822d8ba08131 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 11:53:35 +0200 Subject: [PATCH 30/44] [libcalamares] Add isEmpty() to TranslatedString - Massage the implementation a bit, don't insert a meaningless copy of the key as the untranslated message. - Add isEmpty() to check for presence of the untranslated message. - Document API. - Update tests. --- src/libcalamares/locale/Tests.cpp | 33 ++++++++++++++++++- .../locale/TranslatableConfiguration.cpp | 4 --- .../locale/TranslatableConfiguration.h | 16 ++++++++- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/src/libcalamares/locale/Tests.cpp b/src/libcalamares/locale/Tests.cpp index 664390511..fa84cd2fb 100644 --- a/src/libcalamares/locale/Tests.cpp +++ b/src/libcalamares/locale/Tests.cpp @@ -96,6 +96,10 @@ someLanguages() } +/** @brief Check consistency of test data + * Check that all the languages used in testing, are actually enabled + * in Calamares translations. + */ void LocaleTests::testTranslatableLanguages() { @@ -108,12 +112,19 @@ LocaleTests::testTranslatableLanguages() } } +/** @brief Test strings with no translations + */ void LocaleTests::testTranslatableConfig1() { + CalamaresUtils::Locale::TranslatedString ts0; + QVERIFY( ts0.isEmpty() ); + QCOMPARE( ts0.count(), 1 ); // the empty string + QCOMPARE( QLocale().name(), "C" ); // Otherwise plain get() is dubious CalamaresUtils::Locale::TranslatedString ts1( "Hello" ); QCOMPARE( ts1.count(), 1 ); + QVERIFY( !ts1.isEmpty() ); QCOMPARE( ts1.get(), "Hello" ); QCOMPARE( ts1.get( QLocale( "nl" ) ), "Hello" ); @@ -122,11 +133,14 @@ LocaleTests::testTranslatableConfig1() map.insert( "description", "description (no language)" ); CalamaresUtils::Locale::TranslatedString ts2( map, "description" ); QCOMPARE( ts2.count(), 1 ); + QVERIFY( !ts2.isEmpty() ); QCOMPARE( ts2.get(), "description (no language)" ); QCOMPARE( ts2.get( QLocale( "nl" ) ), "description (no language)" ); } +/** @bref Test strings with translations. + */ void LocaleTests::testTranslatableConfig2() { @@ -143,11 +157,22 @@ LocaleTests::testTranslatableConfig2() } } + // If there's no untranslated string in the map, it is considered empty + CalamaresUtils::Locale::TranslatedString ts0( map, "description" ); + QVERIFY( ts0.isEmpty() ); // Because no untranslated string + QCOMPARE( ts0.count(), + someLanguages().count() + 1 ); // But there are entries for the translations, plus an empty string + + // expand the map with untranslated entries + map.insert( QString( "description" ), "description (no language)" ); + map.insert( QString( "name" ), "name (no language)" ); + CalamaresUtils::Locale::TranslatedString ts1( map, "description" ); // The +1 is because "" is always also inserted QCOMPARE( ts1.count(), someLanguages().count() + 1 ); + QVERIFY( !ts1.isEmpty() ); - QCOMPARE( ts1.get(), "description" ); // it wasn't set + QCOMPARE( ts1.get(), "description (no language)" ); // it wasn't set QCOMPARE( ts1.get( QLocale( "nl" ) ), "description (language nl)" ); for ( const auto& language : someLanguages() ) { @@ -167,4 +192,10 @@ LocaleTests::testTranslatableConfig2() CalamaresUtils::Locale::TranslatedString ts2( map, "name" ); // We skipped dutch this time QCOMPARE( ts2.count(), someLanguages().count() ); + QVERIFY( !ts2.isEmpty() ); + + // This key doesn't exist + CalamaresUtils::Locale::TranslatedString ts3( map, "front" ); + QVERIFY( ts3.isEmpty() ); + QCOMPARE( ts3.count(), 1 ); // The empty string } diff --git a/src/libcalamares/locale/TranslatableConfiguration.cpp b/src/libcalamares/locale/TranslatableConfiguration.cpp index b3b5259c9..7493c836c 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.cpp +++ b/src/libcalamares/locale/TranslatableConfiguration.cpp @@ -38,10 +38,6 @@ TranslatedString::TranslatedString( const QVariantMap& map, const QString& key ) { // Get the un-decorated value for the key QString value = CalamaresUtils::getString( map, key ); - if ( value.isEmpty() ) - { - value = key; - } m_strings[ QString() ] = value; for ( auto it = map.constKeyValueBegin(); it != map.constKeyValueEnd(); ++it ) diff --git a/src/libcalamares/locale/TranslatableConfiguration.h b/src/libcalamares/locale/TranslatableConfiguration.h index b2f598069..a055cbfbd 100644 --- a/src/libcalamares/locale/TranslatableConfiguration.h +++ b/src/libcalamares/locale/TranslatableConfiguration.h @@ -46,9 +46,23 @@ public: TranslatedString( const QString& string ); /// @brief Empty string TranslatedString() - : TranslatedString( QString() ) {} + : TranslatedString( QString() ) + { + } + /** @brief How many strings (translations) are there? + * + * This is always at least 1 (for the untranslated string), + * but may be more than 1 even when isEmpty() is true -- + * if there is no untranslated version, for instance. + */ int count() const { return m_strings.count(); } + /** @brief Consider this string empty? + * + * Only the state of the untranslated string is considered, + * so count() may be more than 1 even while the string is empty. + */ + bool isEmpty() const { return m_strings[ QString() ].isEmpty(); } /// @brief Gets the string in the current locale QString get() const; From 6e05a1ef0550e6f8026334383fb2b46754581920 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 12:02:29 +0200 Subject: [PATCH 31/44] [packagechooser] Load translated strings as well - This makes it possible to put the translations into the config file, and have them displayed when the Calamares language changes. --- .../packagechooser/PackageChooserViewStep.cpp | 26 +------------ src/modules/packagechooser/PackageModel.cpp | 38 +++++++++++++++++-- src/modules/packagechooser/PackageModel.h | 18 +++++++++ 3 files changed, 53 insertions(+), 29 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index 4476eb9e6..a3b853b39 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -232,31 +232,7 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) continue; } - QString id = CalamaresUtils::getString( item_map, "id" ); - QString package = CalamaresUtils::getString( item_map, "package" ); - QString name = CalamaresUtils::getString( item_map, "name" ); - QString description = CalamaresUtils::getString( item_map, "description" ); - QString screenshot = CalamaresUtils::getString( item_map, "screenshot" ); - - if ( name.isEmpty() && id.isEmpty() ) - { - name = tr( "No product" ); - } - else if ( name.isEmpty() ) - { - cWarning() << "PackageChooser item" << id << "has an empty name."; - continue; - } - if ( description.isEmpty() ) - { - description = tr( "No description provided." ); - } - if ( screenshot.isEmpty() ) - { - screenshot = QStringLiteral( ":/images/no-selection.png" ); - } - - m_model->addPackage( PackageItem { id, package, name, description, screenshot } ); + m_model->addPackage( PackageItem( item_map ) ); } } diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index f133f4fbd..3283cbe6f 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -19,6 +19,7 @@ #include "PackageModel.h" #include "utils/Logger.h" +#include "utils/Variant.h" const NamedEnumTable< PackageChooserMode >& roleNames() @@ -73,6 +74,31 @@ PackageItem::PackageItem( const QString& a_id, { } +PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) + : id( CalamaresUtils::getString( item_map, "id" ) ) + , package( CalamaresUtils::getString( item_map, "package" ) ) + , name( CalamaresUtils::Locale::TranslatedString( item_map, "name" ) ) + , description( CalamaresUtils::Locale::TranslatedString( item_map, "description" ) ) + , screenshot( CalamaresUtils::getString( item_map, "screenshot" ) ) +{ + if ( name.isEmpty() && id.isEmpty() ) + { + name = QObject::tr( "No product" ); + } + else if ( name.isEmpty() ) + { + cWarning() << "PackageChooser item" << id << "has an empty name."; + } + if ( description.isEmpty() ) + { + description = QObject::tr( "No description provided." ); + } + if ( screenshot.isNull() ) + { + screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); + } +} + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) @@ -90,10 +116,14 @@ PackageListModel::~PackageListModel() {} void PackageListModel::addPackage( PackageItem&& p ) { - int c = m_packages.count(); - beginInsertRows( QModelIndex(), c, c ); - m_packages.append( p ); - endInsertRows(); + // Only add valid packages + if ( !p.name.isEmpty() ) + { + int c = m_packages.count(); + beginInsertRows( QModelIndex(), c, c ); + m_packages.append( p ); + endInsertRows(); + } } int diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 68e19a25d..f42ff3123 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -56,12 +56,26 @@ struct PackageItem */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description ); + /** @brief Creates a PackageItem from given strings. + * + * Set all the text members and load the screenshot from the given + * @p screenshotPath, which may be a QRC path (:/path/in/qrc) or + * a filesystem path, whatever QPixmap understands. + */ PackageItem( const QString& id, const QString& package, const QString& name, const QString& description, const QString& screenshotPath ); + /** @brief Creates a PackageItem from a QVariantMap + * + * This is intended for use when loading PackageItems from a + * configuration map. It will look up the various keys in the map + * and handle translation strings as well. + */ + PackageItem( const QVariantMap& map ); + // TODO: implement this PackageItem fromAppStream( const QString& filename ); }; @@ -75,6 +89,10 @@ public: PackageListModel( QObject* parent ); virtual ~PackageListModel() override; + /** @brief Add a package @p to the model + * + * Only valid packages are added -- that is, they must have a name. + */ void addPackage( PackageItem&& p ); int rowCount( const QModelIndex& index ) const override; From 6c41151f80dcc9d41553a4f80ed4d4f6de989d88 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 12:38:28 +0200 Subject: [PATCH 32/44] [packagechooser] Just one screenshot, and mark package unused --- src/modules/packagechooser/PackageModel.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index f42ff3123..ce384096c 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -40,11 +40,10 @@ const NamedEnumTable< PackageChooserMode >& roleNames(); struct PackageItem { QString id; - // TODO: may need more than one + // FIXME: unused QString package; CalamaresUtils::Locale::TranslatedString name; CalamaresUtils::Locale::TranslatedString description; - // TODO: may be more than one QPixmap screenshot; /// @brief Create blank PackageItem From 8329d7d7dc8072d958fc460785d57f53b646acf3 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 13:34:32 +0200 Subject: [PATCH 33/44] CI: Add an AppData file --- io.calamares.calamares.appdata.xml | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100644 io.calamares.calamares.appdata.xml diff --git a/io.calamares.calamares.appdata.xml b/io.calamares.calamares.appdata.xml new file mode 100644 index 000000000..355f485c2 --- /dev/null +++ b/io.calamares.calamares.appdata.xml @@ -0,0 +1,29 @@ + + + io.calamares.calamares.desktop + CC0-1.0 + GPL-3.0+ + Calamares + Calamares + Calamares + Calamares + Calamares Linux Installer + Calamares Linux Installer + Linux Installatieprogramma Calamares + +

Calamares is an installer program for Linux distributions.

+

Calamares is een installatieprogramma voor Linux distributies.

+
+ https://calamares.io + https://https://github.com/calamares/calamares/issues/ + https://github.com/calamares/calamares/wiki + + + Calamares Welcome + https://calamares.io/images/cal_640.png + + + + calamares + +
From beb5896fa237f3b6bf8045ee94a8fa7b0d7fcc11 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 14:33:57 +0200 Subject: [PATCH 34/44] [packagechooser] Start implementation of AppData loading - Doing a manual read of the XML, since existing appdata libraries don't seem to have a convenient entry for what I need. - Expand tests to loading AppData (currently, they fail). --- src/modules/packagechooser/CMakeLists.txt | 15 +++++ src/modules/packagechooser/PackageModel.cpp | 64 ++++++++++++++++++--- src/modules/packagechooser/PackageModel.h | 14 ++++- src/modules/packagechooser/Tests.cpp | 17 ++++++ src/modules/packagechooser/Tests.h | 1 + 5 files changed, 101 insertions(+), 10 deletions(-) diff --git a/src/modules/packagechooser/CMakeLists.txt b/src/modules/packagechooser/CMakeLists.txt index 4663ccce7..70a86a3bb 100644 --- a/src/modules/packagechooser/CMakeLists.txt +++ b/src/modules/packagechooser/CMakeLists.txt @@ -1,4 +1,15 @@ find_package( Qt5 COMPONENTS Core Gui Widgets REQUIRED ) +set( _extra_libraries "" ) + +### OPTIONAL AppData XML support in PackageModel +# +# +find_package(Qt5 COMPONENTS Xml) +if ( Qt5Xml_FOUND ) + add_definitions( -DHAVE_XML ) + list( APPEND _extra_libraries Qt5::Xml ) +endif() + calamares_add_plugin( packagechooser TYPE viewmodule @@ -13,6 +24,7 @@ calamares_add_plugin( packagechooser page_package.ui LINK_PRIVATE_LIBRARIES calamaresui + ${_extra_libraries} SHARED_LIB ) @@ -23,8 +35,11 @@ if( ECM_FOUND AND BUILD_TESTING ) packagechoosertest LINK_LIBRARIES ${CALAMARES_LIBRARIES} + calamares_viewmodule_packagechooser Qt5::Core Qt5::Test + Qt5::Gui + ${_extra_libraries} ) calamares_automoc( packagechoosertest) endif() diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 3283cbe6f..f13564d5e 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -21,6 +21,11 @@ #include "utils/Logger.h" #include "utils/Variant.h" +#ifdef HAVE_XML +#include +#include +#endif + const NamedEnumTable< PackageChooserMode >& roleNames() { @@ -41,13 +46,6 @@ roleNames() return names; } -PackageItem -PackageItem::fromAppStream( const QString& filename ) -{ - // TODO: implement this - return PackageItem {}; -} - PackageItem::PackageItem() {} PackageItem::PackageItem( const QString& a_id, @@ -99,6 +97,56 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) } } +#ifdef HAVE_XML +QDomDocument +loadAppData( const QString& fileName ) +{ + QFile file( fileName ); + if ( !file.open( QIODevice::ReadOnly ) ) + { + return QDomDocument(); + } + QDomDocument doc( "AppData" ); + if ( !doc.setContent( &file ) ) + { + file.close(); + return QDomDocument(); + } + file.close(); + return doc; +} + +QString +getChildText( const QDomNode& n, const QString& tagName ) +{ + QDomElement e = n.firstChildElement( tagName ); + return e.isNull() ? QString() : e.text(); +} +#endif + +PackageItem +PackageItem::fromAppData( const QString& fileName ) +{ +#ifdef HAVE_XML + QDomDocument doc = loadAppData( fileName ); + if ( doc.isNull() ) + { + return PackageItem(); + } + + QDomElement componentNode = doc.documentElement(); + if ( !componentNode.isNull() && componentNode.tagName() == "component" ) + { + QString id = getChildText( componentNode, "id" ); + cDebug() << "Got AppData id" << id; + } + + return PackageItem(); +#else + return PackageItem(); +#endif +} + PackageListModel::PackageListModel( QObject* parent ) : QAbstractListModel( parent ) @@ -117,7 +165,7 @@ void PackageListModel::addPackage( PackageItem&& p ) { // Only add valid packages - if ( !p.name.isEmpty() ) + if ( p.isValid() ) { int c = m_packages.count(); beginInsertRows( QModelIndex(), c, c ); diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index ce384096c..7e79b98f1 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -75,8 +75,18 @@ struct PackageItem */ PackageItem( const QVariantMap& map ); - // TODO: implement this - PackageItem fromAppStream( const QString& filename ); + /** @brief Is this item valid? + * + * A valid item has an untranslated name available. + */ + bool isValid() const { return !name.isEmpty(); } + + /** @brief Loads an AppData XML file and returns a PackageItem + * + * Requires XML support in libcalamares, if not present will + * return invalid PackageItems. + */ + static PackageItem fromAppData( const QString& filename ); }; using PackageList = QVector< PackageItem >; diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index c016f1808..6cbab8e38 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -18,6 +18,8 @@ #include "Tests.h" +#include "PackageModel.h" + #include QTEST_GUILESS_MAIN( PackageChooserTests ) @@ -36,3 +38,18 @@ PackageChooserTests::testBogus() { QVERIFY( true ); } + +void +PackageChooserTests::testAppData() +{ + // Path from the build-dir + QString appdataName( "../io.calamares.calamares.appdata.xml" ); + QVERIFY( QFile::exists( appdataName ) ); + + PackageItem p = PackageItem::fromAppData( appdataName ); +#ifdef HAVE_XML + QVERIFY( p.isValid() ); +#else + QVERIFY( !p.isValid() ); +#endif +} diff --git a/src/modules/packagechooser/Tests.h b/src/modules/packagechooser/Tests.h index bc257f5a5..62efe92cc 100644 --- a/src/modules/packagechooser/Tests.h +++ b/src/modules/packagechooser/Tests.h @@ -31,6 +31,7 @@ public: private Q_SLOTS: void initTestCase(); void testBogus(); + void testAppData(); }; #endif From 6821b14d009b92d956f9178232eb24ca3bf4f8cc Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 14:41:40 +0200 Subject: [PATCH 35/44] [packagechooser] Enable logging in tests --- src/modules/packagechooser/PackageModel.cpp | 4 ++++ src/modules/packagechooser/Tests.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index f13564d5e..9a572f036 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -128,6 +128,8 @@ PackageItem PackageItem::fromAppData( const QString& fileName ) { #ifdef HAVE_XML + cDebug() << "Loading AppData XML from" << fileName; + QDomDocument doc = loadAppData( fileName ); if ( doc.isNull() ) { @@ -143,6 +145,8 @@ PackageItem::fromAppData( const QString& fileName ) return PackageItem(); #else + cWarning() << "Loading AppData XML is not supported."; + return PackageItem(); #endif } diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 6cbab8e38..d9cbbf4ed 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -20,6 +20,8 @@ #include "PackageModel.h" +#include "utils/Logger.h" + #include QTEST_GUILESS_MAIN( PackageChooserTests ) @@ -31,6 +33,7 @@ PackageChooserTests::~PackageChooserTests() {} void PackageChooserTests::initTestCase() { + Logger::setupLogLevel( Logger::LOGDEBUG ); } void From 431c4de77fe2c7d7647be00e5051694c5a2b7805 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:19:20 +0200 Subject: [PATCH 36/44] [packagechooser] Use GUI for tests - Because we'll be creating Pixmaps, we need to have a GUI main. --- src/modules/packagechooser/Tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index d9cbbf4ed..e15397613 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -24,7 +24,7 @@ #include -QTEST_GUILESS_MAIN( PackageChooserTests ) +QTEST_MAIN( PackageChooserTests ) PackageChooserTests::PackageChooserTests() {} From fb547364c73c8d36e5b6ed0d2c74ded1e3447513 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:36:34 +0200 Subject: [PATCH 37/44] [packagechooser] Complete parsing of AppData - Document all the static inline methods that do the work - Fill up a QVariantMap from , and

elements, and use that to initialize the PackageItem. --- src/modules/packagechooser/PackageModel.cpp | 152 +++++++++++++++++++- 1 file changed, 147 insertions(+), 5 deletions(-) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 9a572f036..29890ee9b 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -23,6 +23,7 @@ #ifdef HAVE_XML #include +#include #include #endif @@ -98,7 +99,12 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) } #ifdef HAVE_XML -QDomDocument +/** @brief try to load the given @p fileName XML document + * + * Returns a QDomDocument, which will be valid iff the file can + * be read and contains valid XML data. + */ +static inline QDomDocument loadAppData( const QString& fileName ) { QFile file( fileName ); @@ -116,12 +122,138 @@ loadAppData( const QString& fileName ) return doc; } -QString +/** @brief gets the text of child element @p tagName + */ +static inline QString getChildText( const QDomNode& n, const QString& tagName ) { QDomElement e = n.firstChildElement( tagName ); return e.isNull() ? QString() : e.text(); } + +/** @brief Gets a suitable screenshot path + * + * The element contains zero or more + * elements, which can have a *type* associated with them. + * Scan the screenshot elements, return the path + * for the one labeled with type=default or, if there is no + * default, the first element. + */ +static inline QString +getScreenshotPath( const QDomNode& n ) +{ + QDomElement shotsNode = n.firstChildElement( "screenshots" ); + if ( shotsNode.isNull() ) + { + return QString(); + } + + const QDomNodeList shotList = shotsNode.childNodes(); + int firstScreenshot = -1; // Use which screenshot node? + for ( int i = 0; i < shotList.count(); ++i ) + { + if ( !shotList.at( i ).isElement() ) + { + continue; + } + QDomElement e = shotList.at( i ).toElement(); + if ( e.tagName() != "screenshot" ) + { + continue; + } + // If none has the "type=default" attribute, use the first one + if ( firstScreenshot < 0 ) + { + firstScreenshot = i; + } + // But type=default takes precedence. + if ( e.hasAttribute( "type" ) && e.attribute( "type" ) == "default" ) + { + firstScreenshot = i; + break; + } + } + + if ( firstScreenshot >= 0 ) + { + return shotList.at( firstScreenshot ).firstChildElement( "image" ).text(); + } + + return QString(); +} + +/** @brief Returns language of the given element @p e + * + * Transforms the attribute value for xml:lang to something + * suitable for TranslatedString (e.g. [lang]). + */ +static inline QString +getLanguage( const QDomElement& e ) +{ + QString language = e.attribute( "xml:lang" ); + if ( !language.isEmpty() ) + { + language.replace( '-', '_' ); + language.prepend( '[' ); + language.append( ']' ); + } + return language; +} + +/** @brief Scan the list of @p children for @p tagname elements and add them to the map + * + * Uses @p mapname instead of @p tagname for the entries in map @p m + * to allow renaming from XML to map keys (in particular for + * TranslatedString). Also transforms xml:lang attributes to suitable + * key-decorations on @p mapname. + */ +static inline void +fillMap( QVariantMap& m, const QDomNodeList& children, const QString& tagname, const QString& mapname ) +{ + for ( int i = 0; i < children.count(); ++i ) + { + if ( !children.at( i ).isElement() ) + { + continue; + } + + QDomElement e = children.at( i ).toElement(); + if ( e.tagName() != tagname ) + { + continue; + } + + m[ mapname + getLanguage( e ) ] = e.text(); + } +} + +/** @brief gets the and elements +* +* Builds up a map of the elements (which may have a *lang* +* attribute to indicate translations and paragraphs of the +* element (also with lang). Uses the

+* elements to supplement the description if no description +* is available for a given language. +* +* Returns a map with keys suitable for use by TranslatedString. +*/ +static inline QVariantMap +getNameAndSummary( const QDomNode& n ) +{ + QVariantMap m; + + const QDomNodeList children = n.childNodes(); + fillMap( m, children, "name", "name" ); + fillMap( m, children, "summary", "description" ); + + const QDomElement description = n.firstChildElement( "description" ); + if ( !description.isNull() ) + { + fillMap( m, description.childNodes(), "p", "description" ); + } + + return m; +} #endif PackageItem @@ -129,7 +261,7 @@ PackageItem::fromAppData( const QString& fileName ) { #ifdef HAVE_XML cDebug() << "Loading AppData XML from" << fileName; - + QDomDocument doc = loadAppData( fileName ); if ( doc.isNull() ) { @@ -140,13 +272,23 @@ PackageItem::fromAppData( const QString& fileName ) if ( !componentNode.isNull() && componentNode.tagName() == "component" ) { QString id = getChildText( componentNode, "id" ); - cDebug() << "Got AppData id" << id; + if ( id.isEmpty() ) + { + return PackageItem(); + } + + QString screenshotPath = getScreenshotPath( componentNode ); + + QVariantMap map = getNameAndSummary( componentNode ); + map.insert( "id", id ); + map.insert( "screenshot", screenshotPath ); + return PackageItem( map ); } return PackageItem(); #else cWarning() << "Loading AppData XML is not supported."; - + return PackageItem(); #endif } From 9a8b2c5a1e189a1870b7ccec49f01b7fedc1d254 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:45:14 +0200 Subject: [PATCH 38/44] [packagechooser] CHeck that AppData load was succesful --- src/modules/packagechooser/Tests.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index e15397613..5dec8a288 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -52,6 +52,13 @@ PackageChooserTests::testAppData() PackageItem p = PackageItem::fromAppData( appdataName ); #ifdef HAVE_XML QVERIFY( p.isValid() ); + QCOMPARE( p.id, "io.calamares.calamares.desktop" ); + QCOMPARE( p.name.get(), "Calamares" ); + // The entry has precedence + QCOMPARE( p.description.get(), "Calamares is an installer program for Linux distributions." ); + // .. but en_GB doesn't have an entry in description, so uses + QCOMPARE( p.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); + QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); #else QVERIFY( !p.isValid() ); #endif From d72391942ffe6c0bf34482fd1c55566061b45618 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 15:55:27 +0200 Subject: [PATCH 39/44] [packagechooser] Implement AppData loading - An item can refer to *appdata* and load that, or provide the data in the config file itself. - Fix documentation about translations. --- .../packagechooser/PackageChooserViewStep.cpp | 9 ++++++- .../packagechooser/packagechooser.conf | 24 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index a3b853b39..fadacf8d4 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -232,7 +232,14 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) continue; } - m_model->addPackage( PackageItem( item_map ) ); + if ( item_map.contains( "appdata" ) ) + { + m_model->addPackage( PackageItem::fromAppData( CalamaresUtils::getString( item_map, "appdata" ) ) ); + } + else + { + m_model->addPackage( PackageItem( item_map ) ); + } } } diff --git a/src/modules/packagechooser/packagechooser.conf b/src/modules/packagechooser/packagechooser.conf index 7d60b50a4..f20d1da77 100644 --- a/src/modules/packagechooser/packagechooser.conf +++ b/src/modules/packagechooser/packagechooser.conf @@ -24,8 +24,11 @@ mode: required # pretty short list to avoid overwhelming the UI. This is a list # of objects, and the items are displayed in list order. # -# Each item has an id, which is used in setting # the value of -# *packagechooser_*). The following fields +# Either provide the data for an item in the list (using the keys +# below), or use existing AppData XML files as a source for the data. +# +# For data provided by the list: the item has an id, which is used in +# setting the value of *packagechooser_*). The following fields # are mandatory: # # - *id* ID for the product. The ID "" is special, and is used for @@ -33,13 +36,24 @@ mode: required # selecting none. # - *package* Package name for the product. While mandatory, this is # not actually used anywhere. -# - *name* Human-readable, but untranslated, name of the product. -# - *description* Human-readable, but untranslated, description. +# - *name* Human-readable name of the product. To provide translations, +# add a *[lang]* decoration as part of the key name, e.g. `name[nl]` +# for Dutch. The list of usable languages can be found in +# `CMakeLists.txt` or as part of the debug output of Calamares. +# - *description* Human-readable description. These can be translated +# as well. # - *screenshot* Path to a single screenshot of the product. May be # a filesystem path or a QRC path (e.g. ":/images/no-selection.png"). # # Use the empty string "" as ID / key for the "no selection" item if # you want to customize the display of that item as well. +# +# For data provided by AppData XML: the item has an *appdata* +# key which points to an AppData XML file in the local filesystem. +# This file is parsed to provide the id (from AppData id), name +# (from AppData name), description (from AppData description paragraphs +# or the summary entries), and a screenshot (the defautl screenshot +# from AppData). No package is set (but that is unused anyway). items: - id: "" package: "" @@ -58,5 +72,5 @@ items: name: GNOME description: GNU Networked Object Modeling Environment Desktop screenshot: ":/images/gnome.png" - + - appdata: ../io.calamares.calamares.appdata.xml From 6ddae94628d3c3b9cbae028306c3896727477cde Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:36:35 +0200 Subject: [PATCH 40/44] [packagechooser] Allow to override some of AppData - The ID and Screenshot entries might be weird in AppData (in particular, a remove URL) so put those back under the control of Calamares even when using AppData as the source of descriptions. --- .../packagechooser/PackageChooserViewStep.cpp | 2 +- src/modules/packagechooser/PackageModel.cpp | 23 ++++++++++++++++--- src/modules/packagechooser/PackageModel.h | 8 ++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/modules/packagechooser/PackageChooserViewStep.cpp b/src/modules/packagechooser/PackageChooserViewStep.cpp index fadacf8d4..6df785a06 100644 --- a/src/modules/packagechooser/PackageChooserViewStep.cpp +++ b/src/modules/packagechooser/PackageChooserViewStep.cpp @@ -234,7 +234,7 @@ PackageChooserViewStep::fillModel( const QVariantList& items ) if ( item_map.contains( "appdata" ) ) { - m_model->addPackage( PackageItem::fromAppData( CalamaresUtils::getString( item_map, "appdata" ) ) ); + m_model->addPackage( PackageItem::fromAppData( item_map ) ); } else { diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index 29890ee9b..bddc26c7c 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -257,9 +257,15 @@ getNameAndSummary( const QDomNode& n ) #endif PackageItem -PackageItem::fromAppData( const QString& fileName ) +PackageItem::fromAppData( const QVariantMap& item_map ) { #ifdef HAVE_XML + QString fileName = CalamaresUtils::getString( item_map, "appdata" ); + if ( fileName.isEmpty() ) + { + cWarning() << "Can't load AppData without a suitable key."; + return PackageItem(); + } cDebug() << "Loading AppData XML from" << fileName; QDomDocument doc = loadAppData( fileName ); @@ -271,17 +277,28 @@ PackageItem::fromAppData( const QString& fileName ) QDomElement componentNode = doc.documentElement(); if ( !componentNode.isNull() && componentNode.tagName() == "component" ) { - QString id = getChildText( componentNode, "id" ); + // An "id" entry in the Calamares config overrides ID in the AppData + QString id = CalamaresUtils::getString( item_map, "id" ); + if ( id.isEmpty() ) + { + id = getChildText( componentNode, "id" ); + } if ( id.isEmpty() ) { return PackageItem(); } - QString screenshotPath = getScreenshotPath( componentNode ); + // A "screenshot" entry in the Calamares config overrides AppData + QString screenshotPath = CalamaresUtils::getString( item_map, "screenshot" ); + if ( screenshotPath.isEmpty() ) + { + screenshotPath = getScreenshotPath( componentNode ); + } QVariantMap map = getNameAndSummary( componentNode ); map.insert( "id", id ); map.insert( "screenshot", screenshotPath ); + return PackageItem( map ); } diff --git a/src/modules/packagechooser/PackageModel.h b/src/modules/packagechooser/PackageModel.h index 7e79b98f1..869e124f0 100644 --- a/src/modules/packagechooser/PackageModel.h +++ b/src/modules/packagechooser/PackageModel.h @@ -82,11 +82,17 @@ struct PackageItem bool isValid() const { return !name.isEmpty(); } /** @brief Loads an AppData XML file and returns a PackageItem + * + * The @p map must have a key *appdata*. That is used as the + * primary source of information, but keys *id* and *screenshotPath* + * may be used to override parts of the AppData -- so that the + * ID is under the control of Calamares, and the screenshot can be + * forced to a local path available on the installation medium. * * Requires XML support in libcalamares, if not present will * return invalid PackageItems. */ - static PackageItem fromAppData( const QString& filename ); + static PackageItem fromAppData( const QVariantMap& map ); }; using PackageList = QVector< PackageItem >; From 0b72006ffb53fa7ad31a865eb145d8ca5eea34d0 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:41:50 +0200 Subject: [PATCH 41/44] [packagechooser] Use overrides on AppData for example --- src/modules/packagechooser/images/calamares.png | Bin 0 -> 8313 bytes src/modules/packagechooser/packagechooser.conf | 10 +++++++++- src/modules/packagechooser/packagechooser.qrc | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) create mode 100644 src/modules/packagechooser/images/calamares.png diff --git a/src/modules/packagechooser/images/calamares.png b/src/modules/packagechooser/images/calamares.png new file mode 100644 index 0000000000000000000000000000000000000000..452e4450c56c10cda33dcc9c5d03753ace458862 GIT binary patch literal 8313 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 zXkLEnN@images/no-selection.png images/kde.png images/gnome.png + images/calamares.png From 5d4c3ea92c028b7e102cc81dc31ba33e271863a4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:46:36 +0200 Subject: [PATCH 42/44] [packagechooser] Don't give a default pixmap --- src/modules/packagechooser/PackageModel.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/modules/packagechooser/PackageModel.cpp b/src/modules/packagechooser/PackageModel.cpp index bddc26c7c..59c6973ba 100644 --- a/src/modules/packagechooser/PackageModel.cpp +++ b/src/modules/packagechooser/PackageModel.cpp @@ -92,10 +92,6 @@ PackageItem::PackageItem::PackageItem( const QVariantMap& item_map ) { description = QObject::tr( "No description provided." ); } - if ( screenshot.isNull() ) - { - screenshot = QPixmap( QStringLiteral( ":/images/no-selection.png" ) ); - } } #ifdef HAVE_XML From a4362dac654b154e837d4035027c6980ce47101f Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:47:37 +0200 Subject: [PATCH 43/44] [packagechooser] Change tests for modified API --- src/modules/packagechooser/Tests.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 5dec8a288..15b5792bb 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -49,7 +49,10 @@ PackageChooserTests::testAppData() QString appdataName( "../io.calamares.calamares.appdata.xml" ); QVERIFY( QFile::exists( appdataName ) ); - PackageItem p = PackageItem::fromAppData( appdataName ); + QVariantMap m; + m.insert( "appdata", appdataName ); + + PackageItem p = PackageItem::fromAppData( m ); #ifdef HAVE_XML QVERIFY( p.isValid() ); QCOMPARE( p.id, "io.calamares.calamares.desktop" ); @@ -59,6 +62,15 @@ PackageChooserTests::testAppData() // .. but en_GB doesn't have an entry in description, so uses QCOMPARE( p.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( p.screenshot.isNull() ); + + m.insert( "id", "calamares" ); + m.insert( "screenshot", ":/images/calamares.png" ); + PackageItem p_self = PackageItem::fromAppData( m ); + QVERIFY( p.isValid() ); + QCOMPARE( p.id, "calamares" ); + QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( !p.screenshot.isNull() ); #else QVERIFY( !p.isValid() ); #endif From 194a562727e347a32b246613e05836cc405264e4 Mon Sep 17 00:00:00 2001 From: Adriaan de Groot Date: Tue, 6 Aug 2019 22:51:14 +0200 Subject: [PATCH 44/44] [packagechooser] Expand tests with override features --- src/modules/packagechooser/Tests.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/modules/packagechooser/Tests.cpp b/src/modules/packagechooser/Tests.cpp index 15b5792bb..3e7961b92 100644 --- a/src/modules/packagechooser/Tests.cpp +++ b/src/modules/packagechooser/Tests.cpp @@ -52,26 +52,26 @@ PackageChooserTests::testAppData() QVariantMap m; m.insert( "appdata", appdataName ); - PackageItem p = PackageItem::fromAppData( m ); + PackageItem p1 = PackageItem::fromAppData( m ); #ifdef HAVE_XML - QVERIFY( p.isValid() ); - QCOMPARE( p.id, "io.calamares.calamares.desktop" ); - QCOMPARE( p.name.get(), "Calamares" ); + QVERIFY( p1.isValid() ); + QCOMPARE( p1.id, "io.calamares.calamares.desktop" ); + QCOMPARE( p1.name.get(), "Calamares" ); // The entry has precedence - QCOMPARE( p.description.get(), "Calamares is an installer program for Linux distributions." ); + QCOMPARE( p1.description.get(), "Calamares is an installer program for Linux distributions." ); // .. but en_GB doesn't have an entry in description, so uses - QCOMPARE( p.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); - QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); - QVERIFY( p.screenshot.isNull() ); + QCOMPARE( p1.description.get( QLocale( "en_GB" ) ), "Calamares Linux Installer" ); + QCOMPARE( p1.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( p1.screenshot.isNull() ); m.insert( "id", "calamares" ); m.insert( "screenshot", ":/images/calamares.png" ); - PackageItem p_self = PackageItem::fromAppData( m ); - QVERIFY( p.isValid() ); - QCOMPARE( p.id, "calamares" ); - QCOMPARE( p.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); - QVERIFY( !p.screenshot.isNull() ); + PackageItem p2= PackageItem::fromAppData( m ); + QVERIFY( p2.isValid() ); + QCOMPARE( p2.id, "calamares" ); + QCOMPARE( p2.description.get( QLocale( "nl" ) ), "Calamares is een installatieprogramma voor Linux distributies." ); + QVERIFY( !p2.screenshot.isNull() ); #else - QVERIFY( !p.isValid() ); + QVERIFY( !p1.isValid() ); #endif }