diff options
Diffstat (limited to 'crates/flasher-qt/src/ui.cpp')
| -rw-r--r-- | crates/flasher-qt/src/ui.cpp | 404 |
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(); -} |