diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 9e977ec..e9f8bf9 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -93,7 +93,22 @@ Singleton { } // ----------------- - // 2nd. migrate global settings to user settings + // 2nd. remove any non existing widget type + for (var s = 0; s < sections.length; s++) { + const sectionName = sections[s] + const widgets = adapter.bar.widgets[sectionName] + // Iterate backward through the widgets array, so it does not break when removing a widget + for (var i = widgets.length - 1; i >= 0; i--) { + var widget = widgets[i] + if (!BarWidgetRegistry.hasWidget(widget.id)) { + widgets.splice(i, 1) + Logger.warn(`Settings`, `Deleted invalid widget ${widget.id}`) + } + } + } + + // ----------------- + // 3nd. migrate global settings to user settings for (var s = 0; s < sections.length; s++) { const sectionName = sections[s] for (var i = 0; i < adapter.bar.widgets[sectionName].length; i++) { @@ -219,7 +234,6 @@ Singleton { if (!isLoaded) { Logger.log("Settings", "----------------------------") Logger.log("Settings", "Settings loaded successfully") - isLoaded = true upgradeSettingsData() @@ -227,6 +241,8 @@ Singleton { kickOffServices() + isLoaded = true + // Emit the signal root.settingsLoaded() } diff --git a/Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml b/Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml deleted file mode 100644 index 36ad4ab..0000000 --- a/Modules/ArchUpdaterPanel/ArchUpdaterPanel.qml +++ /dev/null @@ -1,527 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import Quickshell.Wayland -import qs.Commons -import qs.Services -import qs.Widgets - -NPanel { - id: root - panelWidth: 380 * scaling - panelHeight: 500 * scaling - panelAnchorRight: true - - panelContent: Rectangle { - color: Color.mSurface - radius: Style.radiusL * scaling - - ColumnLayout { - anchors.fill: parent - anchors.margins: Style.marginL * scaling - spacing: Style.marginM * scaling - - // Header - RowLayout { - Layout.fillWidth: true - spacing: Style.marginM * scaling - - NIcon { - icon: "box" - font.pointSize: Style.fontSizeXXL * scaling - color: Color.mPrimary - } - - NText { - text: "System Updates" - font.pointSize: Style.fontSizeL * scaling - font.weight: Style.fontWeightBold - color: Color.mOnSurface - Layout.fillWidth: true - } - - // Reset button (only show if update failed) - NIconButton { - visible: ArchUpdaterService.updateFailed - icon: "refresh" - tooltipText: "Reset update state" - sizeRatio: 0.8 - colorBg: Color.mError - colorFg: Color.mOnError - onClicked: { - ArchUpdaterService.resetUpdateState() - } - } - - NIconButton { - icon: "close" - tooltipText: "Close" - sizeRatio: 0.8 - onClicked: root.close() - } - } - - NDivider { - Layout.fillWidth: true - } - - // Update summary (only show when packages are available and terminal is configured) - NText { - visible: !ArchUpdaterService.updateInProgress && !ArchUpdaterService.updateFailed - && !ArchUpdaterService.checkFailed && !ArchUpdaterService.aurBusy - && ArchUpdaterService.totalUpdates > 0 && ArchUpdaterService.terminalAvailable - && ArchUpdaterService.aurHelperAvailable - text: ArchUpdaterService.totalUpdates + " package" + (ArchUpdaterService.totalUpdates !== 1 ? "s" : "") + " can be updated" - font.pointSize: Style.fontSizeL * scaling - font.weight: Style.fontWeightMedium - color: Color.mOnSurface - Layout.fillWidth: true - } - - // Package selection info (only show when not updating and have packages and terminal is configured) - NText { - visible: !ArchUpdaterService.updateInProgress && !ArchUpdaterService.updateFailed - && !ArchUpdaterService.checkFailed && !ArchUpdaterService.aurBusy - && ArchUpdaterService.totalUpdates > 0 && ArchUpdaterService.terminalAvailable - && ArchUpdaterService.aurHelperAvailable - text: ArchUpdaterService.selectedPackagesCount + " of " + ArchUpdaterService.totalUpdates + " packages selected" - font.pointSize: Style.fontSizeS * scaling - color: Color.mOnSurfaceVariant - Layout.fillWidth: true - } - - // Update in progress state - ColumnLayout { - Layout.fillWidth: true - Layout.fillHeight: true - visible: ArchUpdaterService.updateInProgress - spacing: Style.marginM * scaling - - Item { - Layout.fillHeight: true - } // Spacer - - NIcon { - icon: "hourglass" - font.pointSize: Style.fontSizeXXXL * scaling - color: Color.mPrimary - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "Update in progress" - font.pointSize: Style.fontSizeL * scaling - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "Please check your terminal window for update progress and prompts." - font.pointSize: Style.fontSizeNormal * scaling - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - Layout.maximumWidth: 280 * scaling - } - - Item { - Layout.fillHeight: true - } // Spacer - } - - // Terminal not available state - Item { - Layout.fillWidth: true - Layout.fillHeight: true - visible: !ArchUpdaterService.terminalAvailable && !ArchUpdaterService.updateInProgress - && !ArchUpdaterService.updateFailed - - ColumnLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - NIcon { - icon: "terminal" - font.pointSize: Style.fontSizeXXXL * scaling - color: Color.mError - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "Terminal not configured" - font.pointSize: Style.fontSizeL * scaling - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "The TERMINAL environment variable is not set. Please set it to your preferred terminal (e.g., kitty, alacritty, foot) in your shell configuration." - font.pointSize: Style.fontSizeNormal * scaling - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - Layout.maximumWidth: 280 * scaling - } - } - } - - // AUR helper not available state - Item { - Layout.fillWidth: true - Layout.fillHeight: true - visible: ArchUpdaterService.terminalAvailable && !ArchUpdaterService.aurHelperAvailable - && !ArchUpdaterService.updateInProgress && !ArchUpdaterService.updateFailed - && !ArchUpdaterService.checkFailed && !ArchUpdaterService.aurBusy - - ColumnLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - NIcon { - icon: "box" - font.pointSize: Style.fontSizeXXXL * scaling - color: Color.mError - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "AUR helper not found" - font.pointSize: Style.fontSizeL * scaling - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "No AUR helper (yay or paru) is installed. Please install either yay or paru to manage AUR packages. yay is recommended." - font.pointSize: Style.fontSizeNormal * scaling - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - Layout.maximumWidth: 280 * scaling - } - } - } - - // Check failed state (AUR down, network issues, etc.) - Item { - Layout.fillWidth: true - Layout.fillHeight: true - visible: ArchUpdaterService.checkFailed && !ArchUpdaterService.updateInProgress - && !ArchUpdaterService.updateFailed && ArchUpdaterService.terminalAvailable - && ArchUpdaterService.aurHelperAvailable - - ColumnLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - NIcon { - icon: "exclamation-triangle" - font.pointSize: Style.fontSizeXXXL * scaling - color: Color.mError - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "Cannot check for updates" - font.pointSize: Style.fontSizeL * scaling - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: ArchUpdaterService.lastCheckError - || "AUR helper is unavailable or network connection failed. This could be due to AUR being down, network issues, or missing AUR helper (yay/paru)." - font.pointSize: Style.fontSizeNormal * scaling - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - Layout.maximumWidth: 280 * scaling - } - - // Prominent refresh button - NIconButton { - icon: "refresh" - tooltipText: "Try checking again" - sizeRatio: 1.2 - colorBg: Color.mPrimary - colorFg: Color.mOnPrimary - onClicked: { - ArchUpdaterService.forceRefresh() - } - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Style.marginL * scaling - } - } - } - - // Update failed state - Item { - Layout.fillWidth: true - Layout.fillHeight: true - visible: ArchUpdaterService.updateFailed - - ColumnLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - NIcon { - icon: "exclamation-triangle" - font.pointSize: Style.fontSizeXXXL * scaling - color: Color.mError - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "Update failed" - font.pointSize: Style.fontSizeL * scaling - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "Check your terminal for error details and try again." - font.pointSize: Style.fontSizeNormal * scaling - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - Layout.maximumWidth: 280 * scaling - } - - // Prominent refresh button - NIconButton { - icon: "refresh" - tooltipText: "Refresh and try again" - sizeRatio: 1.2 - colorBg: Color.mPrimary - colorFg: Color.mOnPrimary - onClicked: { - ArchUpdaterService.resetUpdateState() - } - Layout.alignment: Qt.AlignHCenter - Layout.topMargin: Style.marginL * scaling - } - } - } - - // No updates available state - Item { - Layout.fillWidth: true - Layout.fillHeight: true - visible: !ArchUpdaterService.updateInProgress && !ArchUpdaterService.updateFailed - && !ArchUpdaterService.checkFailed && !ArchUpdaterService.aurBusy - && ArchUpdaterService.totalUpdates === 0 && ArchUpdaterService.terminalAvailable - && ArchUpdaterService.aurHelperAvailable - - ColumnLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - NIcon { - icon: "check" - font.pointSize: Style.fontSizeXXXL * scaling - color: Color.mPrimary - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "System is up to date" - font.pointSize: Style.fontSizeL * scaling - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "All packages are current. Check back later for updates." - font.pointSize: Style.fontSizeNormal * scaling - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - Layout.maximumWidth: 280 * scaling - } - } - } - - // Checking for updates state - Item { - Layout.fillWidth: true - Layout.fillHeight: true - visible: ArchUpdaterService.aurBusy && !ArchUpdaterService.updateInProgress && !ArchUpdaterService.updateFailed - && ArchUpdaterService.terminalAvailable && ArchUpdaterService.aurHelperAvailable - - ColumnLayout { - anchors.centerIn: parent - spacing: Style.marginM * scaling - - NBusyIndicator { - Layout.alignment: Qt.AlignHCenter - size: Style.fontSizeXXXL * scaling - color: Color.mPrimary - } - - NText { - text: "Checking for updates" - font.pointSize: Style.fontSizeL * scaling - color: Color.mOnSurface - Layout.alignment: Qt.AlignHCenter - } - - NText { - text: "Scanning package databases for available updates..." - font.pointSize: Style.fontSizeNormal * scaling - color: Color.mOnSurfaceVariant - Layout.alignment: Qt.AlignHCenter - horizontalAlignment: Text.AlignHCenter - wrapMode: Text.Wrap - Layout.maximumWidth: 280 * scaling - } - } - } - - // Package list (only show when not in any special state) - NBox { - visible: !ArchUpdaterService.updateInProgress && !ArchUpdaterService.updateFailed - && !ArchUpdaterService.checkFailed && !ArchUpdaterService.aurBusy - && ArchUpdaterService.totalUpdates > 0 && ArchUpdaterService.terminalAvailable - && ArchUpdaterService.aurHelperAvailable - Layout.fillWidth: true - Layout.fillHeight: true - - // Combine repo and AUR lists in order: repos first, then AUR - property var items: (ArchUpdaterService.repoPackages || []).concat(ArchUpdaterService.aurPackages || []) - - ListView { - id: unifiedList - anchors.fill: parent - anchors.margins: Style.marginM * scaling - cacheBuffer: Math.round(300 * scaling) - clip: true - - model: parent.items - delegate: Rectangle { - width: unifiedList.width - height: 44 * scaling - color: Color.transparent - radius: Style.radiusS * scaling - - RowLayout { - anchors.fill: parent - spacing: Style.marginS * scaling - - // Checkbox for selection - NCheckbox { - id: checkbox - label: "" - description: "" - checked: ArchUpdaterService.isPackageSelected(modelData.name) - baseSize: Math.max(Style.baseWidgetSize * 0.7, 14) - onToggled: function (checked) { - ArchUpdaterService.togglePackageSelection(modelData.name) - // Force refresh of the checked property - checkbox.checked = ArchUpdaterService.isPackageSelected(modelData.name) - } - } - - // Package info - ColumnLayout { - Layout.fillWidth: true - spacing: Style.marginXXS * scaling - - NText { - text: modelData.name - font.pointSize: Style.fontSizeS * scaling - font.weight: Style.fontWeightBold - color: Color.mOnSurface - Layout.fillWidth: true - Layout.alignment: Qt.AlignVCenter - } - - NText { - text: modelData.oldVersion + " → " + modelData.newVersion - font.pointSize: Style.fontSizeXXS * scaling - color: Color.mOnSurfaceVariant - Layout.fillWidth: true - } - } - - // Source tag (AUR vs PAC) - Rectangle { - visible: !!modelData.source - radius: width * 0.5 - color: modelData.source === "aur" ? Color.mTertiary : Color.mSecondary - Layout.alignment: Qt.AlignVCenter - implicitHeight: Style.fontSizeS * 1.8 * scaling - // Width based on label content + horizontal padding - implicitWidth: badgeText.implicitWidth + Math.max(12 * scaling, Style.marginS * scaling) - - NText { - id: badgeText - anchors.centerIn: parent - text: modelData.source === "aur" ? "AUR" : "PAC" - font.pointSize: Style.fontSizeXXS * scaling - font.weight: Style.fontWeightBold - color: modelData.source === "aur" ? Color.mOnTertiary : Color.mOnSecondary - } - } - } - } - } - } - - // Action buttons (only show when not updating) - RowLayout { - visible: !ArchUpdaterService.updateInProgress && !ArchUpdaterService.updateFailed - && !ArchUpdaterService.checkFailed && ArchUpdaterService.terminalAvailable - && ArchUpdaterService.aurHelperAvailable - Layout.fillWidth: true - spacing: Style.marginL * scaling - - NIconButton { - icon: "refresh" - tooltipText: ArchUpdaterService.aurBusy ? "Checking for updates..." : (!ArchUpdaterService.canPoll ? "Refresh available soon" : "Refresh package lists") - onClicked: { - ArchUpdaterService.forceRefresh() - } - colorBg: Color.mSurfaceVariant - colorFg: Color.mOnSurface - Layout.fillWidth: true - enabled: !ArchUpdaterService.aurBusy - } - - NIconButton { - icon: "box-fill" - tooltipText: "Update all packages" - enabled: ArchUpdaterService.totalUpdates > 0 - onClicked: { - ArchUpdaterService.runUpdate() - root.close() - } - colorBg: ArchUpdaterService.totalUpdates > 0 ? Color.mPrimary : Color.mSurfaceVariant - colorFg: ArchUpdaterService.totalUpdates > 0 ? Color.mOnPrimary : Color.mOnSurfaceVariant - Layout.fillWidth: true - } - - NIconButton { - icon: "box" - tooltipText: "Update selected packages" - enabled: ArchUpdaterService.selectedPackagesCount > 0 - onClicked: { - if (ArchUpdaterService.selectedPackagesCount > 0) { - ArchUpdaterService.runSelectiveUpdate() - root.close() - } - } - colorBg: ArchUpdaterService.selectedPackagesCount > 0 ? Color.mPrimary : Color.mSurfaceVariant - colorFg: ArchUpdaterService.selectedPackagesCount > 0 ? Color.mOnPrimary : Color.mOnSurfaceVariant - Layout.fillWidth: true - } - } - } - } -} diff --git a/Modules/Bar/Widgets/ArchUpdater.qml b/Modules/Bar/Widgets/ArchUpdater.qml deleted file mode 100644 index 9375855..0000000 --- a/Modules/Bar/Widgets/ArchUpdater.qml +++ /dev/null @@ -1,80 +0,0 @@ -import QtQuick -import QtQuick.Controls -import QtQuick.Layouts -import Quickshell -import qs.Commons -import qs.Services -import qs.Widgets - -NIconButton { - id: root - - property ShellScreen screen - property real scaling: 1.0 - - sizeRatio: 0.8 - colorBg: Color.mSurfaceVariant - colorBorder: Color.transparent - colorBorderHover: Color.transparent - colorFg: { - if (!ArchUpdaterService.terminalAvailable || !ArchUpdaterService.aurHelperAvailable) { - return Color.mError - } - return (ArchUpdaterService.totalUpdates === 0) ? Color.mOnSurface : Color.mPrimary - } - - // Icon states - icon: { - if (!ArchUpdaterService.terminalAvailable) { - return "terminal" - } - if (!ArchUpdaterService.aurHelperAvailable) { - return "box" - } - if (ArchUpdaterService.aurBusy) { - return "refresh" - } - if (ArchUpdaterService.totalUpdates > 0) { - return "box-fill" - } - return "box" - } - - // Tooltip with repo vs AUR breakdown and sample lists - tooltipText: { - if (!ArchUpdaterService.terminalAvailable) { - return "Terminal not configured\nSet TERMINAL environment variable" - } - if (!ArchUpdaterService.aurHelperAvailable) { - return "AUR helper not found\nInstall yay or paru" - } - if (ArchUpdaterService.aurBusy) { - return "Checking for updates…" - } - - const total = ArchUpdaterService.totalUpdates - if (total === 0) { - return "System is up to date ✓" - } - let header = (total === 1) ? "1 package can be updated" : (total + " packages can be updated") - - const pacCount = ArchUpdaterService.updates - const aurCount = ArchUpdaterService.aurUpdates - const pacmanTooltip = (pacCount > 0) ? ((pacCount === 1) ? "1 system package" : pacCount + " system packages") : "" - const aurTooltip = (aurCount > 0) ? ((aurCount === 1) ? "1 AUR package" : aurCount + " AUR packages") : "" - - let tooltip = header - if (pacmanTooltip !== "") { - tooltip += "\n" + pacmanTooltip - } - if (aurTooltip !== "") { - tooltip += "\n" + aurTooltip - } - return tooltip - } - - onClicked: { - // Always allow panel to open, never block - PanelService.getPanel("archUpdaterPanel").toggle(screen, this) - } -} diff --git a/Services/BarWidgetRegistry.qml b/Services/BarWidgetRegistry.qml index 6005842..d92fd18 100644 --- a/Services/BarWidgetRegistry.qml +++ b/Services/BarWidgetRegistry.qml @@ -11,7 +11,6 @@ Singleton { // Widget registry object mapping widget names to components property var widgets: ({ "ActiveWindow": activeWindowComponent, - "ArchUpdater": archUpdaterComponent, "Battery": batteryComponent, "Bluetooth": bluetoothComponent, "Brightness": brightnessComponent, @@ -111,9 +110,6 @@ Singleton { property Component activeWindowComponent: Component { ActiveWindow {} } - property Component archUpdaterComponent: Component { - ArchUpdater {} - } property Component batteryComponent: Component { Battery {} } diff --git a/shell.qml b/shell.qml index 823857d..24544f5 100644 --- a/shell.qml +++ b/shell.qml @@ -28,7 +28,6 @@ import qs.Modules.PowerPanel import qs.Modules.SidePanel import qs.Modules.Toast import qs.Modules.WiFiPanel -import qs.Modules.ArchUpdaterPanel import qs.Services import qs.Widgets @@ -95,11 +94,6 @@ ShellRoot { objectName: "bluetoothPanel" } - ArchUpdaterPanel { - id: archUpdaterPanel - objectName: "archUpdaterPanel" - } - Component.onCompleted: { // Save a ref. to our lockScreen so we can access it easily PanelService.lockScreen = lockScreen