r18912 - gnucash/trunk/src/gnc - Add event registration and handling from the qof_event_handlers.

Christian Stimming cstim at code.gnucash.org
Mon Mar 15 14:38:26 EDT 2010


Author: cstim
Date: 2010-03-15 14:38:26 -0400 (Mon, 15 Mar 2010)
New Revision: 18912
Trac: http://svn.gnucash.org/trac/changeset/18912

Added:
   gnucash/trunk/src/gnc/QofEventWrapper.cpp
   gnucash/trunk/src/gnc/QofEventWrapper.hpp
Modified:
   gnucash/trunk/src/gnc/CMakeLists.txt
   gnucash/trunk/src/gnc/SplitListModel.cpp
   gnucash/trunk/src/gnc/SplitListModel.hpp
   gnucash/trunk/src/gnc/main.cpp
Log:
Add event registration and handling from the qof_event_handlers.

This way, the split view is updated correctly even on undo/redo.

Modified: gnucash/trunk/src/gnc/CMakeLists.txt
===================================================================
--- gnucash/trunk/src/gnc/CMakeLists.txt	2010-03-15 16:10:26 UTC (rev 18911)
+++ gnucash/trunk/src/gnc/CMakeLists.txt	2010-03-15 18:38:26 UTC (rev 18912)
@@ -14,6 +14,7 @@
   Book.cpp
   Cmd.cpp
   Numeric.cpp
+  QofEventWrapper.cpp
   RecentFileMenu.cpp
   Session.cpp
   Split.cpp
@@ -32,6 +33,7 @@
   Account.hpp
   Book.hpp
   Cmd.hpp
+  QofEventWrapper.hpp
   Session.hpp
   Split.hpp
   Transaction.hpp

Added: gnucash/trunk/src/gnc/QofEventWrapper.cpp
===================================================================
--- gnucash/trunk/src/gnc/QofEventWrapper.cpp	                        (rev 0)
+++ gnucash/trunk/src/gnc/QofEventWrapper.cpp	2010-03-15 18:38:26 UTC (rev 18912)
@@ -0,0 +1,59 @@
+/*
+ * QofEventWrapper.cpp
+ * 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 "QofEventWrapper.hpp"
+#include "engine/gnc-event.h"
+
+#include "gnc/SplitListModel.hpp"
+#include "gnc/Transaction.hpp"
+
+namespace gnc
+{
+
+// Explicit instantiation to check for compiler errors
+template class QofEventWrapper<SplitListModel, ::Transaction*>;
+
+#define EVENT_TO_STR(result, input, evtype) \
+    if ((input) & (evtype)) result += QString(result.isEmpty() ? "" : ",") + #evtype
+
+QString qofEventToString(QofEventId event_type)
+{
+    if (event_type == QOF_EVENT_NONE)
+        return "NONE";
+    QString r;
+    EVENT_TO_STR(r, event_type, QOF_EVENT_CREATE);
+    EVENT_TO_STR(r, event_type, QOF_EVENT_MODIFY);
+    EVENT_TO_STR(r, event_type, QOF_EVENT_DESTROY);
+    EVENT_TO_STR(r, event_type, QOF_EVENT_ADD);
+    EVENT_TO_STR(r, event_type, QOF_EVENT_REMOVE);
+
+    EVENT_TO_STR(r, event_type, GNC_EVENT_ITEM_ADDED);
+    EVENT_TO_STR(r, event_type, GNC_EVENT_ITEM_REMOVED);
+    EVENT_TO_STR(r, event_type, GNC_EVENT_ITEM_CHANGED);
+
+    if (r.isEmpty())
+        r = QString::number(event_type);
+    return r;
+}
+
+
+} // END namespace gnc

Added: gnucash/trunk/src/gnc/QofEventWrapper.hpp
===================================================================
--- gnucash/trunk/src/gnc/QofEventWrapper.hpp	                        (rev 0)
+++ gnucash/trunk/src/gnc/QofEventWrapper.hpp	2010-03-15 18:38:26 UTC (rev 18912)
@@ -0,0 +1,116 @@
+/*
+ * QofEventWrapper.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_QOFEVENTWRAPPER_HPP
+#define GNC_QOFEVENTWRAPPER_HPP
+
+// gnucash includes
+#include "config.h" // required by qof/qofutil.h
+extern "C"
+{
+#include "qof.h"
+}
+
+#include <QString>
+#include <QDebug>
+
+namespace gnc
+{
+
+/** Conversion of the event_type to string (for debugging) */
+QString qofEventToString(QofEventId event_type);
+
+/** Retrieval of the Qof instance class name (for debugging) */
+inline const char* getQofType(QofInstance* obj)
+{
+    return obj->e_type;
+}
+
+/** Template wrapper class for objects which want to receive
+ * notifications from the qof_event system in any of their member
+ * functions.
+ *
+ * The receiver's class is the first template argument; the argument
+ * type of the to-be-called member function is the second template
+ * (usually a pointer type). */
+template<class ReceiverT, class ValuePtrT, typename SlotFunc = void (ReceiverT::*)(ValuePtrT)>
+class QofEventWrapper
+{
+public:
+    QofEventWrapper(ReceiverT& receiver,
+                    SlotFunc recvSlot,
+                    const char* qof_type,
+                    QofEventId event_type)
+            : m_receiver(receiver)
+            , m_receiveFunc(recvSlot)
+            , m_qof_type(qof_type)
+            , m_event_type(event_type)
+    {
+        m_handler_id = qof_event_register_handler(QofEventWrapper::event_handler, this);
+    }
+
+    ~QofEventWrapper()
+    {
+        qof_event_unregister_handler(m_handler_id);
+    }
+
+    static void event_handler (QofInstance *entity,  QofEventId event_type,
+                               gpointer user_data, gpointer event_data)
+    {
+        QofEventWrapper* wrapper = static_cast<QofEventWrapper *>(user_data);
+        wrapper->private_event_handler(entity, event_type, event_data);
+    }
+
+private:
+    void private_event_handler (QofInstance *entity,  QofEventId event_type,
+                                gpointer event_data)
+    {
+//         qDebug() << "private_event_handler, id=" << qofEventToString(event_type)
+//         << "entity=" << getQofType(entity);
+
+        // Verify that we have the correct QofInstance type and also
+        // correct event type
+        if (!QOF_CHECK_TYPE(entity, m_qof_type))
+            return;
+        if ((event_type & m_event_type) == 0)
+            return;
+
+        qDebug() << "private_event_handler, id=" << qofEventToString(event_type)
+        << "entity=" << getQofType(entity);
+
+        ValuePtrT vptr = reinterpret_cast<ValuePtrT>(entity);
+
+        // Call the pointer-to-member function with that weird C++
+        // syntax
+        (m_receiver.*m_receiveFunc)(vptr);
+    }
+
+    ReceiverT& m_receiver;
+    SlotFunc m_receiveFunc;
+    const char* m_qof_type;
+    QofEventId m_event_type;
+    gint m_handler_id;
+};
+
+} // END namespace gnc
+
+#endif

