Skip to content

Commit

Permalink
Allow to manually add a LoadOption
Browse files Browse the repository at this point in the history
  • Loading branch information
Inokinoki committed May 4, 2022
1 parent cd459df commit 5e5f2b2
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 14 deletions.
110 changes: 108 additions & 2 deletions qefientryview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
#include <QSaveFile>
#include <QInputDialog>
#include <QSpinBox>
#include <QDialogButtonBox>

#include "qefientrydetailview.h"
#include "qefiloadoptioneditorview.h"

#if QT_VERSION >= QT_VERSION_CHECK(5,14,0)
// Fix namsapce change of hex and dec
Expand Down Expand Up @@ -76,13 +78,17 @@ QEFIEntryView::QEFIEntryView(QWidget *parent)

m_bootTimeoutLabel = new QLabel(QString::asprintf("Timeout: %d second(s)",
QEFIEntryStaticList::instance()->timeout()), this);
m_addButton = new QPushButton(QStringLiteral("Add"), this);
m_importButton = new QPushButton(QStringLiteral("Import"), this);
m_saveButton = new QPushButton(QStringLiteral("Save"), this);
m_resetButton = new QPushButton(QStringLiteral("Reset"), this);
m_buttonLayout->addWidget(m_bootTimeoutLabel);
m_buttonLayout->addWidget(m_addButton);
m_buttonLayout->addWidget(m_importButton);
m_buttonLayout->addWidget(m_saveButton);
m_buttonLayout->addWidget(m_resetButton);
QObject::connect(m_addButton, &QPushButton::clicked,
this, &QEFIEntryView::addClicked);
QObject::connect(m_importButton, &QPushButton::clicked,
this, &QEFIEntryView::importClicked);
QObject::connect(m_saveButton, &QPushButton::clicked,
Expand Down Expand Up @@ -116,6 +122,7 @@ QEFIEntryView::~QEFIEntryView()
if (m_rebootTargetButton != nullptr) m_rebootTargetButton->deleteLater();
if (m_bootTimeoutLabel != nullptr) m_bootTimeoutLabel->deleteLater();
if (m_importButton != nullptr) m_importButton->deleteLater();
if (m_addButton != nullptr) m_addButton->deleteLater();
}

void QEFIEntryView::entryChanged(int currentRow)
Expand Down Expand Up @@ -357,8 +364,8 @@ void QEFIEntryView::contextMenuEvent(QContextMenuEvent *event)
menu.addSeparator();
}
}
// TODO: Allow to add new one
// menu.addAction(QStringLiteral("Add"));
connect(menu.addAction(QStringLiteral("Add")), &QAction::triggered,
this, &QEFIEntryView::addClicked);

connect(menu.addAction(QStringLiteral("Import")), &QAction::triggered,
this, &QEFIEntryView::importClicked);
Expand Down Expand Up @@ -445,3 +452,102 @@ void QEFIEntryView::importClicked(bool checked)
m_selectedItemIndex = -1;
resetClicked(false);
}

class BootEntryEditorDialog : public QDialog
{
QEFILoadOptionEditorView *m_view;
QBoxLayout *m_topLevelLayout;
QDialogButtonBox *m_buttonBox;

quint16 m_bootID;
QByteArray m_loadOptionData;
public:
BootEntryEditorDialog(QWidget *parent = nullptr)
: QDialog(parent)
{
m_view = new QEFILoadOptionEditorView(nullptr, this);
setWindowTitle(QStringLiteral("Add EFI Boot Entry"));
m_topLevelLayout = new QBoxLayout(QBoxLayout::Down, this);
m_topLevelLayout->addWidget(m_view);

m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok |
QDialogButtonBox::Cancel);
m_topLevelLayout->addWidget(m_buttonBox);

connect(m_buttonBox, &QDialogButtonBox::accepted,
this, &BootEntryEditorDialog::onAccept);
connect(m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
}

quint16 bootID() const { return m_bootID; }
QByteArray loadOptionData() const { return m_loadOptionData; }

~BootEntryEditorDialog()
{
if (m_topLevelLayout) m_topLevelLayout->deleteLater();
if (m_view) m_view->deleteLater();
if (m_buttonBox) m_buttonBox->deleteLater();
}

public slots:
void onAccept() {
// Init the class from the view
if (m_view != nullptr) {
m_bootID = m_view->getBootEntryID();
m_loadOptionData = m_view->generateLoadOption();
qDebug() << "Will add Boot Entry " << m_bootID << m_loadOptionData;
}
accept();
}
};

