summaryrefslogtreecommitdiff
path: root/crates/flasher-qt/src/ui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'crates/flasher-qt/src/ui.cpp')
-rw-r--r--crates/flasher-qt/src/ui.cpp404
1 files changed, 0 insertions, 404 deletions
diff --git a/crates/flasher-qt/src/ui.cpp b/crates/flasher-qt/src/ui.cpp
deleted file mode 100644
index 0af1987..0000000
--- a/crates/flasher-qt/src/ui.cpp
+++ /dev/null
@@ -1,404 +0,0 @@
-#include <QApplication>
-#include <QButtonGroup>
-#include <QCheckBox>
-#include <QComboBox>
-#include <QDialog>
-#include <QDialogButtonBox>
-#include <QFileDialog>
-#include <QFormLayout>
-#include <QFrame>
-#include <QGroupBox>
-#include <QHBoxLayout>
-#include <QLabel>
-#include <QLineEdit>
-#include <QMainWindow>
-#include <QMenuBar>
-#include <QMessageBox>
-#include <QPushButton>
-#include <QRadioButton>
-#include <QScrollArea>
-#include <QStatusBar>
-#include <QStyle>
-#include <QTreeWidget>
-#include <QVBoxLayout>
-
-namespace {
-
-struct Board {
- QString name;
- QString platform;
-};
-
-QVector<Board> parseBoards(const QString &text) {
- QVector<Board> boards;
- QString platform = QStringLiteral("Other");
- for (const QString &rawLine : text.split('\n')) {
- const QString line = rawLine.trimmed();
- if (line.isEmpty())
- continue;
- if (line.endsWith(':')) {
- platform = line.left(line.size() - 1);
- continue;
- }
- for (const QString &name : line.split(QRegExp(QStringLiteral("\\s+")), Qt::SkipEmptyParts))
- boards.push_back({name, platform});
- }
- return boards;
-}
-
-QLabel *description(const QString &text) {
- auto *label = new QLabel(text);
- label->setWordWrap(true);
- label->setForegroundRole(QPalette::Mid);
- return label;
-}
-
-QGroupBox *group(const QString &title, QLayout *layout) {
- auto *box = new QGroupBox(title);
- box->setLayout(layout);
- return box;
-}
-
-class BoardDialog final : public QDialog {
-public:
- explicit BoardDialog(const QVector<Board> &boards, QWidget *parent = nullptr)
- : QDialog(parent), boards_(boards) {
- setWindowTitle(tr("Select Target Board"));
- resize(620, 620);
- setModal(true);
-
- auto *layout = new QVBoxLayout(this);
- search_ = new QLineEdit;
- search_->setPlaceholderText(tr("Search boards, platforms, or architectures…"));
- search_->setClearButtonEnabled(true);
- tree_ = new QTreeWidget;
- tree_->setHeaderHidden(true);
- tree_->setRootIsDecorated(true);
- tree_->setAlternatingRowColors(true);
- tree_->setUniformRowHeights(true);
- layout->addWidget(search_);
- layout->addWidget(tree_, 1);
-
- auto *buttons = new QDialogButtonBox(QDialogButtonBox::Cancel);
- layout->addWidget(buttons);
- connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
- connect(search_, &QLineEdit::textChanged, this, [this](const QString &text) { populate(text); });
- connect(tree_, &QTreeWidget::itemActivated, this, [this](QTreeWidgetItem *item) {
- if (item && item->parent()) {
- selectedName_ = item->data(0, Qt::UserRole).toString();
- selectedPlatform_ = item->parent()->text(0);
- accept();
- }
- });
- populate({});
- }
-
- QString selectedName() const { return selectedName_; }
- QString selectedPlatform() const { return selectedPlatform_; }
-
-private:
- void populate(const QString &query) {
- tree_->clear();
- QMap<QString, QTreeWidgetItem *> headings;
- const QString needle = query.trimmed();
- for (const Board &board : boards_) {
- if (!needle.isEmpty() && !board.name.contains(needle, Qt::CaseInsensitive)
- && !board.platform.contains(needle, Qt::CaseInsensitive))
- continue;
- auto *&heading = headings[board.platform];
- if (!heading) {
- heading = new QTreeWidgetItem(tree_, {board.platform});
- QFont font = heading->font(0);
- font.setBold(true);
- heading->setFont(0, font);
- heading->setFlags(heading->flags() & ~Qt::ItemIsSelectable);
- }
- auto *item = new QTreeWidgetItem(heading, {board.name});
- item->setData(0, Qt::UserRole, board.name);
- }
- tree_->expandAll();
- if (!query.isEmpty() && tree_->topLevelItemCount() > 0) {
- auto *heading = tree_->topLevelItem(0);
- if (heading->childCount() > 0)
- tree_->setCurrentItem(heading->child(0));
- }
- }
-
- QVector<Board> boards_;
- QLineEdit *search_ = nullptr;
- QTreeWidget *tree_ = nullptr;
- QString selectedName_;
- QString selectedPlatform_;
-};
-
-class MainWindow final : public QMainWindow {
-public:
- MainWindow(const QString &boardsText, const QString &drivesText)
- : boards_(parseBoards(boardsText)) {
- setWindowTitle(tr("ALT Image Writer"));
- resize(780, 820);
- setMinimumSize(620, 600);
-
- auto *about = menuBar()->addMenu(tr("&Help"))->addAction(tr("&About"));
- connect(about, &QAction::triggered, this, [this] {
- QMessageBox::about(this, tr("About ALT Image Writer"),
- tr("<h3>ALT Image Writer</h3><p>Version 0.1.0</p>"
- "<p>Prepare ALT Linux installation media for supported "
- "single-board computers.</p>"));
- });
-
- auto *scroll = new QScrollArea;
- scroll->setWidgetResizable(true);
- scroll->setFrameShape(QFrame::NoFrame);
- setCentralWidget(scroll);
-
- auto *viewport = new QWidget;
- auto *outer = new QHBoxLayout(viewport);
- outer->setContentsMargins(20, 20, 20, 20);
- auto *content = new QWidget;
- content->setMaximumWidth(700);
- auto *layout = new QVBoxLayout(content);
- layout->setSpacing(16);
- outer->addStretch();
- outer->addWidget(content, 1);
- outer->addStretch();
- scroll->setWidget(viewport);
-
- auto *title = new QLabel(tr("Create Installation Media"));
- QFont titleFont = title->font();
- titleFont.setPointSize(titleFont.pointSize() + 7);
- titleFont.setBold(true);
- title->setFont(titleFont);
- title->setAlignment(Qt::AlignCenter);
- layout->addWidget(title);
- auto *intro = description(tr("Prepare an ALT Linux root filesystem or disk image for your board."));
- intro->setAlignment(Qt::AlignCenter);
- layout->addWidget(intro);
-
- createSource(layout);
- createHardware(layout);
- createDestination(layout, drivesText);
- createOptions(layout);
- layout->addStretch();
-
- auto *bar = new QWidget;
- auto *barLayout = new QHBoxLayout(bar);
- barLayout->setContentsMargins(12, 8, 12, 8);
- barLayout->addWidget(description(tr("Nothing will be written until you confirm.")), 1);
- writeButton_ = new QPushButton(tr("Review and Write"));
- writeButton_->setDefault(true);
- writeButton_->setEnabled(false);
- barLayout->addWidget(writeButton_);
- statusBar()->addPermanentWidget(bar, 1);
- connect(writeButton_, &QPushButton::clicked, this, [this] { review(); });
- }
-
-private:
- void createSource(QVBoxLayout *page) {
- auto *layout = new QVBoxLayout;
- layout->addWidget(description(tr("Choose a root filesystem archive or a ready-made disk image.")));
- auto *types = new QHBoxLayout;
- types->addWidget(new QLabel(tr("Source type")));
- types->addStretch();
- rootfsButton_ = new QRadioButton(tr("Root filesystem"));
- imageButton_ = new QRadioButton(tr("Disk image"));
- rootfsButton_->setChecked(true);
- types->addWidget(rootfsButton_);
- types->addWidget(imageButton_);
- layout->addLayout(types);
-
- auto *picker = new QHBoxLayout;
- sourceLabel_ = new QLabel(tr("No source selected"));
- sourceLabel_->setTextInteractionFlags(Qt::TextSelectableByMouse);
- auto *choose = new QPushButton(tr("Choose…"));
- choose->setIcon(style()->standardIcon(QStyle::SP_DialogOpenButton));
- picker->addWidget(sourceLabel_, 1);
- picker->addWidget(choose);
- layout->addLayout(picker);
- sourceHint_ = description(tr("Supported: .tar, .tar.gz, .tar.xz"));
- layout->addWidget(sourceHint_);
- page->addWidget(group(tr("Installation Source"), layout));
-
- connect(rootfsButton_, &QRadioButton::toggled, this, [this](bool checked) {
- if (checked) {
- sourceHint_->setText(tr("Supported: .tar, .tar.gz, .tar.xz"));
- fileOutputButton_->setEnabled(true);
- }
- });
- connect(imageButton_, &QRadioButton::toggled, this, [this](bool checked) {
- if (checked) {
- sourceHint_->setText(tr("Supported: .img, .img.xz"));
- driveOutputButton_->setChecked(true);
- fileOutputButton_->setEnabled(false);
- }
- });
- connect(choose, &QPushButton::clicked, this, [this] {
- const QString filter = imageButton_->isChecked()
- ? tr("Disk images (*.img *.img.xz);;All files (*)")
- : tr("Root filesystem archives (*.tar *.tar.gz *.tar.xz);;All files (*)");
- const QString path = QFileDialog::getOpenFileName(this, tr("Choose Installation Source"), {}, filter);
- if (!path.isEmpty()) {
- sourcePath_ = path;
- sourceLabel_->setText(QFileInfo(path).fileName());
- sourceLabel_->setToolTip(path);
- sourceHint_->setText(QFileInfo(path).absolutePath());
- updateReady();
- }
- });
- }
-
- void createHardware(QVBoxLayout *page) {
- auto *layout = new QVBoxLayout;
- layout->addWidget(description(tr("Boards are grouped by platform, SoC family, and architecture.")));
- auto *row = new QHBoxLayout;
- auto *labels = new QVBoxLayout;
- boardLabel_ = new QLabel(tr("No board selected"));
- boardHint_ = description(tr("Choose from %1 supported boards").arg(boards_.size()));
- labels->addWidget(boardLabel_);
- labels->addWidget(boardHint_);
- auto *select = new QPushButton(tr("Select Board…"));
- row->addLayout(labels, 1);
- row->addWidget(select);
- layout->addLayout(row);
- page->addWidget(group(tr("Target Hardware"), layout));
-
- connect(select, &QPushButton::clicked, this, [this] {
- BoardDialog dialog(boards_, this);
- if (dialog.exec() == QDialog::Accepted) {
- selectedBoard_ = dialog.selectedName();
- selectedPlatform_ = dialog.selectedPlatform();
- boardLabel_->setText(selectedBoard_);
- QFont font = boardLabel_->font();
- font.setBold(true);
- boardLabel_->setFont(font);
- boardHint_->setText(selectedPlatform_);
- updateReady();
- }
- });
- }
-
- void createDestination(QVBoxLayout *page, const QString &drivesText) {
- auto *layout = new QVBoxLayout;
- layout->addWidget(description(tr("Write to removable media or create an image file.")));
- auto *types = new QHBoxLayout;
- types->addWidget(new QLabel(tr("Output type")));
- types->addStretch();
- driveOutputButton_ = new QRadioButton(tr("Drive"));
- fileOutputButton_ = new QRadioButton(tr("Image file"));
- driveOutputButton_->setChecked(true);
- types->addWidget(driveOutputButton_);
- types->addWidget(fileOutputButton_);
- layout->addLayout(types);
-
- driveRow_ = new QWidget;
- auto *driveLayout = new QFormLayout(driveRow_);
- driveBox_ = new QComboBox;
- const QStringList drives = drivesText.split('\n', Qt::SkipEmptyParts);
- driveBox_->addItems(drives);
- if (drives.isEmpty()) {
- driveBox_->addItem(tr("No removable drives detected"));
- driveBox_->setEnabled(false);
- }
- driveLayout->addRow(tr("Storage device"), driveBox_);
- layout->addWidget(driveRow_);
-
- fileRow_ = new QWidget;
- auto *fileLayout = new QHBoxLayout(fileRow_);
- fileLayout->setContentsMargins(0, 0, 0, 0);
- outputLabel_ = new QLabel(tr("Choose where to save the image"));
- auto *choose = new QPushButton(tr("Choose…"));
- choose->setIcon(style()->standardIcon(QStyle::SP_DialogSaveButton));
- fileLayout->addWidget(outputLabel_, 1);
- fileLayout->addWidget(choose);
- fileRow_->hide();
- layout->addWidget(fileRow_);
- page->addWidget(group(tr("Destination"), layout));
-
- connect(driveOutputButton_, &QRadioButton::toggled, this, [this](bool checked) {
- driveRow_->setVisible(checked);
- fileRow_->setVisible(!checked);
- updateReady();
- });
- connect(choose, &QPushButton::clicked, this, [this] {
- const QString path = QFileDialog::getSaveFileName(this, tr("Create Disk Image"),
- QStringLiteral("alt-linux.img"), tr("Raw disk images (*.img);;All files (*)"));
- if (!path.isEmpty()) {
- outputPath_ = path;
- outputLabel_->setText(QFileInfo(path).fileName());
- outputLabel_->setToolTip(path);
- updateReady();
- }
- });
- }
-
- void createOptions(QVBoxLayout *page) {
- auto *layout = new QFormLayout;
- auto *filesystem = new QComboBox;
- filesystem->addItems({QStringLiteral("ext4"), QStringLiteral("f2fs")});
- layout->addRow(tr("Root filesystem"), filesystem);
- auto *resize = new QCheckBox(tr("Grow to fill the destination"));
- resize->setChecked(true);
- layout->addRow(tr("Resize root partition"), resize);
- layout->addRow(tr("Boot partition"), new QCheckBox(tr("Create a separate 512 MiB partition")));
- layout->addRow(tr("Encryption"), new QCheckBox(tr("Encrypt root partition with LUKS")));
- layout->addRow(tr("Serial console"), new QCheckBox(tr("Add to boot arguments")));
- auto *efi = new QComboBox;
- efi->addItems({tr("None"), tr("EFI (GPT)"), tr("EFI (MBR)")});
- layout->addRow(tr("EFI system partition"), efi);
- auto *vnc = new QComboBox;
- vnc->addItems({tr("Use image default"), tr("Enabled"), tr("Disabled")});
- layout->addRow(tr("First-boot VNC"), vnc);
- page->addWidget(group(tr("Options"), layout));
- }
-
- void updateReady() {
- const bool destination = driveOutputButton_->isChecked()
- ? driveBox_->isEnabled() && driveBox_->currentIndex() >= 0
- : !outputPath_.isEmpty();
- writeButton_->setEnabled(!sourcePath_.isEmpty() && !selectedBoard_.isEmpty() && destination);
- }
-
- void review() {
- const QString destination = driveOutputButton_->isChecked() ? driveBox_->currentText() : outputPath_;
- QMessageBox dialog(QMessageBox::Warning, tr("Ready to write?"),
- tr("Board: %1\nPlatform: %2\nDestination: %3\n\n"
- "This is an interface preview. No data will be written.")
- .arg(selectedBoard_, selectedPlatform_, destination),
- QMessageBox::Cancel | QMessageBox::Ok, this);
- dialog.setDefaultButton(QMessageBox::Cancel);
- dialog.button(QMessageBox::Ok)->setText(tr("Write"));
- if (dialog.exec() == QMessageBox::Ok)
- statusBar()->showMessage(tr("Flashing is not implemented in this preview"), 4000);
- }
-
- QVector<Board> boards_;
- QString sourcePath_;
- QString outputPath_;
- QString selectedBoard_;
- QString selectedPlatform_;
- QRadioButton *rootfsButton_ = nullptr;
- QRadioButton *imageButton_ = nullptr;
- QRadioButton *driveOutputButton_ = nullptr;
- QRadioButton *fileOutputButton_ = nullptr;
- QLabel *sourceLabel_ = nullptr;
- QLabel *sourceHint_ = nullptr;
- QLabel *boardLabel_ = nullptr;
- QLabel *boardHint_ = nullptr;
- QLabel *outputLabel_ = nullptr;
- QWidget *driveRow_ = nullptr;
- QWidget *fileRow_ = nullptr;
- QComboBox *driveBox_ = nullptr;
- QPushButton *writeButton_ = nullptr;
-};
-
-} // namespace
-
-extern "C" int run_qt_app(int argc, char **argv, const char *boards, const char *drives) {
- QApplication app(argc, argv);
- QCoreApplication::setApplicationName(QStringLiteral("ALT Image Writer"));
- QCoreApplication::setOrganizationName(QStringLiteral("ALT Linux"));
- QApplication::setWindowIcon(QApplication::style()->standardIcon(QStyle::SP_DriveHDIcon));
- MainWindow window(QString::fromUtf8(boards), QString::fromUtf8(drives));
- window.show();
- return app.exec();
-}