r18889 - gnucash/trunk/src/gnc - Enable editing of the "Description" column in the split list view - WITH UNDO!
Christian Stimming
cstim at code.gnucash.org
Wed Mar 10 16:40:58 EST 2010
Author: cstim
Date: 2010-03-10 16:40:58 -0500 (Wed, 10 Mar 2010)
New Revision: 18889
Trac: http://svn.gnucash.org/trac/changeset/18889
Added:
gnucash/trunk/src/gnc/Cmd.cpp
Modified:
gnucash/trunk/src/gnc/CMakeLists.txt
gnucash/trunk/src/gnc/Cmd.hpp
gnucash/trunk/src/gnc/RecentFileMenu.cpp
gnucash/trunk/src/gnc/Split.hpp
gnucash/trunk/src/gnc/SplitListModel.cpp
gnucash/trunk/src/gnc/SplitListModel.hpp
gnucash/trunk/src/gnc/Transaction.hpp
gnucash/trunk/src/gnc/mainwindow.cpp
Log:
Enable editing of the "Description" column in the split list view - WITH UNDO!
The Qt Undo framework is almost like magic. We just have to create a
command object instead of directly manipulating the value, and suddenly
the undo/redo just works. This is fun!
Modified: gnucash/trunk/src/gnc/CMakeLists.txt
===================================================================
--- gnucash/trunk/src/gnc/CMakeLists.txt 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/CMakeLists.txt 2010-03-10 21:40:58 UTC (rev 18889)
@@ -12,6 +12,7 @@
SET (gnc_SOURCES
AccountItemModel.cpp
Book.cpp
+ Cmd.cpp
Numeric.cpp
RecentFileMenu.cpp
Session.cpp
@@ -30,6 +31,7 @@
SET (gnc_HEADERS ${gnc_QOBJECT_HEADERS}
Account.hpp
Book.hpp
+ Cmd.hpp
Session.hpp
Split.hpp
Transaction.hpp
Added: gnucash/trunk/src/gnc/Cmd.cpp
===================================================================
--- gnucash/trunk/src/gnc/Cmd.cpp (rev 0)
+++ gnucash/trunk/src/gnc/Cmd.cpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -0,0 +1,91 @@
+/*
+ * 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
+ */
+
+#include "Cmd.hpp"
+#include "gnc/Split.hpp"
+#include "gnc/Account.hpp"
+#include "gnc/Transaction.hpp"
+#include <QObject>
+
+namespace gnc
+{
+
+// Explicit instantiations to check for compiler errors
+template class Cmd<Account, QString>;
+
+namespace cmd
+{
+
+QUndoCommand* setSplitMemo(Split& t, const QString& newValue)
+{
+ return new Cmd<Split, QString>(QObject::tr("Edit Split Memo"),
+ t, &Split::setMemo,
+ &Split::getMemo, newValue);
+}
+
+QUndoCommand* setSplitAction(Split& t, const QString& newValue)
+{
+ return new Cmd<Split, QString>(QObject::tr("Edit Split Action"),
+ t, &Split::setAction,
+ &Split::getAction, newValue);
+}
+
+QUndoCommand* setSplitReconcile(Split& t, char newValue)
+{
+ return new Cmd<Split, char>(QObject::tr("Edit Split Reconcile"),
+ t, &Split::setReconcile,
+ &Split::getReconcile, newValue);
+}
+
+QUndoCommand* setTransactionNum(Transaction& t, const QString& newValue)
+{
+ return new Cmd<Transaction, QString>(QObject::tr("Edit Transaction Number"),
+ t, &Transaction::setNum,
+ &Transaction::getNum, newValue);
+}
+
+QUndoCommand* setTransactionDescription(Transaction& t, const QString& newValue)
+{
+ return new Cmd<Transaction, QString>(QObject::tr("Edit Transaction Description"),
+ t, &Transaction::setDescription,
+ &Transaction::getDescription, newValue);
+}
+
+QUndoCommand* setTransactionNotes(Transaction& t, const QString& newValue)
+{
+ return new Cmd<Transaction, QString>(QObject::tr("Edit Transaction Notes"),
+ t, &Transaction::setNotes,
+ &Transaction::getNotes, newValue);
+}
+
+QUndoCommand* setTransactionDate(Transaction& t, const QDateTime& newValue)
+{
+ return new Cmd<Transaction, QDateTime>(QObject::tr("Edit Transaction Date"),
+ t, &Transaction::setDatePosted,
+ &Transaction::getDatePosted, newValue);
+}
+
+
+} // END namespace cmd
+
+
+} // END namespace gnc
Modified: gnucash/trunk/src/gnc/Cmd.hpp
===================================================================
--- gnucash/trunk/src/gnc/Cmd.hpp 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/Cmd.hpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -24,11 +24,16 @@
#define GNC_CMD_HPP
#include <QUndoCommand>
-#include <gnc/Split.hpp>
+#include <gnc/WeakPointer.hpp>
+#include <gnc/Numeric.hpp>
namespace gnc
{
+class Split;
+class Account;
+class Transaction;
+
template<class TargetT, class ValueT>
class Cmd : public QUndoCommand
{
@@ -38,26 +43,27 @@
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,
+// 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,
+ WeakPointer<typename TargetT::element_type>& targetPtr,
+ setter_func setter,
getter_func getter,
const value_type& newValue,
QUndoCommand *parent = 0)
: QUndoCommand(text, parent)
- , m_target(target)
+ , m_target(targetPtr.get())
, m_setter(setter)
, m_previousValue((m_target.*getter)())
, m_newValue(newValue)
@@ -77,7 +83,7 @@
protected:
- TargetT& m_target;
+ TargetT m_target;
setter_func m_setter;
value_type m_previousValue;
value_type m_newValue;
@@ -86,12 +92,18 @@
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);
-}
+// This is the collection of command objects which are already
+// provided for the different data types and their simple
+// members. Just create one of those, add it to a QUndoStack, and
+// magically the values will change with undo/redo back and
+// forth. Spooky, IMHO.
+QUndoCommand* setSplitMemo(Split& split, const QString& newValue);
+QUndoCommand* setSplitAction(Split& t, const QString& newValue);
+QUndoCommand* setSplitReconcile(Split& t, char newValue);
+QUndoCommand* setTransactionNum(Transaction& t, const QString& newValue);
+QUndoCommand* setTransactionDescription(Transaction& t, const QString& newValue);
+QUndoCommand* setTransactionNotes(Transaction& t, const QString& newValue);
+QUndoCommand* setTransactionDate(Transaction& t, const QDateTime& newValue);
} // END namespace cmd
Modified: gnucash/trunk/src/gnc/RecentFileMenu.cpp
===================================================================
--- gnucash/trunk/src/gnc/RecentFileMenu.cpp 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/RecentFileMenu.cpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -80,7 +80,7 @@
const QString& qs = m_fileNames.at(i);
QAction *act = m_actionRecentFile[i];
act->setVisible(true);
- act->setText(tr("&%1 %2").arg(i+1).arg(QFileInfo(qs).fileName()));
+ act->setText(tr("&%1 %2").arg(i + 1).arg(QFileInfo(qs).fileName()));
act->setStatusTip(qs);
act->setData(qs);
}
Modified: gnucash/trunk/src/gnc/Split.hpp
===================================================================
--- gnucash/trunk/src/gnc/Split.hpp 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/Split.hpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -68,7 +68,7 @@
void setAction(const QString& v) { xaccSplitSetAction(get(), v.toUtf8()); }
char getReconcile() const { return xaccSplitGetReconcile(get()); }
- void setReconcile(char v) { xaccSplitSetReconcile(get(), v); }
+ void setReconcile(const char& v) { xaccSplitSetReconcile(get(), v); }
Split getOtherSplit() const { return xaccSplitGetOtherSplit(get()); }
Modified: gnucash/trunk/src/gnc/SplitListModel.cpp
===================================================================
--- gnucash/trunk/src/gnc/SplitListModel.cpp 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/SplitListModel.cpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -22,14 +22,17 @@
#include "SplitListModel.hpp"
#include "gnc/Transaction.hpp"
+#include "gnc/Cmd.hpp"
#include <QDebug>
+#include <QUndoStack>
namespace gnc
{
-SplitListModel::SplitListModel(const SplitQList splits, QObject *parent)
+SplitListModel::SplitListModel(const SplitQList splits, QUndoStack* undoStack, QObject *parent)
: QAbstractItemModel(parent)
, m_list(splits)
+ , m_undoStack(undoStack)
{
}
@@ -100,8 +103,16 @@
if (!index.isValid())
return 0;
- // Ensure read-only access only
- return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ Qt::ItemFlags result = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+ switch (index.column())
+ {
+ case 2:
+ // Allow write access as well
+ return result | Qt::ItemIsEditable;
+ default:
+ // Ensure read-only access only
+ return result;
+ }
}
QVariant SplitListModel::headerData(int section, Qt::Orientation orientation, int role) const
@@ -133,5 +144,28 @@
return QString("%1").arg(1 + section);
}
+bool SplitListModel::setData(const QModelIndex &index, const QVariant &value, int role)
+{
+ if (index.isValid() && role == Qt::EditRole)
+ {
+ Split split(static_cast< ::Split*>(index.internalPointer()));
+ Transaction trans(split.getParent());
+ switch (index.column())
+ {
+ case 2:
+ // We allow to edit column 2. "Editing" is done by
+ // creating a Cmd-object and adding it to the undo
+ // stack. That's in fact all that was needed to create an
+ // *undoable* edit of this data cell. Seems almost spooky,
+ // doesn't it?
+ m_undoStack->push(cmd::setTransactionDescription(trans, value.toString()));
+ emit dataChanged(index, index);
+ return true;
+ default:
+ return false;
+ }
+ }
+ return false;
+}
} // END namespace gnc
Modified: gnucash/trunk/src/gnc/SplitListModel.hpp
===================================================================
--- gnucash/trunk/src/gnc/SplitListModel.hpp 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/SplitListModel.hpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -26,6 +26,7 @@
#include "gnc/Split.hpp"
#include <QAbstractItemModel>
+class QUndoStack;
namespace gnc
{
@@ -36,7 +37,7 @@
{
Q_OBJECT
public:
- SplitListModel(const SplitQList splits, QObject *parent = 0);
+ SplitListModel(const SplitQList splits, QUndoStack* undoStack, QObject *parent = 0);
QModelIndex parent(const QModelIndex &index) const { return QModelIndex(); }
int rowCount(const QModelIndex& parent = QModelIndex()) const { return m_list.size(); }
@@ -47,9 +48,12 @@
QVariant data(const QModelIndex& index, int role) const;
QVariant headerData(int section, Qt::Orientation orientation, int role) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+
protected:
SplitQList m_list;
+ QUndoStack* m_undoStack;
};
} // END namespace gnc
Modified: gnucash/trunk/src/gnc/Transaction.hpp
===================================================================
--- gnucash/trunk/src/gnc/Transaction.hpp 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/Transaction.hpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -61,8 +61,8 @@
int countSplits() const { return xaccTransCountSplits(get()); }
- void setDatePosted(const QDateTime& t);
- void setDateEntered(const QDateTime& t);
+ void setDatePosted(const QDateTime& t) { xaccTransSetDatePostedSecs(get(), t.toTime_t()); }
+ void setDateEntered(const QDateTime& t) { xaccTransSetDateEnteredSecs(get(), t.toTime_t()); }
QDateTime getDatePosted() const { return toQDateTime(xaccTransRetDatePostedTS(get())); }
QDateTime getDateEntered() const { return toQDateTime(xaccTransRetDateEnteredTS(get())); }
Modified: gnucash/trunk/src/gnc/mainwindow.cpp
===================================================================
--- gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-10 19:38:03 UTC (rev 18888)
+++ gnucash/trunk/src/gnc/mainwindow.cpp 2010-03-10 21:40:58 UTC (rev 18889)
@@ -57,9 +57,6 @@
namespace gnc
{
-// Explicit instantiations to check for compiler errors
-template class Cmd<Account, QString>;
-
inline QString errorToString(QofBackendError err)
{
return errorToStringPair(err).first;
@@ -420,7 +417,7 @@
// We create a new model for this list of splits and also a view
// widget for this list.
QTableView *tableView = new QTableView(ui->tabWidget); // FIXME: Is this parent correct?
- SplitListModel *smodel = new SplitListModel(Split::fromGList(slist), tableView);
+ SplitListModel *smodel = new SplitListModel(Split::fromGList(slist), m_undoStack, tableView);
tableView->setModel(smodel);
tableView->setAlternatingRowColors(true);
More information about the gnucash-changes
mailing list