void QEFIEntryView::addClicked(bool checked)
{
Q_UNUSED(checked);
BootEntryEditorDialog dialog(this);
if (dialog.exec() == QDialog::Rejected) return;

// Get Load Option and add it
quint16 bootID = dialog.bootID();
QByteArray data = dialog.loadOptionData();
if (data.size() == 0) {
// Error
QMessageBox::warning(this, QStringLiteral("Add failed"),
QStringLiteral("Data might be invalidated."));
}

// Parse using a QEFILoadOption
QEFILoadOption loadOption(data);
if (!loadOption.isValidated()) {
// Show a warning and stop
QMessageBox::warning(this, QStringLiteral("Add failed"),
QStringLiteral("Data are invalidated."));
return;
}

bool orderFound = m_order.contains(bootID);
if (orderFound) {
// Override: Show a confirmation
if (QMessageBox::question(this, QStringLiteral("Add"),
QString::asprintf("Do you want to override Boot%04X?", bootID)) ==
QMessageBox::No) {
// Show a warning and stop
QMessageBox::warning(this, QStringLiteral("Add failed"),
QStringLiteral("The action is cancelled."));
return;
}
}

if (!QEFIEntryStaticList::instance()->updateBootEntry(bootID, data)) {
// Show a warning and stop
QMessageBox::warning(this, QStringLiteral("Add failed"),
QStringLiteral("Data might be invalidated."));
return;
}

// Check and update the list
if (!orderFound) m_order.append(bootID);
m_entryItems = QEFIEntryStaticList::instance()->entries();
m_selectedItemIndex = -1;
resetClicked(false);
}
2 changes: 2 additions & 0 deletions qefientryview.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ class QEFIEntryView: public QWidget
QPushButton *m_saveButton;
QPushButton *m_resetButton;
QPushButton *m_rebootTargetButton;
QPushButton *m_addButton;

QLabel *m_bootTimeoutLabel;

Expand Down Expand Up @@ -57,6 +58,7 @@ public slots:
void importClicked(bool checked);
void exportClicked(bool checked);
void deleteClicked(bool checked);
void addClicked(bool checked);

void moveUpClicked(bool checked);
void moveDownClicked(bool checked);
Expand Down
55 changes: 43 additions & 12 deletions qefiloadoptioneditorview.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "qefiloadoptioneditorview.h"
#include "qefidpeditorview.h"

#include <QDebug>
#include <QDialog>

class EditorDialog : public QDialog
Expand All @@ -13,7 +14,7 @@ class EditorDialog : public QDialog
{
m_view = new QEFIDPEditorView(nullptr, this);
setWindowTitle(QStringLiteral("Add Device Path"));
m_topLevelLayout = new QBoxLayout(QBoxLayout::LeftToRight, this);
m_topLevelLayout = new QBoxLayout(QBoxLayout::Down, this);
m_topLevelLayout->addWidget(m_view);
}

