Introduce system based updates and add progress and changelog

This commit is contained in:
Simon Stürz 2026-02-03 12:56:23 +01:00
parent 8401af9529
commit 04bc050142
6 changed files with 442 additions and 145 deletions

View File

@ -25,20 +25,23 @@
#include "systemcontroller.h"
#include "types/package.h"
#include "types/repository.h"
#include "types/packages.h"
#include "types/repositories.h"
#include "types/repository.h"
#include <QTimeZone>
#include <QJsonDocument>
#include <QMetaEnum>
#include <QTimeZone>
#include "logging.h"
NYMEA_LOGGING_CATEGORY(dcSystemController, "SystemController")
SystemController::SystemController(JsonRpcClient *jsonRpcClient, QObject *parent):
QObject(parent),
m_jsonRpcClient(jsonRpcClient)
SystemController::SystemController(JsonRpcClient *jsonRpcClient, QObject *parent)
: QObject(parent)
, m_jsonRpcClient(jsonRpcClient)
{
m_jsonRpcClient->registerNotificationHandler(this, "System", "notificationReceived");
m_packages = new Packages(this);
m_repositories = new Repositories(this);
@ -73,6 +76,11 @@ bool SystemController::updateManagementAvailable() const
return m_updateManagementAvailable;
}
SystemController::UpdateType SystemController::updateManagementType() const
{
return m_updateManagementType;
}
int SystemController::restart()
{
return m_jsonRpcClient->sendCommand("System.Restart", this, "restartResponse");
@ -98,6 +106,11 @@ bool SystemController::updateRunning() const
return m_updateRunning;
}
int SystemController::updateProgress() const
{
return m_updateProgress;
}
void SystemController::checkForUpdates()
{
m_jsonRpcClient->sendCommand("System.CheckForUpdates");
@ -172,7 +185,7 @@ QString SystemController::serverTimeZone() const
// NOTE: Ideally we'd just set the TimeZone of our serverTime prooperly, however, there's a bug on Android
// Which doesn't allow to create QTimeZone objects by IANA id.... So, let's keep that separated in a string
// https://bugreports.qt.io/browse/QTBUG-83438
// return m_serverTime.timeZone().id();
// return m_serverTime.timeZone().id();
return m_serverTimeZone;
}
@ -207,12 +220,26 @@ QString SystemController::deviceSerialNumber() const
void SystemController::getCapabilitiesResponse(int /*commandId*/, const QVariantMap &data)
{
qCDebug(dcSystemController()) << data;
m_powerManagementAvailable = data.value("powerManagement").toBool();
emit powerManagementAvailableChanged();
m_updateManagementAvailable = data.value("updateManagement").toBool();
emit updateManagementAvailableChanged();
// Since API version 8.5
if (data.contains("updateManagementType")) {
QMetaEnum updateTypeEnum = QMetaEnum::fromType<SystemController::UpdateType>();
m_updateManagementType = static_cast<SystemController::UpdateType>(updateTypeEnum.keyToValue(data.value("updateManagementType").toByteArray()));
} else {
// Property exists since API 8.5, if there is an update management available, default to UpdateTypePackageManager
if (m_updateManagementAvailable) {
m_updateManagementType = UpdateTypePackageManager;
} else {
m_updateManagementType = UpdateTypeNone;
}
}
m_timeManagementAvailable = data.value("timeManagement").toBool();
emit timeManagementAvailableChanged();
@ -226,7 +253,15 @@ void SystemController::getCapabilitiesResponse(int /*commandId*/, const QVariant
m_jsonRpcClient->sendCommand("System.GetTime", this, "getServerTimeResponse");
}
qCDebug(dcSystemController) << "nymea:core capabilities: Power management:" << m_powerManagementAvailable << "Update management:" << m_updateManagementAvailable << "Time management:" << m_timeManagementAvailable;
qCDebug(dcSystemController())
<< "nymea:core capabilities: Power management:"
<< m_powerManagementAvailable
<< "Update management:"
<< m_updateManagementAvailable
<< "Update management type:"
<< m_updateManagementType
<< "Time management:"
<< m_timeManagementAvailable;
}
void SystemController::getUpdateStatusResponse(int /*commandId*/, const QVariantMap &data)
@ -234,13 +269,17 @@ void SystemController::getUpdateStatusResponse(int /*commandId*/, const QVariant
qCDebug(dcSystemController()) << "Update status:" << qUtf8Printable(QJsonDocument::fromVariant(data).toJson(QJsonDocument::Indented));
m_updateManagementBusy = data.value("busy").toBool();
m_updateRunning = data.value("updateRunning").toBool();
m_updateProgress = data.value("updateProgress", -1).toInt(); // Since API 8.5, optional
emit updateRunningChanged();
emit updateManagementBusyChanged();
emit updateProgressChanged();
}
void SystemController::getPackagesResponse(int commandId, const QVariantMap &data)
{
Q_UNUSED(commandId)
qCDebug(dcSystemController) << "Packages:" << qUtf8Printable(QJsonDocument::fromVariant(data).toJson(QJsonDocument::Indented));
qCDebug(dcSystemController()) << "Packages:" << qUtf8Printable(QJsonDocument::fromVariant(data).toJson(QJsonDocument::Indented));
foreach (const QVariant &packageVariant, data.value("packages").toList()) {
QString id = packageVariant.toMap().value("id").toString();
QString displayName = packageVariant.toMap().value("displayName").toString();
@ -269,12 +308,12 @@ void SystemController::getRepositoriesResponse(int /*commandId*/, const QVariant
void SystemController::removePackageResponse(int commandId, const QVariantMap &params)
{
qCDebug(dcSystemController) << "Remove result" << commandId << params;
qCDebug(dcSystemController()) << "Remove result" << commandId << params;
}
void SystemController::enableRepositoryResponse(int commandId, const QVariantMap &params)
{
qCDebug(dcSystemController) << "Enable repo response" << params;
qCDebug(dcSystemController()) << "Enable repo response" << params;
emit enableRepositoryFinished(commandId, params.value("success").toBool());
}
@ -286,7 +325,7 @@ void SystemController::getServerTimeResponse(int commandId, const QVariantMap &p
// Which doesn't allow to create QTimeZone objects by IANA id.... So, let's keep that separated in a string
// https://bugreports.qt.io/browse/QTBUG-83438
// m_serverTime.setTimeZone(QTimeZone(params.value("timeZone").toString().toUtf8()));
// m_serverTime.setTimeZone(QTimeZone(params.value("timeZone").toString().toUtf8()));
m_serverTimeZone = params.value("timeZone").toString();
emit serverTimeZoneChanged();
@ -302,12 +341,12 @@ void SystemController::getServerTimeResponse(int commandId, const QVariantMap &p
emit automaticTimeAvailableChanged();
m_automaticTime = params.value("automaticTime").toBool();
emit automaticTimeChanged();
qCDebug(dcSystemController) << "Server time:" << m_serverTime << "Automatic Time available:" << m_automaticTimeAvailable << "Automatic time:" << m_automaticTime;
qCDebug(dcSystemController()) << "Server time:" << m_serverTime << "Automatic Time available:" << m_automaticTimeAvailable << "Automatic time:" << m_automaticTime;
}
void SystemController::setTimeResponse(int commandId, const QVariantMap &params)
{
qCDebug(dcSystemController) << "set time response" << commandId << params;
qCDebug(dcSystemController()) << "set time response" << commandId << params;
}
void SystemController::restartResponse(int commandId, const QVariantMap &params)
@ -338,18 +377,26 @@ void SystemController::getSystemInfoResponse(int commandId, const QVariantMap &p
void SystemController::notificationReceived(const QVariantMap &data)
{
QString notification = data.value("notification").toString();
const QVariantMap paramsMap = data.value("params").toMap();
if (notification == "System.UpdateStatusChanged") {
qCDebug(dcSystemController) << "System.UpdateStatusChanged:" << data.value("params").toMap();
if (m_updateManagementBusy != data.value("params").toMap().value("busy").toBool()) {
m_updateManagementBusy = data.value("params").toMap().value("busy").toBool();
qCDebug(dcSystemController()) << "System.UpdateStatusChanged:" << paramsMap;
if (m_updateManagementBusy != paramsMap.value("busy").toBool()) {
m_updateManagementBusy = paramsMap.value("busy").toBool();
emit updateManagementBusyChanged();
}
if (m_updateRunning != data.value("params").toMap().value("updateRunning").toBool()) {
m_updateRunning = data.value("params").toMap().value("updateRunning").toBool();
if (m_updateRunning != paramsMap.value("updateRunning").toBool()) {
m_updateRunning = paramsMap.value("updateRunning").toBool();
emit updateRunningChanged();
}
// Since API 8.5, optional, not supported or not running = -1
if (m_updateProgress != paramsMap.value("updateProgress", -1).toInt()) {
m_updateProgress = paramsMap.value("updateProgress").toInt();
emit updateProgressChanged();
}
} else if (notification == "System.PackageAdded") {
QVariantMap packageMap = data.value("params").toMap().value("package").toMap();
QVariantMap packageMap = paramsMap.value("package").toMap();
QString id = packageMap.value("id").toString();
QString displayName = packageMap.value("displayName").toString();
Package *p = new Package(id, displayName);
@ -362,7 +409,7 @@ void SystemController::notificationReceived(const QVariantMap &data)
p->setCanRemove(packageMap.value("canRemove").toBool());
m_packages->addPackage(p);
} else if (notification == "System.PackageChanged") {
QVariantMap packageMap = data.value("params").toMap().value("package").toMap();
QVariantMap packageMap = paramsMap.value("package").toMap();
QString id = packageMap.value("id").toString();
Package *p = m_packages->getPackage(id);
if (!p) {
@ -377,17 +424,17 @@ void SystemController::notificationReceived(const QVariantMap &data)
p->setRollbackAvailable(packageMap.value("rollbackAvailable").toBool());
p->setCanRemove(packageMap.value("canRemove").toBool());
} else if (notification == "System.PackageRemoved") {
QString packageId = data.value("params").toMap().value("packageId").toString();
QString packageId = paramsMap.value("packageId").toString();
m_packages->removePackage(packageId);
} else if (notification == "System.RepositoryAdded") {
QVariantMap repoMap = data.value("params").toMap().value("repository").toMap();
QVariantMap repoMap = paramsMap.value("repository").toMap();
QString id = repoMap.value("id").toString();
QString displayName = repoMap.value("displayName").toString();
Repository *repo = new Repository(id, displayName);
repo->setEnabled(repoMap.value("enabled").toBool());
m_repositories->addRepository(repo);
} else if (notification == "System.RepositoryChanged") {
QVariantMap repoMap = data.value("params").toMap().value("repository").toMap();
QVariantMap repoMap = paramsMap.value("repository").toMap();
QString id = repoMap.value("id").toString();
Repository *repo = m_repositories->getRepository(id);
if (!repo) {
@ -396,16 +443,36 @@ void SystemController::notificationReceived(const QVariantMap &data)
}
repo->setEnabled(repoMap.value("enabled").toBool());
} else if (notification == "System.RepositoryRemoved") {
QString repositoryId = data.value("params").toMap().value("repositoryId").toString();
QString repositoryId = paramsMap.value("repositoryId").toString();
m_repositories->removeRepository(repositoryId);
} else if (notification == "System.CapabilitiesChanged") {
m_powerManagementAvailable = data.value("params").toMap().value("powerManagement").toBool();
m_updateManagementAvailable = data.value("params").toMap().value("updateManagement").toBool();
qWarning() << "System capabilites changed: power management:" << m_powerManagementAvailable << "update management:" << m_updateManagementAvailable;
m_powerManagementAvailable = paramsMap.value("powerManagement").toBool();
m_updateManagementAvailable = paramsMap.value("updateManagement").toBool();
if (paramsMap.contains("updateManagementType")) {
QMetaEnum updateTypeEnum = QMetaEnum::fromType<SystemController::UpdateType>();
m_updateManagementType = static_cast<SystemController::UpdateType>(updateTypeEnum.keyToValue(paramsMap.value("updateManagementType").toByteArray()));
} else {
// Property exists since API 8.5, if there is an update management available, default to UpdateTypePackageManager
if (m_updateManagementAvailable) {
m_updateManagementType = UpdateTypePackageManager;
} else {
m_updateManagementType = UpdateTypeNone;
}
}
qCDebug(dcSystemController())
<< "System capabilites changed: power management:"
<< m_powerManagementAvailable
<< "update management:"
<< m_updateManagementAvailable
<< "update management type:"
<< m_updateManagementType;
emit powerManagementAvailableChanged();
emit updateManagementAvailableChanged();
emit updateManagementTypeChanged();
} else if (notification == "System.TimeConfigurationChanged") {
qCDebug(dcSystemController) << "System time configuration changed" << data.value("params").toMap().value("timeZone").toByteArray();
qCDebug(dcSystemController()) << "System time configuration changed" << data.value("params").toMap().value("timeZone").toByteArray();
// NOTE: Ideally we'd just set the TimeZone of our serverTime prooperly, however, there's a bug on Android
// Which doesn't allow to create QTimeZone objects by IANA id.... So, let's keep that separated in a string

View File

@ -35,14 +35,18 @@ class SystemController : public QObject
{
Q_OBJECT
Q_PROPERTY(bool powerManagementAvailable READ powerManagementAvailable NOTIFY powerManagementAvailableChanged)
// Whether the update mechanism is available in the connected core
Q_PROPERTY(bool updateManagementAvailable READ updateManagementAvailable NOTIFY updateManagementAvailableChanged)
Q_PROPERTY(UpdateType updateManagementType READ updateManagementType NOTIFY updateManagementTypeChanged FINAL)
Q_PROPERTY(bool timeManagementAvailable READ timeManagementAvailable NOTIFY timeManagementAvailableChanged)
Q_PROPERTY(bool updateManagementBusy READ updateManagementBusy NOTIFY updateManagementBusyChanged)
Q_PROPERTY(bool updateRunning READ updateRunning NOTIFY updateRunningChanged)
Q_PROPERTY(Packages* packages READ packages CONSTANT)
Q_PROPERTY(Repositories* repositories READ repositories CONSTANT)
Q_PROPERTY(int updateProgress READ updateProgress NOTIFY updateProgressChanged)
Q_PROPERTY(Packages *packages READ packages CONSTANT)
Q_PROPERTY(Repositories *repositories READ repositories CONSTANT)
Q_PROPERTY(QDateTime serverTime READ serverTime WRITE setServerTime NOTIFY serverTimeChanged)
Q_PROPERTY(QString serverTimeZone READ serverTimeZone WRITE setServerTimeZone NOTIFY serverTimeZoneChanged)
@ -53,23 +57,34 @@ class SystemController : public QObject
Q_PROPERTY(QString deviceSerialNumber READ deviceSerialNumber NOTIFY deviceSerialNumberChanged)
public:
enum UpdateType {
UpdateTypeNone,
UpdateTypeSystem,
UpdateTypePackageManager
};
Q_ENUM(UpdateType)
explicit SystemController(JsonRpcClient *jsonRpcClient, QObject *parent = nullptr);
void init();
bool powerManagementAvailable() const;
Q_INVOKABLE int restart();
Q_INVOKABLE int reboot();
Q_INVOKABLE int shutdown();
bool updateManagementAvailable() const;
UpdateType updateManagementType() const;
bool updateManagementBusy() const;
bool updateRunning() const;
int updateProgress() const;
Q_INVOKABLE void checkForUpdates();
Packages* packages() const;
Packages *packages() const;
Q_INVOKABLE void updatePackages(const QString packageId = QString());
Q_INVOKABLE void removePackages(const QString packageId = QString());
Repositories* repositories() const;
Repositories *repositories() const;
Q_INVOKABLE int enableRepository(const QString &id, bool enabled);
bool timeManagementAvailable() const;
@ -87,9 +102,11 @@ public:
signals:
void powerManagementAvailableChanged();
void updateManagementAvailableChanged();
void updateManagementTypeChanged();
void timeManagementAvailableChanged();
void updateManagementBusyChanged();
void updateRunningChanged();
void updateProgressChanged();
void enableRepositoryFinished(int id, bool success);
void serverTimeChanged();
void serverTimeZoneChanged();
@ -117,7 +134,6 @@ private slots:
void notificationReceived(const QVariantMap &data);
protected:
void timerEvent(QTimerEvent *event) override;
@ -126,10 +142,12 @@ private:
bool m_powerManagementAvailable = false;
bool m_updateManagementAvailable = false;
UpdateType m_updateManagementType = UpdateTypeNone;
bool m_timeManagementAvailable = false;
bool m_updateManagementBusy = false;
bool m_updateRunning = false;
int m_updateProgress = -1;
Packages *m_packages = nullptr;
Repositories *m_repositories = nullptr;

View File

@ -69,12 +69,16 @@ SettingsPageBase {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
visible: !kioskMode && Qt.platform.os !== "ios"
Label {
Layout.fillWidth: true
text: qsTr("View mode")
}
ComboBox {
Layout.minimumWidth: 200
model: [qsTr("Windowed"), qsTr("Maximized"), qsTr("Fullscreen"), qsTr("Automatic")]
currentIndex: {
switch (settings.viewMode) {

View File

@ -64,6 +64,15 @@ Rectangle {
wrapMode: Text.WordWrap
font.pixelSize: app.largeFont
}
ProgressBar {
Layout.fillWidth: true
Layout.leftMargin: app.margins
Layout.rightMargin: app.margins
visible: engine.systemController.updateProgress >= 0
value: engine.systemController.updateProgress / 100.0
}
Label {
Layout.fillWidth: true
Layout.margins: app.margins * 2

View File

@ -26,6 +26,7 @@ import QtQuick
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Layouts
import Nymea
import "../components"
@ -48,12 +49,12 @@ Page {
Connections {
target: engine.systemController
onEnableRepositoryFinished: {
if (!success) {
var popup = errorDialogComponent.createObject(app, {errorCode: qsTr("Failure adding repository.") })
popup.open();
}
}
onEnableRepositoryFinished: (id, success) => {
if (!success) {
var popup = errorDialogComponent.createObject(app, {errorCode: qsTr("Failure adding repository.") })
popup.open();
}
}
}
PackagesFilterModel {
@ -62,151 +63,350 @@ Page {
updatesOnly: true
}
ColumnLayout {
id: contentColumn
Loader {
id: updateTypeLoader
anchors.fill: parent
sourceComponent: engine.systemController.updateManagementType === SystemController.UpdateTypeSystem ?
updateSystemComponent :
updatePackageManagerComponent
Item {
Layout.fillHeight: true
Layout.fillWidth: true
visible: updatesModel.count === 0
}
Component {
id: updateSystemComponent
ColumnLayout {
id: systemUpdateContentColumn
property Package systemPackage: engine.systemController.packages.get(0)
property bool changelogAvailable: systemUpdateContentColumn.systemPackage.changelog.length !== 0
anchors.fill: parent
anchors.margins: app.margins
Item {
Layout.fillHeight: true
Layout.fillWidth: true
visible: updatesModel.count === 0
ColumnLayout {
width: parent.width
anchors.centerIn: parent
spacing: app.margins * 2
ColorIcon {
Layout.preferredHeight: Style.iconSize * 4
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
name: "qrc:/icons/system-update.svg"
color: Style.accentColor
RotationAnimation on rotation {
from: 0; to: 360
duration: 2000
running: engine.systemController.updateManagementBusy
loops: Animation.Infinite
}
}
Label {
Layout.fillWidth: true
Layout.leftMargin: Style.margins
Layout.rightMargin: Style.margins
wrapMode: Text.WordWrap
horizontalAlignment: Text.AlignHCenter
text: engine.systemController.updateManagementBusy ? qsTr("Checking for updates...") : qsTr("Your system is up to date.")
}
Label {
id: versionLabel
Layout.alignment: Qt.AlignHCenter
wrapMode: Text.WordWrap
text: qsTr("Version:") + " " + systemUpdateContentColumn.systemPackage.installedVersion
MouseArea {
anchors.fill: parent
onClicked: {
PlatformHelper.toClipBoard(versionLabel.text);
ToolTip.show(qsTr("Version copied to clipboard"), 500);
}
}
}
Button {
Layout.fillWidth: true
Layout.leftMargin: Style.margins
Layout.rightMargin: Style.margins
text: qsTr("Check for updates")
enabled: !engine.systemController.updateManagementBusy
onClicked: {
engine.systemController.checkForUpdates()
}
}
}
}
ColumnLayout {
width: parent.width
anchors.centerIn: parent
spacing: app.margins * 2
Layout.fillHeight: true
Layout.fillWidth: true
visible: updatesModel.count > 0
ColorIcon {
Layout.preferredHeight: Style.iconSize * 4
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
name: "qrc:/icons/system-update.svg"
color: Style.accentColor
RotationAnimation on rotation {
from: 0; to: 360
duration: 2000
running: engine.systemController.updateManagementBusy
loops: Animation.Infinite
RowLayout {
Layout.margins: app.margins
spacing: app.margins
ColorIcon {
Layout.preferredHeight: Style.iconSize * 2
Layout.preferredWidth: height
name: "qrc:/icons/system-update.svg"
color: Style.accentColor
RotationAnimation on rotation {
from: 0; to: 360
duration: 2000
running: engine.systemController.updateManagementBusy
loops: Animation.Infinite
}
}
Label {
Layout.fillWidth: true
text: engine.systemController.updateManagementBusy ? qsTr("Checking for updates...") : qsTr("%1 update available").arg(Configuration.systemName)
}
}
Button {
Layout.fillWidth: true
text: qsTr("Check again")
enabled: !engine.systemController.updateManagementBusy
onClicked: engine.systemController.checkForUpdates()
}
NymeaSwipeDelegate {
Layout.fillWidth: true
text: qsTr("Installed version:")
subText: systemUpdateContentColumn.systemPackage.installedVersion
progressive: false
}
NymeaSwipeDelegate {
Layout.fillWidth: true
text: qsTr("Candidate version:")
subText: systemUpdateContentColumn.systemPackage.candidateVersion
visible: systemUpdateContentColumn.systemPackage.updateAvailable || systemUpdateContentColumn.systemPackage.installedVersion.length === 0
progressive: false
}
ThinDivider {
visible: changelogAvailable
}
Label {
Layout.fillWidth: true
Layout.margins: app.margins
horizontalAlignment: Text.AlignHCenter
Layout.leftMargin: Style.margins
Layout.rightMargin: Style.margins
visible: changelogAvailable
text: qsTr("Update changelog:")
}
Label {
Layout.fillWidth: true
Layout.leftMargin: Style.margins
Layout.rightMargin: Style.margins
Layout.alignment: Qt.AlignHCenter
wrapMode: Text.WordWrap
text: engine.systemController.updateManagementBusy ? qsTr("Checking for updates...") : qsTr("Your system is up to date.")
visible: changelogAvailable
text: systemPackage.changelog
}
Item {
Layout.fillWidth: true
Layout.fillHeight: true
}
Button {
Layout.alignment: Qt.AlignHCenter
text: qsTr("Check for updates")
Layout.fillWidth: true
//Layout.leftMargin: Style.margins
//Layout.rightMargin: Style.margins
text: qsTr("Update")
visible: updatesModel.count > 0
enabled: !engine.systemController.updateManagementBusy
onClicked: {
engine.systemController.checkForUpdates()
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/NymeaDialog.qml"));
var text = qsTr("This will start a system update. Note that the update might take several minutes and your %1 system might not be functioning properly during this time and restart during the process.\nDo you want to proceed?").arg(Configuration.systemName)
var popup = dialog.createObject(app,
{
headerIcon: "qrc:/icons/system-update.svg",
title: qsTr("System update"),
text: text,
standardButtons: Dialog.Ok | Dialog.Cancel
});
popup.open();
popup.accepted.connect(function() {
engine.systemController.updatePackages()
})
}
}
}
}
}
Component {
id: updatePackageManagerComponent
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
visible: updatesModel.count > 0
id: contentColumn
anchors.fill: parent
RowLayout {
Layout.margins: app.margins
spacing: app.margins
Item {
Layout.fillHeight: true
Layout.fillWidth: true
Layout.leftMargin: Style.margins
Layout.rightMargin: Style.margins
ColorIcon {
Layout.preferredHeight: Style.iconSize * 2
Layout.preferredWidth: height
name: "qrc:/icons/system-update.svg"
color: Style.accentColor
RotationAnimation on rotation {
from: 0; to: 360
duration: 2000
running: engine.systemController.updateManagementBusy
loops: Animation.Infinite
}
}
visible: updatesModel.count === 0
ColumnLayout {
width: parent.width
anchors.centerIn: parent
spacing: app.margins * 2
ColorIcon {
Layout.preferredHeight: Style.iconSize * 4
Layout.preferredWidth: height
Layout.alignment: Qt.AlignHCenter
name: "qrc:/icons/system-update.svg"
color: Style.accentColor
RotationAnimation on rotation {
from: 0; to: 360
duration: 2000
running: engine.systemController.updateManagementBusy
loops: Animation.Infinite
}
}
Label {
Layout.fillWidth: true
text: engine.systemController.updateManagementBusy ? qsTr("Checking for updates...") : qsTr("%n update(s) available", "", updatesModel.count)
horizontalAlignment: Text.AlignHCenter
wrapMode: Text.WordWrap
text: engine.systemController.updateManagementBusy ? qsTr("Checking for updates...") : qsTr("Your system is up to date.")
}
GridLayout {
columns: width > 250 ? 2 : 1
Button {
Button {
Layout.fillWidth: true
text: qsTr("Check for updates")
enabled: !engine.systemController.updateManagementBusy
onClicked: engine.systemController.checkForUpdates()
}
}
}
ColumnLayout {
Layout.fillHeight: true
Layout.fillWidth: true
visible: updatesModel.count > 0
RowLayout {
spacing: Style.margins
Layout.leftMargin: Style.margins
Layout.rightMargin: Style.margins
ColorIcon {
Layout.preferredHeight: Style.iconSize * 2
Layout.preferredWidth: height
name: "qrc:/icons/system-update.svg"
color: Style.accentColor
RotationAnimation on rotation {
from: 0; to: 360
duration: 2000
running: engine.systemController.updateManagementBusy
loops: Animation.Infinite
}
}
ColumnLayout {
Label {
Layout.fillWidth: true
text: qsTr("Check again")
enabled: !engine.systemController.updateManagementBusy
onClicked: {
engine.systemController.checkForUpdates()
text: engine.systemController.updateManagementBusy ? qsTr("Checking for updates...") : qsTr("%n update(s) available", "", updatesModel.count)
}
GridLayout {
columns: width > 250 ? 2 : 1
Button {
Layout.fillWidth: true
text: qsTr("Check again")
enabled: !engine.systemController.updateManagementBusy
onClicked: {
engine.systemController.checkForUpdates()
}
}
Button {
Layout.fillWidth: true
text: qsTr("Update all")
visible: updatesModel.count > 0
enabled: !engine.systemController.updateManagementBusy
onClicked: {
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/NymeaDialog.qml"));
var text = qsTr("This will start a system update. Note that the update might take several minutes and your %1 system might not be functioning properly during this time and restart during the process.\nDo you want to proceed?").arg(Configuration.systemName)
var popup = dialog.createObject(app,
{
headerIcon: "qrc:/icons/system-update.svg",
title: qsTr("System update"),
text: text,
standardButtons: Dialog.Ok | Dialog.Cancel
});
popup.open();
popup.accepted.connect(function() {
engine.systemController.updatePackages()
})
}
}
}
Button {
Layout.fillWidth: true
text: qsTr("Update all")
visible: updatesModel.count > 0
enabled: !engine.systemController.updateManagementBusy
onClicked: {
var dialog = Qt.createComponent(Qt.resolvedUrl("../components/NymeaDialog.qml"));
var text = qsTr("This will start a system update. Note that the update might take several minutes and your %1 system might not be functioning properly during this time and restart during the process.\nDo you want to proceed?").arg(Configuration.systemName)
var popup = dialog.createObject(app,
{
headerIcon: "qrc:/icons/system-update.svg",
title: qsTr("System update"),
text: text,
standardButtons: Dialog.Ok | Dialog.Cancel
});
popup.open();
popup.accepted.connect(function() {
engine.systemController.updatePackages()
})
}
}
}
ThinDivider {}
ListView {
Layout.fillWidth: true
Layout.fillHeight: true
visible: count > 0
model: updatesModel
clip: true
delegate: NymeaSwipeDelegate {
width: parent.width
text: model.displayName
subText: model.candidateVersion
prominentSubText: false
iconName: model.updateAvailable
? Qt.resolvedUrl("qrc:/icons/system-update.svg")
: Qt.resolvedUrl("qrc:/icons/view-" + (model.installedVersion.length > 0 ? "expand" : "collapse") + ".svg")
iconColor: model.updateAvailable
? "green"
: model.installedVersion.length > 0 ? "blue" : Style.iconColor
onClicked: {
pageStack.push(Qt.resolvedUrl("PackageDetailsPage.qml"), {pkg: updatesModel.get(index)})
}
}
}
}
ThinDivider {}
ListView {
NymeaSwipeDelegate {
Layout.fillWidth: true
Layout.fillHeight: true
visible: count > 0
model: updatesModel
clip: true
delegate: NymeaSwipeDelegate {
width: parent.width
text: model.displayName
subText: model.candidateVersion
prominentSubText: false
iconName: model.updateAvailable
? Qt.resolvedUrl("qrc:/icons/system-update.svg")
: Qt.resolvedUrl("qrc:/icons/view-" + (model.installedVersion.length > 0 ? "expand" : "collapse") + ".svg")
iconColor: model.updateAvailable
? "green"
: model.installedVersion.length > 0 ? "blue" : Style.iconColor
onClicked: {
pageStack.push(Qt.resolvedUrl("PackageDetailsPage.qml"), {pkg: updatesModel.get(index)})
}
text: qsTr("Install or remove software")
onClicked: {
pageStack.push("PackageListPage.qml")
}
}
}
ThinDivider {}
NymeaSwipeDelegate {
Layout.fillWidth: true
text: qsTr("Install or remove software")
onClicked: {
pageStack.push("PackageListPage.qml")
}
}
}
Component {
@ -253,8 +453,7 @@ Page {
}
}
UpdateRunningOverlay {
}
UpdateRunningOverlay { }
Component {
id: errorDialogComponent

View File

@ -1,2 +1,2 @@
1.11.3
700
1.11.4
701