|
From: Tapio V. <aa...@us...> - 2011-01-12 14:12:27
|
Module: editor
Branch: master
Commit: b35bdf99aaa35536ac2eaca82c23a3830d40446d
Author: Tapio Vierros <tap...@gm...>
Date: Wed Jan 12 16:11:23 2011 +0200
Early draft of operation abstraction and partial undo implementation.
---
editor.ui | 3 +++
editorapp.cc | 21 +++++++++++++++++++++
editorapp.hh | 6 ++++++
notegraphwidget.cc | 13 +++++++++++--
notegraphwidget.hh | 4 ++++
operation.cc | 6 ++++++
operation.hh | 20 ++++++++++++++++++++
7 files changed, 71 insertions(+), 2 deletions(-)
diff --git a/editor.ui b/editor.ui
index 52f041d..c71a596 100644
--- a/editor.ui
+++ b/editor.ui
@@ -382,6 +382,9 @@
</property>
</action>
<action name="actionRedo">
+ <property name="enabled">
+ <bool>false</bool>
+ </property>
<property name="text">
<string>&Redo</string>
</property>
diff --git a/editorapp.cc b/editorapp.cc
index bcdc9d1..68b61b7 100644
--- a/editorapp.cc
+++ b/editorapp.cc
@@ -17,6 +17,7 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
ui.splitter->setSizes(ss);
// Custom signals/slots
+ connect(noteGraph, SIGNAL(operationDone(const Operation&)), this, SLOT(operationDone(const Operation&)));
connect(noteGraph, SIGNAL(updateNoteInfo(NoteLabel*)), this, SLOT(updateNoteInfo(NoteLabel*)));
updateNoteInfo(NULL);
@@ -36,6 +37,11 @@ EditorApp::EditorApp(QWidget *parent): QMainWindow(parent)
}
+void EditorApp::operationDone(const Operation& op)
+{
+ opStack.push(op);
+}
+
void EditorApp::updateNoteInfo(NoteLabel *note)
{
if (note) {
@@ -112,6 +118,21 @@ void EditorApp::on_actionExit_triggered()
}
}
+void EditorApp::on_actionUndo_triggered()
+{
+ // TODO: Move popped to redo stack
+ opStack.pop();
+ noteGraph->close();
+ noteGraph = new NoteGraphWidget(NULL);
+ ui.noteGraphScroller->setWidget(noteGraph);
+ // Re-apply all operations in the stack
+ for (OperationStack::const_iterator opit = opStack.begin(); opit != opStack.end(); ++opit) {
+ // FIXME: This should check from the operation what class will implement it
+ // and call the appropriate object. QObject meta info could be very useful.
+ noteGraph->doOperation(*opit, Operation::NO_EMIT);
+ }
+}
+
void EditorApp::on_actionMusicFile_triggered()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open File"),
diff --git a/editorapp.hh b/editorapp.hh
index eaa9fa2..0595dd6 100644
--- a/editorapp.hh
+++ b/editorapp.hh
@@ -1,6 +1,7 @@
#pragma once
#include "ui_editor.h"
+#include "operation.hh"
class NoteLabel;
class NoteGraphWidget;
@@ -13,6 +14,7 @@ public:
EditorApp(QWidget *parent = 0);
public slots:
+ void operationDone(const Operation& op);
void updateNoteInfo(NoteLabel* note);
// Automatic slots
@@ -22,6 +24,9 @@ public slots:
void on_actionOpen_triggered();
void on_actionExit_triggered();
+ // Edit menu
+ void on_actionUndo_triggered();
+
// Insert menu
void on_actionMusicFile_triggered();
void on_actionLyricsFromFile_triggered();
@@ -38,4 +43,5 @@ public slots:
private:
Ui::EditorApp ui;
NoteGraphWidget* noteGraph;
+ OperationStack opStack;
};
diff --git a/notegraphwidget.cc b/notegraphwidget.cc
index e94f743..799cda4 100644
--- a/notegraphwidget.cc
+++ b/notegraphwidget.cc
@@ -247,8 +247,8 @@ void NoteGraphWidget::mouseDoubleClickEvent(QMouseEvent *event)
// Spawn an input dialog
bool ok;
QString text = QInputDialog::getText(this, tr("Edit lyric"),
- tr("Lyric:"), QLineEdit::Normal,
- child->lyric(), &ok);
+ tr("Lyric:"), QLineEdit::Normal,
+ child->lyric(), &ok);
if (ok && !text.isEmpty()) {
child->setLyric(text);
child->createPixmap(child->size());
@@ -314,6 +314,15 @@ void NoteGraphWidget::keyPressEvent(QKeyEvent *event)
}
}
+void NoteGraphWidget::doOperation(const Operation& op, Operation::OperationFlags flags)
+{
+ if (!(flags & Operation::NO_EXEC)) {
+ // TODO: This should perform the operation
+ }
+ if (!(flags & Operation::NO_EMIT))
+ emit operationDone(op);
+}
+
void FloatingGap::addNote(NoteLabel* n)
diff --git a/notegraphwidget.hh b/notegraphwidget.hh
index f9bc4c7..e7fdb5a 100644
--- a/notegraphwidget.hh
+++ b/notegraphwidget.hh
@@ -2,6 +2,7 @@
#include "pitchvis.hh"
#include "notes.hh"
+#include "operation.hh"
#include <QLabel>
#include <list>
@@ -26,8 +27,11 @@ public:
void selectNote(NoteLabel* note);
NoteLabel* selectedNote() const { return m_selectedNote; }
+ void doOperation(const Operation& op, Operation::OperationFlags flags = Operation::NORMAL);
+
signals:
void updateNoteInfo(NoteLabel*);
+ void operationDone(const Operation&);
protected:
void mousePressEvent(QMouseEvent *event);
diff --git a/operation.cc b/operation.cc
new file mode 100644
index 0000000..16faca5
--- /dev/null
+++ b/operation.cc
@@ -0,0 +1,6 @@
+#include "operation.hh"
+
+Operation::Operation(QString opString)
+{
+ (void)opString;
+}
diff --git a/operation.hh b/operation.hh
new file mode 100644
index 0000000..6f516c6
--- /dev/null
+++ b/operation.hh
@@ -0,0 +1,20 @@
+#pragma once
+#include <QString>
+#include <QStack>
+
+///! This is class is draft and subject to change
+
+struct Operation
+{
+ enum OperationFlags { NORMAL = 0, NO_EXEC = 1, NO_EMIT = 2 };
+
+ // FIXME: Somekind of nice serializable type for constructor
+ Operation(QString opString = "");
+
+ QString owner; /// Who performs the operation
+ unsigned id; /// E.g. a child id of the owner
+ unsigned action; /// Id of the action to-be-performed
+ void *data; /// User data
+};
+
+typedef QStack<Operation> OperationStack;
|