From 9666ce4f5a520b76297427656a39397e7a5ceb11 Mon Sep 17 00:00:00 2001 From: LemmyCook Date: Sun, 24 Aug 2025 10:46:28 -0400 Subject: [PATCH] autofmt arch stuff --- Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml | 403 +++++++++--------- Modules/Bar/Widgets/ArchUpdater.qml | 104 ++--- Services/ArchUpdaterService.qml | 285 +++++++------ 3 files changed, 399 insertions(+), 393 deletions(-) diff --git a/Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml b/Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml index 70a23a3..dbf0f59 100644 --- a/Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml +++ b/Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml @@ -8,220 +8,221 @@ import qs.Services import qs.Widgets NPanel { - id: root - panelWidth: 380 * scaling - panelHeight: 500 * scaling - panelAnchorRight: true + id: root + panelWidth: 380 * scaling + panelHeight: 500 * scaling + panelAnchorRight: true - // Auto-refresh when service updates - Connections { - target: ArchUpdaterService - function onUpdatePackagesChanged() { - // Force UI update when packages change - if (root.visible) { - // Small delay to ensure data is fully updated - Qt.callLater(() => { - // Force a UI update by triggering a property change - ArchUpdaterService.updatePackages = ArchUpdaterService.updatePackages; - }, 100); - } - } + // Auto-refresh when service updates + Connections { + target: ArchUpdaterService + function onUpdatePackagesChanged() { + // Force UI update when packages change + if (root.visible) { + // Small delay to ensure data is fully updated + Qt.callLater(() => { + // Force a UI update by triggering a property change + ArchUpdaterService.updatePackages = ArchUpdaterService.updatePackages + }, 100) + } } + } - panelContent: Rectangle { - color: Color.mSurface - radius: Style.radiusL * scaling + panelContent: Rectangle { + color: Color.mSurface + radius: Style.radiusL * scaling - ColumnLayout { - anchors.fill: parent - anchors.margins: Style.marginL * scaling - spacing: Style.marginM * scaling + ColumnLayout { + anchors.fill: parent + anchors.margins: Style.marginL * scaling + spacing: Style.marginM * scaling + + // Header + RowLayout { + Layout.fillWidth: true + spacing: Style.marginM * scaling + + NIcon { + text: "system_update" + font.pointSize: Style.fontSizeXXL * scaling + color: Color.mPrimary + } + + Text { + text: "System Updates" + font.pointSize: Style.fontSizeL * scaling + font.family: Settings.data.ui.fontDefault + font.weight: Style.fontWeightBold + color: Color.mOnSurface + Layout.fillWidth: true + } + + NIconButton { + icon: "close" + tooltipText: "Close" + sizeMultiplier: 0.8 + onClicked: root.close() + } + } + + NDivider { + Layout.fillWidth: true + } + + // Update summary + Text { + text: ArchUpdaterService.updatePackages.length + " package" + (ArchUpdaterService.updatePackages.length + !== 1 ? "s" : "") + " can be updated" + font.pointSize: Style.fontSizeL * scaling + font.family: Settings.data.ui.fontDefault + font.weight: Style.fontWeightMedium + color: Color.mOnSurface + Layout.fillWidth: true + } + + // Package selection info + Text { + text: ArchUpdaterService.selectedPackagesCount + " of " + ArchUpdaterService.updatePackages.length + " packages selected" + font.pointSize: Style.fontSizeS * scaling + font.family: Settings.data.ui.fontDefault + color: Color.mOnSurfaceVariant + Layout.fillWidth: true + } + + // Package list + Rectangle { + Layout.fillWidth: true + Layout.fillHeight: true + color: Color.mSurfaceVariant + radius: Style.radiusM * scaling + + ListView { + id: packageListView + anchors.fill: parent + anchors.margins: Style.marginS * scaling + clip: true + model: ArchUpdaterService.updatePackages + spacing: Style.marginXS * scaling + + delegate: Rectangle { + width: packageListView.width + height: 50 * scaling + color: Color.transparent + radius: Style.radiusS * scaling - // Header RowLayout { - Layout.fillWidth: true - spacing: Style.marginM * scaling + anchors.fill: parent + anchors.margins: Style.marginS * scaling + spacing: Style.marginS * scaling - NIcon { - text: "system_update" - font.pointSize: Style.fontSizeXXL * scaling - color: Color.mPrimary + // Checkbox for selection + NIconButton { + id: checkbox + icon: "check_box_outline_blank" + onClicked: { + const isSelected = ArchUpdaterService.isPackageSelected(modelData.name) + if (isSelected) { + ArchUpdaterService.togglePackageSelection(modelData.name) + icon = "check_box_outline_blank" + colorFg = Color.mOnSurfaceVariant + } else { + ArchUpdaterService.togglePackageSelection(modelData.name) + icon = "check_box" + colorFg = Color.mPrimary + } + } + colorBg: Color.transparent + colorFg: Color.mOnSurfaceVariant + Layout.preferredWidth: 30 * scaling + Layout.preferredHeight: 30 * scaling + + Component.onCompleted: { + // Set initial state + if (ArchUpdaterService.isPackageSelected(modelData.name)) { + icon = "check_box" + colorFg = Color.mPrimary + } + } + } + + // Package info + ColumnLayout { + Layout.fillWidth: true + spacing: Style.marginXXS * scaling + + Text { + text: modelData.name + font.pointSize: Style.fontSizeM * scaling + font.family: Settings.data.ui.fontDefault + font.weight: Style.fontWeightMedium + color: Color.mOnSurface + Layout.fillWidth: true } Text { - text: "System Updates" - font.pointSize: Style.fontSizeL * scaling - font.family: Settings.data.ui.fontDefault - font.weight: Style.fontWeightBold - color: Color.mOnSurface - Layout.fillWidth: true - } - - NIconButton { - icon: "close" - tooltipText: "Close" - sizeMultiplier: 0.8 - onClicked: root.close() + text: modelData.oldVersion + " → " + modelData.newVersion + font.pointSize: Style.fontSizeS * scaling + font.family: Settings.data.ui.fontDefault + color: Color.mOnSurfaceVariant + Layout.fillWidth: true } + } } + } - NDivider { Layout.fillWidth: true } - - // Update summary - Text { - text: ArchUpdaterService.updatePackages.length + " package" + (ArchUpdaterService.updatePackages.length !== 1 ? "s" : "") + " can be updated" - font.pointSize: Style.fontSizeL * scaling - font.family: Settings.data.ui.fontDefault - font.weight: Style.fontWeightMedium - color: Color.mOnSurface - Layout.fillWidth: true - } - - // Package selection info - Text { - text: ArchUpdaterService.selectedPackagesCount + " of " + ArchUpdaterService.updatePackages.length + " packages selected" - font.pointSize: Style.fontSizeS * scaling - font.family: Settings.data.ui.fontDefault - color: Color.mOnSurfaceVariant - Layout.fillWidth: true - } - - // Package list - Rectangle { - Layout.fillWidth: true - Layout.fillHeight: true - color: Color.mSurfaceVariant - radius: Style.radiusM * scaling - - ListView { - id: packageListView - anchors.fill: parent - anchors.margins: Style.marginS * scaling - clip: true - model: ArchUpdaterService.updatePackages - spacing: Style.marginXS * scaling - - delegate: Rectangle { - width: packageListView.width - height: 50 * scaling - color: Color.transparent - radius: Style.radiusS * scaling - - RowLayout { - anchors.fill: parent - anchors.margins: Style.marginS * scaling - spacing: Style.marginS * scaling - - // Checkbox for selection - NIconButton { - id: checkbox - icon: "check_box_outline_blank" - onClicked: { - const isSelected = ArchUpdaterService.isPackageSelected(modelData.name); - if (isSelected) { - ArchUpdaterService.togglePackageSelection(modelData.name); - icon = "check_box_outline_blank"; - colorFg = Color.mOnSurfaceVariant; - } else { - ArchUpdaterService.togglePackageSelection(modelData.name); - icon = "check_box"; - colorFg = Color.mPrimary; - } - } - colorBg: Color.transparent - colorFg: Color.mOnSurfaceVariant - Layout.preferredWidth: 30 * scaling - Layout.preferredHeight: 30 * scaling - - Component.onCompleted: { - // Set initial state - if (ArchUpdaterService.isPackageSelected(modelData.name)) { - icon = "check_box"; - colorFg = Color.mPrimary; - } - } - } - - // Package info - ColumnLayout { - Layout.fillWidth: true - spacing: Style.marginXXS * scaling - - Text { - text: modelData.name - font.pointSize: Style.fontSizeM * scaling - font.family: Settings.data.ui.fontDefault - font.weight: Style.fontWeightMedium - color: Color.mOnSurface - Layout.fillWidth: true - } - - Text { - text: modelData.oldVersion + " → " + modelData.newVersion - font.pointSize: Style.fontSizeS * scaling - font.family: Settings.data.ui.fontDefault - color: Color.mOnSurfaceVariant - Layout.fillWidth: true - } - } - } - } - - ScrollBar.vertical: ScrollBar { - policy: ScrollBar.AsNeeded - } - } - } - - - - // Action buttons - RowLayout { - Layout.fillWidth: true - spacing: Style.marginS * scaling - - NIconButton { - icon: "refresh" - tooltipText: "Check for updates" - onClicked: { - ArchUpdaterService.doPoll(); - } - colorBg: Color.mSurfaceVariant - colorFg: Color.mOnSurface - Layout.fillWidth: true - Layout.preferredHeight: 35 * scaling - } - - NIconButton { - icon: ArchUpdaterService.updateInProgress ? "hourglass_empty" : "system_update" - tooltipText: ArchUpdaterService.updateInProgress ? "Update in progress..." : "Update all packages" - enabled: !ArchUpdaterService.updateInProgress - onClicked: { - ArchUpdaterService.runUpdate(); - } - colorBg: ArchUpdaterService.updateInProgress ? Color.mSurfaceVariant : Color.mPrimary - colorFg: ArchUpdaterService.updateInProgress ? Color.mOnSurfaceVariant : Color.mOnPrimary - Layout.fillWidth: true - Layout.preferredHeight: 35 * scaling - } - - NIconButton { - icon: ArchUpdaterService.updateInProgress ? "hourglass_empty" : "settings" - tooltipText: ArchUpdaterService.updateInProgress ? "Update in progress..." : "Update selected packages" - enabled: !ArchUpdaterService.updateInProgress && ArchUpdaterService.selectedPackagesCount > 0 - onClicked: { - if (ArchUpdaterService.selectedPackagesCount > 0) { - ArchUpdaterService.runSelectiveUpdate(); - } - } - colorBg: ArchUpdaterService.updateInProgress ? Color.mSurfaceVariant : - (ArchUpdaterService.selectedPackagesCount > 0 ? Color.mSecondary : Color.mSurfaceVariant) - colorFg: ArchUpdaterService.updateInProgress ? Color.mOnSurfaceVariant : - (ArchUpdaterService.selectedPackagesCount > 0 ? Color.mOnSecondary : Color.mOnSurfaceVariant) - Layout.fillWidth: true - Layout.preferredHeight: 35 * scaling - } - } + ScrollBar.vertical: ScrollBar { + policy: ScrollBar.AsNeeded + } } + } + + // Action buttons + RowLayout { + Layout.fillWidth: true + spacing: Style.marginS * scaling + + NIconButton { + icon: "refresh" + tooltipText: "Check for updates" + onClicked: { + ArchUpdaterService.doPoll() + } + colorBg: Color.mSurfaceVariant + colorFg: Color.mOnSurface + Layout.fillWidth: true + Layout.preferredHeight: 35 * scaling + } + + NIconButton { + icon: ArchUpdaterService.updateInProgress ? "hourglass_empty" : "system_update" + tooltipText: ArchUpdaterService.updateInProgress ? "Update in progress..." : "Update all packages" + enabled: !ArchUpdaterService.updateInProgress + onClicked: { + ArchUpdaterService.runUpdate() + } + colorBg: ArchUpdaterService.updateInProgress ? Color.mSurfaceVariant : Color.mPrimary + colorFg: ArchUpdaterService.updateInProgress ? Color.mOnSurfaceVariant : Color.mOnPrimary + Layout.fillWidth: true + Layout.preferredHeight: 35 * scaling + } + + NIconButton { + icon: ArchUpdaterService.updateInProgress ? "hourglass_empty" : "settings" + tooltipText: ArchUpdaterService.updateInProgress ? "Update in progress..." : "Update selected packages" + enabled: !ArchUpdaterService.updateInProgress && ArchUpdaterService.selectedPackagesCount > 0 + onClicked: { + if (ArchUpdaterService.selectedPackagesCount > 0) { + ArchUpdaterService.runSelectiveUpdate() + } + } + colorBg: ArchUpdaterService.updateInProgress ? Color.mSurfaceVariant : (ArchUpdaterService.selectedPackagesCount + > 0 ? Color.mSecondary : Color.mSurfaceVariant) + colorFg: ArchUpdaterService.updateInProgress ? Color.mOnSurfaceVariant : (ArchUpdaterService.selectedPackagesCount + > 0 ? Color.mOnSecondary : Color.mOnSurfaceVariant) + Layout.fillWidth: true + Layout.preferredHeight: 35 * scaling + } + } } + } } diff --git a/Modules/Bar/Widgets/ArchUpdater.qml b/Modules/Bar/Widgets/ArchUpdater.qml index 4881966..6b09817 100644 --- a/Modules/Bar/Widgets/ArchUpdater.qml +++ b/Modules/Bar/Widgets/ArchUpdater.qml @@ -6,66 +6,68 @@ import QtQuick.Controls import QtQuick.Layouts NIconButton { - id: root - sizeMultiplier: 0.8 + id: root + sizeMultiplier: 0.8 - readonly property real scaling: ScalingService.scale(screen) + readonly property real scaling: ScalingService.scale(screen) - colorBg: Color.mSurfaceVariant - colorFg: Color.mOnSurface - colorBorder: Color.transparent - colorBorderHover: Color.transparent + colorBg: Color.mSurfaceVariant + colorFg: Color.mOnSurface + colorBorder: Color.transparent + colorBorderHover: Color.transparent - // Enhanced icon states with better visual feedback - icon: { - if (ArchUpdaterService.busy) return "sync" - if (ArchUpdaterService.updatePackages.length > 0) { - // Show different icons based on update count - const count = ArchUpdaterService.updatePackages.length - if (count > 50) return "system_update_alt" // Many updates - if (count > 10) return "system_update" // Moderate updates - return "system_update" // Few updates - } - return "task_alt" + // Enhanced icon states with better visual feedback + icon: { + if (ArchUpdaterService.busy) + return "sync" + if (ArchUpdaterService.updatePackages.length > 0) { + // Show different icons based on update count + const count = ArchUpdaterService.updatePackages.length + if (count > 50) + return "system_update_alt" // Many updates + if (count > 10) + return "system_update" // Moderate updates + return "system_update" // Few updates } + return "task_alt" + } - // Enhanced tooltip with more information - tooltipText: { - if (ArchUpdaterService.busy) - return "Checking for updates…"; + // Enhanced tooltip with more information + tooltipText: { + if (ArchUpdaterService.busy) + return "Checking for updates…" - var count = ArchUpdaterService.updatePackages.length; - if (count === 0) - return "System is up to date ✓"; + var count = ArchUpdaterService.updatePackages.length + if (count === 0) + return "System is up to date ✓" - var header = count === 1 ? "One package can be upgraded:" : (count + " packages can be upgraded:"); + var header = count === 1 ? "One package can be upgraded:" : (count + " packages can be upgraded:") - var list = ArchUpdaterService.updatePackages || []; - var s = ""; - var limit = Math.min(list.length, 8); // Reduced to 8 for better readability - for (var i = 0; i < limit; ++i) { - var p = list[i]; - s += (i ? "\n" : "") + (p.name + ": " + p.oldVersion + " → " + p.newVersion); - } - if (list.length > 8) - s += "\n… and " + (list.length - 8) + " more"; - - return header + "\n\n" + s + "\n\nClick to update system"; + var list = ArchUpdaterService.updatePackages || [] + var s = "" + var limit = Math.min(list.length, 8) + // Reduced to 8 for better readability + for (var i = 0; i < limit; ++i) { + var p = list[i] + s += (i ? "\n" : "") + (p.name + ": " + p.oldVersion + " → " + p.newVersion) } + if (list.length > 8) + s += "\n… and " + (list.length - 8) + " more" - // Enhanced click behavior with confirmation - onClicked: { - if (ArchUpdaterService.busy) - return; - - if (ArchUpdaterService.updatePackages.length > 0) { - // Show confirmation dialog for updates - PanelService.updatePanel.toggle(screen); - } else { - // Just refresh if no updates available - ArchUpdaterService.doPoll(); - } + return header + "\n\n" + s + "\n\nClick to update system" + } + + // Enhanced click behavior with confirmation + onClicked: { + if (ArchUpdaterService.busy) + return + + if (ArchUpdaterService.updatePackages.length > 0) { + // Show confirmation dialog for updates + PanelService.updatePanel.toggle(screen) + } else { + // Just refresh if no updates available + ArchUpdaterService.doPoll() } - - + } } diff --git a/Services/ArchUpdaterService.qml b/Services/ArchUpdaterService.qml index ed392ef..611ce59 100644 --- a/Services/ArchUpdaterService.qml +++ b/Services/ArchUpdaterService.qml @@ -1,153 +1,156 @@ pragma Singleton + import Quickshell import QtQuick import Quickshell.Io Singleton { - id: updateService - - // Core properties - readonly property bool busy: checkupdatesProcess.running - readonly property int updates: updatePackages.length - property var updatePackages: [] - property var selectedPackages: [] - property int selectedPackagesCount: 0 - property bool updateInProgress: false - - // Process for checking updates - Process { - id: checkupdatesProcess - command: ["checkupdates"] - onExited: function(exitCode) { - if (exitCode !== 0 && exitCode !== 2) { - console.warn("[UpdateService] checkupdates failed (code:", exitCode, ")"); - updatePackages = []; - return; - } - } - stdout: StdioCollector { - onStreamFinished: { - parseCheckupdatesOutput(text); - } - } + id: updateService + + // Core properties + readonly property bool busy: checkupdatesProcess.running + readonly property int updates: updatePackages.length + property var updatePackages: [] + property var selectedPackages: [] + property int selectedPackagesCount: 0 + property bool updateInProgress: false + + // Process for checking updates + Process { + id: checkupdatesProcess + command: ["checkupdates"] + onExited: function (exitCode) { + if (exitCode !== 0 && exitCode !== 2) { + console.warn("[UpdateService] checkupdates failed (code:", exitCode, ")") + updatePackages = [] + return + } } - - // Parse checkupdates output - function parseCheckupdatesOutput(output) { - const lines = output.trim().split('\n').filter(line => line.trim()); - const packages = []; - - for (const line of lines) { - const m = line.match(/^(\S+)\s+([^\s]+)\s+->\s+([^\s]+)$/); - if (m) { - packages.push({ - name: m[1], - oldVersion: m[2], - newVersion: m[3], - description: `${m[1]} ${m[2]} -> ${m[3]}` - }); - } - } - - updatePackages = packages; + stdout: StdioCollector { + onStreamFinished: { + parseCheckupdatesOutput(text) + } } - - // Check for updates - function doPoll() { - if (busy) return; - checkupdatesProcess.running = true; + } + + // Parse checkupdates output + function parseCheckupdatesOutput(output) { + const lines = output.trim().split('\n').filter(line => line.trim()) + const packages = [] + + for (const line of lines) { + const m = line.match(/^(\S+)\s+([^\s]+)\s+->\s+([^\s]+)$/) + if (m) { + packages.push({ + "name": m[1], + "oldVersion": m[2], + "newVersion": m[3], + "description": `${m[1]} ${m[2]} -> ${m[3]}` + }) + } } - - // Update all packages - function runUpdate() { - if (updates === 0) { - doPoll(); - return; - } - - updateInProgress = true; - Quickshell.execDetached(["pkexec", "pacman", "-Syu", "--noconfirm"]); - - // Refresh after updates with multiple attempts - refreshAfterUpdate(); + + updatePackages = packages + } + + // Check for updates + function doPoll() { + if (busy) + return + checkupdatesProcess.running = true + } + + // Update all packages + function runUpdate() { + if (updates === 0) { + doPoll() + return } - - // Update selected packages - function runSelectiveUpdate() { - if (selectedPackages.length === 0) return; - - updateInProgress = true; - const command = ["pkexec", "pacman", "-S", "--noconfirm"].concat(selectedPackages); - Quickshell.execDetached(command); - - // Clear selection and refresh - selectedPackages = []; - selectedPackagesCount = 0; - refreshAfterUpdate(); + + updateInProgress = true + Quickshell.execDetached(["pkexec", "pacman", "-Syu", "--noconfirm"]) + + // Refresh after updates with multiple attempts + refreshAfterUpdate() + } + + // Update selected packages + function runSelectiveUpdate() { + if (selectedPackages.length === 0) + return + + updateInProgress = true + const command = ["pkexec", "pacman", "-S", "--noconfirm"].concat(selectedPackages) + Quickshell.execDetached(command) + + // Clear selection and refresh + selectedPackages = [] + selectedPackagesCount = 0 + refreshAfterUpdate() + } + + // Package selection functions + function togglePackageSelection(packageName) { + const index = selectedPackages.indexOf(packageName) + if (index > -1) { + selectedPackages.splice(index, 1) + } else { + selectedPackages.push(packageName) } - - // Package selection functions - function togglePackageSelection(packageName) { - const index = selectedPackages.indexOf(packageName); - if (index > -1) { - selectedPackages.splice(index, 1); - } else { - selectedPackages.push(packageName); - } - selectedPackagesCount = selectedPackages.length; - } - - function selectAllPackages() { - selectedPackages = updatePackages.map(pkg => pkg.name); - selectedPackagesCount = selectedPackages.length; - } - - function deselectAllPackages() { - selectedPackages = []; - selectedPackagesCount = 0; - } - - function isPackageSelected(packageName) { - return selectedPackages.indexOf(packageName) > -1; - } - - // Robust refresh after updates - function refreshAfterUpdate() { - // First refresh attempt after 3 seconds - Qt.callLater(() => { - doPoll(); - }, 3000); - - // Second refresh attempt after 8 seconds - Qt.callLater(() => { - doPoll(); - }, 8000); - - // Third refresh attempt after 15 seconds - Qt.callLater(() => { - doPoll(); - updateInProgress = false; - }, 15000); - - // Final refresh attempt after 30 seconds - Qt.callLater(() => { - doPoll(); - }, 30000); - } - - // Notification helper - function notify(title, body) { - Quickshell.execDetached(["notify-send", "-a", "UpdateService", "-i", "system-software-update", title, body]); - } - - // Auto-poll every 15 minutes - Timer { - interval: 15 * 60 * 1000 // 15 minutes - repeat: true - running: true - onTriggered: doPoll() - } - - // Initial check - Component.onCompleted: doPoll() + selectedPackagesCount = selectedPackages.length + } + + function selectAllPackages() { + selectedPackages = updatePackages.map(pkg => pkg.name) + selectedPackagesCount = selectedPackages.length + } + + function deselectAllPackages() { + selectedPackages = [] + selectedPackagesCount = 0 + } + + function isPackageSelected(packageName) { + return selectedPackages.indexOf(packageName) > -1 + } + + // Robust refresh after updates + function refreshAfterUpdate() { + // First refresh attempt after 3 seconds + Qt.callLater(() => { + doPoll() + }, 3000) + + // Second refresh attempt after 8 seconds + Qt.callLater(() => { + doPoll() + }, 8000) + + // Third refresh attempt after 15 seconds + Qt.callLater(() => { + doPoll() + updateInProgress = false + }, 15000) + + // Final refresh attempt after 30 seconds + Qt.callLater(() => { + doPoll() + }, 30000) + } + + // Notification helper + function notify(title, body) { + Quickshell.execDetached(["notify-send", "-a", "UpdateService", "-i", "system-software-update", title, body]) + } + + // Auto-poll every 15 minutes + Timer { + interval: 15 * 60 * 1000 // 15 minutes + repeat: true + running: true + onTriggered: doPoll() + } + + // Initial check + Component.onCompleted: doPoll() }