r18887 - gnucash/trunk/src/gnc - Cutecash: Add QUndoStack to implement all editing through the Command pattern and make it undoable.
Christian Stimming
cstim at code.gnucash.org
Wed Mar 10 12:51:12 EST 2010
Author: cstim
Date: 2010-03-10 12:51:12 -0500 (Wed, 10 Mar 2010)
New Revision: 18887
Trac: http://svn.gnucash.org/trac/changeset/18887
Added:
gnucash/trunk/src/gnc/Cmd.hpp
Modified:
gnucash/trunk/src/gnc/mainwindow.cpp
gnucash/trunk/src/gnc/mainwindow.hpp
gnucash/trunk/src/gnc/mainwindow.ui
Log:
Cutecash: Add QUndoStack to implement all editing through the Command pattern and make it undoable.
Added: gnucash/trunk/src/gnc/Cmd.hpp
===================================================================
--- gnucash/trunk/src/gnc/Cmd.hpp (rev 0)
+++ gnucash/trunk/src/gnc/Cmd.hpp 2010-03-10 17:51:12 UTC (rev 18887)
@@ -0,0 +1,100 @@
+/*
+ * Cmd.hpp
+ * Copyright (C) 2010 Christian Stimming
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, contact:
+ *
+ * Free Software Foundation Voice: +1-617-542-5942
+ * 51 Franklin Street, Fifth Floor Fax: +1-617-542-2652
+ * Boston, MA 02110-1301, USA gnu at gnu.org
+ */
+
+#ifndef GNC_CMD_HPP
+#define GNC_CMD_HPP
+
+#include <QUndoCommand>
+#include <gnc/Split.hpp>
+
+namespace gnc
+{
+
+template<class TargetT, class ValueT>
+class Cmd : public QUndoCommand
+{
+public:
+ typedef TargetT target_type;
+ typedef ValueT value_type;
+ typedef void (TargetT::*setter_func)(const value_type&);
+ typedef value_type (TargetT::*getter_func)() const;
+
+ Cmd(const QString& text,
+ TargetT& target, setter_func setter,
+ const value_type& previousValue,
+ const value_type& newValue,
+ QUndoCommand *parent = 0)
+ : QUndoCommand(text, parent)
+ , m_target(target)
+ , m_setter(setter)
+ , m_previousValue(previousValue)
+ , m_newValue(newValue)
+ {
+ }
+
+ Cmd(const QString& text,
+ TargetT& target, setter_func setter,
+ getter_func getter,
+ const value_type& newValue,
+ QUndoCommand *parent = 0)
+ : QUndoCommand(text, parent)
+ , m_target(target)
+ , m_setter(setter)
+ , m_previousValue((m_target.*getter)())
+ , m_newValue(newValue)
+ {
+ }
+
+ virtual void redo()
+ {
+ // Uh oh. The calling syntax for pointer-to-member variables
+ // (here: m_setter) looks rather weird:
+ (m_target.*m_setter)(m_newValue);
+ }
+ virtual void undo()
+ {
+ (m_target.*m_setter)(m_previousValue);
+ }
+
+
+protected:
+ TargetT& m_target;
+ setter_func m_setter;
+ value_type m_previousValue;
+ value_type m_newValue;
+};
+
+namespace cmd
+{
+
+QUndoCommand* setSplitMemo(Split& split, const QString& newValue)
+{
+ return new Cmd<Split, QString>(QWidget::tr("Edit Split Memo"),
+ split, &Split::setMemo,
+ &Split::getMemo, newValue);
+}
+
+} // END namespace cmd
+
+} // END namespace gnc
+
+#endif
Modified: gnucash/trunk/src/gnc/mainwindow.cpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-10 17:50:51 UTC (rev 18886)
+++ gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-10 17:51:12 UTC (rev 18887)
@@ -26,6 +26,7 @@
#include <QtGui/QMessageBox>
#include <QtGui/QToolBar>
#include <QtGui/QProgressBar>
+#include <QtGui/QUndoStack>
#include <QDebug>
#include "config.h"
@@ -51,9 +52,14 @@
#include "gnc/SplitListModel.hpp"
#include "gnc/RecentFileMenu.hpp"
+#include "gnc/Cmd.hpp"
+
namespace gnc
{
+// Explicit instantiations to check for compiler errors
+template class Cmd<Account, QString>;
+
inline QString errorToString(QofBackendError err)
{
return errorToStringPair(err).first;
@@ -68,6 +74,7 @@
MainWindow::MainWindow()
: ui(new Ui::MainWindow)
+ , m_undoStack(new QUndoStack(this))
{
ui->setupUi(this);
@@ -79,6 +86,8 @@
// connect(ui->labelMain, SIGNAL(linkActivated(const QString&)),
// this, SLOT(documentWasModified()));
+ connect(m_undoStack, SIGNAL(cleanChanged(bool)),
+ this, SLOT(documentCleanStateChanged(bool)));
setWindowIcon(QIcon(":/pixmaps/gnucash-icon-32x32.png"));
@@ -150,9 +159,18 @@
void MainWindow::documentWasModified()
{
-// setWindowModified(ui->textEdit->document()->isModified());
+ setWindowModified(true);
}
+void MainWindow::documentCleanStateChanged(bool clean)
+{
+ bool unchanged = (clean == isWindowModified());
+
+ setWindowModified(!clean);
+ if (!unchanged)
+ updateWindowTitle();
+}
+
// Auto-connected to ui->textBrowser's signal anchorClicked()
void MainWindow::on_textBrowser_anchorClicked(const QUrl &url)
{
@@ -167,6 +185,21 @@
ui->actionOpen->setShortcuts(QKeySequence::Open);
ui->actionSave->setShortcuts(QKeySequence::Save);
ui->actionSave_as->setShortcuts(QKeySequence::SaveAs);
+
+ QAction *redo = m_undoStack->createRedoAction(ui->menuEdit, tr("&Redo"));
+ redo->setIcon(QIcon(":/gtk-icons/gtk-redo.png"));
+ redo->setShortcuts(QKeySequence::Redo);
+ QAction *undo = m_undoStack->createUndoAction(ui->menuEdit, tr("&Undo"));
+ undo->setIcon(QIcon(":/gtk-icons/gtk-undo.png"));
+ undo->setShortcuts(QKeySequence::Undo);
+ ui->menuEdit->insertAction(ui->actionCut, undo);
+ ui->menuEdit->insertAction(ui->actionCut, redo);
+ ui->menuEdit->insertSeparator(ui->actionCut);
+
+ ui->actionCut->setShortcuts(QKeySequence::Cut);
+ ui->actionCopy->setShortcuts(QKeySequence::Copy);
+ ui->actionPaste->setShortcuts(QKeySequence::Paste);
+
ui->actionViewClose->setShortcuts(QKeySequence::Close);
connect(ui->actionNew, SIGNAL(triggered()), this, SLOT(newFile()));
@@ -257,13 +290,18 @@
// ui->textEdit->document()->setModified(false);
setWindowModified(false);
+ updateWindowTitle();
+}
+
+void MainWindow::updateWindowTitle()
+{
QString shownName;
if (curFile.isEmpty())
shownName = "untitled.txt";
else
shownName = strippedName(curFile);
- setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("Application")));
+ setWindowTitle(tr("%1[*]%2 - %3").arg(shownName).arg(isWindowModified() ? "(*)" : "").arg(tr("Application")));
}
QString MainWindow::strippedName(const QString &fullFileName)
Modified: gnucash/trunk/src/gnc/mainwindow.hpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.hpp 2010-03-10 17:50:51 UTC (rev 18886)
+++ gnucash/trunk/src/gnc/mainwindow.hpp 2010-03-10 17:51:12 UTC (rev 18887)
@@ -32,6 +32,7 @@
class QPlainTextEdit;
class QTextEdit;
class QTabWidget;
+class QUndoStack;
namespace Ui
{
@@ -54,6 +55,7 @@
public slots:
void accountItemActivated(const QModelIndex & index);
void loadFileMaybe(const QString &fileName);
+ void documentCleanStateChanged(bool clean);
protected:
void closeEvent(QCloseEvent *event);
@@ -86,6 +88,7 @@
QString strippedName(const QString &fullFileName);
void viewOrHideTab(bool checkedView, QWidget *widget);
void reallyRemoveTab(int index);
+ void updateWindowTitle();
Ui::MainWindow *ui;
@@ -94,6 +97,7 @@
QToolBar *fileToolBar;
QToolBar *editToolBar;
RecentFileMenu *menuRecentFiles;
+ QUndoStack *m_undoStack;
Session m_session;
AccountListModel *m_accountListModel;
Modified: gnucash/trunk/src/gnc/mainwindow.ui
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.ui 2010-03-10 17:50:51 UTC (rev 18886)
+++ gnucash/trunk/src/gnc/mainwindow.ui 2010-03-10 17:51:12 UTC (rev 18887)
@@ -174,9 +174,6 @@
<property name="title">
<string>&Edit</string>
</property>
- <addaction name="action_Undo"/>
- <addaction name="action_Redo"/>
- <addaction name="separator"/>
<addaction name="actionCut"/>
<addaction name="actionCopy"/>
<addaction name="actionPaste"/>
@@ -368,30 +365,6 @@
<string>About Qt</string>
</property>
</action>
- <action name="action_Undo">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="icon">
- <iconset resource="gtk-icons.qrc">
- <normaloff>:/gtk-icons/gtk-undo.png</normaloff>:/gtk-icons/gtk-undo.png</iconset>
- </property>
- <property name="text">
- <string>&Undo</string>
- </property>
- </action>
- <action name="action_Redo">
- <property name="enabled">
- <bool>false</bool>
- </property>
- <property name="icon">
- <iconset resource="gtk-icons.qrc">
- <normaloff>:/gtk-icons/gtk-redo.png</normaloff>:/gtk-icons/gtk-redo.png</iconset>
- </property>
- <property name="text">
- <string>&Redo</string>
- </property>
- </action>
<action name="actionViewWelcomepage">
<property name="checkable">
<bool>true</bool>
More information about the gnucash-changes
mailing list