From 631f37ee26c19d38408ee733ffda24ad283c7921 Mon Sep 17 00:00:00 2001
From: Nao Pross <naopross@thearcway.org>
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
---
 src/diagram/scope.cpp     |   9 +---
 src/io/serializer.cpp     |  11 +++++
 src/ui/mainwindow.cpp     | 115 ++++++++++++++++++++++++++++++++++++++--------
 src/ui/metadatadialog.cpp |  45 ++++++++++++++++++
 4 files changed, 154 insertions(+), 26 deletions(-)
 create mode 100644 src/io/serializer.cpp

(limited to 'src')

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());
+}
-- 
cgit v1.2.1