summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ui/qt5/CMakeLists.txt13
-rw-r--r--ui/qt5/horizonwizardpage.cc2
-rw-r--r--ui/qt5/horizonwizardpage.hh4
-rw-r--r--ui/qt5/runner/executepage.cc198
-rw-r--r--ui/qt5/runner/executepage.hh70
-rw-r--r--ui/qt5/runner/executorwizard.cc40
-rw-r--r--ui/qt5/runner/executorwizard.hh29
-rw-r--r--ui/qt5/runner/finishedpage.cc17
-rw-r--r--ui/qt5/runner/finishedpage.hh23
-rw-r--r--ui/qt5/runner/main.cc39
10 files changed, 434 insertions, 1 deletions
diff --git a/ui/qt5/CMakeLists.txt b/ui/qt5/CMakeLists.txt
index e752749..930a84a 100644
--- a/ui/qt5/CMakeLists.txt
+++ b/ui/qt5/CMakeLists.txt
@@ -26,6 +26,15 @@ set(UI_SOURCES
horizon.qrc)
+set(RUN_QT_SOURCES
+ horizonwizardpage.cc
+ runner/main.cc
+ runner/executorwizard.cc
+ runner/executepage.cc
+ runner/finishedpage.cc
+
+ horizon.qrc)
+
IF(INSTALL)
LIST(APPEND UI_SOURCES commitpage.cc)
ELSE(INSTALL)
@@ -51,5 +60,7 @@ IF(INSTALL)
pkg_check_modules(LIBX11 REQUIRED x11)
pkg_check_modules(LibCap REQUIRED libcap)
target_link_libraries(horizon-qt5 ${BCNM} ${SKARNET} ${LIBUDEV_LIBRARIES} ${LibCap_LIBRARIES} ${LIBX11_LIBRARIES} ${XKBFile_LIBRARIES})
- # add_executable(horizon-run-qt5 ${RUN_QT_SOURCES})
+ add_executable(horizon-run-qt5 ${RUN_QT_SOURCES})
+ target_link_libraries(horizon-run-qt5 Qt5::Widgets)
+ target_compile_definitions(horizon-run-qt5 PRIVATE IN_RUNNER)
ENDIF(INSTALL)
diff --git a/ui/qt5/horizonwizardpage.cc b/ui/qt5/horizonwizardpage.cc
index 352de0e..dcd3d8f 100644
--- a/ui/qt5/horizonwizardpage.cc
+++ b/ui/qt5/horizonwizardpage.cc
@@ -49,6 +49,8 @@ void HorizonWizardPage::loadWatermark(string page) {
setPixmap(QWizard::WatermarkPixmap, pixmap);
}
+#ifndef IN_RUNNER
HorizonWizard *HorizonWizardPage::horizonWizard() const {
return dynamic_cast<HorizonWizard *>(this->wizard());
}
+#endif /* !IN_RUNNER */
diff --git a/ui/qt5/horizonwizardpage.hh b/ui/qt5/horizonwizardpage.hh
index 6ed8a6e..16cc92c 100644
--- a/ui/qt5/horizonwizardpage.hh
+++ b/ui/qt5/horizonwizardpage.hh
@@ -16,7 +16,9 @@
#include <QWizardPage>
#include <string>
+#ifndef IN_RUNNER
#include "horizonwizard.hh"
+#endif /* !IN_RUNNER */
class HorizonWizardPage : public QWizardPage {
public:
@@ -24,7 +26,9 @@ public:
QPixmap loadDPIAwarePixmap(std::string pixmap, std::string type = ".png");
void loadWatermark(std::string page);
+#ifndef IN_RUNNER
HorizonWizard *horizonWizard() const;
+#endif /* !IN_RUNNER */
};
#endif /* !HORIZONWIZARDPAGE_HH */
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();
+}
diff --git a/ui/qt5/runner/executepage.hh b/ui/qt5/runner/executepage.hh
new file mode 100644
index 0000000..b3d11b4
--- /dev/null
+++ b/ui/qt5/runner/executepage.hh
@@ -0,0 +1,70 @@
+/*
+ * 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
+ */
+
+#ifndef EXECUTEPAGE_HH
+#define EXECUTEPAGE_HH
+
+#include "../horizonwizardpage.hh"
+
+#include <QFile>
+#include <QLabel>
+#include <QProcess>
+#include <QTimer>
+
+class ExecutePage : public HorizonWizardPage {
+public:
+ enum Phase {
+ Prepare,
+ Validate,
+ Disk,
+ PreMeta,
+ Net,
+ Pkg,
+ PostMeta
+ };
+
+ ExecutePage(QWidget *parent = nullptr);
+private:
+ QLabel *prepareStatus;
+ QLabel *prepare;
+ QLabel *validateStatus;
+ QLabel *validate;
+ QLabel *diskStatus;
+ QLabel *disk;
+ QLabel *preMetaStatus;
+ QLabel *preMeta;
+ QLabel *netStatus;
+ QLabel *net;
+ QLabel *pkgStatus;
+ QLabel *pkg;
+ QLabel *postMetaStatus;
+ QLabel *postMeta;
+
+ QFont normalFont, boldFont;
+ QProcess *executor;
+ QTimer *finishTimer;
+ QFile log;
+
+ Phase current;
+
+ Phase stepToPhase(QString step);
+ void labelsForPhase(Phase phase, QLabel **icon, QLabel **text);
+ void markRunning(Phase phase);
+ void markFinished(Phase phase);
+ void markFailed(Phase phase);
+
+ void executorReady();
+ void executorOutReady();
+ void executorFinished(int code, QProcess::ExitStatus status);
+};
+
+#endif /* !EXECUTEPAGE_HH */
diff --git a/ui/qt5/runner/executorwizard.cc b/ui/qt5/runner/executorwizard.cc
new file mode 100644
index 0000000..ae58a21
--- /dev/null
+++ b/ui/qt5/runner/executorwizard.cc
@@ -0,0 +1,40 @@
+/*
+ * executorwizard.cc - Implementation of the wizard class
+ * 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 "executorwizard.hh"
+
+#include <QAbstractButton>
+
+#include "executepage.hh"
+#include "finishedpage.hh"
+
+ExecutorWizard::ExecutorWizard(QWidget *parent) : QWizard(parent) {
+ setWindowTitle(tr("Adélie Linux System Installation"));
+
+ setFixedSize(QSize(650, 450));
+
+ setPage(Page_Execute, new ExecutePage);
+ setPage(Page_Finished, new FinishedPage);
+
+ setOption(NoBackButtonOnStartPage);
+ setOption(NoBackButtonOnLastPage);
+ setOption(NoCancelButtonOnLastPage);
+
+ QList<QWizard::WizardButton> buttonLayout;
+ buttonLayout << Stretch << FinishButton << CancelButton;
+ setButtonLayout(buttonLayout);
+}
+
+/* just plain don't allow rejection (Esc/F3/Cancel) */
+void ExecutorWizard::reject() {
+ return;
+}
diff --git a/ui/qt5/runner/executorwizard.hh b/ui/qt5/runner/executorwizard.hh
new file mode 100644
index 0000000..578f745
--- /dev/null
+++ b/ui/qt5/runner/executorwizard.hh
@@ -0,0 +1,29 @@
+/*
+ * executorwizard.cc - Implementation of the wizard class
+ * 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
+ */
+
+#ifndef EXECUTORWIZARD_HH
+#define EXECUTORWIZARD_HH
+
+#include <QWizard>
+
+class ExecutorWizard : public QWizard {
+public:
+ enum {
+ Page_Execute,
+ Page_Finished
+ };
+
+ ExecutorWizard(QWidget *parent = nullptr);
+ void reject();
+};
+
+#endif /* !EXECUTORWIZARD_HH */
diff --git a/ui/qt5/runner/finishedpage.cc b/ui/qt5/runner/finishedpage.cc
new file mode 100644
index 0000000..153f703
--- /dev/null
+++ b/ui/qt5/runner/finishedpage.cc
@@ -0,0 +1,17 @@
+/*
+ * finishedpage.cc - Implementation of the UI.Finish 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 "finishedpage.hh"
+
+FinishedPage::FinishedPage(QWidget *parent) : QWizardPage(parent) {
+ setTitle(tr("Adélie Linux Successfully Installed"));
+}
diff --git a/ui/qt5/runner/finishedpage.hh b/ui/qt5/runner/finishedpage.hh
new file mode 100644
index 0000000..4a97b28
--- /dev/null
+++ b/ui/qt5/runner/finishedpage.hh
@@ -0,0 +1,23 @@
+/*
+ * finishedpage.hh - Definition of the UI.Finish 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
+ */
+
+#ifndef FINISHEDPAGE_HH
+#define FINISHEDPAGE_HH
+
+#include <QWizardPage>
+
+class FinishedPage : public QWizardPage {
+public:
+ FinishedPage(QWidget *parent = nullptr);
+};
+
+#endif /* !FINISHEDPAGE_HH */
diff --git a/ui/qt5/runner/main.cc b/ui/qt5/runner/main.cc
new file mode 100644
index 0000000..bac429d
--- /dev/null
+++ b/ui/qt5/runner/main.cc
@@ -0,0 +1,39 @@
+/*
+ * main.cc - Implementation of the UI.Perform interface
+ * 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 <QApplication>
+#include <QIcon>
+#include <QLibraryInfo>
+#include <QTranslator>
+
+#include "executorwizard.hh"
+
+int main(int argc, char *argv[]) {
+ QApplication app(argc, argv);
+
+ QString translatorFileName = QLatin1String("qt_");
+ translatorFileName += QLocale::system().name();
+ QTranslator *translator = new QTranslator(&app);
+ if(translator->load(translatorFileName,
+ QLibraryInfo::location(
+ QLibraryInfo::TranslationsPath
+ ))) {
+ app.installTranslator(translator);
+ }
+
+ app.setWindowIcon(QIcon(":/horizon-256.png"));
+
+ ExecutorWizard wizard;
+ wizard.show();
+
+ return app.exec();
+}