aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OrbitingYeti.pro7
-rw-r--r--README.md7
-rw-r--r--forms/mainwindow.ui80
-rw-r--r--forms/metadatadialog.ui25
-rw-r--r--include/debugtools.h27
-rw-r--r--include/diagram/branchstatement.h4
-rw-r--r--include/diagram/iteratorstatement.h4
-rw-r--r--include/diagram/structogram.h10
-rw-r--r--include/io/serializer.h18
-rw-r--r--include/ui/mainwindow.h8
-rw-r--r--include/ui/metadatadialog.h6
-rw-r--r--src/diagram/scope.cpp9
-rw-r--r--src/io/serializer.cpp11
-rw-r--r--src/ui/mainwindow.cpp115
-rw-r--r--src/ui/metadatadialog.cpp45
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 \
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 @@
</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());
+}