summaryrefslogtreecommitdiff
path: root/ui/qt5/runner/executepage.cc
diff options
context:
space:
mode:
Diffstat (limited to 'ui/qt5/runner/executepage.cc')
-rw-r--r--ui/qt5/runner/executepage.cc198
1 files changed, 198 insertions, 0 deletions
diff --git a/ui/qt5/runner/executepage.cc b/ui/qt5/runner/executepage.cc
new file mode 100644
index 0000000..817a61c
--- /dev/null
+++ b/ui/qt5/runner/executepage.cc
@@ -0,0 +1,198 @@
+/*
+ * executepage.cc - Implementation of the UI.Perform page
+ * horizon-run-qt5, the Qt 5 executor user interface for
+ * Project Horizon
+ *
+ * Copyright (c) 2019 Adélie Linux and contributors. All rights reserved.
+ * This code is licensed under the AGPL 3.0 license, as noted in the
+ * LICENSE-code file in the root directory of this repository.
+ *
+ * SPDX-License-Identifier: AGPL-3.0-only
+ */
+
+#include "executepage.hh"
+
+#include <QAbstractButton>
+#include <QGridLayout>
+#include <QProcess>
+#include <QTimer>
+#include <QVBoxLayout>
+
+ExecutePage::ExecutePage(QWidget *parent) : HorizonWizardPage(parent) {
+ setTitle(tr("Installing Adélie Linux…"));
+ loadWatermark("intro");
+
+ QLabel *descLabel = new QLabel(tr("Please wait while System Installation performs the following tasks:"));
+ descLabel->setWordWrap(true);
+
+ prepareStatus = new QLabel;
+ prepare = new QLabel(tr("Prepare installation"));
+ validateStatus = new QLabel;
+ validate = new QLabel(tr("Validate installation"));
+ diskStatus = new QLabel;
+ disk = new QLabel(tr("Configure hard disk(s)"));
+ preMetaStatus = new QLabel;
+ preMeta = new QLabel(tr("Initial configuration"));
+ netStatus = new QLabel;
+ net = new QLabel(tr("Networking configuration"));
+ pkgStatus = new QLabel;
+ pkg = new QLabel(tr("Install software"));
+ postMetaStatus = new QLabel;
+ postMeta = new QLabel(tr("Final configuration"));
+
+ QGridLayout *progressLayout = new QGridLayout;
+ progressLayout->addWidget(prepareStatus, 0, 0);
+ progressLayout->addWidget(prepare, 0, 1);
+ progressLayout->addWidget(validateStatus, 1, 0);
+ progressLayout->addWidget(validate, 1, 1);
+ progressLayout->addWidget(diskStatus, 2, 0);
+ progressLayout->addWidget(disk, 2, 1);
+ progressLayout->addWidget(preMetaStatus, 3, 0);
+ progressLayout->addWidget(preMeta, 3, 1);
+ progressLayout->addWidget(netStatus, 4, 0);
+ progressLayout->addWidget(net, 4, 1);
+ progressLayout->addWidget(pkgStatus, 5, 0);
+ progressLayout->addWidget(pkg, 5, 1);
+ progressLayout->addWidget(postMetaStatus, 6, 0);
+ progressLayout->addWidget(postMeta, 6, 1);
+ progressLayout->setColumnStretch(1, 100);
+
+ normalFont = validate->font();
+ boldFont = normalFont;
+ boldFont.setBold(true);
+
+ QVBoxLayout *mainLayout = new QVBoxLayout;
+ mainLayout->addWidget(descLabel);
+ mainLayout->addStretch();
+ mainLayout->addLayout(progressLayout);
+ mainLayout->addStretch();
+
+ setLayout(mainLayout);
+
+ finishTimer = new QTimer(this);
+ finishTimer->setInterval(1500);
+ finishTimer->setSingleShot(true);
+ connect(finishTimer, &QTimer::timeout, [=]{
+ wizard()->next();
+ });
+
+ log.setFileName("/var/log/horizon/executor.log");
+ Q_ASSERT(log.open(QFile::Append));
+
+ this->current = Prepare;
+ markRunning(this->current);
+
+ executor = new QProcess(this);
+ executor->setProgram("../../tools/hscript-simulate/hscript-simulate");
+ executor->setArguments({"/etc/horizon/installfile"});
+ connect(executor, &QProcess::readyReadStandardError,
+ this, &ExecutePage::executorReady);
+ connect(executor, &QProcess::readyReadStandardOutput,
+ this, &ExecutePage::executorOutReady);
+ connect(executor, QOverload<int, QProcess::ExitStatus>::of(&QProcess::finished),
+ this, &ExecutePage::executorFinished);
+ executor->start();
+}
+
+ExecutePage::Phase ExecutePage::stepToPhase(QString step) {
+ if(step == "validate") return Validate;
+ if(step == "disk") return Disk;
+ if(step == "pre-metadata") return PreMeta;
+ if(step == "net") return Net;
+ if(step == "pkgdb") return Pkg;
+ if(step == "post-metadata") return PostMeta;
+ Q_ASSERT(false);
+}
+
+void ExecutePage::labelsForPhase(Phase phase, QLabel **icon, QLabel **text) {
+ switch(phase) {
+ case Prepare:
+ *icon = prepareStatus;
+ *text = prepare;
+ break;
+ case Validate:
+ *icon = validateStatus;
+ *text = validate;
+ break;
+ case Disk:
+ *icon = diskStatus;
+ *text = disk;
+ break;
+ case PreMeta:
+ *icon = preMetaStatus;
+ *text = preMeta;
+ break;
+ case Net:
+ *icon = netStatus;
+ *text = net;
+ break;
+ case Pkg:
+ *icon = pkgStatus;
+ *text = pkg;
+ break;
+ case PostMeta:
+ *icon = postMetaStatus;
+ *text = postMeta;
+ break;
+ }
+}
+
+void ExecutePage::markRunning(Phase phase) {
+ QLabel *icon, *text;
+ labelsForPhase(phase, &icon, &text);
+ icon->setPixmap(loadDPIAwarePixmap("status-current", ".svg"));
+ text->setFont(boldFont);
+}
+
+void ExecutePage::markFinished(Phase phase) {
+ QLabel *icon, *text;
+ labelsForPhase(phase, &icon, &text);
+ icon->setPixmap(loadDPIAwarePixmap("status-success", ".svg"));
+ text->setFont(normalFont);
+}
+
+void ExecutePage::markFailed(Phase phase) {
+ QLabel *icon, *text;
+ labelsForPhase(phase, &icon, &text);
+ icon->setPixmap(loadDPIAwarePixmap("status-issue", ".svg"));
+ text->setFont(boldFont);
+}
+
+void ExecutePage::executorReady() {
+ QByteArray msgs = executor->readAllStandardError();
+ log.write(msgs);
+
+ QStringList msgList = QString::fromUtf8(msgs).split("\n");
+ for(auto &msg : msgList) {
+ QString msgType = msg.section('\t', 1, 1);
+ if(msgType == "step-start") {
+ this->current = stepToPhase(msg.section('\t', 2));
+ /* validate means prepare is done */
+ if(this->current == Validate) markFinished(Prepare);
+ markRunning(this->current);
+ } else if(msgType == "step-end") {
+ Q_ASSERT(stepToPhase(msg.section('\t', 2)) == this->current);
+ markFinished(this->current);
+ } else if(msgType == "log") {
+ QString severity = msg.section(": ", 1, 1);
+ if(severity == "error") {
+ markFailed(this->current);
+ }
+ } else {
+ /* !? */
+ }
+ }
+}
+
+void ExecutePage::executorOutReady() {
+ log.write(executor->readAllStandardOutput());
+}
+
+void ExecutePage::executorFinished(int code, QProcess::ExitStatus status) {
+ if(status != QProcess::NormalExit || code != 0) {
+ markFailed(this->current);
+ }
+
+ wizard()->button(QWizard::CancelButton)->setEnabled(false);
+ finishTimer->start();
+}