Modified: gnucash/trunk/src/gnc/SplitListModel.cpp
===================================================================
--- gnucash/trunk/src/gnc/SplitListModel.cpp	2010-03-15 16:10:26 UTC (rev 18911)
+++ gnucash/trunk/src/gnc/SplitListModel.cpp	2010-03-15 18:38:26 UTC (rev 18912)
@@ -23,19 +23,33 @@
 #include "SplitListModel.hpp"
 #include "gnc/Transaction.hpp"
 #include "gnc/Cmd.hpp"
+#include "gnc/Session.hpp"
 #include <QDebug>
 #include <QUndoStack>
 
 namespace gnc
 {
 
+
+
 SplitListModel::SplitListModel(const SplitQList splits, QUndoStack* undoStack, QObject *parent)
         : QAbstractItemModel(parent)
         , m_list(splits)
         , m_undoStack(undoStack)
+        , m_eventWrapper(*this, &SplitListModel::transactionModified,
+                         GNC_ID_TRANS, QOF_EVENT_MODIFY)
 {
+    // Cache the mapping of transactions to split in the m_hash
+    for (int k = 0; k < m_list.size(); ++k)
+    {
+        m_hash.insert(Split(m_list[k]).getParent().get(), k);
+    }
 }
 
+SplitListModel::~SplitListModel()
+{
+}
+
 QModelIndex SplitListModel::index(int row, int column,
                                   const QModelIndex &parent) const
 {
@@ -62,6 +76,29 @@
     return 8; // Fixed number for now
 }
 
+Qt::ItemFlags SplitListModel::flags(const QModelIndex &index) const
+{
+    //qDebug() << "flags()" << index;
+    if (!index.isValid())
+        return 0;
+
+    Qt::ItemFlags result = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+    switch (index.column())
+    {
+    case 0:
+    case 1:
+    case 2:
+    case 4:
+        //case 5:
+        //case 6:
+        // Allow write access as well
+        return result | Qt::ItemIsEditable;
+    default:
+        // Ensure read-only access only
+        return result;
+    }
+}
+
 QVariant SplitListModel::data(const QModelIndex& index, int role) const
 {
     //qDebug() << "data(), " << index;
@@ -106,29 +143,6 @@
         return QVariant();
 }
 
-Qt::ItemFlags SplitListModel::flags(const QModelIndex &index) const
-{
-    //qDebug() << "flags()" << index;
-    if (!index.isValid())
-        return 0;
-
-    Qt::ItemFlags result = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
-    switch (index.column())
-    {
-    case 0:
-    case 1:
-    case 2:
-    case 4:
-        //case 5:
-        //case 6:
-        // 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
 {
     //qDebug() << "headerData()" << section;
@@ -222,10 +236,21 @@
     if (cmd)
     {
         m_undoStack->push(cmd);
-        emit dataChanged(index, index);
+        // No dataChanged() signal here because it is emitted from the
+        // transactionChanged slot.
         return true;
     }
     return false;
 }
 
+void SplitListModel::transactionModified( ::Transaction* trans)
+{
+    if (m_hash.contains(trans))
+    {
+        int row = m_hash.value(trans);
+        emit dataChanged(index(row, 0), index(row, columnCount() - 1));
+    }
+
+}
+
 } // END namespace gnc

Modified: gnucash/trunk/src/gnc/SplitListModel.hpp
===================================================================
--- gnucash/trunk/src/gnc/SplitListModel.hpp	2010-03-15 16:10:26 UTC (rev 18911)
+++ gnucash/trunk/src/gnc/SplitListModel.hpp	2010-03-15 18:38:26 UTC (rev 18912)
@@ -24,8 +24,15 @@
 #define GNC_SPLITLISTMODEL_HPP
 
 #include "gnc/Split.hpp"
+#include "gnc/QofEventWrapper.hpp"
 
+extern "C"
+{
+#include "engine/Transaction.h"
+}
+
 #include <QAbstractItemModel>
+#include <QHash>
 class QUndoStack;
 
 namespace gnc
@@ -38,6 +45,7 @@
     Q_OBJECT
 public:
     SplitListModel(const SplitQList splits, QUndoStack* undoStack, QObject *parent = 0);
+    ~SplitListModel();
 
     QModelIndex parent(const QModelIndex &index) const { return QModelIndex(); }
     int rowCount(const QModelIndex& parent = QModelIndex()) const { return m_list.size(); }
@@ -50,10 +58,17 @@
     QVariant headerData(int section, Qt::Orientation orientation, int role) const;
     bool setData(const QModelIndex &index, const QVariant &value, int role);
 
+public slots:
+    void transactionModified( ::Transaction* trans);
 
 protected:
     SplitQList m_list;
     QUndoStack* m_undoStack;
+    typedef QHash< ::Transaction*, int> TransactionRowHash;
+    TransactionRowHash m_hash;
+
+    /** The wrapper for receiving events from gnc. */
+    QofEventWrapper<SplitListModel, ::Transaction*> m_eventWrapper;
 };
 
 } // END namespace gnc

Modified: gnucash/trunk/src/gnc/main.cpp
===================================================================
--- gnucash/trunk/src/gnc/main.cpp	2010-03-15 16:10:26 UTC (rev 18911)
+++ gnucash/trunk/src/gnc/main.cpp	2010-03-15 18:38:26 UTC (rev 18912)
@@ -186,15 +186,21 @@
     gnc_module_init_business_core_xml_init();
     gnc_ui_util_init();
 
-    // From here on the new C++ code
-    QApplication app(argc, argv);
-    gnc::MainWindow mainWin;
-    mainWin.show();
+    int r;
+    {
+        // From here on the new C++ code
+        QApplication app(argc, argv);
+        gnc::MainWindow mainWin;
+        mainWin.show();
 
-    // Go into the main qt event loop
-    int r = app.exec();
+        // Go into the main qt event loop
+        r = app.exec();
 
-    // Shutdown
+        // Destruction of the MainWindow will trigger all the C++
+        // destructors
+    }
+
+    // Shutdown of the C side after all C++ was destructed already.
     //gnc_module_finalize_backend_dbi();
     qof_close();
     return r;



More information about the gnucash-changes mailing list