diff --git a/src/modules/initcpio/initcpio.conf b/src/modules/initcpio/initcpio.conf index b7161e5ae..21f5704cc 100644 --- a/src/modules/initcpio/initcpio.conf +++ b/src/modules/initcpio/initcpio.conf @@ -1,2 +1,2 @@ --- -kernel: _kernel_ +kernel: linux312 diff --git a/src/modules/netinstall/CMakeLists.txt b/src/modules/netinstall/CMakeLists.txt index 2038a2658..1de1c7505 100644 --- a/src/modules/netinstall/CMakeLists.txt +++ b/src/modules/netinstall/CMakeLists.txt @@ -6,10 +6,10 @@ calamares_add_plugin( netinstall SOURCES NetInstallViewStep.cpp NetInstallPage.cpp - widgets/groupselectionwidget.cpp + PackageTreeItem.cpp + PackageModel.cpp UI page_netinst.ui - widgets/groupselectionwidget.ui RESOURCES netinstall.qrc LINK_PRIVATE_LIBRARIES diff --git a/src/modules/netinstall/NetInstallPage.cpp b/src/modules/netinstall/NetInstallPage.cpp index 5c02d0b1b..84c071db9 100644 --- a/src/modules/netinstall/NetInstallPage.cpp +++ b/src/modules/netinstall/NetInstallPage.cpp @@ -18,7 +18,8 @@ #include "NetInstallPage.h" -#include "widgets/groupselectionwidget.h" +#include "PackageModel.h" + #include "ui_page_netinst.h" #include "GlobalStorage.h" #include "JobQueue.h" @@ -33,6 +34,7 @@ #include #include +#include #include #include #include @@ -62,34 +64,9 @@ void NetInstallPage::readGroups( const QByteArray& yamlData ) { YAML::Node groups = YAML::Load( yamlData.constData() ); Q_ASSERT( groups.IsSequence() ); - - for ( YAML::const_iterator it = groups.begin(); it != groups.end(); ++it ) - { - const YAML::Node groupDefinition = *it; - - QString name( tr( yamlToVariant(groupDefinition["name"]).toByteArray() ) ); - QString description( tr( yamlToVariant(groupDefinition["description"]).toByteArray() ) ); - QStringList packages; - - for ( YAML::const_iterator it = groupDefinition["packages"].begin(); - it != groupDefinition["packages"].end(); ++it ) - packages.append( yamlToVariant(*it).toString() ); - - m_groups[name].name = name; - m_groups[name].description = description; - m_groups[name].packages = packages; - - if ( groupDefinition["selected"] ) - m_groups[name].selected = yamlToVariant( groupDefinition["selected"] ).toBool(); - - if ( groupDefinition["hidden"] ) - m_groups[name].hidden = yamlToVariant( groupDefinition["hidden"] ).toBool(); - - if ( groupDefinition["critical"] ) - m_groups[name].critical = yamlToVariant( groupDefinition["critical"] ).toBool(); - - m_groupOrder.append( name ); - } + QVariantList columnHeadings; + columnHeadings << tr( "Name" ) << tr( "Description" ); + m_groups = new PackageModel( groups, columnHeadings ); } void @@ -104,48 +81,17 @@ NetInstallPage::dataIsHere( QNetworkReply* reply ) readGroups( reply->readAll() ); - QSignalMapper* mapper = new QSignalMapper( this ); - foreach ( const QString& groupKey, m_groupOrder ) - { - Group group = m_groups[groupKey]; - if ( group.hidden ) - { - // Do not present on view. - continue; - } - - GroupSelectionWidget* groupWidget = new GroupSelectionWidget( group.name, group.description, group.packages, group.selected, this ); - m_groupWidgets.insert( groupKey, groupWidget ); - ui->groupswidget->layout()->addWidget( groupWidget ); - - mapper->setMapping( groupWidget, groupKey ); - connect( groupWidget, &GroupSelectionWidget::toggled, mapper, - static_cast(&QSignalMapper::map) ); - } + ui->groupswidget->setModel( m_groups ); + ui->groupswidget->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents ); + ui->groupswidget->header()->setSectionResizeMode( 1, QHeaderView::Stretch ); reply->deleteLater(); emit checkReady( isReady() ); } -QList NetInstallPage::selectedGroups() const +QList NetInstallPage::selectedPackages( bool isCritical ) const { - QList selectedGroups; - - // Add all the groups that are toggled in the view. - for ( auto it = m_groupWidgets.constBegin(); it != m_groupWidgets.constEnd(); it++ ) - { - if ( it.value()->isToggled() ) - selectedGroups += m_groups[it.key()]; - } - - // Add all groups that are hidden but selected. - for ( const Group& group : m_groups.values() ) - { - if ( group.hidden && group.selected ) - selectedGroups += group; - } - - return selectedGroups; + return m_groups->getPackages( isCritical ); } void NetInstallPage::loadGroupList() @@ -157,14 +103,14 @@ void NetInstallPage::loadGroupList() QNetworkRequest request; request.setUrl( QUrl( confUrl ) ); // Follows all redirects except unsafe ones (https to http). - request.setAttribute(QNetworkRequest::FollowRedirectsAttribute, true); + request.setAttribute( QNetworkRequest::FollowRedirectsAttribute, true ); // Not everybody likes the default User Agent used by this class (looking at you, // sourceforge.net), so let's set a more descriptive one. request.setRawHeader( "User-Agent", "Mozilla/5.0 (compatible; Calamares)" ); - connect(&m_networkManager, &QNetworkAccessManager::finished, - this, &NetInstallPage::dataIsHere); - m_networkManager.get(request); + connect( &m_networkManager, &QNetworkAccessManager::finished, + this, &NetInstallPage::dataIsHere ); + m_networkManager.get( request ); } void NetInstallPage::onActivate() diff --git a/src/modules/netinstall/NetInstallPage.h b/src/modules/netinstall/NetInstallPage.h index 7460c9c11..0f4866770 100644 --- a/src/modules/netinstall/NetInstallPage.h +++ b/src/modules/netinstall/NetInstallPage.h @@ -19,6 +19,7 @@ #ifndef NETINSTALLPAGE_H #define NETINSTALLPAGE_H +#include "PackageModel.h" #include "Typedefs.h" #include #include @@ -28,36 +29,16 @@ class QByteArray; class QNetworkReply; class GroupSelectionWidget; +class PackageModel; namespace Ui { class Page_NetInst; } -// Representation of a package group. -struct Group -{ - Group() - : Group( "","",false, false, false ) { } - Group( QString name, QString description, bool selected, bool hidden, bool critical ) - : name( name ), description( description ), selected( selected ), hidden( hidden ), critical( critical ) { } - Group( QString name, QString description ) - : Group( name, description, false, false, false ) { } - - QString name; - QString description; - QStringList packages; - - // See README.md for a description of these fields. - bool selected = false; - bool hidden = false; - bool critical = false; -}; - class NetInstallPage : public QWidget { Q_OBJECT - public: NetInstallPage( QWidget* parent = nullptr ); @@ -70,9 +51,10 @@ public: // in the global storage. This should be called before displaying the page. void loadGroupList(); - // Return a list of groups currently selected. No data is cached here, so - // this function does not run in constant time. - QList selectedGroups() const; + // Returns the list of packages belonging to groups that are + // selected in the view in this given moment. No data is cached here, so + // this function does not have constant time. + QList selectedPackages( bool isCritical ) const; public slots: void dataIsHere( QNetworkReply* ); @@ -91,11 +73,10 @@ private: // Handles connection with the remote URL storing the configuration. QNetworkAccessManager m_networkManager; - QHash m_groups; + PackageModel* m_groups; // For each group name, store the selection widget to retrieve UI // properties. QHash m_groupWidgets; - QList m_groupOrder; }; #endif // NETINSTALLPAGE_H diff --git a/src/modules/netinstall/NetInstallViewStep.cpp b/src/modules/netinstall/NetInstallViewStep.cpp index 3313996b2..a653a0c0e 100644 --- a/src/modules/netinstall/NetInstallViewStep.cpp +++ b/src/modules/netinstall/NetInstallViewStep.cpp @@ -125,32 +125,17 @@ NetInstallViewStep::onLeave() cDebug() << "Leaving netinstall, adding packages to be installed" << "to global storage"; - const QList& selectedGroups = m_widget->selectedGroups(); + QMap packagesWithOperation; + QList installPackages = m_widget->selectedPackages( true ); + QList tryInstallPackages = m_widget->selectedPackages( false ); - if ( !selectedGroups.empty() ) + if ( !installPackages.empty() ) + packagesWithOperation.insert( "install", installPackages ); + if ( !tryInstallPackages.empty() ) + packagesWithOperation.insert( "try-install", tryInstallPackages ); + + if ( !packagesWithOperation.isEmpty() ) { - QMap packagesWithOperation; - QStringList packages, critical_packages; - - // We have two types of groups: "critical" (failing to install any of - // the packages makes Calamares fail) and "non critical" (we only log - // an error if the installation fails). We distinguish them here and select - // the correct package operation. - for (const Group& group : selectedGroups) { - if (group.critical) { - critical_packages += group.packages; - } else { - packages += group.packages; - } - } - - if (!critical_packages.empty()) { - packagesWithOperation.insert( "install", critical_packages ); - } - if (!packages.empty()) { - packagesWithOperation.insert( "try_install", packages); - } - Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); gs->insert( "packageOperations", QVariant( packagesWithOperation ) ); } diff --git a/src/modules/netinstall/page_netinst.ui b/src/modules/netinstall/page_netinst.ui index 3b7a260ec..033f30889 100644 --- a/src/modules/netinstall/page_netinst.ui +++ b/src/modules/netinstall/page_netinst.ui @@ -25,7 +25,7 @@ true - + 0 diff --git a/src/modules/netinstall/widgets/groupselectionwidget.cpp b/src/modules/netinstall/widgets/groupselectionwidget.cpp deleted file mode 100644 index 3048fb01f..000000000 --- a/src/modules/netinstall/widgets/groupselectionwidget.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright 2016, Luca Giambonini - * Copyright 2016, Lisa Vitolo - * - * 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 "groupselectionwidget.h" - -#include - -GroupSelectionWidget::GroupSelectionWidget( QString name, QString description, QStringList packages, bool selected, QWidget* parent ) : - QWidget( parent ), - m_isToggled( false ) -{ - ui.setupUi( this ); - - connect( ui.group, &QCheckBox::toggled, this, &GroupSelectionWidget::toggleGroup ); - - ui.group->setText( name ); - ui.group->setChecked( selected ); // also triggers the toggleGroup slot - ui.description->setText( description ); - const int columns = 4; - const int rows = ( packages.size() - 1 ) / columns + 1; - ui.packageview->setRowCount( rows ); - ui.packageview->setColumnCount( columns ); - - ui.packageview->horizontalHeader()->setSectionResizeMode( QHeaderView::Stretch ); - - int r = 0, c = 0; - for ( int i = 0; i < packages.size(); ++i ) - { - ui.packageview->setItem( r++,c, new QTableWidgetItem( packages.at( i ) ) ); - if ( r == ui.packageview->rowCount() ) - { - ++c; - r = 0; - } - } - - int rowsShown = 6; - rowsShown = rows < rowsShown ? rows : 6; - ui.packageview->setFixedHeight( rowsShown * ui.packageview->rowHeight( 0 ) ); - ui.packageview->hide(); -} - -void GroupSelectionWidget::toggleGroup( bool isToggled ) -{ - m_isToggled = isToggled; - emit toggled( isToggled ); -} - -bool GroupSelectionWidget::isToggled() const -{ - return m_isToggled; -} diff --git a/src/modules/netinstall/widgets/groupselectionwidget.h b/src/modules/netinstall/widgets/groupselectionwidget.h deleted file mode 100644 index 1f7a0fc97..000000000 --- a/src/modules/netinstall/widgets/groupselectionwidget.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2016, Luca Giambonini - * Copyright 2016, Lisa Vitolo - * - * 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 GROUPSELECTIONWIDGET_H -#define GROUPSELECTIONWIDGET_H - -#include "ui_groupselectionwidget.h" - -#include -#include - -// Represents a widget to display and select a group. -class GroupSelectionWidget : public QWidget -{ - Q_OBJECT -public: - explicit GroupSelectionWidget( QString name, QString description, QStringList packages, bool selected, QWidget* parent = nullptr ); - - // Current status of the group: is it selected in the view? - bool isToggled() const; - -signals: - void toggled( bool ); - -public slots: - void toggleGroup( bool isToggled ); - -private: - Ui::GroupSelectionWidget ui; - static QSignalMapper* m_mapper; - - bool m_isToggled; -}; - -#endif // GROUPSELECTIONWIDGET_H diff --git a/src/modules/netinstall/widgets/groupselectionwidget.ui b/src/modules/netinstall/widgets/groupselectionwidget.ui deleted file mode 100644 index 8093b48e1..000000000 --- a/src/modules/netinstall/widgets/groupselectionwidget.ui +++ /dev/null @@ -1,138 +0,0 @@ - - - GroupSelectionWidget - - - - 0 - 0 - 805 - 62 - - - - - 0 - 0 - - - - Frame - - - - - - - - - group - - - - - - - description - - - - - - - - 0 - 0 - - - - - - - - :/images/arrow-down.png:/images/arrow-down.png - - - true - - - false - - - - - - - - - - true - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 0 - - - - QAbstractItemView::NoEditTriggers - - - false - - - false - - - false - - - QAbstractItemView::NoSelection - - - false - - - false - - - - - - - - - - - pushButton - toggled(bool) - packageview - setVisible(bool) - - - 772 - 25 - - - 653 - 61 - - - - - - toggled(bool) - - diff --git a/src/modules/packages/main.py b/src/modules/packages/main.py index 3ec60ff2d..a20833797 100644 --- a/src/modules/packages/main.py +++ b/src/modules/packages/main.py @@ -21,7 +21,7 @@ import subprocess import libcalamares from libcalamares.utils import check_target_env_call, target_env_call -from string import Template + class PackageManager: """ Package manager class. @@ -108,20 +108,10 @@ class PackageManager: elif self.backend == "entropy": check_target_env_call(["equo", "update"]) + def run(self, script): + if script != "": + check_target_env_call(script.split(" ")) -def subst_locale(list): - ret = [] - locale = libcalamares.globalstorage.value("locale") - if locale: - for e in list: - if locale != "en": - entry = Template(e) - ret.append(entry.safe_substitute(LOCALE=locale)) - elif 'LOCALE' not in e: - ret.append(e) - else: - ret = list - return ret def run_operations(pkgman, entry): """ Call package manager with given parameters. @@ -130,14 +120,22 @@ def run_operations(pkgman, entry): :param entry: """ for key in entry.keys(): - entry[key] = subst_locale(entry[key]) if key == "install": pkgman.install(entry[key]) elif key == "try_install": - try: - pkgman.install(entry[key]) - except subprocess.CalledProcessError: - libcalamares.utils.debug("WARNING: could not install packages {}".format(", ".join(entry[key]))) + if isinstance(entry[key], list): + for package in entry[key]: + try: + pkgman.run(package["pre-script"]) + pkgman.install([package["package"]]) + pkgman.run(package["post-script"]) + except subprocess.CalledProcessError: + libcalamares.utils.debug("WARNING: could not install packages {}", package["package"]) + else: + try: + pkgman.install(entry[key]) + except subprocess.CalledProcessError: + libcalamares.utils.debug("WARNING: could not install packages {}".format(", ".join(entry[key]))) elif key == "remove": pkgman.remove(entry[key]) elif key == "try_remove":