// Copyright (C) 2026 Danilo M. // // This program is free software; you can redistribute it and/or modify // it under the terms of the GNU General Public License version 2 as // published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. import QtQuick import "../.." // One section per action, in the order they are done, each hidden when it // has nothing and no error. Read-only: installing and building stay in the // terminal. Column { id: page required property var up readonly property var d: up.doc spacing: 16 function tracked(list) { return list.map(r => ({ name: r.name, repo: r.repo, ver: r.from + " → " + r.to })); } readonly property var sections: !d ? [] : [ { title: "Slackware upgrades", err: d.errors.mirror || "", rows: d.slackware.upgrade.map(r => ({ name: r.name, repo: "", ver: r.from + " → " + r.to })) }, { title: "New in Slackware", err: "", rows: d.slackware.new.map(r => ({ name: r.name, repo: "", ver: r.version })) }, { title: "Removed from Slackware", err: "", rows: d.slackware.removed.map(r => ({ name: r.name, repo: "", ver: "removed " + r.date })) }, { title: "Upgrade here", err: d.errors.repo || "", rows: tracked(d.upgrade) }, { title: "Awaiting build", err: "", rows: tracked(d.build) }, { title: "Upstream newer", err: d.errors.nvchecker || "", rows: tracked(d.upstream) }, { title: "App updates", err: "", rows: tracked(d.apps) }, ] function ago(t) { const m = Math.round((Date.now() / 1000 - t) / 60); return m < 1 ? "just now" : m < 60 ? m + " min ago" : Math.round(m / 60) + " h ago"; } Text { visible: page.d !== null && page.up.toInstall === 0 && page.up.toBuild === 0 && page.d.upstream.length === 0 && page.d.apps.length === 0 text: "Up to date" color: Theme.subtext font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 2 } } Repeater { model: page.sections Column { required property var modelData width: page.width spacing: 4 visible: modelData.rows.length > 0 || modelData.err !== "" Text { text: modelData.title + (modelData.rows.length ? " " + modelData.rows.length : "") color: Theme.text font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 1; bold: true } } Text { visible: modelData.err !== "" text: modelData.err color: Theme.subtext font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3; italic: true } } Repeater { model: modelData.rows Item { required property var modelData width: page.width height: 22 Text { anchors { left: parent.left; right: repo.left; rightMargin: 8; verticalCenter: parent.verticalCenter } elide: Text.ElideRight textFormat: Text.PlainText text: modelData.name color: Theme.text font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } } Text { id: repo anchors { right: ver.left; rightMargin: 12; verticalCenter: parent.verticalCenter } text: modelData.repo color: Theme.subtext font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 4 } } Text { id: ver anchors { right: parent.right; verticalCenter: parent.verticalCenter } textFormat: Text.PlainText text: modelData.ver color: Theme.subtext font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } } } } } } Row { spacing: 10 Text { anchors.verticalCenter: parent.verticalCenter text: page.up.checking ? "checking…" : page.d && page.d.checked ? "checked " + page.ago(page.d.checked) : "" color: Theme.subtext font { family: Theme.fontFamily; pixelSize: Theme.fontSize - 3 } } Button { text: "Refresh" enabled: !page.up.checking onClicked: page.up.run(true) } } }