Expand All @@ -29,17 +30,21 @@ QEFILoadOptionEditorView::QEFILoadOptionEditorView(QEFILoadOption *option, QWidg
{
m_topLevelLayout = new QFormLayout(this);

QSpinBox *idSpinBox = new QSpinBox(this);
idSpinBox->setMinimum(0);
idSpinBox->setMaximum(0xFFFF);
idSpinBox->setDisplayIntegerBase(16);
m_idSpinBox = new QSpinBox(this);
m_idSpinBox->setMinimum(0);
m_idSpinBox->setMaximum(0xFFFF);
m_idSpinBox->setValue(0x1000);
m_idSpinBox->setSingleStep(1);
m_idSpinBox->setDisplayIntegerBase(16);

m_topLevelLayout->addRow(QStringLiteral("ID:"), idSpinBox);
m_topLevelLayout->addRow(QStringLiteral("Name:"), new QLineEdit(option == nullptr ?
QStringLiteral("") : option->name(), this));
m_topLevelLayout->addRow(QStringLiteral("Optional Data:"),
new QLineEdit(option == nullptr ? QStringLiteral("") :
QString(option->optionalData().toHex()), this));
m_topLevelLayout->addRow(QStringLiteral("ID:"), m_idSpinBox);
m_nameTextEdit = new QLineEdit(option == nullptr ? QStringLiteral("") :
option->name(), this);
m_topLevelLayout->addRow(QStringLiteral("Name:"), m_nameTextEdit);
m_optionalDataTextEdit = new QLineEdit(option == nullptr ? QStringLiteral("") :
QString(option->optionalData().toHex()), this);
m_topLevelLayout->addRow(QStringLiteral("Optional Data:"), m_optionalDataTextEdit);
#define DP_BEGIN_INDEX 3
QPushButton *button = new QPushButton(QStringLiteral("Add Device Path"), this);
m_topLevelLayout->addRow(QStringLiteral(""), button);
connect(button, &QPushButton::clicked,
Expand All @@ -54,12 +59,38 @@ QEFILoadOptionEditorView::~QEFILoadOptionEditorView()
m_topLevelLayout->deleteLater();
m_topLevelLayout = nullptr;
}
if (m_idSpinBox != nullptr) m_idSpinBox->deleteLater();
}

void QEFILoadOptionEditorView::createDPClicked(bool checked)
{
Q_UNUSED(checked);
EditorDialog dialog(this);
dialog.exec();
if (dialog.exec() == QDialog::Rejected) return;
// TODO: Get Device Path and add it
}

QByteArray QEFILoadOptionEditorView::generateLoadOption()
{
QByteArray data;
if (m_nameTextEdit == nullptr) return data;
if (m_optionalDataTextEdit == nullptr) return data;

QEFILoadOption newLoadOption(data);
newLoadOption.setIsVisible(true);
newLoadOption.setName(m_nameTextEdit->text());
QByteArray optionalData = QByteArray::fromHex(
m_optionalDataTextEdit->text().toLatin1());
// Check format
if (optionalData.size() * 2 != m_optionalDataTextEdit->text().length()) return data;
newLoadOption.setOptionalData(optionalData);
// TODO: Format DPs

return newLoadOption.format();
}

quint16 QEFILoadOptionEditorView::getBootEntryID()
{
if (m_idSpinBox == nullptr) return 0;
return (quint16)(m_idSpinBox->value() & 0xFFFF);
}
8 changes: 8 additions & 0 deletions qefiloadoptioneditorview.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include <QLabel>
#include <QLineEdit>
#include <QPushButton>
#include <QSpinBox>

#include <qefi.h>

Expand All @@ -16,11 +17,18 @@ class QEFILoadOptionEditorView: public QWidget

QFormLayout *m_topLevelLayout;

QSpinBox *m_idSpinBox;
QLineEdit *m_nameTextEdit;
QLineEdit *m_optionalDataTextEdit;

public:
QEFILoadOptionEditorView(QEFILoadOption *option = nullptr,
QWidget *parent = nullptr);
~QEFILoadOptionEditorView();

QByteArray generateLoadOption();
quint16 getBootEntryID();

public slots:
void createDPClicked(bool checked);
};
Expand Down

0 comments on commit 5e5f2b2

Please sign in to comment.