#include <QList>
#include <QColor>
#include <QTimer>
+#include <QIcon>
#include <QtAlgorithms>
const QString TransactionTableModel::Sent = "s";
const QString TransactionTableModel::Received = "r";
const QString TransactionTableModel::Other = "o";
-/* Comparison operator for sort/binary search of model tx list */
+// Comparison operator for sort/binary search of model tx list
struct TxLessThan
{
bool operator()(const TransactionRecord &a, const TransactionRecord &b) const
}
};
-/* Private implementation */
+// Private implementation
struct TransactionTablePriv
{
TransactionTablePriv(TransactionTableModel *parent):
*/
QList<TransactionRecord> cachedWallet;
+ /* Query entire wallet anew from core.
+ */
void refreshWallet()
{
+#ifdef WALLET_UPDATE_DEBUG
qDebug() << "refreshWallet";
-
- /* Query entire wallet from core.
- */
+#endif
cachedWallet.clear();
CRITICAL_BLOCK(cs_mapWallet)
{
}
}
- /* Update our model of the wallet incrementally.
+ /* Update our model of the wallet incrementally, to synchronize our model of the wallet
+ with that of the core.
+
Call with list of hashes of transactions that were added, removed or changed.
*/
void updateWallet(const QList<uint256> &updated)
{
- /* Walk through updated transactions, update model as needed.
- */
+ // Walk through updated transactions, update model as needed.
+#ifdef WALLET_UPDATE_DEBUG
qDebug() << "updateWallet";
-
- /* Sort update list, and iterate through it in reverse, so that model updates
- can be emitted from end to beginning (so that earlier updates will not influence
- the indices of latter ones).
- */
+#endif
+ // Sort update list, and iterate through it in reverse, so that model updates
+ // can be emitted from end to beginning (so that earlier updates will not influence
+ // the indices of latter ones).
QList<uint256> updated_sorted = updated;
qSort(updated_sorted);
inModel = true;
}
+#ifdef WALLET_UPDATE_DEBUG
qDebug() << " " << QString::fromStdString(hash.ToString()) << inWallet << " " << inModel
<< lowerIndex << "-" << upperIndex;
+#endif
if(inWallet && !inModel)
{
- /* Added */
+ // Added -- insert at the right position
QList<TransactionRecord> toInsert =
TransactionRecord::decomposeTransaction(mi->second);
if(!toInsert.isEmpty()) /* only if something to insert */
}
else if(!inWallet && inModel)
{
- /* Removed */
+ // Removed -- remove entire transaction from table
parent->beginRemoveRows(QModelIndex(), lowerIndex, upperIndex-1);
cachedWallet.erase(lower, upper);
parent->endRemoveRows();
}
else if(inWallet && inModel)
{
- /* Updated -- nothing to do, status update will take care of this */
+ // Updated -- nothing to do, status update will take care of this
}
}
}
{
TransactionRecord *rec = &cachedWallet[idx];
- /* If a status update is needed (blocks came in since last check),
- update the status of this transaction from the wallet. Otherwise,
- simply re-use the cached status.
- */
+ // If a status update is needed (blocks came in since last check),
+ // update the status of this transaction from the wallet. Otherwise,
+ // simply re-use the cached status.
if(rec->statusUpdateNeeded())
{
CRITICAL_BLOCK(cs_mapWallet)
};
-/* Credit and Debit columns are right-aligned as they contain numbers */
+// Credit and Debit columns are right-aligned as they contain numbers
static int column_alignments[] = {
Qt::AlignLeft|Qt::AlignVCenter,
Qt::AlignLeft|Qt::AlignVCenter,
{
QList<uint256> updated;
- /* Check if there are changes to wallet map */
+ // Check if there are changes to wallet map
TRY_CRITICAL_BLOCK(cs_mapWallet)
{
if(!vWalletUpdated.empty())
{
priv->updateWallet(updated);
- /* Status (number of confirmations) and (possibly) description
- columns changed for all rows.
- */
+ // Status (number of confirmations) and (possibly) description
+ // columns changed for all rows.
emit dataChanged(index(0, Status), index(priv->size()-1, Status));
emit dataChanged(index(0, Description), index(priv->size()-1, Description));
}
status = tr("Open until ") + GUIUtil::DateTimeStr(wtx->status.open_for);
break;
case TransactionStatus::Offline:
- status = tr("%1/offline").arg(wtx->status.depth);
+ status = tr("Offline (%1)").arg(wtx->status.depth);
break;
case TransactionStatus::Unconfirmed:
- status = tr("%1/unconfirmed").arg(wtx->status.depth);
+ status = tr("Unconfirmed (%1)").arg(wtx->status.depth);
break;
case TransactionStatus::HaveConfirmations:
- status = tr("%1 confirmations").arg(wtx->status.depth);
+ status = tr("Confirmed (%1)").arg(wtx->status.depth);
break;
}
}
}
+QVariant TransactionTableModel::formatTxDecoration(const TransactionRecord *wtx) const
+{
+ switch(wtx->status.status)
+ {
+ case TransactionStatus::OpenUntilBlock:
+ case TransactionStatus::OpenUntilDate:
+ return QColor(64,64,255);
+ break;
+ case TransactionStatus::Offline:
+ return QColor(192,192,192);
+ case TransactionStatus::Unconfirmed:
+ switch(wtx->status.depth)
+ {
+ case 0: return QIcon(":/icons/transaction_0");
+ case 1: return QIcon(":/icons/transaction_1");
+ case 2: return QIcon(":/icons/transaction_2");
+ case 3: return QIcon(":/icons/transaction_3");
+ case 4: return QIcon(":/icons/transaction_4");
+ default: return QIcon(":/icons/transaction_5");
+ };
+ case TransactionStatus::HaveConfirmations:
+ return QIcon(":/icons/transaction_confirmed");
+ }
+ return QColor(0,0,0);
+}
+
QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
{
if(!index.isValid())
return QVariant();
TransactionRecord *rec = static_cast<TransactionRecord*>(index.internalPointer());
- if(role == Qt::DisplayRole)
+ if(role == Qt::DecorationRole)
{
- /* Delegate to specific column handlers */
+ if(index.column() == Status)
+ {
+ return formatTxDecoration(rec);
+ }
+ }
+ else if(role == Qt::DisplayRole)
+ {
+ // Delegate to specific column handlers
switch(index.column())
{
- case Status:
- return formatTxStatus(rec);
case Date:
return formatTxDate(rec);
case Description:
}
else if(role == Qt::EditRole)
{
- /* Edit role is used for sorting so return the real values */
+ // Edit role is used for sorting so return the real values
switch(index.column())
{
case Status:
return rec->credit;
}
}
+ else if (role == Qt::ToolTipRole)
+ {
+ if(index.column() == Status)
+ {
+ return formatTxStatus(rec);
+ }
+ }
else if (role == Qt::TextAlignmentRole)
{
return column_alignments[index.column()];
else if (role == Qt::ForegroundRole)
{
/* Non-confirmed transactions are grey */
- if(rec->status.confirmed)
- {
- return QColor(0, 0, 0);
- }
- else
+ if(!rec->status.confirmed)
{
return QColor(128, 128, 128);
}
else if (role == Qt::TextAlignmentRole)
{
return column_alignments[section];
+ } else if (role == Qt::ToolTipRole)
+ {
+ switch(section)
+ {
+ case Status:
+ return tr("Transaction status. Hover over this field to show number of transactions.");
+ case Date:
+ return tr("Date and time that the transaction was received.");
+ case Description:
+ return tr("Short description of the transaction.");
+ case Debit:
+ return tr("Amount removed from balance.");
+ case Credit:
+ return tr("Amount added to balance.");
+ }
}
}
return QVariant();