Dear all, I've been working on implementing an undo/redo framework. The attached patches are what I've done so far. I only have undo working for the deleted dives.
This is not in anyway fully working, just a view of what I have done so that you can point me in the right direction Thanks! - Grace K.
From b3e44d087bd4ce4e92e9a9beed8230eeb4d1fbbd Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Mon, 9 Feb 2015 09:44:10 +0100 Subject: [PATCH 4/4] Add ability to undo deleted dives Before the dive is deleted, a copy is made and passed to the undo buffer. When edit->undo is clicked, this dive is restored to the dive list. Signed-off-by: Grace Karanja <[email protected]> --- qt-ui/divelistview.cpp | 4 ++++ qt-ui/undobuffer.cpp | 36 +++++++++++++++++++++++++++--------- qt-ui/undobuffer.h | 4 +++- 3 files changed, 34 insertions(+), 10 deletions(-) diff --git a/qt-ui/divelistview.cpp b/qt-ui/divelistview.cpp index ec54af9..89b851a 100644 --- a/qt-ui/divelistview.cpp +++ b/qt-ui/divelistview.cpp @@ -11,6 +11,7 @@ #include <QSettings> #include <QFileDialog> #include "qthelper.h" +#include "undobuffer.h" // # Date Rtg Dpth Dur Tmp Wght Suit Cyl Gas SAC OTU CNS Loc static int defaultWidth[] = { 70, 140, 90, 50, 50, 50, 50, 70, 50, 50, 70, 50, 50, 500}; @@ -730,6 +731,9 @@ void DiveListView::deleteDive() for_each_dive (i, d) { if (!d->selected) continue; + struct dive* undo_entry = alloc_dive(); + copy_dive(get_dive(i), undo_entry); + MainWindow::instance()->undoBuffer->recordbefore("Delete Dive", undo_entry); delete_single_dive(i); i--; // so the next dive isn't skipped... it's now #i lastDiveNr = i; diff --git a/qt-ui/undobuffer.cpp b/qt-ui/undobuffer.cpp index b0c1d26..4ee0cf6 100644 --- a/qt-ui/undobuffer.cpp +++ b/qt-ui/undobuffer.cpp @@ -1,8 +1,9 @@ #include "undobuffer.h" +#include "mainwindow.h" UndoBuffer::UndoBuffer(QObject *parent) : QObject(parent) { - + curIdx = 0; } UndoBuffer::~UndoBuffer() @@ -12,32 +13,46 @@ UndoBuffer::~UndoBuffer() bool UndoBuffer::canUndo() { - + return curIdx > 0; } bool UndoBuffer::canRedo() { - + return curIdx < list.count(); } void UndoBuffer::redo() { - + current()->redo(); + curIdx++; + if (curIdx > list.count()) + curIdx = list.count() - 1; } void UndoBuffer::undo() { - + current()->undo(); + curIdx = list.indexOf(current()); } void UndoBuffer::recordbefore(QString commandName, dive *affectedDive) { - + UndoCommand *cmd = new UndoCommand(commandName, affectedDive); + //If we are within the list, clear the extra UndoCommands. + if (list.count() > 0) { + if (curIdx + 1 < list.count()) { + for (int i = curIdx + 1; i < list.count(); i++) { + list.removeAt(i); + } + } + } + list.append(cmd); + curIdx = list.count(); } void UndoBuffer::recordAfter(dive *affectedDive) { - + list.at(curIdx - 1)->setStateAfter(affectedDive); } @@ -50,11 +65,14 @@ UndoCommand::UndoCommand(QString commandName, dive *affectedDive) void UndoCommand::undo() { - + if (name == "Delete Dive") { + record_dive(stateBefore); + MainWindow::instance()->recreateDiveList(); + } } void UndoCommand::redo() { - + //To be implemented } diff --git a/qt-ui/undobuffer.h b/qt-ui/undobuffer.h index beae8e3..9fac147 100644 --- a/qt-ui/undobuffer.h +++ b/qt-ui/undobuffer.h @@ -12,7 +12,7 @@ private: public: explicit UndoCommand(QString commandName, dive* affectedDive); - void setStateAfter(dive* affectedDive); + void setStateAfter(dive* affectedDive) { stateAfter = affectedDive; } void undo(); void redo(); }; @@ -25,7 +25,9 @@ public: ~UndoBuffer(); bool canUndo(); bool canRedo(); + UndoCommand *current() const { return list.at(curIdx - 1); } private: + QList<UndoCommand*> list; int curIdx; public slots: void redo(); -- 1.9.1
From 091542cd2468f995f1d737846a785da10fbc38a3 Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Mon, 9 Feb 2015 09:30:27 +0100 Subject: [PATCH 3/4] Add UndoCommand class Add a class to handle all undo/redo events. Whenever a user action affects a dive, an undo command will be created. A list of these commands will be stored in the UndoBuffer, to allow for moving forwards/backwards in the list. Signed-off-by: Grace Karanja <[email protected]> --- qt-ui/undobuffer.cpp | 18 ++++++++++++++++++ qt-ui/undobuffer.h | 13 +++++++++++++ 2 files changed, 31 insertions(+) diff --git a/qt-ui/undobuffer.cpp b/qt-ui/undobuffer.cpp index 92c0dee..b0c1d26 100644 --- a/qt-ui/undobuffer.cpp +++ b/qt-ui/undobuffer.cpp @@ -40,3 +40,21 @@ void UndoBuffer::recordAfter(dive *affectedDive) } + + +UndoCommand::UndoCommand(QString commandName, dive *affectedDive) +{ + name = commandName; + stateBefore = affectedDive; +} + +void UndoCommand::undo() +{ + +} + +void UndoCommand::redo() +{ + +} + diff --git a/qt-ui/undobuffer.h b/qt-ui/undobuffer.h index a292d3b..beae8e3 100644 --- a/qt-ui/undobuffer.h +++ b/qt-ui/undobuffer.h @@ -4,6 +4,19 @@ #include <QObject> #include "dive.h" +class UndoCommand { +private: + dive* stateBefore; + dive* stateAfter; + QString name; + +public: + explicit UndoCommand(QString commandName, dive* affectedDive); + void setStateAfter(dive* affectedDive); + void undo(); + void redo(); +}; + class UndoBuffer : public QObject { Q_OBJECT -- 1.9.1
From fa4f42b22f8ae91928d1efd60ed60087e2521f5d Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Mon, 9 Feb 2015 09:24:32 +0100 Subject: [PATCH 2/4] Add menu entries for undo/redo Add an edit menu with undo and redo submenus, and connect them to the UndoBuffer class. The submenus are only enabled when needed. Signed-off-by: Grace Karanja <[email protected]> --- qt-ui/mainwindow.cpp | 19 +++++++++++++++++++ qt-ui/mainwindow.h | 5 +++++ qt-ui/mainwindow.ui | 26 +++++++++++++++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/qt-ui/mainwindow.cpp b/qt-ui/mainwindow.cpp index 3142f5a..57af5e0 100644 --- a/qt-ui/mainwindow.cpp +++ b/qt-ui/mainwindow.cpp @@ -31,6 +31,7 @@ #include "usermanual.h" #endif #include <QNetworkProxy> +#include "undobuffer.h" MainWindow *MainWindow::m_Instance = NULL; @@ -77,6 +78,7 @@ MainWindow::MainWindow() : QMainWindow(), connect(DivePlannerPointsModel::instance(), SIGNAL(planCreated()), this, SLOT(planCreated())); connect(DivePlannerPointsModel::instance(), SIGNAL(planCanceled()), this, SLOT(planCanceled())); connect(ui.printPlan, SIGNAL(pressed()), ui.divePlannerWidget, SLOT(printDecoPlan())); + connect(ui.menu_Edit, SIGNAL(aboutToShow()), this, SLOT(checkForUndoAndRedo())); #ifdef NO_PRINTING ui.printPlan->hide(); #endif @@ -152,6 +154,7 @@ MainWindow::MainWindow() : QMainWindow(), toolBar->setContentsMargins(zeroMargins); updateManager = new UpdateManager(this); + undoBuffer = new UndoBuffer(this); } MainWindow::~MainWindow() @@ -1466,3 +1469,19 @@ void MainWindow::on_actionFilterTags_triggered() else ui.multiFilter->setVisible(true); } + +void MainWindow::on_action_Undo_triggered() +{ + undoBuffer->undo(); +} + +void MainWindow::on_action_Redo_triggered() +{ + undoBuffer->redo(); +} + +void MainWindow::checkForUndoAndRedo() +{ + ui.action_Undo->setEnabled(undoBuffer->canUndo()); + ui.action_Redo->setEnabled(undoBuffer->canRedo()); +} diff --git a/qt-ui/mainwindow.h b/qt-ui/mainwindow.h index 2364caa..641c9ec 100644 --- a/qt-ui/mainwindow.h +++ b/qt-ui/mainwindow.h @@ -30,6 +30,7 @@ class QWebView; class QSettings; class UpdateManager; class UserManual; +class UndoBuffer; enum MainWindowTitleFormat { MWTF_DEFAULT, @@ -82,6 +83,7 @@ public: void setPlanNotes(const char *notes); void printPlan(); void checkSurvey(QSettings *s); + UndoBuffer *undoBuffer; private slots: /* file menu action */ @@ -151,6 +153,9 @@ slots: void on_paste_triggered(); void on_actionFilterTags_triggered(); void on_actionConfigure_Dive_Computer_triggered(); + void on_action_Undo_triggered(); + void on_action_Redo_triggered(); + void checkForUndoAndRedo(); protected: void closeEvent(QCloseEvent *); diff --git a/qt-ui/mainwindow.ui b/qt-ui/mainwindow.ui index 8ffb8bb..9507b5f 100644 --- a/qt-ui/mainwindow.ui +++ b/qt-ui/mainwindow.ui @@ -195,7 +195,7 @@ p, li { white-space: pre-wrap; } <x>0</x> <y>0</y> <width>1682</width> - <height>27</height> + <height>25</height> </rect> </property> <widget class="QMenu" name="menuFile"> @@ -271,7 +271,15 @@ p, li { white-space: pre-wrap; } <addaction name="actionDownloadWeb"/> <addaction name="actionDivelogs_de"/> </widget> + <widget class="QMenu" name="menu_Edit"> + <property name="title"> + <string>&Edit</string> + </property> + <addaction name="action_Undo"/> + <addaction name="action_Redo"/> + </widget> <addaction name="menuFile"/> + <addaction name="menu_Edit"/> <addaction name="menuImport"/> <addaction name="menuLog"/> <addaction name="menuView"/> @@ -813,6 +821,22 @@ p, li { white-space: pre-wrap; } <string>User &survey</string> </property> </action> + <action name="action_Undo"> + <property name="text"> + <string>&Undo</string> + </property> + <property name="shortcut"> + <string>Ctrl+Z</string> + </property> + </action> + <action name="action_Redo"> + <property name="text"> + <string>&Redo</string> + </property> + <property name="shortcut"> + <string>Ctrl+Shift+Z</string> + </property> + </action> </widget> <customwidgets> <customwidget> -- 1.9.1
From ce968daea4d8d7f76dc58b2d464d3446f11c677d Mon Sep 17 00:00:00 2001 From: Grace Karanja <[email protected]> Date: Mon, 9 Feb 2015 09:17:38 +0100 Subject: [PATCH 1/4] Create UndoBuffer class Add an empty UndoBuffer class. This will be built up on to implement a working undo/redo mechanism. Signed-off-by: Grace Karanja <[email protected]> --- qt-ui/undobuffer.cpp | 42 ++++++++++++++++++++++++++++++++++++++++++ qt-ui/undobuffer.h | 24 ++++++++++++++++++++++++ subsurface.pro | 6 ++++-- 3 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 qt-ui/undobuffer.cpp create mode 100644 qt-ui/undobuffer.h diff --git a/qt-ui/undobuffer.cpp b/qt-ui/undobuffer.cpp new file mode 100644 index 0000000..92c0dee --- /dev/null +++ b/qt-ui/undobuffer.cpp @@ -0,0 +1,42 @@ +#include "undobuffer.h" + +UndoBuffer::UndoBuffer(QObject *parent) : QObject(parent) +{ + +} + +UndoBuffer::~UndoBuffer() +{ + +} + +bool UndoBuffer::canUndo() +{ + +} + +bool UndoBuffer::canRedo() +{ + +} + +void UndoBuffer::redo() +{ + +} + +void UndoBuffer::undo() +{ + +} + +void UndoBuffer::recordbefore(QString commandName, dive *affectedDive) +{ + +} + +void UndoBuffer::recordAfter(dive *affectedDive) +{ + +} + diff --git a/qt-ui/undobuffer.h b/qt-ui/undobuffer.h new file mode 100644 index 0000000..a292d3b --- /dev/null +++ b/qt-ui/undobuffer.h @@ -0,0 +1,24 @@ +#ifndef UNDOBUFFER_H +#define UNDOBUFFER_H + +#include <QObject> +#include "dive.h" + +class UndoBuffer : public QObject +{ + Q_OBJECT +public: + explicit UndoBuffer(QObject *parent = 0); + ~UndoBuffer(); + bool canUndo(); + bool canRedo(); +private: + int curIdx; +public slots: + void redo(); + void undo(); + void recordbefore(QString commandName, dive *affectedDive); + void recordAfter(dive *affectedDive); +}; + +#endif // UNDOBUFFER_H diff --git a/subsurface.pro b/subsurface.pro index 2cc6b09..000806f 100644 --- a/subsurface.pro +++ b/subsurface.pro @@ -104,7 +104,8 @@ HEADERS = \ qt-ui/statistics/statisticsbar.h \ qt-ui/statistics/yearstatistics.h \ qt-ui/diveshareexportdialog.h \ - qt-ui/filtermodels.h + qt-ui/filtermodels.h \ + qt-ui/undobuffer.h android: HEADERS -= \ qt-ui/usermanual.h \ @@ -198,7 +199,8 @@ SOURCES = \ qt-ui/statistics/statisticsbar.cpp \ qt-ui/statistics/monthstatistics.cpp \ qt-ui/diveshareexportdialog.cpp \ - qt-ui/filtermodels.cpp + qt-ui/filtermodels.cpp \ + qt-ui/undobuffer.cpp android: SOURCES += android.cpp else: win32: SOURCES += windows.c -- 1.9.1
_______________________________________________ subsurface mailing list [email protected] http://lists.subsurface-divelog.org/cgi-bin/mailman/listinfo/subsurface
