update category changes

This commit is contained in:
2026-05-15 18:59:04 +02:00
parent f6c4dc8ee1
commit 33f6706658
2 changed files with 239 additions and 95 deletions
+79
View File
@@ -11,10 +11,13 @@ Singleton {
id: root id: root
property int availableUpdates: 0 property int availableUpdates: 0
property string cmd: ""
property bool commandReady property bool commandReady
property bool loaded property bool loaded
property double now: Date.now() property double now: Date.now()
property var updates: ({}) property var updates: ({})
property bool updating
property string updatingPackage: ""
function formatUpdateTime(timestamp) { function formatUpdateTime(timestamp) {
const diffMs = root.now - timestamp; const diffMs = root.now - timestamp;
@@ -34,6 +37,22 @@ Singleton {
return Qt.formatDateTime(new Date(timestamp), "dd hh:mm"); return Qt.formatDateTime(new Date(timestamp), "dd hh:mm");
} }
function performPackageUpdate(pkg: string): void {
if (root.cmd === "pacman")
pkgUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Sy", pkg];
else
pkgUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Sy", pkg];
pkgUpdateProc.running = true;
}
function performSystemUpdate(): void {
if (root.cmd === "pacman")
sysUpdateProc.command = ["pkexec", root.cmd, "--noconfirm", "-Syu"];
else
sysUpdateProc.command = [root.cmd, "--noconfirm", "--sudo", "pkexec", "-Syu"];
sysUpdateProc.running = true;
}
onUpdatesChanged: { onUpdatesChanged: {
if (!root.loaded) if (!root.loaded)
return; return;
@@ -92,6 +111,28 @@ Singleton {
} }
} }
Process {
id: updateCmdDetect
command: ["sh", "-c", "command -v yay || command -v paru"]
running: true
stdout: StdioCollector {
onStreamFinished: {
const cmd = this.text.trim();
let helper;
if (cmd.length > 0) {
helper = cmd.split("/").pop();
} else {
helper = "pacman";
}
root.cmd = helper;
}
}
}
Process { Process {
id: updatesProc id: updatesProc
@@ -115,6 +156,44 @@ Singleton {
} }
} }
Process {
id: sysUpdateProc
command: []
running: false
stdout: StdioCollector {
onStreamFinished: {
root.updating = false;
}
}
onRunningChanged: {
if (running)
root.updating = true;
}
}
Process {
id: pkgUpdateProc
command: []
running: false
stdout: StdioCollector {
onStreamFinished: {
root.updating = false;
}
}
onRunningChanged: {
if (running) {
root.updatingPackage = command[command.length - 1];
root.updating = true;
}
}
}
Timer { Timer {
id: saveTimer id: saveTimer
+160 -95
View File
@@ -6,127 +6,192 @@ import qs.Helpers
import qs.Components import qs.Components
import qs.Modules.Settings.Controls import qs.Modules.Settings.Controls
SettingsPage { ColumnLayout {
SettingsSection { id: root
sectionId: "Updates"
SettingsHeader { RowLayout {
name: "System updates" Layout.fillWidth: true
Layout.margins: Appearance.padding.large
spacing: Appearance.spacing.large
MaterialIcon {
font.pointSize: Appearance.font.size.larger * 4
text: "update"
} }
CustomListView { ColumnLayout {
id: view CustomText {
font.pointSize: Appearance.font.size.large * 2
text: "System updates"
}
readonly property int itemHeight: 50 + Appearance.padding.smaller * 2 RowLayout {
id: row
Layout.fillWidth: true // Layout.fillHeight: true
Layout.preferredHeight: contentHeight Layout.fillWidth: true
spacing: Appearance.spacing.normal
delegate: CustomRect {
id: update
required property var modelData
readonly property list<string> sections: modelData.update.split(" ")
// anchors.left: parent.left // anchors.left: parent.left
// anchors.margins: Appearance.padding.small
// anchors.right: parent.right // anchors.right: parent.right
color: DynamicColors.tPalette.m3surfaceContainer // anchors.verticalCenter: parent.verticalCenter
implicitHeight: view.itemHeight
implicitWidth: parent.width
radius: Appearance.rounding.small - Appearance.padding.small
RowLayout { CustomText {
anchors.fill: parent id: text
anchors.leftMargin: Appearance.padding.smaller
anchors.rightMargin: Appearance.padding.smaller
MaterialIcon { Layout.alignment: Qt.AlignLeft | Qt.AlignVCenter
font.pointSize: Appearance.font.size.large * 2 Layout.fillWidth: true
text: "package_2" font.pointSize: Appearance.font.size.larger
} text: `${Updates.availableUpdates} available updates`
}
ColumnLayout { CustomRect {
Layout.fillWidth: true Layout.preferredHeight: 40
Layout.preferredWidth: 150
CustomText { color: Updates.updating ? DynamicColors.layer(DynamicColors.palette.m3outline, 2) : DynamicColors.palette.m3primary
Layout.fillWidth: true radius: Appearance.rounding.full
Layout.preferredHeight: 25
elide: Text.ElideRight
font.pointSize: Appearance.font.size.large
text: update.sections[0]
}
CustomText {
Layout.fillWidth: true
color: DynamicColors.palette.m3onSurfaceVariant
text: Updates.formatUpdateTime(update.modelData.timestamp)
}
}
RowLayout { RowLayout {
Layout.fillHeight: true anchors.centerIn: parent
Layout.preferredWidth: 500
MarqueeText {
id: versionFrom
Layout.fillHeight: true
Layout.preferredWidth: 225
animate: true
color: DynamicColors.palette.m3tertiary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignHCenter
marqueeEnabled: true
pauseMs: 4000
text: update.sections[1]
width: 225
}
MaterialIcon { MaterialIcon {
Layout.fillHeight: true animate: true
color: DynamicColors.palette.m3secondary color: DynamicColors.palette.m3onPrimary
font.pointSize: Appearance.font.size.extraLarge font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignHCenter text: Updates.updating ? "update" : "download"
text: "arrow_right_alt"
verticalAlignment: Text.AlignVCenter
} }
MarqueeText { CustomText {
id: versionTo color: Updates.updating ? DynamicColors.palette.m3onSurface : DynamicColors.palette.m3onPrimary
text: "Update all"
Layout.fillHeight: true
Layout.preferredWidth: 225
animate: true
color: DynamicColors.palette.m3primary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignHCenter
marqueeEnabled: true
pauseMs: 4000
text: update.sections[3]
width: 225
} }
} }
IconButton { StateLayer {
Layout.preferredHeight: width color: DynamicColors.palette.m3onPrimary
icon: "download" disabled: Updates.updating
onClicked: { onClicked: Updates.performSystemUpdate()
Quickshell.execDetached(["pkexec", "yay", "-Sy", update.sections[0], "--noconfirm"]);
}
} }
} }
} }
model: ScriptModel { }
id: script }
objectProp: "update" CustomListView {
values: Object.entries(Updates.updates).sort((a, b) => b[1] - a[1]).map(([update, timestamp]) => ({ id: view
update,
timestamp readonly property int itemHeight: 50 + Appearance.padding.smaller * 2
}))
Layout.fillHeight: true
Layout.fillWidth: true
clip: true
contentHeight: height
spacing: Appearance.spacing.normal
delegate: CustomRect {
id: update
required property var modelData
readonly property list<string> sections: modelData.update.split(" ")
// anchors.left: parent.left
// anchors.right: parent.right
color: DynamicColors.tPalette.m3surfaceContainer
implicitHeight: view.itemHeight
implicitWidth: parent.width
radius: Appearance.rounding.small - Appearance.padding.small
RowLayout {
anchors.fill: parent
anchors.leftMargin: Appearance.padding.smaller
anchors.rightMargin: Appearance.padding.smaller
MaterialIcon {
font.pointSize: Appearance.font.size.large * 2
text: "package_2"
}
ColumnLayout {
Layout.fillWidth: true
CustomText {
Layout.fillWidth: true
Layout.preferredHeight: 25
elide: Text.ElideRight
font.pointSize: Appearance.font.size.large
text: update.sections[0]
}
CustomText {
Layout.fillWidth: true
color: DynamicColors.palette.m3onSurfaceVariant
text: Updates.formatUpdateTime(update.modelData.timestamp)
}
}
RowLayout {
Layout.fillHeight: true
Layout.preferredWidth: 500
MarqueeText {
id: versionFrom
Layout.fillHeight: true
Layout.preferredWidth: 225
animate: true
color: DynamicColors.palette.m3tertiary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignHCenter
marqueeEnabled: true
pauseMs: 4000
text: update.sections[1]
width: 225
}
MaterialIcon {
Layout.fillHeight: true
color: DynamicColors.palette.m3secondary
font.pointSize: Appearance.font.size.extraLarge
horizontalAlignment: Text.AlignHCenter
text: "arrow_right_alt"
verticalAlignment: Text.AlignVCenter
}
MarqueeText {
id: versionTo
Layout.fillHeight: true
Layout.preferredWidth: 225
animate: true
color: DynamicColors.palette.m3primary
font.pointSize: Appearance.font.size.large
horizontalAlignment: Text.AlignHCenter
marqueeEnabled: true
pauseMs: 4000
text: update.sections[3]
width: 225
}
}
IconButton {
Layout.preferredHeight: width
icon: "download"
onClicked: {
Updates.performPackageUpdate(update.sections[0]);
}
}
} }
} }
model: ScriptModel {
id: script
objectProp: "update"
values: Object.entries(Updates.updates).sort((a, b) => b[1] - a[1]).map(([update, timestamp]) => ({
update,
timestamp
}))
}
} }
} }