Rewrite the pkgselect module and its processing.

ubuntu/plucky ubuntu/1%25.04.1
Simon Quigley 3 months ago
parent f415963f24
commit e687608175

@ -1,5 +1,4 @@
#!/bin/bash #!/bin/bash
loadkeys "$(cat /dev/shm/fixconkeys-layout)" loadkeys "$(cat /dev/shm/fixconkeys-layout)"
setupcon --save-only setupcon --save-only
update-initramfs -c -k all
rm /usr/libexec/fixconkeys-part2 rm /usr/libexec/fixconkeys-part2

@ -7,7 +7,7 @@ set( CMAKE_CXX_STANDARD_REQUIRED ON )
set( CALAMARES_VERSION_REQUIRED 3.3.9 ) 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}) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_MODULE_PATH})
include(KDEInstallDirs) include(KDEInstallDirs)
find_package(KF6 REQUIRED COMPONENTS CoreAddons) find_package(KF6 REQUIRED COMPONENTS CoreAddons)

@ -1,35 +1,55 @@
#include "PackageSelectViewStep.h" #include "PackageSelectViewStep.h"
#include "ui_pkgselect.h"
#include "JobQueue.h" #include "JobQueue.h"
#include "GlobalStorage.h" #include "GlobalStorage.h"
#include "Branding.h"
#include "network/Manager.h" #include "network/Manager.h"
#include <QVariantMap> #include <QCheckBox>
#include <QVariant>
PackageSelectViewStep::PackageSelectViewStep( QObject* parent ) #include <QDebug>
: Calamares::ViewStep( parent ), #include <QLabel>
m_packageSelections(QVariantMap()), #include <QVBoxLayout>
ui(new Ui::pkgselect) #include <QGridLayout>
#include <QRadioButton>
/**
* @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); ui->setupUi(m_widget);
// Layout Adjustment to Prevent Shifting
// Ensures that hiding/showing elements does not disrupt the layout
QGridLayout* mainLayout = qobject_cast<QGridLayout*>(ui->gridLayout);
if (mainLayout) {
mainLayout->setRowStretch(mainLayout->rowCount(), 1);
}
} }
/**
* @brief Cleans up the PackageSelectViewStep object.
*/
PackageSelectViewStep::~PackageSelectViewStep() PackageSelectViewStep::~PackageSelectViewStep()
{ {
delete ui; delete ui;
delete m_widget; delete m_widget;
} }
QString QString PackageSelectViewStep::prettyName() const
PackageSelectViewStep::prettyName() const
{ {
return tr( "Customize" ); return tr("Customize");
} }
bool PackageSelectViewStep::exists_and_true(const QString& key) const 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() QWidget* PackageSelectViewStep::widget()
@ -62,147 +82,282 @@ bool PackageSelectViewStep::isAtEnd() const
return true; return true;
} }
void PackageSelectViewStep::setConfigurationMap(const QVariantMap& configurationMap)
{
m_configurationMap = configurationMap;
}
/**
* @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() void PackageSelectViewStep::onActivate()
{ {
// Connect the Minimal Installation radio button // Check network availability
connect(ui->minimal_button, &QRadioButton::toggled, this, [this](bool checked) {
Calamares::Network::Manager network; Calamares::Network::Manager network;
if (checked && network.hasInternet()) { bool hasInternet = network.hasInternet();
// Handle network unavailability
if (!hasInternet) {
ui->full_button->setVisible(false);
ui->full_text->setVisible(false);
ui->left_spacer->changeSize(20, 20, QSizePolicy::Fixed, QSizePolicy::Fixed);
ui->right_spacer->changeSize(0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed);
ui->additional_label->setVisible(false);
ui->updates_button->setVisible(false);
ui->updates_text->setVisible(false);
ui->extraparty_scroll->setVisible(false); ui->extraparty_scroll->setVisible(false);
ui->extraparty_text->setVisible(false); ui->extraparty_text->setVisible(false);
ui->mandatory_warning_label->setVisible(false); ui->mandatory_warning_label->setVisible(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<QVBoxLayout*>("packages_layout");
if (!packagesLayout) {
qWarning() << "packages_layout not found in UI.";
return;
}
ui->element_button->setChecked(false); for (const QVariant& var : additionalPackages) {
ui->thunderbird_button->setChecked(false); QVariantMap pkg = var.toMap();
ui->virtmanager_button->setChecked(false); QString packageId = pkg.value("id").toString();
ui->krita_button->setChecked(false); 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);
}
}
// 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);
ui->element_button->setEnabled(false); // Uncheck and disable all additional package checkboxes
ui->thunderbird_button->setEnabled(false); QVariantList removePackages = m_configurationMap.value("packages").toMap().value("minimal_remove_packages").toList();
ui->virtmanager_button->setEnabled(false); for (const QVariant& var : removePackages) {
ui->krita_button->setEnabled(false); QString packageId = var.toString();
QCheckBox* checkbox = m_packageCheckBoxes.value(packageId, nullptr);
if (checkbox) {
checkbox->setChecked(false);
checkbox->setEnabled(false);
}
}
} }
}); });
// Connect the Normal Installation radio button connect(ui->normal_button, &QRadioButton::toggled, this, [this, hasInternet](bool checked) {
connect(ui->normal_button, &QRadioButton::toggled, this, [this](bool checked) { if (checked && hasInternet) {
Calamares::Network::Manager network; // Show additional packages UI
if (checked && network.hasInternet()) {
ui->extraparty_scroll->setVisible(true); ui->extraparty_scroll->setVisible(true);
ui->extraparty_text->setVisible(true); ui->extraparty_text->setVisible(true);
ui->mandatory_warning_label->setVisible(true); ui->mandatory_warning_label->setVisible(true);
ui->element_button->setChecked(false); // Enable all additional package checkboxes
ui->thunderbird_button->setChecked(false); for (auto checkbox : m_packageCheckBoxes) {
ui->virtmanager_button->setChecked(false); if (checkbox) {
ui->krita_button->setChecked(false); checkbox->setEnabled(true);
}
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, hasInternet](bool checked) {
connect(ui->full_button, &QRadioButton::toggled, this, [this](bool checked) { if (checked && hasInternet) {
Calamares::Network::Manager network; // Show additional packages UI
if (checked && network.hasInternet()) {
ui->extraparty_scroll->setVisible(true); ui->extraparty_scroll->setVisible(true);
ui->extraparty_text->setVisible(true); ui->extraparty_text->setVisible(true);
ui->mandatory_warning_label->setVisible(true); ui->mandatory_warning_label->setVisible(true);
ui->element_button->setChecked(true); // Check and disable all additional package checkboxes
ui->thunderbird_button->setChecked(true); for (auto checkbox : m_packageCheckBoxes) {
ui->virtmanager_button->setChecked(true); if (checkbox) {
ui->krita_button->setChecked(true); checkbox->setChecked(true);
checkbox->setEnabled(false);
ui->element_button->setEnabled(false); }
ui->thunderbird_button->setEnabled(false); }
ui->virtmanager_button->setEnabled(false);
ui->krita_button->setEnabled(false);
} }
}); });
// Disable many bits of functionality if network is not enabled m_connectionsMade = true;
Calamares::Network::Manager network; }
if (!network.hasInternet()) {
ui->full_button->setVisible(false);
ui->full_text->setVisible(false);
ui->left_spacer->changeSize(20, 20, QSizePolicy::Fixed, QSizePolicy::Fixed);
ui->right_spacer->changeSize(0, 0, QSizePolicy::Fixed, QSizePolicy::Fixed);
ui->additional_label->setVisible(false);
ui->updates_button->setVisible(false);
ui->updates_text->setVisible(false);
ui->extraparty_scroll->setVisible(false);
ui->extraparty_text->setVisible(false);
ui->mandatory_warning_label->setVisible(false);
ui->element_button->setChecked(false); // Layout Adjustment to Prevent Shifting
ui->thunderbird_button->setChecked(false); // Ensure that hiding/showing elements does not center the remaining widgets
ui->virtmanager_button->setChecked(false); // This is generally handled by Qt's layout system, but adding stretch ensures stability
ui->krita_button->setChecked(false); QGridLayout* mainLayout = qobject_cast<QGridLayout*>(ui->gridLayout);
if (mainLayout) {
ui->element_button->setEnabled(false); mainLayout->setRowStretch(mainLayout->rowCount(), 1);
ui->thunderbird_button->setEnabled(false); }
ui->virtmanager_button->setEnabled(false);
ui->krita_button->setEnabled(false);
}
// 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();
}
// 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);
} }
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(); Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
QVariantMap config; if (!gs) {
for (auto i = m_packageSelections.begin(); i != m_packageSelections.end(); ++i) { qWarning() << "GlobalStorage is not available.";
if (exists_and_true(i.key())) { return;
config.insert(i.key(), i.value());
} }
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();
}
QVariantMap globalData;
// 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";
} }
gs->insert("packages", config);
}
void PackageSelectViewStep::updatePackageSelections(bool checked) { globalData.insert("installation_mode", installationMode);
QObject* sender_obj = sender();
if (!sender_obj) return;
QString key = sender_obj->objectName(); 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);
}
// snake_case -> camelCase globalData.insert("packages_to_install", selectedPackagesList);
QStringList parts = key.split("_", Qt::SkipEmptyParts); QVariantList installerPackages = m_configurationMap.value("packages").toMap().value("installer_remove_packages").toList();
for (int i = 1; i < parts.size(); ++i) { globalData.insert("packages_to_remove", installerPackages);
parts[i][0] = parts[i][0].toUpper(); globalData.insert("present_snaps", presentSnapList);
} }
QString camelCaseKey = parts.join("");
m_packageSelections[camelCaseKey] = checked; // 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<QCheckBox*>(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<PackageSelectViewStep>(); )

@ -1,52 +1,143 @@
#ifndef PACKAGESELECTVIEWSTEP_H #ifndef PACKAGESELECTVIEWSTEP_H
#define PACKAGESELECTVIEWSTEP_H #define PACKAGESELECTVIEWSTEP_H
#include <QFile> #include <QObject>
#include <QTextStream> #include <QVariantMap>
#include <QMap>
#include "DllMacro.h" #include "DllMacro.h"
#include "utils/PluginFactory.h" #include "utils/PluginFactory.h"
#include "viewpages/ViewStep.h" #include "viewpages/ViewStep.h"
#include "ui_pkgselect.h"
namespace Ui { namespace Ui {
class pkgselect; 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 class PLUGINDLLEXPORT PackageSelectViewStep : public Calamares::ViewStep
{ {
Q_OBJECT Q_OBJECT
public: 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; ~PackageSelectViewStep() override;
/**
* @brief Returns the display name of the step.
* @return The pretty name as a QString.
*/
QString prettyName() const override; QString prettyName() const override;
/**
* @brief Returns the widget associated with this step.
* @return A pointer to the QWidget.
*/
QWidget* widget() override; QWidget* widget() override;
/**
* @brief Returns the list of jobs to execute for this step.
* @return An empty Calamares::JobList.
*/
Calamares::JobList jobs() const override; Calamares::JobList jobs() const override;
/**
* @brief Indicates whether the "Next" button is enabled.
* @return Always returns true.
*/
bool isNextEnabled() const override; bool isNextEnabled() const override;
/**
* @brief Indicates whether the "Back" button is enabled.
* @return Always returns true.
*/
bool isBackEnabled() const override; bool isBackEnabled() const override;
/**
* @brief Indicates whether the step is at the beginning.
* @return Always returns true.
*/
bool isAtBeginning() const override; bool isAtBeginning() const override;
/**
* @brief Indicates whether the step is at the end.
* @return Always returns true.
*/
bool isAtEnd() const override; bool isAtEnd() const override;
/**
* @brief Activates the step, setting up the UI based on network availability and configuration.
*/
void onActivate() override; void onActivate() override;
/**
* @brief Handles actions to perform when leaving the step, such as storing selected packages.
*/
void onLeave() override; 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; } 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); void updatePackageSelections(bool checked);
signals: signals:
/**
* @brief Signal emitted when package selections change.
*/
void packageSelectionsChanged(); void packageSelectionsChanged();
private: private:
QVariantMap m_packageSelections; /**
Ui::pkgselect *ui; * @brief Retrieves the checkbox associated with a given package ID.
QWidget* m_widget; * @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; 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<QString, QCheckBox*> 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

@ -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"

@ -11,7 +11,7 @@
</rect> </rect>
</property> </property>
<property name="windowTitle"> <property name="windowTitle">
<string>Form</string> <string>Package Selection</string>
</property> </property>
<property name="styleSheet"> <property name="styleSheet">
<string notr="true">QRadioButton { <string notr="true">QRadioButton {
@ -28,102 +28,29 @@ QLabel {
}</string> }</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="9" column="1">
<widget class="QRadioButton" name="minimal_button"> <!-- Installation Mode Label -->
<property name="maximumSize"> <item row="1" column="1">
<size> <widget class="QLabel" name="apps_label">
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="font">
<font>
<pointsize>12</pointsize>
</font>
</property>
<property name="text">
<string>Minimal Installation</string>
</property>
</widget>
</item>
<item row="0" column="2">
<spacer name="right_spacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="21" column="1">
<spacer name="pushup">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="20" column="0" colspan="3">
<widget class="QLabel" name="mandatory_warning_label">
<property name="font"> <property name="font">
<font> <font>
<pointsize>11</pointsize> <pointsize>18</pointsize>
<weight>75</weight> <weight>50</weight>
<italic>false</italic> <bold>false</bold>
<bold>true</bold>
</font> </font>
</property> </property>
<property name="text"> <property name="styleSheet">
<string>Note: Ubuntu and flavors are NOT responsible for third-party software installed from this list.</string> <string notr="true">padding-left: 0px; padding-right: 0px;</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="14" column="1">
<widget class="QLabel" name="updates_text">
<property name="font">
<font>
<pointsize>10</pointsize>
<italic>true</italic>
</font>
</property> </property>
<property name="text"> <property name="text">
<string>This saves time after installation, and keeps your system secure</string> <string>Installation Mode</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<spacer name="verticalSpacer"> <!-- Minimal Installation Radio Button -->
<property name="orientation"> <item row="9" column="1">
<enum>Qt::Vertical</enum> <widget class="QRadioButton" name="minimal_button">
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QRadioButton" name="full_button">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
@ -136,28 +63,14 @@ QLabel {
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Full Installation</string> <string>Minimal Installation</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="0">
<spacer name="left_spacer"> <!-- Minimal Installation Description -->
<property name="orientation"> <item row="10" column="1">
<enum>Qt::Horizontal</enum> <widget class="QLabel" name="minimal_text">
</property>
<property name="sizeType">
<enum>QSizePolicy::Minimum</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="3" column="1">
<widget class="QLabel" name="full_text">
<property name="font"> <property name="font">
<font> <font>
<pointsize>10</pointsize> <pointsize>10</pointsize>
@ -165,31 +78,14 @@ QLabel {
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>All applications in the Normal Installation, and all extra third-party packages listed below</string> <string>Only the desktop environment</string>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
</widget> </widget>
</item> </item>
<item row="8" column="1">
<spacer name="verticalSpacer_6"> <!-- Normal Installation Radio Button -->
<property name="orientation"> <item row="6" column="1">
<enum>Qt::Vertical</enum> <widget class="QRadioButton" name="normal_button">
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="13" column="1">
<widget class="QCheckBox" name="updates_button">
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>16777215</width> <width>16777215</width>
@ -202,98 +98,17 @@ QLabel {
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Download and install updates following installation</string> <string>Normal Installation</string>
</property>
</widget>
</item>
<item row="18" column="1">
<spacer name="verticalSpacer_11">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>3</height>
</size>
</property> </property>
</spacer> <property name="checked">
</item>
<item row="19" column="1">
<widget class="QScrollArea" name="extraparty_scroll">
<property name="widgetResizable">
<bool>true</bool> <bool>true</bool>
</property> </property>
<widget class="QWidget" name="extraparty_scrollhouse">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>762</width>
<height>281</height>
</rect>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<item row="8" column="1">
<widget class="QCheckBox" name="virtmanager_button">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="text">
<string>Virtual Machine Manager</string>
</property>
</widget> </widget>
</item> </item>
<item row="1" column="1">
<widget class="QCheckBox" name="element_button"> <!-- Normal Installation Description -->
<property name="maximumSize"> <item row="7" column="1">
<size> <widget class="QLabel" name="normal_text">
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="text">
<string>Element</string>
</property>
</widget>
</item>
<item row="11" column="1">
<widget class="QCheckBox" name="krita_button">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="text">
<string>Krita</string>
</property>
</widget>
</item>
<item row="6" column="1">
<spacer name="thunderbird_spacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>10</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="1">
<widget class="QLabel" name="element_text">
<property name="font"> <property name="font">
<font> <font>
<pointsize>10</pointsize> <pointsize>10</pointsize>
@ -301,57 +116,34 @@ QLabel {
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Matrix-based end-to-end encrypted messenger and secure collaboration app</string> <string>Web browser, utilities, office software, games, and media players</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="10" column="1">
<spacer name="verticalSpacer_10"> <!-- Full Installation Radio Button -->
<property name="orientation"> <item row="2" column="1">
<enum>Qt::Vertical</enum> <widget class="QRadioButton" name="full_button">
</property> <property name="maximumSize">
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>16777215</width>
<height>10</height> <height>21</height>
</size> </size>
</property> </property>
</spacer>
</item>
<item row="9" column="1">
<widget class="QLabel" name="virtmanager_text">
<property name="font"> <property name="font">
<font> <font>
<pointsize>10</pointsize> <pointsize>12</pointsize>
<italic>true</italic>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Desktop user interface for managing virtual machines through libvirt</string> <string>Full Installation</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<spacer name="verticalSpacer_4"> <!-- Full Installation Description -->
<property name="orientation"> <item row="3" column="1">
<enum>Qt::Vertical</enum> <widget class="QLabel" name="full_text">
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>1</width>
<height>5</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<widget class="QLabel" name="thunderbird_text">
<property name="font"> <property name="font">
<font> <font>
<pointsize>10</pointsize> <pointsize>10</pointsize>
@ -359,41 +151,33 @@ QLabel {
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Email, newsfeed, chat, and calendaring client</string> <string>All applications in the Normal Installation, and all extra third-party packages listed below</string>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QCheckBox" name="thunderbird_button">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property> </property>
<property name="text"> <property name="alignment">
<string>Thunderbird</string> <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="1">
<spacer name="verticalSpacer_8"> <!-- Spacer Elements -->
<item row="0" column="0">
<spacer name="left_spacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeType"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum> <enum>QSizePolicy::Minimum</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>10</height> <height>20</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="13" column="1"> <item row="0" column="1">
<spacer name="pushup_tiny"> <spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
@ -403,59 +187,29 @@ QLabel {
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>6</height> <height>20</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="0"> <item row="0" column="2">
<spacer name="horizontalSpacer_12"> <spacer name="right_spacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Horizontal</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeType"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum> <enum>QSizePolicy::Minimum</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>5</width> <width>20</width>
<height>20</height> <height>20</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="12" column="1"> <item row="8" column="1">
<widget class="QLabel" name="krita_text"> <spacer name="verticalSpacer_6">
<property name="font">
<font>
<pointsize>10</pointsize>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Graphics editor designed primarily for digital art and 2D animation</string>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item row="10" column="1">
<widget class="QLabel" name="minimal_text">
<property name="font">
<font>
<pointsize>10</pointsize>
<italic>true</italic>
</font>
</property>
<property name="text">
<string>Only the desktop environment</string>
</property>
</widget>
</item>
<item row="15" column="1">
<spacer name="verticalSpacer_3">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
@ -465,13 +219,15 @@ QLabel {
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>20</height> <height>10</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="1" column="1">
<widget class="QLabel" name="apps_label"> <!-- Additional Options Label -->
<item row="12" column="1">
<widget class="QLabel" name="additional_label">
<property name="font"> <property name="font">
<font> <font>
<pointsize>18</pointsize> <pointsize>18</pointsize>
@ -483,29 +239,34 @@ QLabel {
<string notr="true">padding-left: 0px; padding-right: 0px;</string> <string notr="true">padding-left: 0px; padding-right: 0px;</string>
</property> </property>
<property name="text"> <property name="text">
<string>Installation Mode</string> <string>Additional Options</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="12" column="1">
<widget class="QLabel" name="additional_label"> <!-- Update Checkbox -->
<item row="13" column="1">
<widget class="QCheckBox" name="updates_button">
<property name="maximumSize">
<size>
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>18</pointsize> <pointsize>12</pointsize>
<weight>50</weight>
<bold>false</bold>
</font> </font>
</property> </property>
<property name="styleSheet">
<string notr="true">padding-left: 0px; padding-right: 0px;</string>
</property>
<property name="text"> <property name="text">
<string>Additional Options</string> <string>Download and install updates following installation</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="7" column="1">
<widget class="QLabel" name="normal_text"> <!-- Updates Text -->
<item row="14" column="1">
<widget class="QLabel" name="updates_text">
<property name="font"> <property name="font">
<font> <font>
<pointsize>10</pointsize> <pointsize>10</pointsize>
@ -513,31 +274,47 @@ QLabel {
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Web browser, utilities, office software, games, and media players</string> <string>This saves time after installation, and keeps your system secure</string>
</property> </property>
</widget> </widget>
</item> </item>
<item row="6" column="1">
<widget class="QRadioButton" name="normal_button"> <!-- Mandatory Warning Label -->
<property name="maximumSize"> <item row="20" column="0" colspan="3">
<size> <widget class="QLabel" name="mandatory_warning_label">
<width>16777215</width>
<height>21</height>
</size>
</property>
<property name="font"> <property name="font">
<font> <font>
<pointsize>12</pointsize> <pointsize>11</pointsize>
<weight>75</weight>
<italic>false</italic>
<bold>true</bold>
</font> </font>
</property> </property>
<property name="text"> <property name="text">
<string>Normal Installation</string> <string>Note: Ubuntu and flavors are NOT responsible for third-party software installed from this list.</string>
</property> </property>
<property name="checked"> <property name="wordWrap">
<bool>true</bool> <bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
<!-- Pushup Spacer -->
<item row="21" column="1">
<spacer name="pushup">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<!-- Additional Packages Label -->
<item row="16" column="1"> <item row="16" column="1">
<widget class="QLabel" name="extraparty_text"> <widget class="QLabel" name="extraparty_text">
<property name="font"> <property name="font">
@ -555,51 +332,47 @@ QLabel {
</property> </property>
</widget> </widget>
</item> </item>
<item row="11" column="1">
<spacer name="verticalSpacer_2"> <!-- Scroll Area for Additional Packages -->
<property name="orientation"> <item row="19" column="1">
<enum>Qt::Vertical</enum> <widget class="QScrollArea" name="extraparty_scroll">
</property> <property name="widgetResizable">
<property name="sizeType"> <bool>true</bool>
<enum>QSizePolicy::Fixed</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <widget class="QWidget" name="extraparty_scrollhouse">
<size> <property name="geometry">
<width>20</width> <rect>
<height>20</height> <x>0</x>
</size> <y>0</y>
<width>762</width>
<height>281</height>
</rect>
</property> </property>
</spacer> <layout class="QVBoxLayout" name="packages_layout">
<!-- Dynamic Checkboxes will be added here -->
</layout>
</widget>
</widget>
</item> </item>
<item row="4" column="1">
<spacer name="verticalSpacer_5"> <!-- Stretch to Push Elements Up -->
<item row="22" column="1">
<spacer name="stretch_spacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Vertical</enum>
</property> </property>
<property name="sizeType"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum> <enum>QSizePolicy::Expanding</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>10</height> <height>40</height>
</size>
</property>
</spacer>
</item>
<item row="17" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>0</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

@ -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
)

@ -0,0 +1,390 @@
#include "PackageSelectProcess.h"
#include "GlobalStorage.h"
#include "JobQueue.h"
#include <QProcess>
#include <QDebug>
#include <QDir>
#include <QCoreApplication>
#include <QRegularExpression>
CALAMARES_PLUGIN_FACTORY_DEFINITION(PackageSelectProcessFactory, registerPlugin<PackageSelectProcess>();)
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<double>(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, &currentDescription, 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<QString, QVector<ProgressAllocation>> 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<ProgressAllocation> 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();
}

@ -0,0 +1,53 @@
#ifndef PACKAGESELECTPROCESS_H
#define PACKAGESELECTPROCESS_H
#include <QObject>
#include <QVariantMap>
#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

@ -0,0 +1,7 @@
---
type: "job"
name: "pkgselectprocess"
interface: "qtplugin"
load: "libcalamares_job_pkgselectprocess.so"
noconfig: true
weight: 12

5
debian/changelog vendored

@ -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! * Welcome to Plucky Puffin!
* Port to Qt 6. * Port to Qt 6.
* Rewrite the pkgselect module and its processing.
-- Simon Quigley <tsimonq2@ubuntu.com> Tue, 15 Oct 2024 21:05:10 -0500 -- Simon Quigley <tsimonq2@ubuntu.com> Tue, 22 Oct 2024 19:23:22 -0500
calamares-settings-ubuntu (1:24.10.5) oracular; urgency=medium calamares-settings-ubuntu (1:24.10.5) oracular; urgency=medium

1
debian/control vendored

@ -71,6 +71,7 @@ Depends: calamares (>= 3.3.9),
python3-distro, python3-distro,
qml6-module-qtquick, qml6-module-qtquick,
qml6-module-qtquick-window, qml6-module-qtquick-window,
snapd-seed-glue,
squashfs-tools, squashfs-tools,
sudo, sudo,
${misc:Depends}, ${misc:Depends},

10
debian/rules vendored

@ -5,20 +5,23 @@ export DEB_BUILD_MAINT_OPTIONS = hardening=+all
export GOPATH=/usr/share/gocode export GOPATH=/usr/share/gocode
export GO111MODULE=off export GO111MODULE=off
export GOCACHE=$(CURDIR)/.gocache 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) 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 $@ dh $@
override_dh_auto_configure: override_dh_auto_configure:
(cd $(PKGSELECT) && mkdir build && cd build && cmake ..) (cd $(PKGSELECT) && mkdir build && cd build && cmake ..)
(cd $(PKGSELECTPROCESS) && mkdir build && cd build && cmake ..)
override_dh_auto_build: override_dh_auto_build:
make; make;
(cd $(PKGSELECT)/build && $(MAKE)) (cd $(PKGSELECT)/build && $(MAKE))
(cd $(PKGSELECTPROCESS)/build && $(MAKE))
override_dh_auto_clean: override_dh_auto_clean:
dh_auto_clean dh_auto_clean
@ -26,6 +29,7 @@ override_dh_auto_clean:
override_dh_auto_install: override_dh_auto_install:
(cd $(PKGSELECT)/build && $(MAKE) DESTDIR=$(CURDIR)/debian/calamares-settings-ubuntu-common/ 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: override_dh_missing:
dh_missing dh_missing
@ -38,6 +42,8 @@ override_dh_missing:
chmod 644 $(MODULES_DIR)/automirror/module.desc chmod 644 $(MODULES_DIR)/automirror/module.desc
chmod 644 $(MODULES_DIR)/pkgselect/libcalamares_viewmodule_pkgselect.so chmod 644 $(MODULES_DIR)/pkgselect/libcalamares_viewmodule_pkgselect.so
chmod 644 $(MODULES_DIR)/pkgselect/module.desc 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/bin/
mkdir -pv debian/calamares-settings-ubuntu-common/usr/libexec/ mkdir -pv debian/calamares-settings-ubuntu-common/usr/libexec/
cp -v common/fixconkeys-part1 debian/calamares-settings-ubuntu-common/usr/libexec/fixconkeys-part1 cp -v common/fixconkeys-part1 debian/calamares-settings-ubuntu-common/usr/libexec/fixconkeys-part1

@ -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

@ -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"

@ -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"

@ -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"

@ -17,12 +17,6 @@ instances:
- id: add386arch - id: add386arch
module: shellprocess module: shellprocess
config: shellprocess_add386arch.conf 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 - id: oemprep
module: shellprocess module: shellprocess
config: shellprocess_oemprep.conf config: shellprocess_oemprep.conf
@ -61,18 +55,16 @@ sequence:
- hwclock - hwclock
- contextualprocess@before_bootloader_mkdirs - contextualprocess@before_bootloader_mkdirs
- shellprocess@bug-LP#1829805 - shellprocess@bug-LP#1829805
- shellprocess@fixconkeys_part1
- shellprocess@fixconkeys_part2
- initramfscfg - initramfscfg
- initramfs - initramfs
- grubcfg - grubcfg
- contextualprocess@before_bootloader - contextualprocess@before_bootloader
- bootloader - bootloader
- automirror
- shellprocess@add386arch - shellprocess@add386arch
- shellprocess@fixconkeys_part1 - automirror
- shellprocess@fixconkeys_part2 - pkgselectprocess
- packages
- contextualprocess@pkgselect_action
- contextualprocess@pkgselect_snap_action
- shellprocess@logs - shellprocess@logs
- umount - umount
- show: - show:

@ -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

@ -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"

@ -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"

@ -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"

@ -17,12 +17,6 @@ instances:
- id: add386arch - id: add386arch
module: shellprocess module: shellprocess
config: shellprocess_add386arch.conf 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 - id: oemprep
module: shellprocess module: shellprocess
config: shellprocess_oemprep.conf config: shellprocess_oemprep.conf
@ -61,18 +55,16 @@ sequence:
- hwclock - hwclock
- contextualprocess@before_bootloader_mkdirs - contextualprocess@before_bootloader_mkdirs
- shellprocess@bug-LP#1829805 - shellprocess@bug-LP#1829805
- shellprocess@fixconkeys_part1
- shellprocess@fixconkeys_part2
- initramfscfg - initramfscfg
- initramfs - initramfs
- grubcfg - grubcfg
- contextualprocess@before_bootloader - contextualprocess@before_bootloader
- bootloader - bootloader
- automirror
- shellprocess@add386arch - shellprocess@add386arch
- shellprocess@fixconkeys_part1 - automirror
- shellprocess@fixconkeys_part2 - pkgselectprocess
- packages
- contextualprocess@pkgselect_action
- contextualprocess@pkgselect_snap_action
- shellprocess@logs - shellprocess@logs
- umount - umount
- show: - show:

@ -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

@ -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"

@ -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"

@ -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"

@ -17,12 +17,6 @@ instances:
- id: add386arch - id: add386arch
module: shellprocess module: shellprocess
config: shellprocess_add386arch.conf 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 - id: oemprep
module: shellprocess module: shellprocess
config: shellprocess_oemprep.conf config: shellprocess_oemprep.conf
@ -61,18 +55,16 @@ sequence:
- hwclock - hwclock
- contextualprocess@before_bootloader_mkdirs - contextualprocess@before_bootloader_mkdirs
- shellprocess@bug-LP#1829805 - shellprocess@bug-LP#1829805
- shellprocess@fixconkeys_part1
- shellprocess@fixconkeys_part2
- initramfscfg - initramfscfg
- initramfs - initramfs
- grubcfg - grubcfg
- contextualprocess@before_bootloader - contextualprocess@before_bootloader
- bootloader - bootloader
- automirror
- shellprocess@add386arch - shellprocess@add386arch
- shellprocess@fixconkeys_part1 - automirror
- shellprocess@fixconkeys_part2 - pkgselectprocess
- packages
- contextualprocess@pkgselect_action
- contextualprocess@pkgselect_snap_action
- shellprocess@logs - shellprocess@logs
- umount - umount
- show: - show:

Loading…
Cancel
Save