From a2b9e9880193cd5ba0e33bd1eebae27cbfcd3ca0 Mon Sep 17 00:00:00 2001 From: Florian RICHER Date: Sat, 26 Jul 2025 19:32:26 +0200 Subject: [PATCH] waydroid: Use KAuth progressStep --- .../kauth/waydroidhelper.cpp | 42 ++++++++++++++- .../waydroidstate.cpp | 10 ++++ .../waydroidintegrationplugin/waydroidstate.h | 2 + .../ui/WaydroidDownloadStatus.qml | 53 +++++++++++++++++++ kcms/waydroidintegration/ui/main.qml | 15 +++++- 5 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 kcms/waydroidintegration/ui/WaydroidDownloadStatus.qml diff --git a/components/waydroidintegrationplugin/kauth/waydroidhelper.cpp b/components/waydroidintegrationplugin/kauth/waydroidhelper.cpp index 8b8e7abf..ecaad9f9 100644 --- a/components/waydroidintegrationplugin/kauth/waydroidhelper.cpp +++ b/components/waydroidintegrationplugin/kauth/waydroidhelper.cpp @@ -15,11 +15,16 @@ #include #include #include +#include using namespace Qt::StringLiterals; #define WAYDROID_COMMAND "waydroid" +// Extract current downloaded size, total_size and speed. +// Example of log: "[Downloading] 62.19 MB/1197.24 MB 96740.75 kbps(approx.)" +static const QRegularExpression downloadingStatusRegExp(R"(\[Downloading]\s*(\d+\.\d+)\s*MB/(\d+\.\d+)\s*MB\s*(\d+\.\d+)\s*kbps\(approx\.\))"); + class WaydroidHelper : public QObject { Q_OBJECT @@ -41,7 +46,42 @@ KAuth::ActionReply WaydroidHelper::initialize(const QVariantMap &args) QProcess *process = new QProcess(this); process->start(WAYDROID_COMMAND, arguments); - process->waitForFinished(); + + connect(process, &QProcess::readyReadStandardOutput, this, [process]() { + const QByteArray output = process->readAllStandardOutput(); + const QByteArray lastLine = output.split('\r').last(); + + QVariantMap informations = {{u"log"_s, lastLine.constData()}}; + + QRegularExpressionMatch match = downloadingStatusRegExp.match(lastLine); + if (!match.hasMatch()) { + KAuth::HelperSupport::progressStep(informations); + return; + } + + const QString downloadMatch = match.captured(1); + const QString totalMatch = match.captured(2); + const QString speedMatch = match.captured(3); + if (downloadMatch.isEmpty() || totalMatch.isEmpty() || speedMatch.isEmpty()) { + KAuth::HelperSupport::progressStep(informations); + return; + } + + bool downloadCastOk, totalCastOk, speedCastOk; + float downloadedMB = downloadMatch.toFloat(&downloadCastOk); + float totalMB = totalMatch.toFloat(&totalCastOk); + float speedKbps = speedMatch.toFloat(&speedCastOk); + + if (downloadCastOk && totalCastOk && speedCastOk) { + informations.insert(u"downloaded"_s, downloadedMB); + informations.insert(u"total"_s, totalMB); + informations.insert(u"speed"_s, speedKbps); + } + + KAuth::HelperSupport::progressStep(informations); + }); + + process->waitForFinished(-1); if (process->exitCode() == 0) { return KAuth::ActionReply::SuccessReply(); diff --git a/components/waydroidintegrationplugin/waydroidstate.cpp b/components/waydroidintegrationplugin/waydroidstate.cpp index 371094ef..057d1f1b 100644 --- a/components/waydroidintegrationplugin/waydroidstate.cpp +++ b/components/waydroidintegrationplugin/waydroidstate.cpp @@ -220,6 +220,16 @@ void WaydroidState::initialize(const SystemType systemType, const RomType romTyp KAuth::ExecuteJob *job = writeAction.execute(); job->start(); + connect(job, &KAuth::ExecuteJob::newData, this, [this](const QVariantMap &data) { + QString log = data.value("log", "").toString(); + float downloaded = data.value("downloaded", 0.0).toFloat(); + float total = data.value("total", 0.0).toFloat(); + float speed = data.value("speed", 0.0).toFloat(); + + qCDebug(WAYDROIDINTEGRATIONPLUGIN) << "log: " << log; + Q_EMIT downloadStatusChanged(downloaded, total, speed); + }); + connect(job, &KAuth::ExecuteJob::finished, this, [this](KJob *job, auto) { if (job->error() == 0) { m_status = Initialized; diff --git a/components/waydroidintegrationplugin/waydroidstate.h b/components/waydroidintegrationplugin/waydroidstate.h index 99eb2ad6..c9765c20 100644 --- a/components/waydroidintegrationplugin/waydroidstate.h +++ b/components/waydroidintegrationplugin/waydroidstate.h @@ -118,6 +118,8 @@ public: Q_SIGNALS: void statusChanged(); + // download and total is in MB and speed in Kbps + void downloadStatusChanged(float downloaded, float total, float speed); void sessionStatusChanged(); void systemTypeChanged(); void ipAddressChanged(); diff --git a/kcms/waydroidintegration/ui/WaydroidDownloadStatus.qml b/kcms/waydroidintegration/ui/WaydroidDownloadStatus.qml new file mode 100644 index 00000000..c06f6bba --- /dev/null +++ b/kcms/waydroidintegration/ui/WaydroidDownloadStatus.qml @@ -0,0 +1,53 @@ +/* + * SPDX-FileCopyrightText: 2025 Florian RICHER + * SPDX-License-Identifier: LGPL-2.0-or-later + */ + +import QtQuick +import QtQuick.Layouts 1.15 +import QtQuick.Controls 2.15 as QQC2 + +import org.kde.kirigami 2.19 as Kirigami +import org.kde.plasma.components 3.0 as PC3 + +ColumnLayout { + id: root + property string text + property real downloaded: 0.0 + property real total: 0.0 + property real speed: 0.0 + + anchors.centerIn: parent + spacing: Kirigami.Units.largeSpacing + + QQC2.Label { + text: root.text + horizontalAlignment: Text.AlignHCenter + Layout.alignment: Qt.AlignHCenter + } + + QQC2.ProgressBar { + from: 0 + value: downloaded + to: total + indeterminate: total <= 0.0 + + Layout.alignment: Qt.AlignHCenter + } + + QQC2.Label { + visible: total > 0.0 + text: i18n("Downloading %1MB/%2MB Speed %3", downloaded.toFixed(2), total.toFixed(2), formatSpeed()) + horizontalAlignment: Text.AlignHCenter + Layout.alignment: Qt.AlignHCenter + font.pixelSize: Kirigami.Theme.smallFont.pixelSize + } + + function formatSpeed(): string { + if (speed > 1024) { + return i18n("%1Mb/s", (speed / 1024).toFixed(0)) + } else { + return i18n("%1Kb/s", speed.toFixed(0)) + } + } +} \ No newline at end of file diff --git a/kcms/waydroidintegration/ui/main.qml b/kcms/waydroidintegration/ui/main.qml index 539a8f4d..b055ceae 100644 --- a/kcms/waydroidintegration/ui/main.qml +++ b/kcms/waydroidintegration/ui/main.qml @@ -46,9 +46,20 @@ KCM.SimpleKCM { visible: AIP.WaydroidState.errorTitle === "" && AIP.WaydroidState.status == AIP.WaydroidState.NotInitialized } - WaydroidLoader { + WaydroidDownloadStatus { + id: downloadStatus visible: AIP.WaydroidState.errorTitle === "" && AIP.WaydroidState.status == AIP.WaydroidState.Initializing - text: i18n("Waydroid is initializing.\nIt can take a few minutes.") + text: i18n("Downloading Android and vendor images.\nIt can take a few minutes.") + + Connections { + target: AIP.WaydroidState + + function onDownloadStatusChanged(downloaded, total, speed) { + downloadStatus.downloaded = downloaded + downloadStatus.total = total + downloadStatus.speed = speed + } + } } ColumnLayout {