diff --git a/src/studio/lib/CMakeLists.txt b/src/studio/lib/CMakeLists.txt index 03843aadc..aa69c9844 100644 --- a/src/studio/lib/CMakeLists.txt +++ b/src/studio/lib/CMakeLists.txt @@ -9,17 +9,21 @@ add_library( NostalgiaStudio SHARED newwizard.cpp + project.cpp ) target_link_libraries( NostalgiaStudio Qt5::Core Qt5::Widgets + ${OxFS_LIBRARY} + ${OxStd_LIBRARY} ) install( FILES newwizard.hpp + project.hpp DESTINATION include/nostalgia/studio/lib ) diff --git a/src/studio/lib/newwizard.cpp b/src/studio/lib/newwizard.cpp index 06db3431d..afd2ff733 100644 --- a/src/studio/lib/newwizard.cpp +++ b/src/studio/lib/newwizard.cpp @@ -6,7 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include +#include #include #include #include @@ -18,16 +18,22 @@ namespace nostalgia { namespace studio { -using namespace std; - WizardSelect::WizardSelect() { m_listWidget = new QListWidget(this); auto layout = new QVBoxLayout(this); layout->addWidget(m_listWidget); setLayout(layout); - connect(m_listWidget, &QListWidget::activated, this, &WizardSelect::itemSelected); - connect(m_listWidget, &QListWidget::clicked, this, &WizardSelect::itemSelected); + connect(m_listWidget, &QListWidget::currentRowChanged, 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() { @@ -44,80 +50,174 @@ bool WizardSelect::isComplete() const { return m_complete; } -bool WizardSelect::isFinalPage() const { - return false; -} - int WizardSelect::nextId() const { return m_nextId; } -void WizardSelect::itemSelected(const QModelIndex &idx) { - m_complete = true; - auto w = wizard(); +void WizardSelect::itemSelected(int row) { + if (row > -1) { + auto w = wizard(); - if (nextId() > -1) { - w->removePage(nextId()); - m_nextId = -1; - } + if (nextId() > -1) { + w->removePage(nextId()); + m_nextId = -1; + } - auto selected = m_listWidget->currentItem()->text(); - if (m_options.contains(selected)) { - m_nextId = w->addPage(m_options[selected]()); - // for some reason the continue button only appears correctly after remove runs - w->removePage(nextId()); - m_nextId = w->addPage(m_options[selected]()); + auto selected = m_listWidget->currentItem()->text(); + if (m_options.contains(selected)) { + m_nextId = w->addPage(m_options[selected]()); + // for some reason the continue button only appears correctly after remove runs + w->removePage(nextId()); + m_nextId = w->addPage(m_options[selected]()); + } } } - -Wizard::FormPage::FormPage() { +WizardFormPage::WizardFormPage() { m_layout = new QGridLayout(this); m_layout->setColumnMinimumWidth(0, 20); this->setLayout(m_layout); } -Wizard::FormPage::~FormPage() { +WizardFormPage::~WizardFormPage() { for (auto l : m_subLayout) { 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 le = new QLineEdit(this); lbl->setBuddy(le); - m_layout->addWidget(lbl, currentLine, 0); - m_layout->addWidget(le, currentLine, 1); + m_layout->addWidget(lbl, m_currentLine, 0); + m_layout->addWidget(le, m_currentLine, 1); + + m_fields[fieldName].defaultValue = defaultVal; + m_fields[fieldName].lineEdit = 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 lbl = new QLabel(displayName, this); - auto le = new QLineEdit(this); + auto le = new QLineEdit("", this); auto btn = new QPushButton("Browse...", this); lbl->setBuddy(le); layout->addWidget(le); layout->addWidget(btn); - m_layout->addWidget(lbl, currentLine, 0); - m_layout->addLayout(layout, currentLine, 1); + m_layout->addWidget(lbl, m_currentLine, 0); + m_layout->addLayout(layout, m_currentLine, 1); 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); - 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) { setWindowTitle(tr("New...")); + setModal(true); } } diff --git a/src/studio/lib/newwizard.hpp b/src/studio/lib/newwizard.hpp index 46ae5b4ef..bb12542ed 100644 --- a/src/studio/lib/newwizard.hpp +++ b/src/studio/lib/newwizard.hpp @@ -9,7 +9,9 @@ #pragma once #include +#include #include +#include #include #include #include @@ -30,41 +32,54 @@ class WizardSelect: public QWizardPage { public: WizardSelect(); - void initializePage(); - void addOption(QString name, std::function makePage); - bool isComplete() const; + void initializePage() override; - bool isFinalPage() const; + bool isComplete() const override; - int nextId() const; + int nextId() const override; 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 validator; + }; + QLabel *m_errorMsg = nullptr; + QGridLayout *m_layout = nullptr; + QVector m_subLayout; + QMap 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 { Q_OBJECT - public: - class FormPage: public QWizardPage { - private: - QGridLayout *m_layout = nullptr; - QVector m_subLayout; - int currentLine = 0; - - public: - FormPage(); - - ~FormPage(); - - void addLineEdit(QString displayName, QString fieldName); - - void addFileBrowse(QString displayName, QString fieldName, QString defaultVal = ""); - }; - public: Wizard(QWidget *parent = 0); }; diff --git a/src/studio/lib/project.cpp b/src/studio/lib/project.cpp new file mode 100644 index 000000000..2bb756bd0 --- /dev/null +++ b/src/studio/lib/project.cpp @@ -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 +#include +#include +#include + +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(); +} + +} +} diff --git a/src/studio/lib/project.hpp b/src/studio/lib/project.hpp new file mode 100644 index 000000000..61bcf3fca --- /dev/null +++ b/src/studio/lib/project.hpp @@ -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); +}; + +} +} diff --git a/src/studio/mainwindow.cpp b/src/studio/mainwindow.cpp index 71c0feb76..aca63aa29 100644 --- a/src/studio/mainwindow.cpp +++ b/src/studio/mainwindow.cpp @@ -6,7 +6,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ -#include #include #include #include @@ -20,8 +19,6 @@ namespace nostalgia { namespace studio { -using namespace std; - MainWindow::MainWindow(NostalgiaStudioProfile config, QWidget *parent) { auto screenSize = QApplication::desktop()->screenGeometry(); @@ -93,9 +90,9 @@ void MainWindow::showNewWizard() { auto ws = new WizardSelect(); wizard.addPage(ws); ws->addOption(tr("Project"), []() { - auto pg = new Wizard::FormPage(); - pg->addLineEdit(tr("Project &Name"), "projectName"); - pg->addFileBrowse(tr("Project &Path"), "projectPath"); + auto pg = new WizardFormPage(); + pg->addLineEdit(tr("Project &Name:"), "projectName*"); + pg->addDirBrowse(tr("Project &Path:"), "projectPath*"); return pg; } );