From 631f37ee26c19d38408ee733ffda24ad283c7921 Mon Sep 17 00:00:00 2001 From: Nao Pross Date: Tue, 19 Dec 2017 22:47:05 +0100 Subject: Implement basic ui Changes: - Clean up code to use Qt coding style - Add comments to some methods - Add debugtools to have debug_msg() and debug_err() macros - New Serializer class header to save / load data - MetadataDialog: check validity of metadata - MainWindow: initial code for `tool' buttons to edit the structogram - MainWindow: open / save dialog --- OrbitingYeti.pro | 7 ++- README.md | 7 +-- forms/mainwindow.ui | 80 ++++++++++++++++++++++++- forms/metadatadialog.ui | 25 ++++---- include/debugtools.h | 27 +++++++++ include/diagram/branchstatement.h | 4 +- include/diagram/iteratorstatement.h | 4 +- include/diagram/structogram.h | 10 +++- include/io/serializer.h | 18 ++++++ include/ui/mainwindow.h | 8 ++- include/ui/metadatadialog.h | 6 ++ src/diagram/scope.cpp | 9 +-- src/io/serializer.cpp | 11 ++++ src/ui/mainwindow.cpp | 115 ++++++++++++++++++++++++++++++------ src/ui/metadatadialog.cpp | 45 ++++++++++++++ 15 files changed, 323 insertions(+), 53 deletions(-) create mode 100644 include/debugtools.h create mode 100644 include/io/serializer.h create mode 100644 src/io/serializer.cpp diff --git a/OrbitingYeti.pro b/OrbitingYeti.pro index 2353696..7351c0c 100644 --- a/OrbitingYeti.pro +++ b/OrbitingYeti.pro @@ -33,7 +33,8 @@ SOURCES += \ src/diagram/statement.cpp \ src/diagram/structogram.cpp \ src/ui/metadatadialog.cpp \ - src/ui/painter.cpp + src/ui/painter.cpp \ + src/io/serializer.cpp HEADERS += \ include/ui/mainwindow.h \ @@ -43,7 +44,9 @@ HEADERS += \ include/diagram/iteratorstatement.h \ include/diagram/branchstatement.h \ include/ui/metadatadialog.h \ - include/ui/painter.h + include/ui/painter.h \ + include/debugtools.h \ + include/io/serializer.h FORMS += \ forms/mainwindow.ui \ diff --git a/README.md b/README.md index 911a52f..bd18385 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,4 @@ # OrbitingYeti: a tool to write Nassi-Schneidermann diagrams -## TO DO list / Roadmap - -- [ ] Structogram data structure -- [ ] GUI with Qt5 -- [ ] PDF Generator +## Coding style +[https://wiki.qt.io/Qt_Coding_Style] diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui index 86d6381..23125a1 100644 --- a/forms/mainwindow.ui +++ b/forms/mainwindow.ui @@ -165,7 +165,7 @@ - + @@ -255,11 +255,20 @@ + + true + PDF + + Ctrl+E + + + true + LaTeX TikZ @@ -280,7 +289,7 @@ Ctrl+V - + Save As @@ -327,5 +336,70 @@ - + + + actionNew + triggered() + newButton + click() + + + -1 + -1 + + + 23 + 53 + + + + + actionSave + triggered() + saveButton + click() + + + -1 + -1 + + + 99 + 53 + + + + + actionOpen + triggered() + openButton + click() + + + -1 + -1 + + + 61 + 53 + + + + + actionQuit + triggered() + MainWindow + close() + + + -1 + -1 + + + 411 + 300 + + + + diff --git a/forms/metadatadialog.ui b/forms/metadatadialog.ui index 070242e..62fca5c 100644 --- a/forms/metadatadialog.ui +++ b/forms/metadatadialog.ui @@ -11,19 +11,9 @@ - Set metadata + Metadata - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - @@ -44,6 +34,19 @@ + + + + true + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + diff --git a/include/debugtools.h b/include/debugtools.h new file mode 100644 index 0000000..cd6940b --- /dev/null +++ b/include/debugtools.h @@ -0,0 +1,27 @@ +#ifndef DEBUGTOOLS_H +#define DEBUGTOOLS_H + +#ifdef QT_NO_DEBUG + +void debug_msg(...) {} +void debug_err(...) {} + +#else +#include + +#define debug_msg(msg) \ +do { \ + std::cout << "DEBUG [" \ + << __FILE__ << " @ " << __LINE__ \ + << "]: " << msg << std::endl; \ +} while (0) + +#define debug_err(msg) \ +do { \ + std::cerr << "ERROR [" \ + << __FILE__ << " @ " << __LINE__ \ + << "]: " << msg << std::endl; \ +} while (0) + +#endif // QT_NO_DEBUG +#endif // DEBUGTOOLS_H diff --git a/include/diagram/branchstatement.h b/include/diagram/branchstatement.h index 6c5e416..3d8c385 100644 --- a/include/diagram/branchstatement.h +++ b/include/diagram/branchstatement.h @@ -8,13 +8,15 @@ namespace samb { +/* Implementation for Statement::DECISION, Statement::SWITCH + */ class BranchStatement : public Statement { public: BranchStatement(Type t, const QString &condition, pointer next); /* accessors */ - const std::map& branches() const { return _branches; } + std::map& branches() { return _branches; } std::size_t branches_count() const { return _branchesCount; } inline const QString& condition() const { return text(); } diff --git a/include/diagram/iteratorstatement.h b/include/diagram/iteratorstatement.h index a8f6d59..e7fbba0 100644 --- a/include/diagram/iteratorstatement.h +++ b/include/diagram/iteratorstatement.h @@ -8,13 +8,15 @@ namespace samb { +/* Implementation for Statement::WHILE Statement::UNTIL + */ class IteratorStatement : public Statement { public: IteratorStatement(Type t, const QString &condition, pointer next); /* accessors */ - const Scope& inner() const { return _inner; } + Scope& inner() { return _inner; } inline const QString& condition() const { return text(); } inline void condition(const QString &condition) { return text(condition); } diff --git a/include/diagram/structogram.h b/include/diagram/structogram.h index 6b2e0db..cd501aa 100644 --- a/include/diagram/structogram.h +++ b/include/diagram/structogram.h @@ -7,15 +7,19 @@ namespace samb { +/* A structogram is a specific type of scope, that is the root scope. + * As a result it contains some metadata informations about the author, + * date of creation ecc. + */ class Structogram : public Scope { public: Structogram(const QString &title, const QString &author); - ~Structogram(); + virtual ~Structogram(); /* accessors */ - void title(const QString &title) { text(title); } - const QString& title() const { return text(); } + inline void title(const QString &title) { text(title); } + inline const QString& title() const { return text(); } void author(const QString &author) { _author = author; } const QString& author() const { return _author; } diff --git a/include/io/serializer.h b/include/io/serializer.h new file mode 100644 index 0000000..901d913 --- /dev/null +++ b/include/io/serializer.h @@ -0,0 +1,18 @@ +#ifndef SERIALIZER_H +#define SERIALIZER_H + +#include "diagram/structogram.h" + +#include + +class Serializer +{ +public: + explicit Serializer(); + virtual ~Serializer(); + + bool write(const samb::Structogram &structogram, QFileInfo into); + bool load(samb::Structogram &structogram, QFileInfo from); +}; + +#endif // SERIALIZER_H diff --git a/include/ui/mainwindow.h b/include/ui/mainwindow.h index 0beb4a2..3061440 100644 --- a/include/ui/mainwindow.h +++ b/include/ui/mainwindow.h @@ -19,13 +19,19 @@ public: private slots: void on_newButton_clicked(); + void on_openButton_clicked(); + void on_saveButton_clicked(); + + void on_refreshButton_clicked(); void on_metadataButton_clicked(); + void on_newStatementButton_clicked(); private: Ui::MainWindow *_ui; samb::Structogram *_structogram; - void initData(); + bool askSaveDialog(); + void toolButtonsEnabled(bool state); }; #endif // MAINWINDOW_H diff --git a/include/ui/metadatadialog.h b/include/ui/metadatadialog.h index 0ed2f17..81af9da 100644 --- a/include/ui/metadatadialog.h +++ b/include/ui/metadatadialog.h @@ -2,6 +2,7 @@ #define NEWDIALOG_H #include +#include namespace Ui { class MetadataDialog; @@ -15,10 +16,15 @@ public: explicit MetadataDialog(QWidget *parent = 0); ~MetadataDialog(); + bool isValid() const; void setMetadata(const QString& title, const QString& author); QString title() const; QString author() const; +private slots: + void on_titleEdit_textChanged(); + void on_authorEdit_textChanged(); + private: Ui::MetadataDialog *_ui; }; diff --git a/src/diagram/scope.cpp b/src/diagram/scope.cpp index 5f6b4df..b0f56cf 100644 --- a/src/diagram/scope.cpp +++ b/src/diagram/scope.cpp @@ -17,8 +17,7 @@ Scope::iterator::~iterator() Scope::iterator& Scope::iterator::operator++() { - if (_current->next() == nullptr) - { + if (_current->next() == nullptr) { // TODO: remove throw throw std::logic_error("Statement::iterator::operator++() m_current->next() is nullptr"); } @@ -40,9 +39,7 @@ Scope::iterator& Scope::iterator::operator++(int) Statement& Scope::iterator::operator*() const { if (_current == nullptr) - { throw std::logic_error("Statement::iterator::operator*() m_current is nullptr"); - } return *_current; } @@ -76,9 +73,7 @@ Scope::~Scope() { Scope::iterator Scope::insert_after(Scope::iterator it, Statement::pointer statement) { if (statement == nullptr) - { throw std::invalid_argument("Statement::insert_after() cannot insert nullptr"); - } statement->next(it->next()); it->next(statement); @@ -91,9 +86,7 @@ Scope::iterator Scope::insert_after(Scope::iterator it, Statement::pointer state Scope::iterator Scope::erase_after(Scope::iterator it) { if (it->next() == nullptr) - { return end(); - } it->next(it->next()->next()); diff --git a/src/io/serializer.cpp b/src/io/serializer.cpp new file mode 100644 index 0000000..6ebfa44 --- /dev/null +++ b/src/io/serializer.cpp @@ -0,0 +1,11 @@ +#include "io/serializer.h" + +Serializer::Serializer() +{ + +} + +Serializer::~Serializer() +{ + +} diff --git a/src/ui/mainwindow.cpp b/src/ui/mainwindow.cpp index 5a60391..5776db7 100644 --- a/src/ui/mainwindow.cpp +++ b/src/ui/mainwindow.cpp @@ -1,17 +1,22 @@ -#include "ui/mainwindow.h" -#include "ui_mainwindow.h" +#include "debugtools.h" #include "ui/metadatadialog.h" +#include "ui/mainwindow.h" +#include "ui_mainwindow.h" #include +#include +#include + MainWindow::MainWindow(samb::Structogram *structogram, QWidget *parent) : QMainWindow(parent), _ui(new Ui::MainWindow), _structogram(structogram) { _ui->setupUi(this); - initData(); + + toolButtonsEnabled((_structogram != nullptr)); } MainWindow::~MainWindow() @@ -24,43 +29,117 @@ MainWindow::~MainWindow() void MainWindow::on_newButton_clicked() { if (_structogram != nullptr) - { - // TODO: implement save dialog - std::cout << "TODO: implement save dialog" << std::endl; + if (!askSaveDialog()) + return; - delete _structogram; - _structogram = nullptr; - } + delete _structogram; + _structogram = nullptr; MetadataDialog *dialog = new MetadataDialog(this); - if (dialog->exec() == QDialog::Accepted) - { + if (dialog->exec() == QDialog::Accepted) { _structogram = new samb::Structogram(dialog->title(), dialog->author()); + toolButtonsEnabled(true); + } else { + toolButtonsEnabled(false); } delete dialog; } +void MainWindow::on_openButton_clicked() +{ + if (_structogram != nullptr) + if (!askSaveDialog()) + return; + + QString fileName = QFileDialog::getOpenFileName(this, + tr("Load diagram"), "", "NS Diagram (*.nsdg);;All Files (*)"); + + if (fileName.isEmpty()) + return; + + debug_err("load dialog is unimplemented"); + + // toolButtonsEnabled(true); +} + +void MainWindow::on_saveButton_clicked() +{ + QString fileName = QFileDialog::getSaveFileName(this, + tr("Save diagram"), "", tr("NS Diagram (*.nsdg);;All Files (*)")); + + if (fileName.isEmpty()) + return; + + debug_err("saved dialog is unimplemented"); + + // toolButtonsEnabled(true); +} + +void MainWindow::on_refreshButton_clicked() +{ + +} + void MainWindow::on_metadataButton_clicked() { - if (_structogram == nullptr) { return; } + if (_structogram == nullptr) + return; MetadataDialog *dialog = new MetadataDialog(this); dialog->setMetadata(_structogram->title(), _structogram->author()); - if (dialog->exec() == QDialog::Accepted) - { + if (dialog->exec() == QDialog::Accepted) { _structogram->title(dialog->title()); _structogram->author(dialog->author()); } } +void MainWindow::on_newStatementButton_clicked() +{ + +} + /**** private methods ****/ -void MainWindow::initData() +/* @brief open a save dialog + * @return true if operation completed successfully + */ +bool MainWindow::askSaveDialog() { - if (_structogram == nullptr) - { - _structogram = new samb::Structogram("", ""); + // TODO: check if it has already been saved once + auto reply = QMessageBox::question(this, + "Save " + _structogram->title(), + "'" + _structogram->title() + "' is not saved.\nDo you want to save it?", + QMessageBox::Save, QMessageBox::Discard); + + if (reply == QMessageBox::Save) { + on_saveButton_clicked(); + + // TODO: check if file has been ACTUALLY saved + return true; + } else { + return true; + } + +} + +/* @brief control ui elements that are relate to _structogram member + */ +void MainWindow::toolButtonsEnabled(bool state) +{ + if (_structogram == nullptr && state == true) { + debug_err("called enableToolButtons(true) but _structogram is nullptr"); + return; } + + // buttons + _ui->refreshButton->setEnabled(state); + _ui->metadataButton->setEnabled(state); + _ui->newStatementButton->setEnabled(state); + + // actions + _ui->actionSave->setEnabled(state); + _ui->actionSaveAs->setEnabled(state); + _ui->actionClose->setEnabled(state); } diff --git a/src/ui/metadatadialog.cpp b/src/ui/metadatadialog.cpp index 348f225..1235603 100644 --- a/src/ui/metadatadialog.cpp +++ b/src/ui/metadatadialog.cpp @@ -1,11 +1,22 @@ #include "ui/metadatadialog.h" #include "ui_metadatadialog.h" +#include "debugtools.h" +#include + MetadataDialog::MetadataDialog(QWidget *parent) : QDialog(parent), _ui(new Ui::MetadataDialog) { _ui->setupUi(this); + + QPushButton *button = _ui->buttonBox->button(QDialogButtonBox::Ok); + + if (button != 0) { + button->setEnabled(false); + } else { + debug_err("failed to get ok button"); + } } MetadataDialog::~MetadataDialog() @@ -13,6 +24,14 @@ MetadataDialog::~MetadataDialog() delete _ui; } +/*** public methods ***/ + +bool MetadataDialog::isValid() const +{ + return !title().trimmed().isEmpty() + && !author().trimmed().isEmpty(); +} + void MetadataDialog::setMetadata(const QString& title, const QString& author) { _ui->titleEdit->setText(title); @@ -29,3 +48,29 @@ QString MetadataDialog::author() const { return _ui->authorEdit->text(); } + +/*** private slots ***/ + +void MetadataDialog::on_titleEdit_textChanged() +{ + QPushButton *button = _ui->buttonBox->button(QDialogButtonBox::Ok); + + if (button == 0) { + debug_err("failed to get ok button"); + return; + } + + button->setEnabled(isValid()); +} + +void MetadataDialog::on_authorEdit_textChanged() +{ + QPushButton *button = _ui->buttonBox->button(QDialogButtonBox::Ok); + + if (button == 0) { + debug_err("failed to get ok button"); + return; + } + + button->setEnabled(isValid()); +} -- cgit v1.2.1