diff options
author | Nao Pross <naopross@thearcway.org> | 2017-12-19 22:47:05 +0100 |
---|---|---|
committer | Nao Pross <naopross@thearcway.org> | 2017-12-19 22:47:05 +0100 |
commit | 631f37ee26c19d38408ee733ffda24ad283c7921 (patch) | |
tree | 0d12f7201337ac9c459aac48b5e4421f6a1f7db2 | |
parent | Update gitignore for QtCreator (diff) | |
download | OrbitingYeti-631f37ee26c19d38408ee733ffda24ad283c7921.tar.gz OrbitingYeti-631f37ee26c19d38408ee733ffda24ad283c7921.zip |
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
-rw-r--r-- | OrbitingYeti.pro | 7 | ||||
-rw-r--r-- | README.md | 7 | ||||
-rw-r--r-- | forms/mainwindow.ui | 80 | ||||
-rw-r--r-- | forms/metadatadialog.ui | 25 | ||||
-rw-r--r-- | include/debugtools.h | 27 | ||||
-rw-r--r-- | include/diagram/branchstatement.h | 4 | ||||
-rw-r--r-- | include/diagram/iteratorstatement.h | 4 | ||||
-rw-r--r-- | include/diagram/structogram.h | 10 | ||||
-rw-r--r-- | include/io/serializer.h | 18 | ||||
-rw-r--r-- | include/ui/mainwindow.h | 8 | ||||
-rw-r--r-- | include/ui/metadatadialog.h | 6 | ||||
-rw-r--r-- | src/diagram/scope.cpp | 9 | ||||
-rw-r--r-- | src/io/serializer.cpp | 11 | ||||
-rw-r--r-- | src/ui/mainwindow.cpp | 115 | ||||
-rw-r--r-- | src/ui/metadatadialog.cpp | 45 |
15 files changed, 323 insertions, 53 deletions
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 \ @@ -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 @@ </widget> <addaction name="actionNew"/> <addaction name="actionSave"/> - <addaction name="actionSave_As"/> + <addaction name="actionSaveAs"/> <addaction name="actionOpen"/> <addaction name="actionClose"/> <addaction name="menuExport"/> @@ -255,11 +255,20 @@ </property> </action> <action name="actionPDF"> + <property name="enabled"> + <bool>true</bool> + </property> <property name="text"> <string>PDF</string> </property> + <property name="shortcut"> + <string>Ctrl+E</string> + </property> </action> <action name="actionLaTeX_TikZ"> + <property name="enabled"> + <bool>true</bool> + </property> <property name="text"> <string>LaTeX TikZ</string> </property> @@ -280,7 +289,7 @@ <string>Ctrl+V</string> </property> </action> - <action name="actionSave_As"> + <action name="actionSaveAs"> <property name="text"> <string>Save As</string> </property> @@ -327,5 +336,70 @@ </action> </widget> <resources/> - <connections/> + <connections> + <connection> + <sender>actionNew</sender> + <signal>triggered()</signal> + <receiver>newButton</receiver> + <slot>click()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>23</x> + <y>53</y> + </hint> + </hints> + </connection> + <connection> + <sender>actionSave</sender> + <signal>triggered()</signal> + <receiver>saveButton</receiver> + <slot>click()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>99</x> + <y>53</y> + </hint> + </hints> + </connection> + <connection> + <sender>actionOpen</sender> + <signal>triggered()</signal> + <receiver>openButton</receiver> + <slot>click()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>61</x> + <y>53</y> + </hint> + </hints> + </connection> + <connection> + <sender>actionQuit</sender> + <signal>triggered()</signal> + <receiver>MainWindow</receiver> + <slot>close()</slot> + <hints> + <hint type="sourcelabel"> + <x>-1</x> + <y>-1</y> + </hint> + <hint type="destinationlabel"> + <x>411</x> + <y>300</y> + </hint> + </hints> + </connection> + </connections> </ui> 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 @@ </rect> </property> <property name="windowTitle"> - <string>Set metadata</string> + <string>Metadata</string> </property> <layout class="QFormLayout" name="formLayout"> - <item row="5" column="1"> - <widget class="QDialogButtonBox" name="buttonBox"> - <property name="orientation"> - <enum>Qt::Horizontal</enum> - </property> - <property name="standardButtons"> - <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> - </property> - </widget> - </item> <item row="1" column="1"> <widget class="QLabel" name="titleLabel"> <property name="text"> @@ -44,6 +34,19 @@ <item row="4" column="1"> <widget class="QLineEdit" name="authorEdit"/> </item> + <item row="5" column="1"> + <widget class="QDialogButtonBox" name="buttonBox"> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="orientation"> + <enum>Qt::Horizontal</enum> + </property> + <property name="standardButtons"> + <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set> + </property> + </widget> + </item> </layout> </widget> <resources/> 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 <iostream> + +#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<QString, pointer>& branches() const { return _branches; } + std::map<QString, pointer>& 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 <QFileInfo> + +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 <QDialog> +#include <QAbstractButton> 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 <iostream> +#include <QMessageBox> +#include <QFileDialog> + 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 <QPushButton> + 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()); +} |