From e687608175159e3981b085a1346b0b29fd736aee Mon Sep 17 00:00:00 2001 From: Simon Quigley Date: Tue, 29 Oct 2024 19:23:46 -0500 Subject: [PATCH] Rewrite the pkgselect module and its processing. --- common/fixconkeys-part2 | 1 - common/modules/pkgselect/CMakeLists.txt | 2 +- .../pkgselect/PackageSelectViewStep.cpp | 401 +++++++++---- .../modules/pkgselect/PackageSelectViewStep.h | 113 +++- common/modules/pkgselect/pkgselect.conf | 55 ++ common/modules/pkgselect/pkgselect.ui | 535 +++++------------- .../modules/pkgselectprocess/CMakeLists.txt | 30 + .../pkgselectprocess/PackageSelectProcess.cpp | 390 +++++++++++++ .../pkgselectprocess/PackageSelectProcess.h | 53 ++ common/modules/pkgselectprocess/module.desc | 7 + debian/changelog | 5 +- debian/control | 1 + debian/rules | 10 +- kubuntu/modules/packages.conf | 16 - kubuntu/modules/pkgselect.conf | 53 ++ kubuntu/modules/pkgselect_context.conf | 19 - kubuntu/modules/pkgselect_snap_context.conf | 9 - kubuntu/settings.conf | 16 +- lubuntu/modules/packages.conf | 17 - lubuntu/modules/pkgselect.conf | 55 ++ lubuntu/modules/pkgselect_context.conf | 19 - lubuntu/modules/pkgselect_snap_context.conf | 9 - lubuntu/settings.conf | 16 +- ubuntuunity/modules/packages.conf | 15 - ubuntuunity/modules/pkgselect.conf | 52 ++ ubuntuunity/modules/pkgselect_context.conf | 19 - .../modules/pkgselect_snap_context.conf | 9 - ubuntuunity/settings.conf | 16 +- 28 files changed, 1254 insertions(+), 689 deletions(-) create mode 100644 common/modules/pkgselect/pkgselect.conf create mode 100644 common/modules/pkgselectprocess/CMakeLists.txt create mode 100644 common/modules/pkgselectprocess/PackageSelectProcess.cpp create mode 100644 common/modules/pkgselectprocess/PackageSelectProcess.h create mode 100644 common/modules/pkgselectprocess/module.desc delete mode 100644 kubuntu/modules/packages.conf create mode 100644 kubuntu/modules/pkgselect.conf delete mode 100644 kubuntu/modules/pkgselect_context.conf delete mode 100644 kubuntu/modules/pkgselect_snap_context.conf delete mode 100644 lubuntu/modules/packages.conf create mode 100644 lubuntu/modules/pkgselect.conf delete mode 100644 lubuntu/modules/pkgselect_context.conf delete mode 100644 lubuntu/modules/pkgselect_snap_context.conf delete mode 100644 ubuntuunity/modules/packages.conf create mode 100644 ubuntuunity/modules/pkgselect.conf delete mode 100644 ubuntuunity/modules/pkgselect_context.conf delete mode 100644 ubuntuunity/modules/pkgselect_snap_context.conf diff --git a/common/fixconkeys-part2 b/common/fixconkeys-part2 index 6fca6fe..72b1160 100755 --- a/common/fixconkeys-part2 +++ b/common/fixconkeys-part2 @@ -1,5 +1,4 @@ #!/bin/bash loadkeys "$(cat /dev/shm/fixconkeys-layout)" setupcon --save-only -update-initramfs -c -k all rm /usr/libexec/fixconkeys-part2 diff --git a/common/modules/pkgselect/CMakeLists.txt b/common/modules/pkgselect/CMakeLists.txt index 2ea9424..0dc029d 100644 --- a/common/modules/pkgselect/CMakeLists.txt +++ b/common/modules/pkgselect/CMakeLists.txt @@ -7,7 +7,7 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON ) set( CALAMARES_VERSION_REQUIRED 3.3.9 ) -find_package(ECM ${ECM_VERSION} NO_MODULE) +find_package(ECM "6.0.0" NO_MODULE) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) include(KDEInstallDirs) find_package(KF6 REQUIRED COMPONENTS CoreAddons) diff --git a/common/modules/pkgselect/PackageSelectViewStep.cpp b/common/modules/pkgselect/PackageSelectViewStep.cpp index c9a3b53..3200eb7 100644 --- a/common/modules/pkgselect/PackageSelectViewStep.cpp +++ b/common/modules/pkgselect/PackageSelectViewStep.cpp @@ -1,39 +1,59 @@ #include "PackageSelectViewStep.h" +#include "ui_pkgselect.h" #include "JobQueue.h" #include "GlobalStorage.h" -#include "Branding.h" #include "network/Manager.h" -#include - -PackageSelectViewStep::PackageSelectViewStep( QObject* parent ) - : Calamares::ViewStep( parent ), - m_packageSelections(QVariantMap()), - ui(new Ui::pkgselect) +#include +#include +#include +#include +#include +#include +#include + +/** + * @brief Initializes a new PackageSelectViewStep object. + * @param parent The parent QObject. + */ +PackageSelectViewStep::PackageSelectViewStep(QObject* parent) + : Calamares::ViewStep(parent), + m_packageSelections(), + ui(new Ui::pkgselect), + m_widget(new QWidget()), // Parent set to nullptr + m_connectionsMade(false) { - m_widget = new QWidget(); ui->setupUi(m_widget); + + // Layout Adjustment to Prevent Shifting + // Ensures that hiding/showing elements does not disrupt the layout + QGridLayout* mainLayout = qobject_cast(ui->gridLayout); + if (mainLayout) { + mainLayout->setRowStretch(mainLayout->rowCount(), 1); + } } +/** + * @brief Cleans up the PackageSelectViewStep object. + */ PackageSelectViewStep::~PackageSelectViewStep() { delete ui; delete m_widget; } -QString -PackageSelectViewStep::prettyName() const +QString PackageSelectViewStep::prettyName() const { - return tr( "Customize" ); + return tr("Customize"); } bool PackageSelectViewStep::exists_and_true(const QString& key) const { - return m_packageSelections.contains(key) && m_packageSelections[key].toBool() == true; + return m_packageSelections.contains(key) && m_packageSelections.value(key).toBool(); } QWidget* PackageSelectViewStep::widget() -{ +{ return m_widget; } @@ -62,71 +82,25 @@ bool PackageSelectViewStep::isAtEnd() const return true; } -void PackageSelectViewStep::onActivate() +void PackageSelectViewStep::setConfigurationMap(const QVariantMap& configurationMap) { - // Connect the Minimal Installation radio button - connect(ui->minimal_button, &QRadioButton::toggled, this, [this](bool checked) { - Calamares::Network::Manager network; - if (checked && network.hasInternet()) { - ui->extraparty_scroll->setVisible(false); - ui->extraparty_text->setVisible(false); - ui->mandatory_warning_label->setVisible(false); - - ui->element_button->setChecked(false); - ui->thunderbird_button->setChecked(false); - ui->virtmanager_button->setChecked(false); - ui->krita_button->setChecked(false); - - ui->element_button->setEnabled(false); - ui->thunderbird_button->setEnabled(false); - ui->virtmanager_button->setEnabled(false); - ui->krita_button->setEnabled(false); - } - }); - - // Connect the Normal Installation radio button - connect(ui->normal_button, &QRadioButton::toggled, this, [this](bool checked) { - Calamares::Network::Manager network; - if (checked && network.hasInternet()) { - ui->extraparty_scroll->setVisible(true); - ui->extraparty_text->setVisible(true); - ui->mandatory_warning_label->setVisible(true); - - ui->element_button->setChecked(false); - ui->thunderbird_button->setChecked(false); - ui->virtmanager_button->setChecked(false); - ui->krita_button->setChecked(false); - - ui->element_button->setEnabled(true); - ui->thunderbird_button->setEnabled(true); - ui->virtmanager_button->setEnabled(true); - ui->krita_button->setEnabled(true); - } - }); - - // Connect the Full Installation radio button - connect(ui->full_button, &QRadioButton::toggled, this, [this](bool checked) { - Calamares::Network::Manager network; - if (checked && network.hasInternet()) { - ui->extraparty_scroll->setVisible(true); - ui->extraparty_text->setVisible(true); - ui->mandatory_warning_label->setVisible(true); - - ui->element_button->setChecked(true); - ui->thunderbird_button->setChecked(true); - ui->virtmanager_button->setChecked(true); - ui->krita_button->setChecked(true); - - ui->element_button->setEnabled(false); - ui->thunderbird_button->setEnabled(false); - ui->virtmanager_button->setEnabled(false); - ui->krita_button->setEnabled(false); - } - }); + m_configurationMap = configurationMap; +} - // Disable many bits of functionality if network is not enabled +/** + * @brief Activates the step, setting up the UI based on network availability and configuration. + * + * This method is called when the step becomes active. It handles network checks, + * dynamically creates package selection checkboxes, and connects signal handlers. + */ +void PackageSelectViewStep::onActivate() +{ + // Check network availability Calamares::Network::Manager network; - if (!network.hasInternet()) { + bool hasInternet = network.hasInternet(); + + // Handle network unavailability + if (!hasInternet) { ui->full_button->setVisible(false); ui->full_text->setVisible(false); @@ -140,69 +114,250 @@ void PackageSelectViewStep::onActivate() ui->extraparty_scroll->setVisible(false); ui->extraparty_text->setVisible(false); ui->mandatory_warning_label->setVisible(false); + } - ui->element_button->setChecked(false); - ui->thunderbird_button->setChecked(false); - ui->virtmanager_button->setChecked(false); - ui->krita_button->setChecked(false); + // Dynamically create package checkboxes only once + if (m_packageCheckBoxes.isEmpty()) { + QVariantList additionalPackages = m_configurationMap.value("packages").toMap().value("additional_packages").toList(); + QVBoxLayout* packagesLayout = ui->extraparty_scrollhouse->findChild("packages_layout"); + if (!packagesLayout) { + qWarning() << "packages_layout not found in UI."; + return; + } - ui->element_button->setEnabled(false); - ui->thunderbird_button->setEnabled(false); - ui->virtmanager_button->setEnabled(false); - ui->krita_button->setEnabled(false); + for (const QVariant& var : additionalPackages) { + QVariantMap pkg = var.toMap(); + QString packageId = pkg.value("id").toString(); + QString packageName = pkg.value("name").toString(); + QString packageDescription = pkg.value("description").toString(); + bool isSnap = pkg.value("snap").toBool(); + + // Create checkbox + QCheckBox* checkbox = new QCheckBox(packageName, m_widget); + checkbox->setObjectName(packageId); // Naming as packageId directly + + // Create description label + QLabel* descriptionLabel = new QLabel(packageDescription, m_widget); + QFont descFont = descriptionLabel->font(); + descFont.setPointSize(10); + descFont.setItalic(true); + descriptionLabel->setFont(descFont); + descriptionLabel->setWordWrap(true); + + // Add to layout + packagesLayout->addWidget(checkbox); + packagesLayout->addWidget(descriptionLabel); + + // Store in the map + m_packageCheckBoxes.insert(packageId, checkbox); + + // Connect checkbox toggled signal + connect(checkbox, &QCheckBox::toggled, this, &PackageSelectViewStep::updatePackageSelections); + } } - // Thunderbird exists on Kubuntu already - if (Calamares::Branding::instance()->componentName() == "kubuntu") { - ui->thunderbird_button->setChecked(false); - ui->thunderbird_button->setEnabled(false); - ui->thunderbird_button->setVisible(false); - ui->thunderbird_text->setVisible(false); - ui->thunderbird_spacer->changeSize(0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed); - ui->thunderbird_spacer->invalidate(); + // Handle installation modes + // Connect radio buttons to lambda functions only once + if (!m_connectionsMade) { + connect(ui->minimal_button, &QRadioButton::toggled, this, [this, hasInternet](bool checked) { + if (checked && hasInternet) { + // Hide additional packages UI + ui->extraparty_scroll->setVisible(false); + ui->extraparty_text->setVisible(false); + ui->mandatory_warning_label->setVisible(false); + + // Uncheck and disable all additional package checkboxes + QVariantList removePackages = m_configurationMap.value("packages").toMap().value("minimal_remove_packages").toList(); + for (const QVariant& var : removePackages) { + QString packageId = var.toString(); + QCheckBox* checkbox = m_packageCheckBoxes.value(packageId, nullptr); + if (checkbox) { + checkbox->setChecked(false); + checkbox->setEnabled(false); + } + } + } + }); + + connect(ui->normal_button, &QRadioButton::toggled, this, [this, hasInternet](bool checked) { + if (checked && hasInternet) { + // Show additional packages UI + ui->extraparty_scroll->setVisible(true); + ui->extraparty_text->setVisible(true); + ui->mandatory_warning_label->setVisible(true); + + // Enable all additional package checkboxes + for (auto checkbox : m_packageCheckBoxes) { + if (checkbox) { + checkbox->setEnabled(true); + } + } + } + }); + + connect(ui->full_button, &QRadioButton::toggled, this, [this, hasInternet](bool checked) { + if (checked && hasInternet) { + // Show additional packages UI + ui->extraparty_scroll->setVisible(true); + ui->extraparty_text->setVisible(true); + ui->mandatory_warning_label->setVisible(true); + + // Check and disable all additional package checkboxes + for (auto checkbox : m_packageCheckBoxes) { + if (checkbox) { + checkbox->setChecked(true); + checkbox->setEnabled(false); + } + } + } + }); + + m_connectionsMade = true; } - // Connect the storage items - /// Full/Normal/Minimal - connect(ui->minimal_button, &QRadioButton::toggled, this, &PackageSelectViewStep::updatePackageSelections); - connect(ui->normal_button, &QRadioButton::toggled, this, &PackageSelectViewStep::updatePackageSelections); - connect(ui->full_button, &QRadioButton::toggled, this, &PackageSelectViewStep::updatePackageSelections); - /// Additional Options - connect(ui->updates_button, &QRadioButton::toggled, this, &PackageSelectViewStep::updatePackageSelections); - /// Third-Party Apps - connect(ui->element_button, &QCheckBox::toggled, this, &PackageSelectViewStep::updatePackageSelections); - connect(ui->thunderbird_button, &QCheckBox::toggled, this, &PackageSelectViewStep::updatePackageSelections); - connect(ui->virtmanager_button, &QCheckBox::toggled, this, &PackageSelectViewStep::updatePackageSelections); - connect(ui->krita_button, &QCheckBox::toggled, this, &PackageSelectViewStep::updatePackageSelections); + // Layout Adjustment to Prevent Shifting + // Ensure that hiding/showing elements does not center the remaining widgets + // This is generally handled by Qt's layout system, but adding stretch ensures stability + QGridLayout* mainLayout = qobject_cast(ui->gridLayout); + if (mainLayout) { + mainLayout->setRowStretch(mainLayout->rowCount(), 1); + } } -void -PackageSelectViewStep::onLeave() +/** + * @brief Handles actions to perform when leaving the step, such as storing selected packages. + * + * This method gathers the selected packages, determines the installation mode, + * and stores the relevant data into Calamares' GlobalStorage for use in subsequent steps. + */ +void PackageSelectViewStep::onLeave() { Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage(); - QVariantMap config; - for (auto i = m_packageSelections.begin(); i != m_packageSelections.end(); ++i) { - if (exists_and_true(i.key())) { - config.insert(i.key(), i.value()); - } + if (!gs) { + qWarning() << "GlobalStorage is not available."; + return; } - gs->insert("packages", config); -} -void PackageSelectViewStep::updatePackageSelections(bool checked) { - QObject* sender_obj = sender(); - if (!sender_obj) return; + QVariantMap installationData = gs->value("installation_data").toMap(); + QString installationMode = installationData.value("installation_mode").toString(); + bool downloadUpdates = installationData.value("download_updates").toBool(); + QVariantList packagesToInstall = installationData.value("packages_to_install").toList(); + QVariantList packagesToRemove = installationData.value("packages_to_remove").toList(); + QVariantList presentSnaps = installationData.value("present_snaps").toList(); + + // Handle default value for rootMountPoint + QString rootMountPoint = "/"; + if (gs->contains("rootMountPoint")) { + rootMountPoint = gs->value("rootMountPoint").toString(); + } - QString key = sender_obj->objectName(); + QVariantMap globalData; - // snake_case -> camelCase - QStringList parts = key.split("_", Qt::SkipEmptyParts); - for (int i = 1; i < parts.size(); ++i) { - parts[i][0] = parts[i][0].toUpper(); + // Determine selected installation mode + if (ui->minimal_button->isChecked()) { + installationMode = "minimal"; + } else if (ui->normal_button->isChecked()) { + installationMode = "normal"; + } else if (ui->full_button->isChecked()) { + installationMode = "full"; } - QString camelCaseKey = parts.join(""); - m_packageSelections[camelCaseKey] = checked; + globalData.insert("installation_mode", installationMode); + + if (installationMode == "minimal") { + QVariantList minimalPackages = m_configurationMap.value("packages").toMap().value("minimal_remove_packages").toList(); + QVariantList installerPackages = m_configurationMap.value("packages").toMap().value("installer_remove_packages").toList(); + QVariantList combinedRemove = minimalPackages + installerPackages; + globalData.insert("packages_to_remove", combinedRemove); + } + else { + // For normal and full, store packages to install + QVariantList selectedPackagesList; + // Store the snaps that are already on the system by default + QStringList presentSnapList; + + // Process all checked boxes + for (auto it = m_packageCheckBoxes.constBegin(); it != m_packageCheckBoxes.constEnd(); ++it) { + const QString& packageId = it.key(); + QCheckBox* checkbox = it.value(); + if (checkbox && checkbox->isChecked()) { + // Retrieve package details from configuration + QVariantList additionalPackages = m_configurationMap.value("packages").toMap().value("additional_packages").toList(); + QVariantMap packageDetails; + for (const QVariant& var : additionalPackages) { + QVariantMap pkg = var.toMap(); + if (pkg.value("id").toString() == packageId) { + packageDetails.insert("id", pkg.value("id").toString()); + packageDetails.insert("snap", pkg.value("snap").toBool()); + break; + } + } + if (!packageDetails.isEmpty()) { + selectedPackagesList.append(packageDetails); + } + } + } + + // Add the additional packages to be installed and substitute locale + QVariantList installPackages = m_configurationMap.value("packages").toMap().value("regular_install_packages").toList(); + QString localeVal = gs->value("locale").toString(); + for (const QVariant& installPackage : installPackages) { + QString packageId = installPackage.toString().replace("$LOCALE", localeVal); + QVariantMap packageDetails; + packageDetails.insert("id", packageId); + packageDetails.insert("snap", false); + selectedPackagesList.append(packageDetails); + } + + // Ensure delta updates are processed first + QVariantList refreshSnaps = m_configurationMap.value("packages").toMap().value("refresh_snaps").toList(); + for (const QVariant& snapVar : refreshSnaps) { + QString snapId = snapVar.toString(); + presentSnapList.append(snapId); + } + + globalData.insert("packages_to_install", selectedPackagesList); + QVariantList installerPackages = m_configurationMap.value("packages").toMap().value("installer_remove_packages").toList(); + globalData.insert("packages_to_remove", installerPackages); + globalData.insert("present_snaps", presentSnapList); + } + + // Store the state of 'download_updates' checkbox + bool updatesChecked = ui->updates_button->isChecked(); + globalData.insert("download_updates", updatesChecked); + + gs->insert("installation_data", globalData); +} + +/** + * @brief Slot to handle checkbox toggle events. + * + * This method updates the internal package selection map based on user interactions + * with the package checkboxes. + * + * @param checked The new checked state of the checkbox. + */ +void PackageSelectViewStep::updatePackageSelections(bool checked) +{ + QCheckBox* checkbox = qobject_cast(sender()); + if (!checkbox) + return; + + QString packageId = checkbox->objectName(); + m_packageSelections[packageId] = checked; + + emit packageSelectionsChanged(); +} + +/** + * @brief Retrieves the checkbox associated with a given package ID. + * + * @param id The package ID. + * @return A pointer to the QCheckBox, or nullptr if not found. + */ +QCheckBox* PackageSelectViewStep::getCheckboxById(const QString& id) const +{ + return m_packageCheckBoxes.value(id, nullptr); } -CALAMARES_PLUGIN_FACTORY_DEFINITION( PackageSelectViewStepFactory, registerPlugin< PackageSelectViewStep >(); ) +CALAMARES_PLUGIN_FACTORY_DEFINITION(PackageSelectViewStepFactory, registerPlugin(); ) diff --git a/common/modules/pkgselect/PackageSelectViewStep.h b/common/modules/pkgselect/PackageSelectViewStep.h index a68b4a1..c345ae0 100644 --- a/common/modules/pkgselect/PackageSelectViewStep.h +++ b/common/modules/pkgselect/PackageSelectViewStep.h @@ -1,52 +1,143 @@ #ifndef PACKAGESELECTVIEWSTEP_H #define PACKAGESELECTVIEWSTEP_H -#include -#include - +#include +#include +#include #include "DllMacro.h" #include "utils/PluginFactory.h" #include "viewpages/ViewStep.h" -#include "ui_pkgselect.h" - namespace Ui { class pkgselect; } +class QCheckBox; + +/** + * @class PackageSelectViewStep + * @brief A Calamares view step for selecting and customizing packages during installation. + * + * This class provides a user interface for selecting additional packages to install, + * managing installation modes, and handling network availability scenarios. + */ class PLUGINDLLEXPORT PackageSelectViewStep : public Calamares::ViewStep { Q_OBJECT public: - explicit PackageSelectViewStep( QObject* parent = nullptr ); + /** + * @brief Constructs a new PackageSelectViewStep object. + * @param parent The parent QObject. + */ + explicit PackageSelectViewStep(QObject* parent = nullptr); + + /** + * @brief Destroys the PackageSelectViewStep object. + */ ~PackageSelectViewStep() override; + /** + * @brief Returns the display name of the step. + * @return The pretty name as a QString. + */ QString prettyName() const override; + + /** + * @brief Returns the widget associated with this step. + * @return A pointer to the QWidget. + */ QWidget* widget() override; + + /** + * @brief Returns the list of jobs to execute for this step. + * @return An empty Calamares::JobList. + */ Calamares::JobList jobs() const override; + /** + * @brief Indicates whether the "Next" button is enabled. + * @return Always returns true. + */ bool isNextEnabled() const override; + + /** + * @brief Indicates whether the "Back" button is enabled. + * @return Always returns true. + */ bool isBackEnabled() const override; + + /** + * @brief Indicates whether the step is at the beginning. + * @return Always returns true. + */ bool isAtBeginning() const override; + + /** + * @brief Indicates whether the step is at the end. + * @return Always returns true. + */ bool isAtEnd() const override; + /** + * @brief Activates the step, setting up the UI based on network availability and configuration. + */ void onActivate() override; + + /** + * @brief Handles actions to perform when leaving the step, such as storing selected packages. + */ void onLeave() override; + /** + * @brief Sets the configuration map for the step. + * @param configurationMap The QVariantMap containing configuration data. + */ + void setConfigurationMap(const QVariantMap& configurationMap) override; + + /** + * @brief Retrieves the current package selections. + * @return A QVariantMap of package selections. + */ QVariantMap packageSelections() const { return m_packageSelections; } + +public slots: + /** + * @brief Slot to handle checkbox toggle events. + * @param checked The new checked state of the checkbox. + */ void updatePackageSelections(bool checked); signals: + /** + * @brief Signal emitted when package selections change. + */ void packageSelectionsChanged(); private: - QVariantMap m_packageSelections; - Ui::pkgselect *ui; - QWidget* m_widget; + /** + * @brief Retrieves the checkbox associated with a given package ID. + * @param id The package ID. + * @return A pointer to the QCheckBox, or nullptr if not found. + */ + QCheckBox* getCheckboxById(const QString& id) const; + + /** + * @brief Checks if a given key exists in package selections and is set to true. + * @param key The key to check. + * @return True if the key exists and is true, otherwise false. + */ bool exists_and_true(const QString& key) const; + + QVariantMap m_packageSelections; ///< Stores the state of package selections. + Ui::pkgselect* ui; ///< Pointer to the UI class. + QWidget* m_widget; ///< Pointer to the main widget of the step. + QVariantMap m_configurationMap; ///< Stores configuration data. + + QMap m_packageCheckBoxes; ///< Maps package IDs to their corresponding checkboxes. + bool m_connectionsMade; ///< Flag to ensure signal connections are made only once. }; -CALAMARES_PLUGIN_FACTORY_DECLARATION( PackageSelectViewStepFactory ) +CALAMARES_PLUGIN_FACTORY_DECLARATION(PackageSelectViewStepFactory) -#endif +#endif // PACKAGESELECTVIEWSTEP_H diff --git a/common/modules/pkgselect/pkgselect.conf b/common/modules/pkgselect/pkgselect.conf new file mode 100644 index 0000000..d73df8f --- /dev/null +++ b/common/modules/pkgselect/pkgselect.conf @@ -0,0 +1,55 @@ +--- +packages: + additional_packages: + - id: "element-desktop" + name: "Element" + description: "Matrix-based end-to-end encrypted messenger and secure collaboration app." + snap: true + - id: "thunderbird" + name: "Thunderbird" + description: "Email, newsfeed, chat, and calendaring client." + snap: true + - id: "virt-manager" + name: "Virtual Machine Manager" + description: "Desktop user interface for managing virtual machines through libvirt." + snap: false + - id: "krita" + name: "Krita" + description: "Graphics editor designed primarily for digital art and 2D animation." + snap: true + minimal_remove_packages: + - "snapd" + - "lubuntu-snap-installation-monitor" + - "vlc" + - "plasma-discover" + - "transmission-qt" + - "quassel" + - "2048-qt" + - "featherpad" + - "noblenote" + - "kcalc" + - "qps" + - "zsync" + - "partitionmanager" + - "qapt-deb-installer" + - "picom" + - "qlipper" + - "qtpass" + - "libreoffice*" + installer_remove_packages: + - "^live-*" + - calamares-settings-lubuntu + - calamares + - zram-config + - cifs-utils + - lubuntu-installer-prompt + regular_install_packages: + - language-pack-$LOCALE + - language-pack-gnome-$LOCALE + - language-pack-kde-$LOCALE + - hunspell-$LOCALE + - libreoffice-help-$LOCALE + - libreoffice-l10n-$LOCALE + refresh_snaps: + - "firefox" + - "firmware-updater" diff --git a/common/modules/pkgselect/pkgselect.ui b/common/modules/pkgselect/pkgselect.ui index aed59e3..70d4698 100644 --- a/common/modules/pkgselect/pkgselect.ui +++ b/common/modules/pkgselect/pkgselect.ui @@ -11,7 +11,7 @@ - Form + Package Selection QRadioButton { @@ -28,6 +28,27 @@ QLabel { } + + + + + + + 18 + 50 + false + + + + padding-left: 0px; padding-right: 0px; + + + Installation Mode + + + + + @@ -46,55 +67,48 @@ QLabel { - - - - Qt::Horizontal - - - QSizePolicy::Minimum + + + + + + + 10 + true + - - - 20 - 20 - + + Only the desktop environment - + - - - - Qt::Vertical - - + + + + + - 20 - 40 + 16777215 + 21 - - - - - 11 - 75 - false - true + 12 - Note: Ubuntu and flavors are NOT responsible for third-party software installed from this list. + Normal Installation - + true - - + + + + 10 @@ -102,26 +116,12 @@ QLabel { - This saves time after installation, and keeps your system secure + Web browser, utilities, office software, games, and media players - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - - - - + + @@ -140,22 +140,8 @@ QLabel { - - - - Qt::Horizontal - - - QSizePolicy::Minimum - - - - 20 - 20 - - - - + + @@ -172,42 +158,26 @@ QLabel { - - + + + + - Qt::Vertical + Qt::Horizontal - QSizePolicy::Fixed + QSizePolicy::Minimum 20 - 10 + 20 - - - - - 16777215 - 21 - - - - - 12 - - - - Download and install updates following installation - - - - - + + Qt::Vertical @@ -217,245 +187,29 @@ QLabel { 20 - 3 + 20 - - - - true + + + + Qt::Horizontal - - - - 0 - 0 - 762 - 281 - - - - - - - - 16777215 - 21 - - - - Virtual Machine Manager - - - - - - - - 16777215 - 21 - - - - Element - - - - - - - - 16777215 - 21 - - - - Krita - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - - 10 - true - - - - Matrix-based end-to-end encrypted messenger and secure collaboration app - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - - 10 - true - - - - Desktop user interface for managing virtual machines through libvirt - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 1 - 5 - - - - - - - - - 10 - true - - - - Email, newsfeed, chat, and calendaring client - - - - - - - - 16777215 - 21 - - - - Thunderbird - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 10 - - - - - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 6 - - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 5 - 20 - - - - - - - - - 10 - true - - - - Graphics editor designed primarily for digital art and 2D animation - - - - - - - - - - - - 10 - true - + + QSizePolicy::Minimum - - Only the desktop environment + + + 20 + 20 + - + - - + + Qt::Vertical @@ -465,13 +219,15 @@ QLabel { 20 - 20 + 10 - - + + + + 18 @@ -483,29 +239,34 @@ QLabel { padding-left: 0px; padding-right: 0px; - Installation Mode + Additional Options - - + + + + + + + 16777215 + 21 + + - 18 - 50 - false + 12 - - padding-left: 0px; padding-right: 0px; - - Additional Options + Download and install updates following installation - - + + + + 10 @@ -513,31 +274,47 @@ QLabel { - Web browser, utilities, office software, games, and media players + This saves time after installation, and keeps your system secure - - - - - 16777215 - 21 - - + + + + - 12 + 11 + 75 + false + true - Normal Installation + Note: Ubuntu and flavors are NOT responsible for third-party software installed from this list. - + true + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + @@ -555,51 +332,47 @@ QLabel { - - - - Qt::Vertical - - - QSizePolicy::Fixed - - - - 20 - 20 - + + + + + + true - + + + + 0 + 0 + 762 + 281 + + + + + + + - - + + + + Qt::Vertical - QSizePolicy::Fixed + QSizePolicy::Expanding 20 - 10 - - - - - - - - Qt::Horizontal - - - - 40 - 0 + 40 + diff --git a/common/modules/pkgselectprocess/CMakeLists.txt b/common/modules/pkgselectprocess/CMakeLists.txt new file mode 100644 index 0000000..a523eb5 --- /dev/null +++ b/common/modules/pkgselectprocess/CMakeLists.txt @@ -0,0 +1,30 @@ +cmake_minimum_required(VERSION 3.16 FATAL_ERROR) + +include(FeatureSummary) + +set( CMAKE_CXX_STANDARD 20 ) +set( CMAKE_CXX_STANDARD_REQUIRED ON ) + +set( CALAMARES_VERSION_REQUIRED 3.3.9 ) + +find_package(ECM "6.0.0" NO_MODULE) +set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH}) +include(KDEInstallDirs) +find_package(KF6 REQUIRED COMPONENTS CoreAddons) +find_package(Calamares ${CALAMARES_VERSION_REQUIRED} NO_CMAKE_PACKAGE_REGISTRY) +if (NOT TARGET Calamares::calamares OR NOT TARGET Calamares::calamaresui) + find_package(Calamares ${CALAMARES_VERSION_REQUIRED} REQUIRED) +endif() + +message(STATUS "Found Calamares version ${Calamares_VERSION}") +message(STATUS " libraries ${Calamares_LIB_DIRS}") +message(STATUS "") + +calamares_add_plugin( pkgselectprocess + TYPE job + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + PackageSelectProcess.cpp + SHARED_LIB + NO_CONFIG +) diff --git a/common/modules/pkgselectprocess/PackageSelectProcess.cpp b/common/modules/pkgselectprocess/PackageSelectProcess.cpp new file mode 100644 index 0000000..54efb12 --- /dev/null +++ b/common/modules/pkgselectprocess/PackageSelectProcess.cpp @@ -0,0 +1,390 @@ +#include "PackageSelectProcess.h" +#include "GlobalStorage.h" +#include "JobQueue.h" +#include +#include +#include +#include +#include + +CALAMARES_PLUGIN_FACTORY_DEFINITION(PackageSelectProcessFactory, registerPlugin();) + +PackageSelectProcess::PackageSelectProcess(QObject* parent) + : Calamares::CppJob(parent), + m_prettyStatus(tr("Preparing to install selected packages...")) +{ +} + +QString PackageSelectProcess::prettyName() const +{ + return tr("Installing selected packages"); +} + +QString PackageSelectProcess::prettyStatusMessage() const +{ + return m_prettyStatus; +} + +void PackageSelectProcess::setConfigurationMap(const QVariantMap& configurationMap) +{ + m_configurationMap = configurationMap; +} + +Calamares::JobResult PackageSelectProcess::runAptCommand(const QString& command, + const QString& rootMountPoint, + double startProgress, + double endProgress, + bool verboseProgress) +{ + QProcess aptProcess(this); + aptProcess.setProgram("/usr/sbin/chroot"); + aptProcess.setArguments({ rootMountPoint, "/bin/bash", "-c", command }); + aptProcess.setProcessChannelMode(QProcess::MergedChannels); + + constexpr int MAX_LINES = 5000; + double progressRange = endProgress - startProgress; + double progressPerLine = progressRange / static_cast(MAX_LINES); + int lineCount = 0; + + QString commandHRPrefix; + if (command.contains("install")) { + commandHRPrefix = tr("Installing packages: "); + } else if (command.contains("full-upgrade")) { + commandHRPrefix = tr("Upgrading installed system: "); + } else if (command.contains("autoremove")) { + commandHRPrefix = tr("Cleaning up packages: "); + } + + QRegularExpression getRegex(R"(Get:\d+\s+[^ ]+\s+[^ ]+\s+(.+?)\s+\S+\s+(\S+)\s+\[(.*?)\])"); + + connect(&aptProcess, &QProcess::readyReadStandardOutput, this, + [this, &aptProcess, &lineCount, progressPerLine, startProgress, endProgress, verboseProgress, commandHRPrefix, getRegex]() mutable { + while (aptProcess.canReadLine()) { + QString line = QString::fromUtf8(aptProcess.readLine()).trimmed(); + if (line.isEmpty()) { + continue; + } + + if (verboseProgress && !line.contains("Running in chroot, ignoring command") && + !line.contains("Waiting until unit") && !line.contains("Stopping snap") && + !line.contains("/dev/pts")) { + + // Process "Get:" lines to show download information + if (line.startsWith("Get:")) { + QRegularExpressionMatch match = getRegex.match(line); + if (match.hasMatch()) { + QString packageName = match.captured(1); + QString packageVersion = match.captured(2); + QString packageSize = match.captured(3); + line = tr("Downloading %1 %2 (%3)").arg(packageName, packageVersion, packageSize); + } + } + + m_prettyStatus = commandHRPrefix + line; + emit prettyStatusMessageChanged(m_prettyStatus); + qDebug() << m_prettyStatus; + } + + lineCount++; + double currentProgress = startProgress + (lineCount * progressPerLine); + currentProgress = qBound(startProgress, currentProgress, endProgress); + emit progress(currentProgress); + } + }); + + aptProcess.start(); + if (!aptProcess.waitForStarted()) { + qWarning() << "Failed to start apt command:" << aptProcess.errorString(); + return Calamares::JobResult::error(tr("Apt command failed"), + tr("Failed to start apt command: %1").arg(aptProcess.errorString())); + } + + while (!aptProcess.waitForFinished(100)) { + QCoreApplication::processEvents(); + } + + if (aptProcess.exitStatus() != QProcess::NormalExit || aptProcess.exitCode() != 0) { + QString errorOutput = QString::fromUtf8(aptProcess.readAllStandardError()).trimmed(); + qWarning() << "Apt command error:" << errorOutput; + return Calamares::JobResult::error(tr("Apt command failed"), + tr("Failed to execute apt command: %1").arg(errorOutput)); + } + + emit progress(endProgress); + m_prettyStatus = tr("Command executed successfully."); + emit prettyStatusMessageChanged(m_prettyStatus); + + return Calamares::JobResult::ok(); +} + +Calamares::JobResult PackageSelectProcess::runSnapCommand(const QStringList& snapPackages, + const QString& rootMountPoint, + double startProgress, + double endProgress) +{ + const QString seedDirectory = QDir::cleanPath(rootMountPoint + "/var/lib/snapd/seed"); + QDir dir(seedDirectory); + if (!dir.exists() && !dir.mkpath(".")) { + return Calamares::JobResult::error(tr("Snap installation failed"), + tr("Failed to create seed directory: %1").arg(seedDirectory)); + } + + QStringList snapCommandArgs = { "--seed", seedDirectory }; + snapCommandArgs += snapPackages; + + qDebug() << "Executing Snap Command:" << snapCommandArgs.join(" "); + + QProcess snapProcess(this); + snapProcess.setProgram("/usr/bin/snapd-seed-glue"); + snapProcess.setArguments(snapCommandArgs); + snapProcess.setProcessChannelMode(QProcess::MergedChannels); + + QString currentDescription; + + connect(&snapProcess, &QProcess::readyReadStandardOutput, this, + [&snapProcess, this, ¤tDescription, startProgress, endProgress]( ) { + while (snapProcess.canReadLine()) { + QString line = QString::fromUtf8(snapProcess.readLine()).trimmed(); + if (line.isEmpty()) { + continue; + } + + QStringList parts = line.split("\t"); + if (parts.size() != 2) { + qWarning() << "Unexpected output format from snap-seed-glue:" << line; + continue; + } + + bool ok = false; + double percentage = parts[0].toDouble(&ok); + const QString& description = parts[1]; + + if (!ok) { + qWarning() << "Failed to parse percentage from line:" << line; + continue; + } + + if (description != currentDescription) { + m_prettyStatus = description; + emit prettyStatusMessageChanged(m_prettyStatus); + currentDescription = description; + qDebug() << description; + } + + double scaledProgress = startProgress + (percentage / 100.0) * (endProgress - startProgress); + emit progress(scaledProgress); + } + }); + + m_prettyStatus = tr("Installing snap packages..."); + emit prettyStatusMessageChanged(m_prettyStatus); + emit progress(startProgress); + + snapProcess.start(); + if (!snapProcess.waitForStarted()) { + qWarning() << "Failed to start snap installation process:" << snapProcess.errorString(); + return Calamares::JobResult::error(tr("Snap installation failed"), + tr("Failed to start snap installation process: %1").arg(snapProcess.errorString())); + } + + while (!snapProcess.waitForFinished(100)) { + QCoreApplication::processEvents(); + } + + if (snapProcess.exitStatus() != QProcess::NormalExit || snapProcess.exitCode() != 0) { + QString errorOutput = QString::fromUtf8(snapProcess.readAllStandardError()).trimmed(); + qWarning() << "Snap installation error:" << errorOutput; + return Calamares::JobResult::error(tr("Snap installation failed"), + tr("Failed to install snap packages: %1").arg(errorOutput)); + } + + emit progress(endProgress); + m_prettyStatus = tr("Snap packages installed successfully."); + emit prettyStatusMessageChanged(m_prettyStatus); + + return Calamares::JobResult::ok(); +} + +Calamares::JobResult PackageSelectProcess::exec() +{ + auto gs = Calamares::JobQueue::instance()->globalStorage(); + if (!gs || !gs->contains("installation_data")) { + return Calamares::JobResult::error(tr("No installation data found."), + tr("Installation data is missing from global storage.")); + } + + const QVariantMap installationData = gs->value("installation_data").toMap(); + const QString installationMode = installationData.value("installation_mode").toString(); + const bool downloadUpdates = installationData.value("download_updates").toBool(); + const QVariantList packagesToInstall = installationData.value("packages_to_install").toList(); + const QVariantList packagesToRemove = installationData.value("packages_to_remove").toList(); + const QVariantList presentSnaps = installationData.value("present_snaps").toList(); + + // Handle default value for rootMountPoint + QString rootMountPoint = "/"; + if (gs->contains("rootMountPoint")) { + rootMountPoint = gs->value("rootMountPoint").toString(); + } + + static const QMap> allocationMap = { + { "minimal", { {0.0, 1.0} } }, + { "normal", { {0.0, 0.4}, {0.4, 1.0} } }, + { "full", { {0.0, 0.25}, {0.25, 1.0} } } + }; + + const QVector allocations = allocationMap.value(installationMode, { {0.0, 1.0} }); + + // Run apt update + const double aptRange = allocations[0].end - allocations[0].start; + const double updateStart = allocations[0].start; + const double updateEnd = updateStart + 0.1 * aptRange; + + m_prettyStatus = tr("Updating apt cache"); + emit prettyStatusMessageChanged(m_prettyStatus); + emit progress(updateStart); + + Calamares::JobResult updateResult = runAptCommand("DEBIAN_FRONTEND=noninteractive apt-get update", + rootMountPoint, + updateStart, + updateEnd, + false); + if (!updateResult) { // Using operator bool() to check for errors + return std::move(updateResult); // Move to avoid copy + } + + QStringList debPackages; + for (const QVariant& var : packagesToInstall) { + const QVariantMap pkg = var.toMap(); + if (!pkg.value("snap").toBool()) { + debPackages << pkg.value("id").toString(); + } + } + + double installStart; + double installEnd; + if (downloadUpdates) { + const double upgradeStart = updateEnd; + const double upgradeEnd = upgradeStart + 0.25 * aptRange; + + Calamares::JobResult upgradeResult = runAptCommand( + "DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confnew' full-upgrade", + rootMountPoint, + upgradeStart, + upgradeEnd, + true + ); + if (!upgradeResult) { // Using operator bool() to check for errors + return std::move(upgradeResult); // Move to avoid copy + } + + installStart = upgradeEnd; + installEnd = installStart + 0.25 * aptRange; + } + else { + installStart = updateEnd; + installEnd = installStart + 0.5 * aptRange; + installEnd = qMin(installEnd, allocations[0].end); + } + + qDebug() << "Progress range: installStart:" << installStart << "installEnd:" << installEnd; + + if (!debPackages.isEmpty()) { + const QString packageList = debPackages.join(" -e "); + const QString installCommand = QString( + "DEBIAN_FRONTEND=noninteractive apt-get -y install $(apt-cache --no-generate pkgnames %1 | grep -Fx -e %2)" + ).arg(debPackages.join(" ")).arg(packageList); + + Calamares::JobResult installResult = runAptCommand(installCommand, + rootMountPoint, + installStart, + installEnd, + true); + if (!installResult) { // Using operator bool() to check for errors + return std::move(installResult); // Move to avoid copy + } + } + else { + qDebug() << "No packages to install."; + } + + QStringList removeDebPackages; + for (const QVariant& var : packagesToRemove) { + removeDebPackages << var.toString(); + } + + const double removeStart = installEnd; + const double removeEnd = removeStart + 0.2 * aptRange; + + if (!removeDebPackages.isEmpty()) { + const QString removeCommand = QString("DEBIAN_FRONTEND=noninteractive apt-get -y --purge remove %1") + .arg(removeDebPackages.join(" ")); + Calamares::JobResult removeResult = runAptCommand(removeCommand, + rootMountPoint, + removeStart, + removeEnd, + true); + if (!removeResult) { // Using operator bool() to check for errors + return std::move(removeResult); // Move to avoid copy + } + } + + const double autoremoveStart = removeEnd; + const double autoremoveEnd = autoremoveStart + 0.2 * aptRange; + + Calamares::JobResult autoremoveResult = runAptCommand("DEBIAN_FRONTEND=noninteractive apt-get -y autoremove", + rootMountPoint, + autoremoveStart, + autoremoveEnd, + true); + if (!autoremoveResult) { // Using operator bool() to check for errors + return std::move(autoremoveResult); // Move to avoid copy + } + + // Handle snap packages + if (installationMode != "minimal") { + QStringList snapPackages; + QStringList presentSnapsList; + // Convert QVariantList to QStringList + for (const QVariant& var : presentSnaps) { + presentSnapsList << var.toString(); + } + + for (const QVariant& var : packagesToInstall) { + const QVariantMap pkg = var.toMap(); + if (pkg.value("snap").toBool()) { + snapPackages << pkg.value("id").toString(); + } + } + + QStringList finalSnapPackages; + + if (!snapPackages.isEmpty() && !presentSnapsList.isEmpty()) { + finalSnapPackages = presentSnapsList + snapPackages; + } + else if (!snapPackages.isEmpty()) { + finalSnapPackages = snapPackages; + } + else if (!presentSnapsList.isEmpty() && downloadUpdates) { + finalSnapPackages = presentSnapsList; + } + + if (!finalSnapPackages.isEmpty()) { + double snapStart = allocations.size() > 1 ? allocations[1].start : allocations[0].end; + double snapEnd = allocations.size() > 1 ? allocations[1].end : allocations[0].end; + + Calamares::JobResult snapResult = runSnapCommand(finalSnapPackages, + rootMountPoint, + snapStart, + snapEnd); + if (!snapResult) { // Using operator bool() to check for errors + return std::move(snapResult); // Move to avoid copy + } + } + } + + emit progress(1.0); + m_prettyStatus = tr("All selected packages installed successfully."); + emit prettyStatusMessageChanged(m_prettyStatus); + + return Calamares::JobResult::ok(); +} diff --git a/common/modules/pkgselectprocess/PackageSelectProcess.h b/common/modules/pkgselectprocess/PackageSelectProcess.h new file mode 100644 index 0000000..c3d14b5 --- /dev/null +++ b/common/modules/pkgselectprocess/PackageSelectProcess.h @@ -0,0 +1,53 @@ +#ifndef PACKAGESELECTPROCESS_H +#define PACKAGESELECTPROCESS_H + +#include +#include +#include "CppJob.h" +#include "utils/PluginFactory.h" +#include "DllMacro.h" + +class QProcess; + +class PLUGINDLLEXPORT PackageSelectProcess : public Calamares::CppJob +{ + Q_OBJECT + +public: + explicit PackageSelectProcess(QObject* parent = nullptr); + ~PackageSelectProcess() override = default; + + QString prettyName() const override; + QString prettyStatusMessage() const override; + + Calamares::JobResult exec() override; + + void setConfigurationMap(const QVariantMap& configurationMap) override; + +signals: + void prettyStatusMessageChanged(const QString&); + +private: + struct ProgressAllocation + { + double start; + double end; + }; + + Calamares::JobResult runAptCommand(const QString& command, + const QString& rootMountPoint, + double startProgress, + double endProgress, + bool verboseProgress); + Calamares::JobResult runSnapCommand(const QStringList& snapPackages, + const QString& rootMountPoint, + double startProgress, + double endProgress); + + QVariantMap m_configurationMap; + QString m_prettyStatus; +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION(PackageSelectProcessFactory) + +#endif // PACKAGESELECTPROCESS_H diff --git a/common/modules/pkgselectprocess/module.desc b/common/modules/pkgselectprocess/module.desc new file mode 100644 index 0000000..cd31c4c --- /dev/null +++ b/common/modules/pkgselectprocess/module.desc @@ -0,0 +1,7 @@ +--- +type: "job" +name: "pkgselectprocess" +interface: "qtplugin" +load: "libcalamares_job_pkgselectprocess.so" +noconfig: true +weight: 12 diff --git a/debian/changelog b/debian/changelog index cd7f210..6f2f1c2 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,9 +1,10 @@ -calamares-settings-ubuntu (1:25.04.1) UNRELEASED; urgency=medium +calamares-settings-ubuntu (1:25.04.1) plucky; urgency=medium * Welcome to Plucky Puffin! * Port to Qt 6. + * Rewrite the pkgselect module and its processing. - -- Simon Quigley Tue, 15 Oct 2024 21:05:10 -0500 + -- Simon Quigley Tue, 22 Oct 2024 19:23:22 -0500 calamares-settings-ubuntu (1:24.10.5) oracular; urgency=medium diff --git a/debian/control b/debian/control index f724f55..4e6a673 100644 --- a/debian/control +++ b/debian/control @@ -71,6 +71,7 @@ Depends: calamares (>= 3.3.9), python3-distro, qml6-module-qtquick, qml6-module-qtquick-window, + snapd-seed-glue, squashfs-tools, sudo, ${misc:Depends}, diff --git a/debian/rules b/debian/rules index 0f2c5e3..45ecd2e 100755 --- a/debian/rules +++ b/debian/rules @@ -5,20 +5,23 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all export GOPATH=/usr/share/gocode export GO111MODULE=off export GOCACHE=$(CURDIR)/.gocache +export PKGSELECT = "common/modules/pkgselect" +export PKGSELECTPROCESS = "common/modules/pkgselectprocess" +export MODULES_DIR = "debian/calamares-settings-ubuntu-common/usr/lib/$(DEB_HOST_MULTIARCH)/calamares/modules" DEB_HOST_MULTIARCH ?= $(shell dpkg-architecture -qDEB_HOST_MULTIARCH) -PKGSELECT = "common/modules/pkgselect" -MODULES_DIR = "debian/calamares-settings-ubuntu-common/usr/lib/$(DEB_HOST_MULTIARCH)/calamares/modules" %: dh $@ override_dh_auto_configure: (cd $(PKGSELECT) && mkdir build && cd build && cmake ..) + (cd $(PKGSELECTPROCESS) && mkdir build && cd build && cmake ..) override_dh_auto_build: make; (cd $(PKGSELECT)/build && $(MAKE)) + (cd $(PKGSELECTPROCESS)/build && $(MAKE)) override_dh_auto_clean: dh_auto_clean @@ -26,6 +29,7 @@ override_dh_auto_clean: override_dh_auto_install: (cd $(PKGSELECT)/build && $(MAKE) DESTDIR=$(CURDIR)/debian/calamares-settings-ubuntu-common/ install) + (cd $(PKGSELECTPROCESS)/build && $(MAKE) DESTDIR=$(CURDIR)/debian/calamares-settings-ubuntu-common/ install) override_dh_missing: dh_missing @@ -38,6 +42,8 @@ override_dh_missing: chmod 644 $(MODULES_DIR)/automirror/module.desc chmod 644 $(MODULES_DIR)/pkgselect/libcalamares_viewmodule_pkgselect.so chmod 644 $(MODULES_DIR)/pkgselect/module.desc + chmod 644 $(MODULES_DIR)/pkgselectprocess/libcalamares_job_pkgselectprocess.so + chmod 644 $(MODULES_DIR)/pkgselectprocess/module.desc mkdir -pv debian/calamares-settings-ubuntu-common/usr/bin/ mkdir -pv debian/calamares-settings-ubuntu-common/usr/libexec/ cp -v common/fixconkeys-part1 debian/calamares-settings-ubuntu-common/usr/libexec/fixconkeys-part1 diff --git a/kubuntu/modules/packages.conf b/kubuntu/modules/packages.conf deleted file mode 100644 index 931dac2..0000000 --- a/kubuntu/modules/packages.conf +++ /dev/null @@ -1,16 +0,0 @@ -update_db: true -backend: apt -operations: - - remove: - - "^live-*" - - calamares-settings-kubuntu - - calamares - - cifs-utils - - kubuntu-installer-prompt - - try_install: - - language-pack-$LOCALE - - language-pack-gnome-$LOCALE - - language-pack-kde-$LOCALE - - hunspell-$LOCALE - - libreoffice-help-$LOCALE - - libreoffice-l10n-$LOCALE diff --git a/kubuntu/modules/pkgselect.conf b/kubuntu/modules/pkgselect.conf new file mode 100644 index 0000000..4c809a3 --- /dev/null +++ b/kubuntu/modules/pkgselect.conf @@ -0,0 +1,53 @@ +--- +packages: + additional_packages: + - id: "element-desktop" + name: "Element" + description: "Matrix-based end-to-end encrypted messenger and secure collaboration app." + snap: true + - id: "virt-manager" + name: "Virtual Machine Manager" + description: "Desktop user interface for managing virtual machines through libvirt." + snap: false + - id: "krita" + name: "Krita" + description: "Graphics editor designed primarily for digital art and 2D animation." + snap: true + minimal_remove_packages: + - kmahjongg + - kmines + - kpat + - ksudoku + - skanlite + - skanpage + - okular + - "libreoffice*" + - kdeconnect + - krdc + - konversation + - neochat + - elisa + - haruna + - vim + - snapd + - partitionmanager + - usb-creator* + - plasma-welcome + - kde-config-tablet + installer_remove_packages: + - "^live-*" + - calamares-settings-kubuntu + - calamares + - cifs-utils + - kubuntu-installer-prompt + regular_install_packages: + - language-pack-$LOCALE + - language-pack-gnome-$LOCALE + - language-pack-kde-$LOCALE + - hunspell-$LOCALE + - libreoffice-help-$LOCALE + - libreoffice-l10n-$LOCALE + refresh_snaps: + - "firefox" + - "thunderbird" + - "firmware-updater" diff --git a/kubuntu/modules/pkgselect_context.conf b/kubuntu/modules/pkgselect_context.conf deleted file mode 100644 index 74aa744..0000000 --- a/kubuntu/modules/pkgselect_context.conf +++ /dev/null @@ -1,19 +0,0 @@ ---- -dontChroot: false -timeout: 10800 -"packages.minimalButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get -y --purge remove kmahjongg kmines kpat ksudoku skanlite skanpage okular libreoffice* kdeconnect krdc konversation neochat elisa haruna vim snapd partitionmanager usb-creator* plasma-welcome kde-config-tablet plasma-welcome" - - "apt-get -y autoremove" -"packages.partyButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y install ubuntu-restricted-addons unrar" -"packages.updatesButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confnew' full-upgrade" -"packages.virtmanagerButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y install virt-manager" diff --git a/kubuntu/modules/pkgselect_snap_context.conf b/kubuntu/modules/pkgselect_snap_context.conf deleted file mode 100644 index 2a045ec..0000000 --- a/kubuntu/modules/pkgselect_snap_context.conf +++ /dev/null @@ -1,9 +0,0 @@ ---- -dontChroot: true -timeout: 10800 -"packages.elementButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed element-desktop" -"packages.kritaButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed krita" -"packages.thunderbirdButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed thunderbird" diff --git a/kubuntu/settings.conf b/kubuntu/settings.conf index 3e75911..7490e37 100644 --- a/kubuntu/settings.conf +++ b/kubuntu/settings.conf @@ -17,12 +17,6 @@ instances: - id: add386arch module: shellprocess config: shellprocess_add386arch.conf -- id: pkgselect_action - module: contextualprocess - config: pkgselect_context.conf -- id: pkgselect_snap_action - module: contextualprocess - config: pkgselect_snap_context.conf - id: oemprep module: shellprocess config: shellprocess_oemprep.conf @@ -61,18 +55,16 @@ sequence: - hwclock - contextualprocess@before_bootloader_mkdirs - shellprocess@bug-LP#1829805 + - shellprocess@fixconkeys_part1 + - shellprocess@fixconkeys_part2 - initramfscfg - initramfs - grubcfg - contextualprocess@before_bootloader - bootloader - - automirror - shellprocess@add386arch - - shellprocess@fixconkeys_part1 - - shellprocess@fixconkeys_part2 - - packages - - contextualprocess@pkgselect_action - - contextualprocess@pkgselect_snap_action + - automirror + - pkgselectprocess - shellprocess@logs - umount - show: diff --git a/lubuntu/modules/packages.conf b/lubuntu/modules/packages.conf deleted file mode 100644 index bff093c..0000000 --- a/lubuntu/modules/packages.conf +++ /dev/null @@ -1,17 +0,0 @@ -update_db: true -backend: apt -operations: - - remove: - - "^live-*" - - calamares-settings-lubuntu - - calamares - - zram-config - - cifs-utils - - lubuntu-installer-prompt - - try_install: - - language-pack-$LOCALE - - language-pack-gnome-$LOCALE - - language-pack-kde-$LOCALE - - hunspell-$LOCALE - - libreoffice-help-$LOCALE - - libreoffice-l10n-$LOCALE diff --git a/lubuntu/modules/pkgselect.conf b/lubuntu/modules/pkgselect.conf new file mode 100644 index 0000000..ff43dbb --- /dev/null +++ b/lubuntu/modules/pkgselect.conf @@ -0,0 +1,55 @@ +--- +packages: + additional_packages: + - id: "element-desktop" + name: "Element" + description: "Matrix-based end-to-end encrypted messenger and secure collaboration app." + snap: true + - id: "thunderbird" + name: "Thunderbird" + description: "Email, newsfeed, chat, and calendaring client." + snap: true + - id: "virt-manager" + name: "Virtual Machine Manager" + description: "Desktop user interface for managing virtual machines through libvirt." + snap: false + - id: "krita" + name: "Krita" + description: "Graphics editor designed primarily for digital art and 2D animation." + snap: true + minimal_remove_packages: + - snapd + - snapd-installation-monitor + - vlc + - plasma-discover + - transmission-qt + - quassel + - 2048-qt + - featherpad + - noblenote + - kcalc + - qps + - zsync + - partitionmanager + - qapt-deb-installer + - picom + - qlipper + - qtpass + - "libreoffice*" + installer_remove_packages: + - "^live-*" + - calamares-settings-lubuntu + - calamares + - zram-config + - cifs-utils + - lubuntu-installer-prompt + regular_install_packages: + - language-pack-$LOCALE + - language-pack-gnome-$LOCALE + - language-pack-kde-$LOCALE + - hunspell-$LOCALE + - libreoffice-help-$LOCALE + - libreoffice-l10n-$LOCALE + refresh_snaps: + - "firefox" + - "firmware-updater" diff --git a/lubuntu/modules/pkgselect_context.conf b/lubuntu/modules/pkgselect_context.conf deleted file mode 100644 index 6b304fe..0000000 --- a/lubuntu/modules/pkgselect_context.conf +++ /dev/null @@ -1,19 +0,0 @@ ---- -dontChroot: false -timeout: 10800 -"packages.minimalButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get -y --purge remove snapd lubuntu-snap-installation-monitor vlc plasma-discover transmission-qt quassel 2048-qt featherpad noblenote kcalc qps zsync partitionmanager qapt-deb-installer picom qlipper qtpass libreoffice*" - - "apt-get -y autoremove" -"packages.partyButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y install ubuntu-restricted-addons unrar" -"packages.updatesButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confnew' full-upgrade" -"packages.virtmanagerButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y install virt-manager" diff --git a/lubuntu/modules/pkgselect_snap_context.conf b/lubuntu/modules/pkgselect_snap_context.conf deleted file mode 100644 index 2a045ec..0000000 --- a/lubuntu/modules/pkgselect_snap_context.conf +++ /dev/null @@ -1,9 +0,0 @@ ---- -dontChroot: true -timeout: 10800 -"packages.elementButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed element-desktop" -"packages.kritaButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed krita" -"packages.thunderbirdButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed thunderbird" diff --git a/lubuntu/settings.conf b/lubuntu/settings.conf index 5decae2..e0a2713 100644 --- a/lubuntu/settings.conf +++ b/lubuntu/settings.conf @@ -17,12 +17,6 @@ instances: - id: add386arch module: shellprocess config: shellprocess_add386arch.conf -- id: pkgselect_action - module: contextualprocess - config: pkgselect_context.conf -- id: pkgselect_snap_action - module: contextualprocess - config: pkgselect_snap_context.conf - id: oemprep module: shellprocess config: shellprocess_oemprep.conf @@ -61,18 +55,16 @@ sequence: - hwclock - contextualprocess@before_bootloader_mkdirs - shellprocess@bug-LP#1829805 + - shellprocess@fixconkeys_part1 + - shellprocess@fixconkeys_part2 - initramfscfg - initramfs - grubcfg - contextualprocess@before_bootloader - bootloader - - automirror - shellprocess@add386arch - - shellprocess@fixconkeys_part1 - - shellprocess@fixconkeys_part2 - - packages - - contextualprocess@pkgselect_action - - contextualprocess@pkgselect_snap_action + - automirror + - pkgselectprocess - shellprocess@logs - umount - show: diff --git a/ubuntuunity/modules/packages.conf b/ubuntuunity/modules/packages.conf deleted file mode 100644 index 8ec8c47..0000000 --- a/ubuntuunity/modules/packages.conf +++ /dev/null @@ -1,15 +0,0 @@ -update_db: true -backend: apt -operations: - - remove: - - "^live-*" - - calamares-settings-ubuntu-unity - - calamares - - cifs-utils - - try_install: - - language-pack-$LOCALE - - language-pack-gnome-$LOCALE - - language-pack-kde-$LOCALE - - hunspell-$LOCALE - - libreoffice-help-$LOCALE - - libreoffice-l10n-$LOCALE diff --git a/ubuntuunity/modules/pkgselect.conf b/ubuntuunity/modules/pkgselect.conf new file mode 100644 index 0000000..fe445cb --- /dev/null +++ b/ubuntuunity/modules/pkgselect.conf @@ -0,0 +1,52 @@ +--- +packages: + additional_packages: + - id: "element-desktop" + name: "Element" + description: "Matrix-based end-to-end encrypted messenger and secure collaboration app." + snap: true + - id: "thunderbird" + name: "Thunderbird" + description: "Email, newsfeed, chat, and calendaring client." + snap: true + - id: "virt-manager" + name: "Virtual Machine Manager" + description: "Desktop user interface for managing virtual machines through libvirt." + snap: false + - id: "krita" + name: "Krita" + description: "Graphics editor designed primarily for digital art and 2D animation." + snap: true + minimal_remove_packages: + - snapd aisleriot + - atril + - cheese + - simple-scan + - gdebi + - gparted + - "*kvantum*" + - "libreoffice*" + - gnome-mahjongg + - gnome-mines + - remmina + - rhythmbox + - shotwell + - gnome-sudoku + - synaptic + - transmission-gtk + - vlc + - stacer + installer_remove_packages: + - "^live-*" + - calamares-settings-ubuntu-unity + - calamares + - cifs-utils + regular_install_packages: + - language-pack-$LOCALE + - language-pack-gnome-$LOCALE + - language-pack-kde-$LOCALE + - hunspell-$LOCALE + - libreoffice-help-$LOCALE + - libreoffice-l10n-$LOCALE + refresh_snaps: + - "firefox" diff --git a/ubuntuunity/modules/pkgselect_context.conf b/ubuntuunity/modules/pkgselect_context.conf deleted file mode 100644 index a0718db..0000000 --- a/ubuntuunity/modules/pkgselect_context.conf +++ /dev/null @@ -1,19 +0,0 @@ ---- -dontChroot: false -timeout: 10800 -"packages.minimalButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get -y --purge remove snapd aisleriot atril cheese simple-scan gdebi gparted *kvantum* libreoffice* gnome-mahjongg gnome-mines remmina rhythmbox shotwell gnome-sudoku synaptic transmission-gtk vlc stacer" - - "apt-get -y autoremove" -"packages.partyButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y install ubuntu-restricted-addons unrar" -"packages.updatesButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y -o Dpkg::Options::='--force-confnew' full-upgrade" -"packages.virtmanagerButton": - true: - - "DEBIAN_FRONTEND=noninteractive apt-get update" - - "DEBIAN_FRONTEND=noninteractive apt-get -y install virt-manager" diff --git a/ubuntuunity/modules/pkgselect_snap_context.conf b/ubuntuunity/modules/pkgselect_snap_context.conf deleted file mode 100644 index 2a045ec..0000000 --- a/ubuntuunity/modules/pkgselect_snap_context.conf +++ /dev/null @@ -1,9 +0,0 @@ ---- -dontChroot: true -timeout: 10800 -"packages.elementButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed element-desktop" -"packages.kritaButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed krita" -"packages.thunderbirdButton": - true: "snap-seed-glue --seed ${ROOT}/var/lib/snapd/seed thunderbird" diff --git a/ubuntuunity/settings.conf b/ubuntuunity/settings.conf index cee9de0..10956a5 100644 --- a/ubuntuunity/settings.conf +++ b/ubuntuunity/settings.conf @@ -17,12 +17,6 @@ instances: - id: add386arch module: shellprocess config: shellprocess_add386arch.conf -- id: pkgselect_action - module: contextualprocess - config: pkgselect_context.conf -- id: pkgselect_snap_action - module: contextualprocess - config: pkgselect_snap_context.conf - id: oemprep module: shellprocess config: shellprocess_oemprep.conf @@ -61,18 +55,16 @@ sequence: - hwclock - contextualprocess@before_bootloader_mkdirs - shellprocess@bug-LP#1829805 + - shellprocess@fixconkeys_part1 + - shellprocess@fixconkeys_part2 - initramfscfg - initramfs - grubcfg - contextualprocess@before_bootloader - bootloader - - automirror - shellprocess@add386arch - - shellprocess@fixconkeys_part1 - - shellprocess@fixconkeys_part2 - - packages - - contextualprocess@pkgselect_action - - contextualprocess@pkgselect_snap_action + - automirror + - pkgselectprocess - shellprocess@logs - umount - show: