auto-update transaction list
authorWladimir J. van der Laan <laanwj@gmail.com>
Sat, 28 May 2011 18:32:19 +0000 (20:32 +0200)
committerWladimir J. van der Laan <laanwj@gmail.com>
Sat, 28 May 2011 18:32:19 +0000 (20:32 +0200)
bitcoin.pro
gui/include/guiconstants.h [new file with mode: 0644]
gui/include/transactionrecord.h
gui/include/transactiontablemodel.h
gui/src/bitcoingui.cpp
gui/src/clientmodel.cpp
gui/src/transactiontablemodel.cpp

index 5f406e8..e4d694e 100644 (file)
@@ -56,7 +56,8 @@ HEADERS += gui/include/bitcoingui.h \
     gui/src/clientmodel.h \
     gui/include/clientmodel.h \
     gui/include/guiutil.h \
-    gui/include/transactionrecord.h
+    gui/include/transactionrecord.h \
+    gui/include/guiconstants.h
 SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
     gui/src/transactiontablemodel.cpp \
     gui/src/addresstablemodel.cpp \
diff --git a/gui/include/guiconstants.h b/gui/include/guiconstants.h
new file mode 100644 (file)
index 0000000..cdd1a74
--- /dev/null
@@ -0,0 +1,11 @@
+#ifndef GUICONSTANTS_H
+#define GUICONSTANTS_H
+
+/* milliseconds between model updates */
+static const int MODEL_UPDATE_DELAY = 250;
+
+/* size of cache */
+static const unsigned int WALLET_CACHE_SIZE = 100;
+
+
+#endif // GUICONSTANTS_H
index 646f87c..9769d80 100644 (file)
@@ -75,6 +75,8 @@ public:
     {
     }
 
+    /* Decompose CWallet transaction to model transaction records.
+     */
     static bool showTransaction(const CWalletTx &wtx);
     static QList<TransactionRecord> decomposeTransaction(const CWalletTx &wtx);
 
index 1ea749d..b02019d 100644 (file)
@@ -37,8 +37,6 @@ public:
     QVariant headerData(int section, Qt::Orientation orientation, int role) const;
     Qt::ItemFlags flags(const QModelIndex &index) const;
     QModelIndex index ( int row, int column, const QModelIndex & parent = QModelIndex() ) const;
-public slots:
-    void updateWallet();
 private:
     QStringList columns;
     TransactionTableImpl *impl;
@@ -48,6 +46,9 @@ private:
     QVariant formatTxDescription(const TransactionRecord *wtx) const;
     QVariant formatTxDebit(const TransactionRecord *wtx) const;
     QVariant formatTxCredit(const TransactionRecord *wtx) const;
+
+private slots:
+    void update();
 };
 
 #endif
index 831bef3..b409744 100644 (file)
@@ -147,7 +147,7 @@ void BitcoinGUI::setModel(ClientModel *model)
     this->model = model;
 
     setBalance(model->getBalance());
-    connect(model, SIGNAL(balanceChanged(double)), this, SLOT(setBalance(double)));
+    connect(model, SIGNAL(balanceChanged(qint64)), this, SLOT(setBalance(qint64)));
 
     setNumConnections(model->getNumConnections());
     connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
@@ -197,12 +197,14 @@ QWidget *BitcoinGUI::createTabs()
         proxy_model->setDynamicSortFilter(true);
         proxy_model->setFilterRole(TransactionTableModel::TypeRole);
         proxy_model->setFilterRegExp(QRegExp(tab_filters.at(i)));
+        proxy_model->setSortRole(Qt::EditRole);
 
         QTableView *transaction_table = new QTableView(this);
         transaction_table->setModel(proxy_model);
         transaction_table->setSelectionBehavior(QAbstractItemView::SelectRows);
         transaction_table->setSelectionMode(QAbstractItemView::ExtendedSelection);
         transaction_table->setSortingEnabled(true);
