From b29c52bb23e218048b27c473e2c163bd5841919e Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 16:21:48 +0000 Subject: [PATCH 01/16] bump version -> 0.2.21 --- src/gui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index aa0ef94..d45c284 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.16\n" + "Version: 0.2.21\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From 460f85f02fef860afb569f9017db448eca711a92 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 16:31:31 +0000 Subject: [PATCH 02/16] update todo --- TODO.md | 2 +- src/gui/home_widget.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 7301e79..1b5b1cc 100644 --- a/TODO.md +++ b/TODO.md @@ -2,7 +2,7 @@ - [x] Add launch button on package card if package is installed and remove when uninstalled - [] Add detailed mirrorlist tab to set mirrorlist - [] Add version information -- [] +- [] Implement an AUR helper in core to remove dependence on paru and yay ## Future Enhancements diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 2939122..6a3b700 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -75,7 +75,7 @@ void HomeWidget::loadFeaturedPackages() { pkg.repository = repoInfo.repository; pkg.version = repoInfo.version; pkg.description = repoInfo.description; - Logger::info(QString("✅ Package %1 found in %2 repository, will use pacman instead of AUR helper") + Logger::info(QString("Package %1 found in %2 repository, will use pacman instead of AUR helper") .arg(pkg.name, pkg.repository)); } else { Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); From b197cfdfd2eae1ccd262fc7756576dd98211ec34 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 16:38:40 +0000 Subject: [PATCH 03/16] show correct version information for all apps --- src/gui/home_widget.cpp | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 6a3b700..4446649 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -65,21 +65,23 @@ void HomeWidget::loadFeaturedPackages() { {"zoom", "Latest", "Video Conferencing and Web Conferencing Service", "AUR"} }; - // Check if packages marked as AUR are actually available in automated repos (like chaotic-aur) + // Fetch actual package information from repositories for (auto& pkg : m_featuredPackages) { - if (pkg.repository.toLower() == "aur") { - Logger::debug(QString("Checking if AUR package %1 is available in official repos...").arg(pkg.name)); - PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); - if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { - // Package found in automated repos, use that repository instead - pkg.repository = repoInfo.repository; - pkg.version = repoInfo.version; - pkg.description = repoInfo.description; - Logger::info(QString("Package %1 found in %2 repository, will use pacman instead of AUR helper") - .arg(pkg.name, pkg.repository)); - } else { - Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); + PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); + + if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { + // Package found in official repos, update with actual information + pkg.repository = repoInfo.repository; + pkg.version = repoInfo.version; + pkg.description = repoInfo.description; + + if (pkg.repository.toLower() != "aur") { + Logger::debug(QString("Package %1 found in %2 repository with version %3") + .arg(pkg.name, pkg.repository, pkg.version)); } + } else if (pkg.repository.toLower() == "aur") { + // Package not found in official repos, will use AUR helper + Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); } } From 4b0727ee520905ab530608b84c66c9ef523cb5df Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 18:08:29 +0000 Subject: [PATCH 04/16] remove paru support and default to yay --- src/core/package_manager.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index 8e2b129..f3588f3 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -41,13 +41,13 @@ void PackageManager::detectHelper() { return; } - // Check for paru - QString paruPath = QStandardPaths::findExecutable("paru"); - if (!paruPath.isEmpty()) { - m_helper = Helper::Paru; - Logger::info("Using paru as package helper"); - return; - } + // Check for paru - deprecate because paru doesn't allow running with pkexec + // QString paruPath = QStandardPaths::findExecutable("paru"); + // if (!paruPath.isEmpty()) { + // m_helper = Helper::Paru; + // Logger::info("Using paru as package helper"); + // return; + // } // Default to pacman m_helper = Helper::Pacman; @@ -57,7 +57,6 @@ void PackageManager::detectHelper() { QString PackageManager::getHelperName() const { switch (m_helper) { case Helper::Yay: return "yay"; - case Helper::Paru: return "paru"; case Helper::Pacman: return "pacman"; default: return "pacman"; } @@ -75,9 +74,10 @@ void PackageManager::installPackage(const QString& packageName, const QString& r QString helper = getHelperName(); QString command; - if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { - // AUR packages - run helper as regular user (no pkexec) - command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); + if (isAUR && (m_helper == Helper::Yay)) { + // AUR packages - use pkexec to get userpassword before hand + // Paru has a problem here, so default to yay + command = QString("pkexec %1 -S %2 --noconfirm").arg(helper, packageName); } else { // Official repos and chaotic-aur need root access and use pacman command = QString("pkexec pacman -S %1 --noconfirm").arg(packageName); @@ -110,7 +110,7 @@ void PackageManager::updatePackage(const QString& packageName, const QString& re QString helper = getHelperName(); QString command; - if (isAUR && (m_helper == Helper::Yay || m_helper == Helper::Paru)) { + if (isAUR && (m_helper == Helper::Yay)) { // AUR packages - run helper as regular user (no pkexec) command = QString("%1 -S %2 --noconfirm").arg(helper, packageName); } else { From c1a53832af10597ee56d319f38ec7eaaa457f6b4 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 18:46:58 +0000 Subject: [PATCH 05/16] add cancel operation button; remove revert button --- src/core/package_manager.cpp | 27 ++++++++ src/core/package_manager.h | 2 + src/gui/settings_widget.cpp | 129 +++++++++++++++++++++++++---------- src/gui/settings_widget.h | 4 +- 4 files changed, 125 insertions(+), 37 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index f3588f3..c85901c 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -187,3 +187,30 @@ void PackageManager::onProcessOutput() { emit operationOutput(output); } } + +void PackageManager::cancelRunningOperation() { + if (m_process && m_process->state() != QProcess::NotRunning) { + Logger::warning("Cancelling running operation..."); + emit operationOutput("\n>>> Operation cancelled by user <<<\n"); + + // First try to terminate gracefully + m_process->terminate(); + + // Wait up to 5 seconds for graceful termination + if (!m_process->waitForFinished(5000)) { + // If it doesn't terminate gracefully, force kill + Logger::warning("Process did not terminate gracefully, forcing kill..."); + m_process->kill(); + m_process->waitForFinished(1000); + } + + emit operationCompleted(false, "Operation cancelled by user"); + Logger::info("Operation cancelled successfully"); + } else { + Logger::warning("No operation is currently running"); + } +} + +bool PackageManager::isOperationRunning() const { + return m_process && m_process->state() != QProcess::NotRunning; +} diff --git a/src/core/package_manager.h b/src/core/package_manager.h index ad77fc2..5cf1cc8 100644 --- a/src/core/package_manager.h +++ b/src/core/package_manager.h @@ -31,6 +31,8 @@ class PackageManager : public QObject { void uninstallPackage(const QString& packageName, const QString& repository = QString()); void updatePackage(const QString& packageName, const QString& repository = QString()); void updateAllPackages(); + void cancelRunningOperation(); + bool isOperationRunning() const; Helper getHelper() const { return m_helper; } QString getHelperName() const; diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index 6d9fbd5..e245581 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -1,6 +1,7 @@ #include "settings_widget.h" #include "../utils/logger.h" #include "../core/alpm_wrapper.h" +#include "../core/package_manager.h" #include #include #include @@ -23,8 +24,8 @@ SettingsWidget::SettingsWidget(QWidget* parent) , m_maintenanceGroup(nullptr) , m_removeLockButton(nullptr) , m_syncReposButton(nullptr) + , m_cancelProcessButton(nullptr) , m_applyButton(nullptr) - , m_revertButton(nullptr) , m_statusLabel(nullptr) , m_originalMultilibState(false) , m_originalChaoticAurState(false) { @@ -80,24 +81,6 @@ void SettingsWidget::setupUi() { m_statusLabel->hide(); mainLayout->addWidget(m_statusLabel); - // Buttons - auto* buttonLayout = new QHBoxLayout(); - buttonLayout->addStretch(); - - m_revertButton = new QPushButton("Revert", contentWidget); - m_revertButton->setMinimumWidth(100); - m_revertButton->setEnabled(false); - connect(m_revertButton, &QPushButton::clicked, this, &SettingsWidget::onRevertClicked); - buttonLayout->addWidget(m_revertButton); - - m_applyButton = new QPushButton("Apply", contentWidget); - m_applyButton->setMinimumWidth(100); - m_applyButton->setEnabled(false); - connect(m_applyButton, &QPushButton::clicked, this, &SettingsWidget::onApplyClicked); - buttonLayout->addWidget(m_applyButton); - - mainLayout->addLayout(buttonLayout); - // Add stretch at the bottom mainLayout->addStretch(); @@ -165,6 +148,18 @@ void SettingsWidget::createRepositorySettings() { infoLabel->setStyleSheet("QLabel { color: #888; font-style: italic; margin-top: 10px; }"); repoLayout->addWidget(infoLabel); + // Apply button + auto* applyLayout = new QHBoxLayout(); + applyLayout->addStretch(); + + m_applyButton = new QPushButton("Apply Changes", this); + m_applyButton->setMinimumWidth(150); + m_applyButton->setEnabled(false); + connect(m_applyButton, &QPushButton::clicked, this, &SettingsWidget::onApplyClicked); + applyLayout->addWidget(m_applyButton); + + repoLayout->addLayout(applyLayout); + m_repositoryGroup->setLayout(repoLayout); } @@ -316,6 +311,40 @@ void SettingsWidget::createMaintenanceSettings() { syncInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); maintenanceLayout->addWidget(syncInfoLabel); + // Spacer + maintenanceLayout->addSpacing(15); + + // Cancel running process section + auto* cancelProcessLayout = new QHBoxLayout(); + + auto* cancelProcessLabel = new QLabel( + "Cancel Running Process:", + this); + cancelProcessLabel->setStyleSheet("QLabel { font-weight: bold; }"); + cancelProcessLayout->addWidget(cancelProcessLabel); + + cancelProcessLayout->addStretch(); + + m_cancelProcessButton = new QPushButton("Cancel Process", this); + m_cancelProcessButton->setMinimumWidth(150); + m_cancelProcessButton->setToolTip( + "Cancel any running package operation (install, uninstall, update).\n" + "Use this if an operation is stuck or taking too long.\n" + "This is different from removing the lock file - it actually stops the running process."); + connect(m_cancelProcessButton, &QPushButton::clicked, this, &SettingsWidget::onCancelProcessClicked); + cancelProcessLayout->addWidget(m_cancelProcessButton); + + maintenanceLayout->addLayout(cancelProcessLayout); + + // Cancel process info + auto* cancelInfoLabel = new QLabel( + "Use this to cancel a stuck installation, uninstallation, or update process.\n" + "This is useful when you see 'Another operation is already in progress' and want to stop it.", + this); + cancelInfoLabel->setWordWrap(true); + cancelInfoLabel->setStyleSheet("QLabel { color: #888; font-size: 11px; margin-top: 5px; margin-left: 10px; }"); + maintenanceLayout->addWidget(cancelInfoLabel); + m_maintenanceGroup->setLayout(maintenanceLayout); } @@ -680,11 +709,10 @@ bool SettingsWidget::disableChaoticAurInPacmanConf() { } void SettingsWidget::onSettingsChanged() { - // Enable apply and revert buttons when settings change + // Enable apply button when settings change bool hasChanges = (m_multilibRepoCheckbox->isChecked() != m_originalMultilibState) || (m_chaoticAurCheckbox->isChecked() != m_originalChaoticAurState); m_applyButton->setEnabled(hasChanges); - m_revertButton->setEnabled(hasChanges); m_statusLabel->hide(); } @@ -785,7 +813,6 @@ void SettingsWidget::onApplyClicked() { m_statusLabel->show(); m_applyButton->setEnabled(false); - m_revertButton->setEnabled(false); // Suggest database sync auto reply = QMessageBox::question(this, "Sync Package Database", @@ -820,19 +847,6 @@ void SettingsWidget::onApplyClicked() { } } -void SettingsWidget::onRevertClicked() { - // Revert to original state - m_multilibRepoCheckbox->setChecked(m_originalMultilibState); - m_chaoticAurCheckbox->setChecked(m_originalChaoticAurState); - m_applyButton->setEnabled(false); - m_revertButton->setEnabled(false); - m_statusLabel->setText("Changes reverted"); - m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); - m_statusLabel->show(); - - Logger::info("Settings reverted to original state"); -} - bool SettingsWidget::isMultilibEnabled() const { return m_multilibRepoCheckbox->isChecked() && (m_multilibRepoCheckbox->isChecked() == m_originalMultilibState); @@ -1083,3 +1097,48 @@ void SettingsWidget::onSyncReposClicked() { process->start("pkexec", QStringList() << "pacman" << "-Sy"); } + +void SettingsWidget::onCancelProcessClicked() { + // Check if there's actually a process running + if (!PackageManager::instance().isOperationRunning()) { + QMessageBox::information(this, "No Process Running", + "There is no package operation currently running.\n" + "Nothing to cancel."); + return; + } + + // Show confirmation dialog + QMessageBox msgBox(this); + msgBox.setIcon(QMessageBox::Warning); + msgBox.setWindowTitle("Cancel Running Process"); + msgBox.setText("Are you sure you want to cancel the running package operation?"); + msgBox.setInformativeText( + "This will stop the current installation, uninstallation, or update process.\n\n" + "WARNING: Cancelling a package operation may leave your system in an inconsistent state.\n" + "You may need to run the operation again to complete it properly.\n\n" + "It's recommended to only cancel if the process is truly stuck or unresponsive."); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::No); + + if (msgBox.exec() != QMessageBox::Yes) { + return; + } + + m_statusLabel->setText("Cancelling running process..."); + m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); + m_statusLabel->show(); + + // Cancel the operation + PackageManager::instance().cancelRunningOperation(); + + m_statusLabel->setText("Process cancelled successfully!"); + m_statusLabel->setStyleSheet("QLabel { color: #00aa00; padding: 10px; font-weight: bold; }"); + m_statusLabel->show(); + + Logger::info("User cancelled running package operation from settings"); + + QMessageBox::information(this, "Process Cancelled", + "The running package operation has been cancelled.\n\n" + "If you were in the middle of installing or updating a package, " + "you may need to run the operation again to complete it."); +} diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index 5fd48ae..6985381 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -52,10 +52,10 @@ class SettingsWidget : public QWidget { QGroupBox* m_maintenanceGroup; QPushButton* m_removeLockButton; QPushButton* m_syncReposButton; + QPushButton* m_cancelProcessButton; // Control buttons QPushButton* m_applyButton; - QPushButton* m_revertButton; // Status QLabel* m_statusLabel; @@ -66,12 +66,12 @@ class SettingsWidget : public QWidget { private slots: void onApplyClicked(); - void onRevertClicked(); void onSettingsChanged(); void onSetupChaoticClicked(); void onRemoveChaoticClicked(); void onRemoveLockClicked(); void onSyncReposClicked(); + void onCancelProcessClicked(); }; #endif // SETTINGS_WIDGET_H From 63befddc4559f06147546a07a48a1f9b0cf8b4bd Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 18:48:34 +0000 Subject: [PATCH 06/16] bump version -> 0.2.25 --- src/gui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index d45c284..0e63344 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.21\n" + "Version: 0.2.25\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From ff121318ab89215c106ab8e8e2932efe2fa56b49 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 19:00:12 +0000 Subject: [PATCH 07/16] home_tab should default to yay if chaotic is disabled --- src/gui/home_widget.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/gui/home_widget.cpp b/src/gui/home_widget.cpp index 4446649..cba1315 100644 --- a/src/gui/home_widget.cpp +++ b/src/gui/home_widget.cpp @@ -70,7 +70,7 @@ void HomeWidget::loadFeaturedPackages() { PackageInfo repoInfo = AlpmWrapper::instance().getPackageInfo(pkg.name); if (!repoInfo.name.isEmpty() && !repoInfo.repository.isEmpty()) { - // Package found in official repos, update with actual information + // Package found in official repos (including chaotic-aur), update with actual information pkg.repository = repoInfo.repository; pkg.version = repoInfo.version; pkg.description = repoInfo.description; @@ -80,8 +80,10 @@ void HomeWidget::loadFeaturedPackages() { .arg(pkg.name, pkg.repository, pkg.version)); } } else if (pkg.repository.toLower() == "aur") { - // Package not found in official repos, will use AUR helper - Logger::debug(QString("Package %1 not found in official repos, will use AUR helper").arg(pkg.name)); + // Package not found in official repos (including chaotic-aur) + // Default to AUR helper (yay/paru) since chaotic-aur is not enabled or doesn't have this package + pkg.repository = "aur"; + Logger::debug(QString("Package %1 not found in enabled repositories, defaulting to AUR helper").arg(pkg.name)); } } From 890d35b841ea1145a0eb20ed7684162d70d0da4a Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 19:13:33 +0000 Subject: [PATCH 08/16] ensure chaotic is not added multiple times in pacman.conf --- src/gui/settings_widget.cpp | 54 ++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 19 deletions(-) diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index e245581..a5db25e 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -577,27 +577,37 @@ bool SettingsWidget::enableChaoticAurInPacmanConf() { QStringList lines; QTextStream in(&file); - bool chaoticAurSectionFound = false; - bool chaoticAurExists = false; + bool inCommentedChaoticAurSection = false; + bool chaoticAurSectionExists = false; while (!in.atEnd()) { QString line = in.readLine(); + QString trimmedLine = line.trimmed(); - // Check if chaotic-aur section already exists (uncommented) - if (line.trimmed() == "[chaotic-aur]") { - chaoticAurExists = true; - } - - // Check if this is a commented [chaotic-aur] section - if (line.trimmed() == "#[chaotic-aur]") { - lines.append("[chaotic-aur]"); - chaoticAurSectionFound = true; + // Check if chaotic-aur section already exists (uncommented or commented) + if (trimmedLine == "[chaotic-aur]" || trimmedLine == "#[chaotic-aur]") { + chaoticAurSectionExists = true; + + // If it's commented, uncomment it + if (trimmedLine == "#[chaotic-aur]") { + lines.append("[chaotic-aur]"); + inCommentedChaoticAurSection = true; + } else { + // Already uncommented, keep as is + lines.append(line); + } } // Check if the Include/Server line in chaotic-aur section is commented - else if (chaoticAurSectionFound && line.trimmed().startsWith("#") && - (line.contains("Include") || line.contains("Server"))) { - lines.append(line.mid(line.indexOf('#') + 1)); // Remove the # comment character - chaoticAurSectionFound = false; // Reset flag after processing + else if (inCommentedChaoticAurSection && trimmedLine.startsWith("#") && + (trimmedLine.contains("Include") || trimmedLine.contains("Server"))) { + // Remove the # comment character + lines.append(line.mid(line.indexOf('#') + 1)); + inCommentedChaoticAurSection = false; + } + // Check if we hit another section, reset flag + else if (trimmedLine.startsWith("[") && trimmedLine != "[chaotic-aur]" && trimmedLine != "#[chaotic-aur]") { + lines.append(line); + inCommentedChaoticAurSection = false; } else { lines.append(line); @@ -606,7 +616,7 @@ bool SettingsWidget::enableChaoticAurInPacmanConf() { file.close(); // If chaotic-aur section doesn't exist at all, add it - if (!chaoticAurExists && !chaoticAurSectionFound) { + if (!chaoticAurSectionExists) { lines.append(""); lines.append("[chaotic-aur]"); lines.append("Include = /etc/pacman.d/chaotic-mirrorlist"); @@ -657,18 +667,24 @@ bool SettingsWidget::disableChaoticAurInPacmanConf() { QString line = in.readLine(); QString trimmedLine = line.trimmed(); - // Check if this is [chaotic-aur] section + // Check if this is [chaotic-aur] section (uncommented or already commented) if (trimmedLine == "[chaotic-aur]") { lines.append("#[chaotic-aur]"); inChaoticAurSection = true; } - // Check if we're in chaotic-aur section and this is the Include/Server line + else if (trimmedLine == "#[chaotic-aur]") { + // Already commented, keep as is + lines.append(line); + inChaoticAurSection = false; + } + // Check if we're in chaotic-aur section and this is the Include/Server line (not already commented) else if (inChaoticAurSection && !trimmedLine.startsWith("#") && (trimmedLine.startsWith("Include") || trimmedLine.startsWith("Server"))) { lines.append("#" + line); + inChaoticAurSection = false; } // Check if we hit another section - else if (trimmedLine.startsWith("[") && trimmedLine != "[chaotic-aur]") { + else if (trimmedLine.startsWith("[") && trimmedLine != "[chaotic-aur]" && trimmedLine != "#[chaotic-aur]") { lines.append(line); inChaoticAurSection = false; } From 02f3cf43b71e43244b9bad62a14040ad21a11301 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 20:22:05 +0000 Subject: [PATCH 09/16] add postinstall stylesheet path --- src/gui/mainwindow.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 0e63344..4a0d6d9 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -128,15 +128,20 @@ void MainWindow::loadStyleSheet() { QFile styleFile(":/stylesheet.qss"); if (!styleFile.exists()) { - // Try loading from file system + // Try loading from current directory (for development) styleFile.setFileName("stylesheet.qss"); } + if (!styleFile.exists()) { + // Try loading from system installation path + styleFile.setFileName("/usr/share/alg-app-store/stylesheet.qss"); + } + if (styleFile.open(QFile::ReadOnly)) { QString styleSheet = QLatin1String(styleFile.readAll()); qApp->setStyleSheet(styleSheet); styleFile.close(); - Logger::info("Stylesheet loaded successfully"); + Logger::info(QString("Stylesheet loaded successfully from: %1").arg(styleFile.fileName())); } else { Logger::warning("Could not load stylesheet"); } From 948a2c93c1dd10f6d72c0e30d812f1129697d538 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Wed, 12 Nov 2025 20:33:28 +0000 Subject: [PATCH 10/16] update desktop entry --- assets/alg-app-store.desktop | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/assets/alg-app-store.desktop b/assets/alg-app-store.desktop index c7449b1..9844259 100644 --- a/assets/alg-app-store.desktop +++ b/assets/alg-app-store.desktop @@ -2,12 +2,12 @@ Type=Application Version=1.0 Name=App Store -GenericName=ALG - App Store -Keywords=utility;system;welcome; +GenericName=ALG App Store +Keywords=app;store;software;install;system; Encoding=UTF-8 Terminal=false Exec=alg-app-store -Icon=/usr/share/pixmaps/alg-app-store.png -Comment=ALG - App Store -Categories=System;Go; +Icon=alg-app-store +Comment=Install all your favourite apps +Categories=System;Apps; StartupNotify=true From acc639a31ca5dc599f28bfd35bfad497245e733a Mon Sep 17 00:00:00 2001 From: demonkiller Date: Fri, 14 Nov 2025 22:08:07 +0000 Subject: [PATCH 11/16] fixed chaotic-setup button --- src/gui/settings_widget.cpp | 60 +++++++++++++++++++++++++++---------- 1 file changed, 45 insertions(+), 15 deletions(-) diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index a5db25e..0e3bac2 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -945,11 +945,11 @@ void SettingsWidget::onSetupChaoticClicked() { msgBox.setWindowTitle("Setup Chaotic-AUR"); msgBox.setText("Install Chaotic-AUR repository?"); msgBox.setInformativeText( - "This will install:\n" - "• chaotic-keyring\n" - "• chaotic-mirrorlist\n\n" - "These packages are required to use the Chaotic-AUR repository.\n" - "You may need to manually add the repository to /etc/pacman.conf if not already configured."); + "This will:\n" + "1. Download chaotic-keyring and chaotic-mirrorlist packages\n" + "2. Install them using pacman\n" + "3. Add the repository to /etc/pacman.conf\n\n" + "This requires internet connection and administrator privileges."); msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); msgBox.setDefaultButton(QMessageBox::Yes); @@ -957,15 +957,37 @@ void SettingsWidget::onSetupChaoticClicked() { return; } - m_statusLabel->setText("Installing Chaotic-AUR packages..."); + m_statusLabel->setText("Setting up Chaotic-AUR repository..."); m_statusLabel->setStyleSheet("QLabel { color: #0066cc; padding: 10px; }"); m_statusLabel->show(); m_setupChaoticButton->setEnabled(false); - // Install chaotic-keyring and chaotic-mirrorlist + // Use a shell script to download and install chaotic-aur packages + // This follows the official installation guide from aur.chaotic.cx + QString script = + "cd /tmp && " + "rm -f chaotic-keyring.pkg.tar.zst chaotic-mirrorlist.pkg.tar.zst && " + "curl -L -O https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-keyring.pkg.tar.zst && " + "curl -L -O https://cdn-mirror.chaotic.cx/chaotic-aur/chaotic-mirrorlist.pkg.tar.zst && " + "pacman -U --noconfirm chaotic-keyring.pkg.tar.zst chaotic-mirrorlist.pkg.tar.zst"; + QProcess* process = new QProcess(this); + + // Capture both stdout and stderr for debugging + process->setProcessChannelMode(QProcess::MergedChannels); + connect(process, QOverload::of(&QProcess::finished), this, [this, process](int exitCode, QProcess::ExitStatus exitStatus) { + QString output = process->readAll(); + + Logger::info(QString("Chaotic-AUR setup exit code: %1, status: %2") + .arg(exitCode) + .arg(exitStatus == QProcess::NormalExit ? "Normal" : "Crashed")); + + if (!output.isEmpty()) { + Logger::debug(QString("Chaotic-AUR setup output:\n%1").arg(output)); + } + process->deleteLater(); m_setupChaoticButton->setEnabled(true); @@ -980,23 +1002,31 @@ void SettingsWidget::onSetupChaoticClicked() { QMessageBox::information(this, "Success", "Chaotic-AUR packages installed successfully!\n\n" - "If the repository is not yet configured, you may need to add it to /etc/pacman.conf:\n\n" - "[chaotic-aur]\n" - "Include = /etc/pacman.d/chaotic-mirrorlist"); + "You can now enable the Chaotic-AUR repository using the checkbox above.\n" + "After enabling, remember to sync the package databases."); } else { m_statusLabel->setText("Failed to install Chaotic-AUR packages."); m_statusLabel->setStyleSheet("QLabel { color: #aa0000; padding: 10px; }"); m_statusLabel->show(); - Logger::error("Failed to install Chaotic-AUR packages"); + Logger::error(QString("Failed to install Chaotic-AUR packages. Exit code: %1").arg(exitCode)); + + // Show output in error message if available + QString errorDetails = "Possible reasons:\n" + "• No internet connection\n" + "• Download failed\n" + "• Installation cancelled\n" + "• User denied authentication\n\n"; + + if (!output.isEmpty() && output.length() < 500) { + errorDetails += "Error output:\n" + output; + } QMessageBox::critical(this, "Error", - "Failed to install Chaotic-AUR packages.\n" - "Please check the logs for details."); + "Failed to install Chaotic-AUR packages.\n\n" + errorDetails); } }); - process->start("pkexec", QStringList() << "pacman" << "-S" << "--noconfirm" - << "chaotic-keyring" << "chaotic-mirrorlist"); + process->start("pkexec", QStringList() << "bash" << "-c" << script); } void SettingsWidget::onRemoveChaoticClicked() { From d9731e61ad5ddcbc282ab884e91298e13bf6aa73 Mon Sep 17 00:00:00 2001 From: demonkiller Date: Fri, 14 Nov 2025 22:57:14 +0000 Subject: [PATCH 12/16] cancel button now kills processes --- src/core/package_manager.cpp | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index c85901c..58e0c4c 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -193,13 +193,24 @@ void PackageManager::cancelRunningOperation() { Logger::warning("Cancelling running operation..."); emit operationOutput("\n>>> Operation cancelled by user <<<\n"); - // First try to terminate gracefully + // When using pkexec, we need to kill the actual pacman/yay/paru process + // not just the pkexec wrapper. Use pkill to terminate all package manager processes. + QProcess killProcess; + killProcess.start("pkexec", QStringList() << "bash" << "-c" + << "pkill -TERM pacman; pkill -TERM yay; pkill -TERM paru"); + killProcess.waitForFinished(2000); + + // Also terminate the QProcess wrapper m_process->terminate(); - // Wait up to 5 seconds for graceful termination - if (!m_process->waitForFinished(5000)) { - // If it doesn't terminate gracefully, force kill + // Wait up to 3 seconds for graceful termination + if (!m_process->waitForFinished(3000)) { + // Force kill if still running Logger::warning("Process did not terminate gracefully, forcing kill..."); + killProcess.start("pkexec", QStringList() << "bash" << "-c" + << "pkill -KILL pacman; pkill -KILL yay; pkill -KILL paru"); + killProcess.waitForFinished(2000); + m_process->kill(); m_process->waitForFinished(1000); } From 0f1b6f980d796adb709d009b6098c9f9208e8c8e Mon Sep 17 00:00:00 2001 From: demonkiller Date: Fri, 14 Nov 2025 23:00:02 +0000 Subject: [PATCH 13/16] bump version -> 0.2.26 --- src/gui/mainwindow.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 4a0d6d9..8282b08 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -117,7 +117,7 @@ void MainWindow::createMenuBar() { QMessageBox::about(this, "About ALG App Store", "ALG App Store (Beta)\n\n" "A modern package manager for Arch Linux\n" - "Version: 0.2.25\n" + "Version: 0.2.26\n" "Built with Qt6 and C++17\n\n" "© 2025 Arka Linux GUI"); }); From 3e258a0a2fb929c384bde1c4b9d345017375e61e Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Wed, 17 Dec 2025 22:30:13 +0000 Subject: [PATCH 14/16] [refactor] strictly follow RAII, standardize ownership & cleanup redundant initializers --- src/core/alpm_wrapper.cpp | 4 +-- src/core/alpm_wrapper.h | 17 +++++++-- src/core/aur_helper.h | 7 ++++ src/core/package_manager.cpp | 1 - src/core/package_manager.h | 11 ++++-- src/gui/home_widget.h | 19 ++++++++--- src/gui/installed_widget.h | 20 +++++++---- src/gui/mainwindow.h | 20 ++++++++--- src/gui/package_card.cpp | 3 +- src/gui/package_card.h | 21 ++++++++---- src/gui/package_details_dialog.cpp | 6 +--- src/gui/package_details_dialog.h | 55 +++++++++++++++++------------- src/gui/search_widget.h | 25 ++++++++++---- src/gui/settings_widget.cpp | 18 +--------- src/gui/settings_widget.h | 48 ++++++++++++++------------ src/gui/updates_widget.cpp | 3 +- src/gui/updates_widget.h | 40 +++++++++++++--------- 17 files changed, 194 insertions(+), 124 deletions(-) diff --git a/src/core/alpm_wrapper.cpp b/src/core/alpm_wrapper.cpp index 2d19d83..3fc92b7 100644 --- a/src/core/alpm_wrapper.cpp +++ b/src/core/alpm_wrapper.cpp @@ -10,8 +10,8 @@ AlpmWrapper& AlpmWrapper::instance() { return instance; } -AlpmWrapper::AlpmWrapper() - : m_handle(nullptr), m_syncDbs(nullptr), m_initialized(false) { +AlpmWrapper::AlpmWrapper() { + // Member initialization is done in header file } AlpmWrapper::~AlpmWrapper() { diff --git a/src/core/alpm_wrapper.h b/src/core/alpm_wrapper.h index e0894b9..b1f8906 100644 --- a/src/core/alpm_wrapper.h +++ b/src/core/alpm_wrapper.h @@ -9,6 +9,17 @@ #include #include "../utils/types.h" +/** + * @brief Singleton wrapper for libalpm (Arch Linux Package Manager library). + * + * Memory Management: + * - m_handle: Raw pointer to libalpm handle, manually managed via initialize()/release() + * - m_syncDbs: Raw pointer to libalpm list, managed by libalpm internally + * - Thread-safe via m_mutex + * + * Note: libalpm uses C-style memory management, so smart pointers are not + * directly applicable to the alpm types. + */ class AlpmWrapper { public: static AlpmWrapper& instance(); @@ -34,10 +45,10 @@ class AlpmWrapper { private: AlpmWrapper(); - alpm_handle_t* m_handle; - alpm_list_t* m_syncDbs; + alpm_handle_t* m_handle = nullptr; + alpm_list_t* m_syncDbs = nullptr; std::mutex m_mutex; - bool m_initialized; + bool m_initialized = false; QStringList convertDependList(alpm_list_t* deps); void searchInDatabase(alpm_db_t* db, const QString& query, diff --git a/src/core/aur_helper.h b/src/core/aur_helper.h index a78bb13..e29321f 100644 --- a/src/core/aur_helper.h +++ b/src/core/aur_helper.h @@ -9,6 +9,13 @@ #include #include "../utils/types.h" +/** + * @brief Helper class for interacting with the Arch User Repository (AUR). + * + * Memory Management: + * - m_networkManager: Owned by std::unique_ptr for RAII-style cleanup + * - Network replies are managed via Qt parent-child and deleteLater() + */ class AurHelper : public QObject { Q_OBJECT diff --git a/src/core/package_manager.cpp b/src/core/package_manager.cpp index 58e0c4c..5b50364 100644 --- a/src/core/package_manager.cpp +++ b/src/core/package_manager.cpp @@ -10,7 +10,6 @@ PackageManager& PackageManager::instance() { PackageManager::PackageManager() : QObject(nullptr) - , m_helper(Helper::Pacman) , m_process(std::make_unique()) { detectHelper(); diff --git a/src/core/package_manager.h b/src/core/package_manager.h index 5cf1cc8..0e86a9b 100644 --- a/src/core/package_manager.h +++ b/src/core/package_manager.h @@ -7,6 +7,13 @@ #include #include +/** + * @brief Singleton class for managing package operations (install, uninstall, update). + * + * Memory Management: + * - m_process: Owned by std::unique_ptr for RAII-style cleanup and clear ownership + * - Thread-safe via m_mutex for operation serialization + */ class PackageManager : public QObject { Q_OBJECT @@ -49,9 +56,9 @@ class PackageManager : public QObject { void detectHelper(); void executeCommand(const QString& command, const QStringList& args); - Helper m_helper; + Helper m_helper = Helper::Pacman; std::unique_ptr m_process; - std::mutex m_mutex; + mutable std::mutex m_mutex; private slots: void onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus); diff --git a/src/gui/home_widget.h b/src/gui/home_widget.h index 5882b8f..08684a2 100644 --- a/src/gui/home_widget.h +++ b/src/gui/home_widget.h @@ -10,6 +10,13 @@ class PackageCard; +/** + * @brief Widget displaying featured packages on the home screen. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - m_packageCards contains non-owning pointers to cards owned by m_contentWidget + */ class HomeWidget : public QWidget { Q_OBJECT @@ -24,11 +31,13 @@ class HomeWidget : public QWidget { void checkInstalledPackages(); QVector m_featuredPackages; - QVector m_packageCards; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QGridLayout* m_gridLayout; - QTimer* m_updateTimer; + QVector m_packageCards; // Non-owning pointers, owned by m_contentWidget + + // Qt parent-child managed widgets (non-owning pointers) + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QGridLayout* m_gridLayout = nullptr; + QTimer* m_updateTimer = nullptr; private slots: void onPackageClicked(const PackageInfo& info); diff --git a/src/gui/installed_widget.h b/src/gui/installed_widget.h index 1e2bc67..d4cbe0b 100644 --- a/src/gui/installed_widget.h +++ b/src/gui/installed_widget.h @@ -9,6 +9,13 @@ #include #include "../utils/types.h" +/** + * @brief Widget displaying installed packages. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - Package cards are dynamically created/destroyed in displayPackages/clearResults + */ class InstalledWidget : public QWidget { Q_OBJECT @@ -25,12 +32,13 @@ class InstalledWidget : public QWidget { void filterPackages(const QString& query); void clearResults(); - QLineEdit* m_filterInput; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QGridLayout* m_gridLayout; - QLabel* m_statusLabel; - QLabel* m_countLabel; + // Qt parent-child managed widgets (non-owning pointers) + QLineEdit* m_filterInput = nullptr; + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QGridLayout* m_gridLayout = nullptr; + QLabel* m_statusLabel = nullptr; + QLabel* m_countLabel = nullptr; QVector m_allPackages; QVector m_filteredPackages; diff --git a/src/gui/mainwindow.h b/src/gui/mainwindow.h index 3f2b4f7..cf6d531 100644 --- a/src/gui/mainwindow.h +++ b/src/gui/mainwindow.h @@ -12,6 +12,14 @@ class InstalledWidget; class UpdatesWidget; class SettingsWidget; +/** + * @brief Main application window for ALG App Store. + * + * Memory Management: + * - m_tabWidget: Owned by std::unique_ptr (central widget) + * - Child widgets (m_homeWidget, etc.): Owned by Qt parent-child hierarchy + * through m_tabWidget. Raw pointers are used as non-owning references. + */ class MainWindow : public QMainWindow { Q_OBJECT @@ -25,11 +33,13 @@ class MainWindow : public QMainWindow { void loadStyleSheet(); std::unique_ptr m_tabWidget; - HomeWidget* m_homeWidget; - SearchWidget* m_searchWidget; - InstalledWidget* m_installedWidget; - UpdatesWidget* m_updatesWidget; - SettingsWidget* m_settingsWidget; + + // Non-owning pointers - owned by m_tabWidget via Qt parent-child hierarchy + HomeWidget* m_homeWidget = nullptr; + SearchWidget* m_searchWidget = nullptr; + InstalledWidget* m_installedWidget = nullptr; + UpdatesWidget* m_updatesWidget = nullptr; + SettingsWidget* m_settingsWidget = nullptr; }; #endif // MAINWINDOW_H diff --git a/src/gui/package_card.cpp b/src/gui/package_card.cpp index 864e26b..62cdee8 100644 --- a/src/gui/package_card.cpp +++ b/src/gui/package_card.cpp @@ -12,8 +12,7 @@ PackageCard::PackageCard(const PackageInfo& info, QWidget* parent) , m_descriptionLabel(new QLabel(this)) , m_versionLabel(new QLabel(this)) , m_repositoryLabel(new QLabel(this)) - , m_statusLabel(new QLabel(this)) - , m_isInstalled(false) { + , m_statusLabel(new QLabel(this)) { setupUi(); checkInstallStatus(); diff --git a/src/gui/package_card.h b/src/gui/package_card.h index aaf38f6..bdb6f86 100644 --- a/src/gui/package_card.h +++ b/src/gui/package_card.h @@ -6,6 +6,12 @@ #include #include "../utils/types.h" +/** + * @brief A clickable card widget displaying package information. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + */ class PackageCard : public QWidget { Q_OBJECT @@ -29,12 +35,15 @@ class PackageCard : public QWidget { void setupUi(); PackageInfo m_info; - QLabel* m_nameLabel; - QLabel* m_descriptionLabel; - QLabel* m_versionLabel; - QLabel* m_repositoryLabel; - QLabel* m_statusLabel; - bool m_isInstalled; + + // Qt parent-child managed widgets (non-owning pointers) + QLabel* m_nameLabel = nullptr; + QLabel* m_descriptionLabel = nullptr; + QLabel* m_versionLabel = nullptr; + QLabel* m_repositoryLabel = nullptr; + QLabel* m_statusLabel = nullptr; + + bool m_isInstalled = false; }; #endif // PACKAGE_CARD_H diff --git a/src/gui/package_details_dialog.cpp b/src/gui/package_details_dialog.cpp index bbe9dd2..cacebce 100644 --- a/src/gui/package_details_dialog.cpp +++ b/src/gui/package_details_dialog.cpp @@ -22,7 +22,6 @@ PackageDetailsDialog::PackageDetailsDialog(const PackageInfo& info, QWidget* parent) : QDialog(parent) , m_info(info) - , m_isInstalled(false) , m_nameLabel(new QLabel(this)) , m_versionLabel(new QLabel(this)) , m_repositoryLabel(new QLabel(this)) @@ -41,10 +40,7 @@ PackageDetailsDialog::PackageDetailsDialog(const PackageInfo& info, QWidget* par , m_progressWidget(new QWidget(this)) , m_logViewer(new QTextEdit(this)) , m_toggleLogButton(new QPushButton("Show Logs", this)) - , m_logWidget(new QWidget(this)) - , m_logVisible(false) - , m_totalPackages(0) - , m_currentPackage(0) { + , m_logWidget(new QWidget(this)) { setupUi(); checkInstallStatus(); diff --git a/src/gui/package_details_dialog.h b/src/gui/package_details_dialog.h index dd94aee..4a8a324 100644 --- a/src/gui/package_details_dialog.h +++ b/src/gui/package_details_dialog.h @@ -8,6 +8,12 @@ #include #include "../utils/types.h" +/** + * @brief Dialog showing detailed package information and actions. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + */ class PackageDetailsDialog : public QDialog { Q_OBJECT @@ -29,38 +35,39 @@ class PackageDetailsDialog : public QDialog { void launchApplication(); PackageInfo m_info; - bool m_isInstalled; + bool m_isInstalled = false; - QLabel* m_nameLabel; - QLabel* m_versionLabel; - QLabel* m_repositoryLabel; - QLabel* m_maintainerLabel; - QLabel* m_urlLabel; - QTextEdit* m_descriptionText; - QTextEdit* m_dependenciesText; - QLabel* m_lastUpdatedLabel; + // Qt parent-child managed widgets (non-owning pointers) + QLabel* m_nameLabel = nullptr; + QLabel* m_versionLabel = nullptr; + QLabel* m_repositoryLabel = nullptr; + QLabel* m_maintainerLabel = nullptr; + QLabel* m_urlLabel = nullptr; + QTextEdit* m_descriptionText = nullptr; + QTextEdit* m_dependenciesText = nullptr; + QLabel* m_lastUpdatedLabel = nullptr; - QPushButton* m_installButton; - QPushButton* m_uninstallButton; - QPushButton* m_launchButton; - QPushButton* m_closeButton; + QPushButton* m_installButton = nullptr; + QPushButton* m_uninstallButton = nullptr; + QPushButton* m_launchButton = nullptr; + QPushButton* m_closeButton = nullptr; - QLabel* m_statusBadge; + QLabel* m_statusBadge = nullptr; - QProgressBar* m_progressBar; - QLabel* m_progressLabel; - QWidget* m_progressWidget; + QProgressBar* m_progressBar = nullptr; + QLabel* m_progressLabel = nullptr; + QWidget* m_progressWidget = nullptr; - // Log viewer - QTextEdit* m_logViewer; - QPushButton* m_toggleLogButton; - QWidget* m_logWidget; - bool m_logVisible; + // Log viewer (Qt parent-child managed) + QTextEdit* m_logViewer = nullptr; + QPushButton* m_toggleLogButton = nullptr; + QWidget* m_logWidget = nullptr; + bool m_logVisible = false; // Progress tracking QString m_currentOperation; - int m_totalPackages; - int m_currentPackage; + int m_totalPackages = 0; + int m_currentPackage = 0; private slots: void onInstall(); diff --git a/src/gui/search_widget.h b/src/gui/search_widget.h index ed48b8e..5767dcf 100644 --- a/src/gui/search_widget.h +++ b/src/gui/search_widget.h @@ -13,6 +13,14 @@ #include "../utils/types.h" #include "../core/aur_helper.h" +/** + * @brief Widget for searching packages across repositories. + * + * Memory Management: + * - m_aurHelper: Owned by std::unique_ptr for explicit lifetime management + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - Package cards are dynamically created/destroyed in displayResults/clearResults + */ class SearchWidget : public QWidget { Q_OBJECT @@ -29,15 +37,18 @@ public slots: void displayResults(const QVector& results); void clearResults(); - QLineEdit* m_searchInput; - QPushButton* m_searchButton; - QComboBox* m_filterCombo; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QGridLayout* m_gridLayout; - QLabel* m_statusLabel; + // Qt parent-child managed widgets (non-owning pointers) + QLineEdit* m_searchInput = nullptr; + QPushButton* m_searchButton = nullptr; + QComboBox* m_filterCombo = nullptr; + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QGridLayout* m_gridLayout = nullptr; + QLabel* m_statusLabel = nullptr; + // Owned resources std::unique_ptr m_aurHelper; + QVector m_currentResults; QVector m_allResults; diff --git a/src/gui/settings_widget.cpp b/src/gui/settings_widget.cpp index 0e3bac2..6d31e71 100644 --- a/src/gui/settings_widget.cpp +++ b/src/gui/settings_widget.cpp @@ -12,23 +12,7 @@ #include SettingsWidget::SettingsWidget(QWidget* parent) - : QWidget(parent) - , m_repositoryGroup(nullptr) - , m_coreRepoCheckbox(nullptr) - , m_extraRepoCheckbox(nullptr) - , m_multilibRepoCheckbox(nullptr) - , m_chaoticAurCheckbox(nullptr) - , m_chaoticAurGroup(nullptr) - , m_setupChaoticButton(nullptr) - , m_removeChaoticButton(nullptr) - , m_maintenanceGroup(nullptr) - , m_removeLockButton(nullptr) - , m_syncReposButton(nullptr) - , m_cancelProcessButton(nullptr) - , m_applyButton(nullptr) - , m_statusLabel(nullptr) - , m_originalMultilibState(false) - , m_originalChaoticAurState(false) { + : QWidget(parent) { setupUi(); loadCurrentSettings(); diff --git a/src/gui/settings_widget.h b/src/gui/settings_widget.h index 6985381..064f2f8 100644 --- a/src/gui/settings_widget.h +++ b/src/gui/settings_widget.h @@ -8,6 +8,12 @@ #include #include +/** + * @brief Widget for application and repository settings. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + */ class SettingsWidget : public QWidget { Q_OBJECT @@ -36,33 +42,33 @@ class SettingsWidget : public QWidget { bool disableChaoticAurInPacmanConf(); void applySettings(); - // Repository settings - QGroupBox* m_repositoryGroup; - QCheckBox* m_coreRepoCheckbox; - QCheckBox* m_extraRepoCheckbox; - QCheckBox* m_multilibRepoCheckbox; - QCheckBox* m_chaoticAurCheckbox; + // Repository settings (Qt parent-child managed, non-owning pointers) + QGroupBox* m_repositoryGroup = nullptr; + QCheckBox* m_coreRepoCheckbox = nullptr; + QCheckBox* m_extraRepoCheckbox = nullptr; + QCheckBox* m_multilibRepoCheckbox = nullptr; + QCheckBox* m_chaoticAurCheckbox = nullptr; - // Chaotic-AUR setup - QGroupBox* m_chaoticAurGroup; - QPushButton* m_setupChaoticButton; - QPushButton* m_removeChaoticButton; + // Chaotic-AUR setup (Qt parent-child managed) + QGroupBox* m_chaoticAurGroup = nullptr; + QPushButton* m_setupChaoticButton = nullptr; + QPushButton* m_removeChaoticButton = nullptr; - // Maintenance settings - QGroupBox* m_maintenanceGroup; - QPushButton* m_removeLockButton; - QPushButton* m_syncReposButton; - QPushButton* m_cancelProcessButton; + // Maintenance settings (Qt parent-child managed) + QGroupBox* m_maintenanceGroup = nullptr; + QPushButton* m_removeLockButton = nullptr; + QPushButton* m_syncReposButton = nullptr; + QPushButton* m_cancelProcessButton = nullptr; - // Control buttons - QPushButton* m_applyButton; + // Control buttons (Qt parent-child managed) + QPushButton* m_applyButton = nullptr; - // Status - QLabel* m_statusLabel; + // Status (Qt parent-child managed) + QLabel* m_statusLabel = nullptr; // Track original state - bool m_originalMultilibState; - bool m_originalChaoticAurState; + bool m_originalMultilibState = false; + bool m_originalChaoticAurState = false; private slots: void onApplyClicked(); diff --git a/src/gui/updates_widget.cpp b/src/gui/updates_widget.cpp index 347803b..f191a46 100644 --- a/src/gui/updates_widget.cpp +++ b/src/gui/updates_widget.cpp @@ -94,8 +94,7 @@ UpdatesWidget::UpdatesWidget(QWidget* parent) , m_progressLabel(new QLabel(this)) , m_toggleLogButton(new QPushButton("Show Logs", this)) , m_logWidget(new QWidget(this)) - , m_logViewer(new QTextEdit(this)) - , m_logVisible(false) { + , m_logViewer(new QTextEdit(this)) { setupUi(); diff --git a/src/gui/updates_widget.h b/src/gui/updates_widget.h index bf045e4..4742f2e 100644 --- a/src/gui/updates_widget.h +++ b/src/gui/updates_widget.h @@ -14,6 +14,13 @@ class UpdateItem; +/** + * @brief Widget for displaying and managing package updates. + * + * Memory Management: + * - All Qt widget members use Qt parent-child ownership (raw pointers are non-owning) + * - UpdateItem widgets are dynamically created/destroyed in displayUpdates/clearUpdates + */ class UpdatesWidget : public QWidget { Q_OBJECT @@ -33,23 +40,24 @@ class UpdatesWidget : public QWidget { void hideProgress(); void toggleLogViewer(); - QLineEdit* m_searchInput; - QScrollArea* m_scrollArea; - QWidget* m_contentWidget; - QVBoxLayout* m_contentLayout; - QLabel* m_statusLabel; - QLabel* m_countLabel; - QPushButton* m_updateAllButton; - QPushButton* m_checkButton; + // Qt parent-child managed widgets (non-owning pointers) + QLineEdit* m_searchInput = nullptr; + QScrollArea* m_scrollArea = nullptr; + QWidget* m_contentWidget = nullptr; + QVBoxLayout* m_contentLayout = nullptr; + QLabel* m_statusLabel = nullptr; + QLabel* m_countLabel = nullptr; + QPushButton* m_updateAllButton = nullptr; + QPushButton* m_checkButton = nullptr; - // Progress bar and log viewer - QWidget* m_progressWidget; - QProgressBar* m_progressBar; - QLabel* m_progressLabel; - QPushButton* m_toggleLogButton; - QWidget* m_logWidget; - QTextEdit* m_logViewer; - bool m_logVisible; + // Progress bar and log viewer (Qt parent-child managed) + QWidget* m_progressWidget = nullptr; + QProgressBar* m_progressBar = nullptr; + QLabel* m_progressLabel = nullptr; + QPushButton* m_toggleLogButton = nullptr; + QWidget* m_logWidget = nullptr; + QTextEdit* m_logViewer = nullptr; + bool m_logVisible = false; QVector m_updates; QVector m_filteredUpdates; From 337414068bfb3634cec86561ced284da18c5e9ee Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Wed, 17 Dec 2025 22:48:44 +0000 Subject: [PATCH 15/16] update TODO --- TODO.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/TODO.md b/TODO.md index 1b5b1cc..047078a 100644 --- a/TODO.md +++ b/TODO.md @@ -1,9 +1,13 @@ - [x] Add chaotic aur to search tab if enabled - [x] Add launch button on package card if package is installed and remove when uninstalled - [] Add detailed mirrorlist tab to set mirrorlist -- [] Add version information +- [x] Add version information - [] Implement an AUR helper in core to remove dependence on paru and yay - +- [] Ask password only once on startup - startup_auth +- [] Improve settings page - settings_tab +- [] Move all styles to single stylesheet - style_and_theme +- [] Clean up UI; make UI look more modern (check gnome's styling options) - style_and_theme +- [] Set a light/dark theme toggle, or follow system's theme - style_and_theme ## Future Enhancements From 4ed6c9991a8b952c37e54b25b193223e1ce81c59 Mon Sep 17 00:00:00 2001 From: demonkillerr Date: Sun, 21 Dec 2025 13:01:12 +0000 Subject: [PATCH 16/16] update todo --- TODO.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/TODO.md b/TODO.md index 047078a..6998488 100644 --- a/TODO.md +++ b/TODO.md @@ -8,6 +8,8 @@ - [] Move all styles to single stylesheet - style_and_theme - [] Clean up UI; make UI look more modern (check gnome's styling options) - style_and_theme - [] Set a light/dark theme toggle, or follow system's theme - style_and_theme +- [] Look into spdlog for logging +- [] Look into CppUTest or Google Test (gtest) for test ## Future Enhancements