Add validation to the new project wizard

This commit is contained in:
Gary Talent 2017-04-20 18:35:14 -05:00
parent 681eb55db3
commit 9730ef773e
6 changed files with 237 additions and 63 deletions

View File

@ -9,17 +9,21 @@ add_library(
NostalgiaStudio NostalgiaStudio
SHARED SHARED
newwizard.cpp newwizard.cpp
project.cpp
) )
target_link_libraries( target_link_libraries(
NostalgiaStudio NostalgiaStudio
Qt5::Core Qt5::Core
Qt5::Widgets Qt5::Widgets
${OxFS_LIBRARY}
${OxStd_LIBRARY}
) )
install( install(
FILES FILES
newwizard.hpp newwizard.hpp
project.hpp
DESTINATION DESTINATION
include/nostalgia/studio/lib include/nostalgia/studio/lib
) )

View File

@ -6,7 +6,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
#include <iostream> #include <QFileDialog>
#include <QHBoxLayout> #include <QHBoxLayout>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
@ -18,16 +18,22 @@
namespace nostalgia { namespace nostalgia {
namespace studio { namespace studio {
using namespace std;
WizardSelect::WizardSelect() { WizardSelect::WizardSelect() {
m_listWidget = new QListWidget(this); m_listWidget = new QListWidget(this);
auto layout = new QVBoxLayout(this); auto layout = new QVBoxLayout(this);
layout->addWidget(m_listWidget); layout->addWidget(m_listWidget);
setLayout(layout); setLayout(layout);
connect(m_listWidget, &QListWidget::activated, this, &WizardSelect::itemSelected); connect(m_listWidget, &QListWidget::currentRowChanged, this, &WizardSelect::itemSelected);
connect(m_listWidget, &QListWidget::clicked, this, &WizardSelect::itemSelected); connect(m_listWidget, &QListWidget::itemSelectionChanged, [this]() {
m_complete = true;
emit completeChanged();
}
);
connect(m_listWidget, &QListWidget::doubleClicked, [this]() {
wizard()->next();
}
);
} }
void WizardSelect::initializePage() { void WizardSelect::initializePage() {
@ -44,80 +50,174 @@ bool WizardSelect::isComplete() const {
return m_complete; return m_complete;
} }
bool WizardSelect::isFinalPage() const {
return false;
}
int WizardSelect::nextId() const { int WizardSelect::nextId() const {
return m_nextId; return m_nextId;
} }
void WizardSelect::itemSelected(const QModelIndex &idx) { void WizardSelect::itemSelected(int row) {
m_complete = true; if (row > -1) {
auto w = wizard(); auto w = wizard();
if (nextId() > -1) { if (nextId() > -1) {
w->removePage(nextId()); w->removePage(nextId());
m_nextId = -1; m_nextId = -1;
} }
auto selected = m_listWidget->currentItem()->text(); auto selected = m_listWidget->currentItem()->text();
if (m_options.contains(selected)) { if (m_options.contains(selected)) {
m_nextId = w->addPage(m_options[selected]()); m_nextId = w->addPage(m_options[selected]());
// for some reason the continue button only appears correctly after remove runs // for some reason the continue button only appears correctly after remove runs
w->removePage(nextId()); w->removePage(nextId());
m_nextId = w->addPage(m_options[selected]()); m_nextId = w->addPage(m_options[selected]());
}
} }
} }
WizardFormPage::WizardFormPage() {
Wizard::FormPage::FormPage() {
m_layout = new QGridLayout(this); m_layout = new QGridLayout(this);
m_layout->setColumnMinimumWidth(0, 20); m_layout->setColumnMinimumWidth(0, 20);
this->setLayout(m_layout); this->setLayout(m_layout);
} }
Wizard::FormPage::~FormPage() { WizardFormPage::~WizardFormPage() {
for (auto l : m_subLayout) { for (auto l : m_subLayout) {
delete l; delete l;
} }
} }
void Wizard::FormPage::addLineEdit(QString displayName, QString fieldName) { void WizardFormPage::initializePage() {
for (auto it = m_fields.begin(); it != m_fields.end(); it++) {
auto key = it.key();
auto le = m_fields[key].lineEdit;
auto defaultVal = it.value().defaultValue;
if (le) {
le->setText(defaultVal);
}
}
}
bool WizardFormPage::validatePage() {
bool retval = true;
// check validators
for (auto f : m_fields) {
if (f.validator != nullptr) {
if (f.validator(f.lineEdit->text()) != 0) {
retval = false;
break;
}
}
}
// clear error
if (retval) {
showValidationError("");
}
return retval;
}
void WizardFormPage::addLineEdit(QString displayName, QString fieldName, QString defaultVal) {
auto lbl = new QLabel(displayName, this); auto lbl = new QLabel(displayName, this);
auto le = new QLineEdit(this); auto le = new QLineEdit(this);
lbl->setBuddy(le); lbl->setBuddy(le);
m_layout->addWidget(lbl, currentLine, 0); m_layout->addWidget(lbl, m_currentLine, 0);
m_layout->addWidget(le, currentLine, 1); m_layout->addWidget(le, m_currentLine, 1);
m_fields[fieldName].defaultValue = defaultVal;
m_fields[fieldName].lineEdit = le;
registerField(fieldName, le); registerField(fieldName, le);
currentLine++; connect(le, &QLineEdit::textChanged, [this, fieldName, le](QString txt) {
if (m_fields[fieldName].value == "" && txt != "") {
m_validFields++;
} else if (m_fields[fieldName].value != "" && txt == "") {
m_validFields--;
}
m_fields[fieldName].value = txt;
emit completeChanged();
}
);
m_currentLine++;
} }
void Wizard::FormPage::addFileBrowse(QString displayName, QString fieldName, QString defaultVal) { void WizardFormPage::addDirBrowse(QString displayName, QString fieldName, QString defaultVal) {
auto layout = new QHBoxLayout(); auto layout = new QHBoxLayout();
auto lbl = new QLabel(displayName, this); auto lbl = new QLabel(displayName, this);
auto le = new QLineEdit(this); auto le = new QLineEdit("", this);
auto btn = new QPushButton("Browse...", this); auto btn = new QPushButton("Browse...", this);
lbl->setBuddy(le); lbl->setBuddy(le);
layout->addWidget(le); layout->addWidget(le);
layout->addWidget(btn); layout->addWidget(btn);
m_layout->addWidget(lbl, currentLine, 0); m_layout->addWidget(lbl, m_currentLine, 0);
m_layout->addLayout(layout, currentLine, 1); m_layout->addLayout(layout, m_currentLine, 1);
m_subLayout.push_back(layout); m_subLayout.push_back(layout);
m_fields[fieldName].defaultValue = defaultVal;
m_fields[fieldName].lineEdit = le;
m_fields[fieldName].validator = [this](QString path) {
if (!QDir(path).exists()) {
showValidationError(tr("Specified Project Path directory does not exist."));
return 1;
} else {
return 0;
}
};
registerField(fieldName, le); registerField(fieldName, le);
currentLine++; connect(le, &QLineEdit::textChanged, [this, fieldName, le](QString txt) {
if (m_fields[fieldName].value == "" && txt != "") {
m_validFields++;
} else if (m_fields[fieldName].value != "" && txt == "") {
m_validFields--;
}
m_fields[fieldName].value = txt;
emit completeChanged();
}
);
connect(btn, &QPushButton::clicked, [this, defaultVal, le]() {
auto p = QFileDialog::getExistingDirectory(this, tr("Select Directory..."), defaultVal);
if (p != "") {
le->setText(p);
}
}
);
m_currentLine++;
}
void WizardFormPage::showValidationError(QString msg) {
// create label if it is null
if (!m_errorMsg) {
m_errorMsg = new QLabel(this);
m_layout->addWidget(m_errorMsg, m_currentLine, 0, m_currentLine, 2);
// set text color
auto pal = m_errorMsg->palette();
pal.setColor(m_errorMsg->backgroundRole(), Qt::red);
pal.setColor(m_errorMsg->foregroundRole(), Qt::red);
m_errorMsg->setPalette(pal);
}
// set message
if (msg != "") {
m_errorMsg->setText(tr("Error: ") + msg);
} else {
m_errorMsg->setText("");
}
} }
Wizard::Wizard(QWidget *parent): QWizard(parent) { Wizard::Wizard(QWidget *parent): QWizard(parent) {
setWindowTitle(tr("New...")); setWindowTitle(tr("New..."));
setModal(true);
} }
} }

View File

@ -9,7 +9,9 @@
#pragma once #pragma once
#include <functional> #include <functional>
#include <QDir>
#include <QGridLayout> #include <QGridLayout>
#include <QLabel>
#include <QListWidget> #include <QListWidget>
#include <QMap> #include <QMap>
#include <QVector> #include <QVector>
@ -30,41 +32,54 @@ class WizardSelect: public QWizardPage {
public: public:
WizardSelect(); WizardSelect();
void initializePage();
void addOption(QString name, std::function<QWizardPage*()> makePage); void addOption(QString name, std::function<QWizardPage*()> makePage);
bool isComplete() const; void initializePage() override;
bool isFinalPage() const; bool isComplete() const override;
int nextId() const; int nextId() const override;
private slots: private slots:
void itemSelected(const QModelIndex &idx); void itemSelected(int row);
};
class WizardFormPage: public QWizardPage {
Q_OBJECT
private:
struct Field {
QString defaultValue = "";
QString value = "";
QLineEdit *lineEdit = nullptr;
std::function<int(QString)> validator;
};
QLabel *m_errorMsg = nullptr;
QGridLayout *m_layout = nullptr;
QVector<QLayout*> m_subLayout;
QMap<QString, Field> m_fields;
int m_currentLine = 0;
int m_validFields = 0;
public:
WizardFormPage();
~WizardFormPage();
void initializePage() override;
bool validatePage() override;
void addLineEdit(QString displayName, QString fieldName, QString defaultVal = "");
void addDirBrowse(QString displayName, QString fieldName, QString defaultVal = QDir::homePath());
void showValidationError(QString msg);
}; };
class Wizard: public QWizard { class Wizard: public QWizard {
Q_OBJECT Q_OBJECT
public:
class FormPage: public QWizardPage {
private:
QGridLayout *m_layout = nullptr;
QVector<QLayout*> m_subLayout;
int currentLine = 0;
public:
FormPage();
~FormPage();
void addLineEdit(QString displayName, QString fieldName);
void addFileBrowse(QString displayName, QString fieldName, QString defaultVal = "");
};
public: public:
Wizard(QWidget *parent = 0); Wizard(QWidget *parent = 0);
}; };

View File

@ -0,0 +1,33 @@
/*
* Copyright 2016-2017 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#include <QByteArray>
#include <QDir>
#include <ox/fs/filesystem.hpp>
#include <project.hpp>
namespace nostalgia {
namespace studio {
using namespace ox::fs;
void Project::create(QString path) {
QDir().mkpath(path);
size_t buffLen = 1024;
m_romBuff = new QByteArray(buffLen, 0);
FileSystem32::format(m_romBuff->data(), buffLen, true);
QFile file(path + "/ROM.oxfs");
file.open(QIODevice::WriteOnly);
file.write(*m_romBuff);
file.close();
}
}
}

View File

@ -0,0 +1,25 @@
/*
* Copyright 2016-2017 gtalent2@gmail.com
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#pragma once
namespace nostalgia {
namespace studio {
class Project: public QObject {
Q_OBJECT
private:
QByteArray *m_romBuff = nullptr;
public:
void create(QString path);
};
}
}

View File

@ -6,7 +6,6 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. * file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/ */
#include <iostream>
#include <QApplication> #include <QApplication>
#include <QDesktopWidget> #include <QDesktopWidget>
#include <QDialog> #include <QDialog>
@ -20,8 +19,6 @@
namespace nostalgia { namespace nostalgia {
namespace studio { namespace studio {
using namespace std;
MainWindow::MainWindow(NostalgiaStudioProfile config, QWidget *parent) { MainWindow::MainWindow(NostalgiaStudioProfile config, QWidget *parent) {
auto screenSize = QApplication::desktop()->screenGeometry(); auto screenSize = QApplication::desktop()->screenGeometry();
@ -93,9 +90,9 @@ void MainWindow::showNewWizard() {
auto ws = new WizardSelect(); auto ws = new WizardSelect();
wizard.addPage(ws); wizard.addPage(ws);
ws->addOption(tr("Project"), []() { ws->addOption(tr("Project"), []() {
auto pg = new Wizard::FormPage(); auto pg = new WizardFormPage();
pg->addLineEdit(tr("Project &Name"), "projectName"); pg->addLineEdit(tr("Project &Name:"), "projectName*");
pg->addFileBrowse(tr("Project &Path"), "projectPath"); pg->addDirBrowse(tr("Project &Path:"), "projectPath*");
return pg; return pg;
} }
); );