+        transaction_table->sortByColumn(TransactionTableModel::Status, Qt::DescendingOrder);
         transaction_table->verticalHeader()->hide();
 
         transaction_table->horizontalHeader()->resizeSection(
index cc52df4..e355676 100644 (file)
@@ -1,11 +1,9 @@
 #include "clientmodel.h"
 #include "main.h"
+#include "guiconstants.h"
 
 #include <QTimer>
 
-/* milliseconds between model updates */
-const int MODEL_UPDATE_DELAY = 250;
-
 ClientModel::ClientModel(QObject *parent) :
     QObject(parent)
 {
index af8234b..3a50197 100644 (file)
@@ -1,12 +1,14 @@
 #include "transactiontablemodel.h"
 #include "guiutil.h"
 #include "transactionrecord.h"
+#include "guiconstants.h"
 #include "main.h"
 
 #include <QLocale>
 #include <QDebug>
 #include <QList>
 #include <QColor>
+#include <QTimer>
 
 const QString TransactionTableModel::Sent = "s";
 const QString TransactionTableModel::Received = "r";
@@ -16,14 +18,15 @@ const QString TransactionTableModel::Other = "o";
 class TransactionTableImpl
 {
 public:
+    /* Local cache of wallet.
+     * As it is in the same order as the CWallet, by definition
+     * this is sorted by sha256.
+     */
     QList<TransactionRecord> cachedWallet;
 
-    /* Update our model of the wallet */
-    void updateWallet()
+    void refreshWallet()
     {
-        QList<int> insertedIndices;
-        QList<int> removedIndices;
-
+        qDebug() << "refreshWallet";
         cachedWallet.clear();
 
         /* Query wallet from core, and compare with our own
@@ -45,6 +48,26 @@ public:
         /* beginEndRows */
     }
 
+    /* Update our model of the wallet.
+       Call with list of hashes of transactions that were added, removed or changed.
+     */
+    void updateWallet(const QList<uint256> &updated)
+    {
+        /* TODO: update only transactions in updated, and only if
+           the transactions are really part of the visible wallet.
+
+           Update status of the other transactions in the cache just in case,
+           because this call means that a new block came in.
+         */
+        qDebug() << "updateWallet";
+        foreach(uint256 hash, updated)
+        {
+            qDebug() << "  " << QString::fromStdString(hash.ToString());
+        }
+
+        refreshWallet();
+    }
+
     int size()
     {
         return cachedWallet.size();
@@ -59,6 +82,7 @@ public:
             return 0;
         }
     }
+
 };
 
 /* Credit and Debit columns are right-aligned as they contain numbers */
@@ -77,7 +101,11 @@ TransactionTableModel::TransactionTableModel(QObject *parent):
 {
     columns << tr("Status") << tr("Date") << tr("Description") << tr("Debit") << tr("Credit");
 
-    impl->updateWallet();
+    impl->refreshWallet();
+
+    QTimer *timer = new QTimer(this);
+    connect(timer, SIGNAL(timeout()), this, SLOT(update()));
+    timer->start(MODEL_UPDATE_DELAY);
 }
 
 TransactionTableModel::~TransactionTableModel()
@@ -85,15 +113,33 @@ TransactionTableModel::~TransactionTableModel()
     delete impl;
 }
 
-void TransactionTableModel::updateWallet()
+void TransactionTableModel::update()
 {
-    /* TODO: improve this, way too brute-force at the moment,
-       only update transactions that actually changed, and add/remove
-       transactions that were added/removed.
-     */
-    beginResetModel();
-    impl->updateWallet();
-    endResetModel();
+    QList<uint256> updated;
+
+    /* Check if there are changes to wallet map */
+    TRY_CRITICAL_BLOCK(cs_mapWallet)
+    {
+        if(!vWalletUpdated.empty())
+        {
+            BOOST_FOREACH(uint256 hash, vWalletUpdated)
+            {
+                updated.append(hash);
+            }
+            vWalletUpdated.clear();
+        }
+    }
+
+    if(!updated.empty())
+    {
+        /* TODO: improve this, way too brute-force at the moment,
+           only update transactions that actually changed, and add/remove
+           transactions that were added/removed.
+         */
+        beginResetModel();
+        impl->updateWallet(updated);
+        endResetModel();
+    }
 }
 
 int TransactionTableModel::rowCount(const QModelIndex &parent) const
@@ -261,6 +307,22 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
         case Credit:
             return formatTxCredit(rec);
         }
+    } else if(role == Qt::EditRole)
+    {
+        /* Edit role is used for sorting so return the real values */
+        switch(index.column())
+        {
+        case Status:
+            return QString::fromStdString(rec->status.sortKey);
+        case Date:
+            return rec->time;
+        case Description:
+            return formatTxDescription(rec);
+        case Debit:
+            return rec->debit;
+        case Credit:
+            return rec->credit;
+        }
     } else if (role == Qt::TextAlignmentRole)
     {
         return column_alignments[index.column()];