X-Git-Url: https://git.novaco.in/?a=blobdiff_plain;f=src%2Fqt%2Ftransactiontablemodel.cpp;h=17622e07faacf10949e6817aa4e672bf8368b0da;hb=51d7cc07f10209ac12bd5286391e3c8b095abd34;hp=bed08d7802526b004989e4c446ea611f90fa1326;hpb=0f3981bea94cea957f0de4b128f7feffbfc2d9c6;p=novacoin.git diff --git a/src/qt/transactiontablemodel.cpp b/src/qt/transactiontablemodel.cpp index bed08d7..17622e0 100644 --- a/src/qt/transactiontablemodel.cpp +++ b/src/qt/transactiontablemodel.cpp @@ -2,8 +2,11 @@ #include "guiutil.h" #include "transactionrecord.h" #include "guiconstants.h" -#include "main.h" #include "transactiondesc.h" +#include "walletmodel.h" +#include "addresstablemodel.h" + +#include "headers.h" #include #include @@ -11,11 +14,17 @@ #include #include #include +#include #include -const QString TransactionTableModel::Sent = "s"; -const QString TransactionTableModel::Received = "r"; -const QString TransactionTableModel::Other = "o"; +// Credit and Debit columns are right-aligned as they contain numbers +static int column_alignments[] = { + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignLeft|Qt::AlignVCenter, + Qt::AlignRight|Qt::AlignVCenter + }; // Comparison operator for sort/binary search of model tx list struct TxLessThan @@ -37,11 +46,12 @@ struct TxLessThan // Private implementation struct TransactionTablePriv { - TransactionTablePriv(TransactionTableModel *parent): + TransactionTablePriv(CWallet *wallet, TransactionTableModel *parent): + wallet(wallet), parent(parent) { } - + CWallet *wallet; TransactionTableModel *parent; /* Local cache of wallet. @@ -58,11 +68,11 @@ struct TransactionTablePriv qDebug() << "refreshWallet"; #endif cachedWallet.clear(); - CRITICAL_BLOCK(cs_mapWallet) + CRITICAL_BLOCK(wallet->cs_mapWallet) { - for(std::map::iterator it = mapWallet.begin(); it != mapWallet.end(); ++it) + for(std::map::iterator it = wallet->mapWallet.begin(); it != wallet->mapWallet.end(); ++it) { - cachedWallet.append(TransactionRecord::decomposeTransaction(it->second)); + cachedWallet.append(TransactionRecord::decomposeTransaction(wallet, it->second)); } } } @@ -84,14 +94,14 @@ struct TransactionTablePriv QList updated_sorted = updated; qSort(updated_sorted); - CRITICAL_BLOCK(cs_mapWallet) + CRITICAL_BLOCK(wallet->cs_mapWallet) { for(int update_idx = updated_sorted.size()-1; update_idx >= 0; --update_idx) { const uint256 &hash = updated_sorted.at(update_idx); /* Find transaction in wallet */ - std::map::iterator mi = mapWallet.find(hash); - bool inWallet = mi != mapWallet.end(); + std::map::iterator mi = wallet->mapWallet.find(hash); + bool inWallet = mi != wallet->mapWallet.end(); /* Find bounds of this transaction in model */ QList::iterator lower = qLowerBound( cachedWallet.begin(), cachedWallet.end(), hash, TxLessThan()); @@ -100,6 +110,7 @@ struct TransactionTablePriv int lowerIndex = (lower - cachedWallet.begin()); int upperIndex = (upper - cachedWallet.begin()); + // Determine if transaction is in model already bool inModel = false; if(lower != upper) { @@ -115,7 +126,7 @@ struct TransactionTablePriv { // Added -- insert at the right position QList toInsert = - TransactionRecord::decomposeTransaction(mi->second); + TransactionRecord::decomposeTransaction(wallet, mi->second); if(!toInsert.isEmpty()) /* only if something to insert */ { parent->beginInsertRows(QModelIndex(), lowerIndex, lowerIndex+toInsert.size()-1); @@ -159,11 +170,11 @@ struct TransactionTablePriv // simply re-use the cached status. if(rec->statusUpdateNeeded()) { - CRITICAL_BLOCK(cs_mapWallet) + CRITICAL_BLOCK(wallet->cs_mapWallet) { - std::map::iterator mi = mapWallet.find(rec->hash); + std::map::iterator mi = wallet->mapWallet.find(rec->hash); - if(mi != mapWallet.end()) + if(mi != wallet->mapWallet.end()) { rec->updateStatus(mi->second); } @@ -179,12 +190,12 @@ struct TransactionTablePriv QString describe(TransactionRecord *rec) { - CRITICAL_BLOCK(cs_mapWallet) + CRITICAL_BLOCK(wallet->cs_mapWallet) { - std::map::iterator mi = mapWallet.find(rec->hash); - if(mi != mapWallet.end()) + std::map::iterator mi = wallet->mapWallet.find(rec->hash); + if(mi != wallet->mapWallet.end()) { - return QString::fromStdString(TransactionDesc::toHTML(mi->second)); + return QString::fromStdString(TransactionDesc::toHTML(wallet, mi->second)); } } return QString(""); @@ -192,21 +203,13 @@ struct TransactionTablePriv }; -// Credit and Debit columns are right-aligned as they contain numbers -static int column_alignments[] = { - Qt::AlignLeft|Qt::AlignVCenter, - Qt::AlignLeft|Qt::AlignVCenter, - Qt::AlignLeft|Qt::AlignVCenter, - Qt::AlignRight|Qt::AlignVCenter, - Qt::AlignRight|Qt::AlignVCenter, - Qt::AlignLeft|Qt::AlignVCenter - }; - -TransactionTableModel::TransactionTableModel(QObject *parent): +TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *parent): QAbstractTableModel(parent), - priv(new TransactionTablePriv(this)) + wallet(wallet), + walletModel(parent), + priv(new TransactionTablePriv(wallet, this)) { - columns << tr("Status") << tr("Date") << tr("Description") << tr("Debit") << tr("Credit"); + columns << QString() << tr("Date") << tr("Type") << tr("Address") << tr("Amount"); priv->refreshWallet(); @@ -225,15 +228,15 @@ void TransactionTableModel::update() QList updated; // Check if there are changes to wallet map - TRY_CRITICAL_BLOCK(cs_mapWallet) + TRY_CRITICAL_BLOCK(wallet->cs_mapWallet) { - if(!vWalletUpdated.empty()) + if(!wallet->vWalletUpdated.empty()) { - BOOST_FOREACH(uint256 hash, vWalletUpdated) + BOOST_FOREACH(uint256 hash, wallet->vWalletUpdated) { updated.append(hash); } - vWalletUpdated.clear(); + wallet->vWalletUpdated.clear(); } } @@ -244,7 +247,7 @@ void TransactionTableModel::update() // 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)); + emit dataChanged(index(0, ToAddress), index(priv->size()-1, ToAddress)); } } @@ -270,18 +273,37 @@ QVariant TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) con status = tr("Open for %n block(s)","",wtx->status.open_for); break; case TransactionStatus::OpenUntilDate: - status = tr("Open until ") + GUIUtil::DateTimeStr(wtx->status.open_for); + status = tr("Open until %1").arg(GUIUtil::DateTimeStr(wtx->status.open_for)); break; case TransactionStatus::Offline: - status = tr("Offline (%1)").arg(wtx->status.depth); + status = tr("Offline (%1 confirmations)").arg(wtx->status.depth); break; case TransactionStatus::Unconfirmed: - status = tr("Unconfirmed (%1)").arg(wtx->status.depth); + status = tr("Unconfirmed (%1 of %2 confirmations required)").arg(wtx->status.depth).arg(TransactionRecord::NumConfirmations); break; case TransactionStatus::HaveConfirmations: - status = tr("Confirmed (%1)").arg(wtx->status.depth); + status = tr("Confirmed (%1 confirmations)").arg(wtx->status.depth); break; } + if(wtx->type == TransactionRecord::Generated) + { + status += "\n\n"; + switch(wtx->status.maturity) + { + case TransactionStatus::Immature: + status += tr("Mined balance will be available in %n more blocks", "", + wtx->status.matures_in); + break; + case TransactionStatus::Mature: + break; + case TransactionStatus::MaturesWarning: + status += tr("This block was not received by any other nodes and will probably not be accepted!"); + break; + case TransactionStatus::NotAccepted: + status += tr("Generated but not accepted"); + break; + } + } return QVariant(status); } @@ -299,128 +321,134 @@ QVariant TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const } /* Look up address in address book, if found return - address[0:12]... (label) + address (label) otherwise just return address */ -std::string lookupAddress(const std::string &address) +QString TransactionTableModel::lookupAddress(const std::string &address) const { - std::string description; - CRITICAL_BLOCK(cs_mapAddressBook) + QString label = walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(address)); + QString description; + if(label.isEmpty()) { - std::map::iterator mi = mapAddressBook.find(address); - if (mi != mapAddressBook.end() && !(*mi).second.empty()) - { - std::string label = (*mi).second; - description += address.substr(0,12) + "... "; - description += "(" + label + ")"; - } - else - { - description += address; - } + description = QString::fromStdString(address); + } + else + { + description = label + QString(" (") + QString::fromStdString(address) + QString(")"); } return description; } -QVariant TransactionTableModel::formatTxDescription(const TransactionRecord *wtx) const +QVariant TransactionTableModel::formatTxType(const TransactionRecord *wtx) const { QString description; switch(wtx->type) { case TransactionRecord::RecvWithAddress: - description = tr("Received with: ") + QString::fromStdString(lookupAddress(wtx->address)); + description = tr("Received with"); break; case TransactionRecord::RecvFromIP: - description = tr("Received from IP: ") + QString::fromStdString(wtx->address); + description = tr("Received from IP"); break; case TransactionRecord::SendToAddress: - description = tr("Sent to: ") + QString::fromStdString(lookupAddress(wtx->address)); + description = tr("Sent to"); break; case TransactionRecord::SendToIP: - description = tr("Sent to IP: ") + QString::fromStdString(wtx->address); + description = tr("Sent to IP"); break; case TransactionRecord::SendToSelf: description = tr("Payment to yourself"); break; case TransactionRecord::Generated: - switch(wtx->status.maturity) - { - case TransactionStatus::Immature: - description = tr("Generated (matures in %n more blocks)", "", - wtx->status.matures_in); - break; - case TransactionStatus::Mature: - description = tr("Generated"); - break; - case TransactionStatus::MaturesWarning: - description = tr("Generated - Warning: This block was not received by any other nodes and will probably not be accepted!"); - break; - case TransactionStatus::NotAccepted: - description = tr("Generated (not accepted)"); - break; - } + description = tr("Mined"); break; } return QVariant(description); } -QVariant TransactionTableModel::formatTxDebit(const TransactionRecord *wtx) const +QVariant TransactionTableModel::formatTxToAddress(const TransactionRecord *wtx) const { - if(wtx->debit) - { - QString str = QString::fromStdString(FormatMoney(wtx->debit)); - if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature) - { - str = QString("[") + str + QString("]"); - } - return QVariant(str); - } - else + QString description; + + switch(wtx->type) { - return QVariant(); + case TransactionRecord::RecvWithAddress: + description = lookupAddress(wtx->address); + break; + case TransactionRecord::RecvFromIP: + description = QString::fromStdString(wtx->address); + break; + case TransactionRecord::SendToAddress: + description = lookupAddress(wtx->address); + break; + case TransactionRecord::SendToIP: + description = QString::fromStdString(wtx->address); + break; + case TransactionRecord::SendToSelf: + description = QString(); + break; + case TransactionRecord::Generated: + description = QString(); + break; } + return QVariant(description); } -QVariant TransactionTableModel::formatTxCredit(const TransactionRecord *wtx) const +QVariant TransactionTableModel::formatTxAmount(const TransactionRecord *wtx, bool showUnconfirmed) const { - if(wtx->credit) + QString str = QString::fromStdString(FormatMoney(wtx->credit + wtx->debit)); + if(showUnconfirmed) { - QString str = QString::fromStdString(FormatMoney(wtx->credit)); if(!wtx->status.confirmed || wtx->status.maturity != TransactionStatus::Mature) { str = QString("[") + str + QString("]"); } - return QVariant(str); - } - else - { - return QVariant(); } + return QVariant(str); } QVariant TransactionTableModel::formatTxDecoration(const TransactionRecord *wtx) const { - switch(wtx->status.status) + if(wtx->type == TransactionRecord::Generated) { - 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) + switch(wtx->status.maturity) { - 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"); + case TransactionStatus::Immature: { + int total = wtx->status.depth + wtx->status.matures_in; + int part = (wtx->status.depth * 4 / total) + 1; + return QIcon(QString(":/icons/transaction_%1").arg(part)); + } + case TransactionStatus::Mature: + return QIcon(":/icons/transaction_confirmed"); + case TransactionStatus::MaturesWarning: + case TransactionStatus::NotAccepted: + return QIcon(":/icons/transaction_0"); + } + } + else + { + 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); } @@ -445,12 +473,12 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const { case Date: return formatTxDate(rec); - case Description: - return formatTxDescription(rec); - case Debit: - return formatTxDebit(rec); - case Credit: - return formatTxCredit(rec); + case Type: + return formatTxType(rec); + case ToAddress: + return formatTxToAddress(rec); + case Amount: + return formatTxAmount(rec); } } else if(role == Qt::EditRole) @@ -462,12 +490,12 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const 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; + case Type: + return formatTxType(rec); + case ToAddress: + return formatTxToAddress(rec); + case Amount: + return rec->credit + rec->debit; } } else if (role == Qt::ToolTipRole) @@ -488,27 +516,47 @@ QVariant TransactionTableModel::data(const QModelIndex &index, int role) const { return QColor(128, 128, 128); } + if(index.column() == Amount && (rec->credit+rec->debit) < 0) + { + return QColor(255, 0, 0); + } } else if (role == TypeRole) { - /* Role for filtering tabs by type */ - switch(rec->type) - { - case TransactionRecord::RecvWithAddress: - case TransactionRecord::RecvFromIP: - return TransactionTableModel::Received; - case TransactionRecord::SendToAddress: - case TransactionRecord::SendToIP: - case TransactionRecord::SendToSelf: - return TransactionTableModel::Sent; - default: - return TransactionTableModel::Other; - } + return rec->type; + } + else if (role == DateRole) + { + return QDateTime::fromTime_t(static_cast(rec->time)); } else if (role == LongDescriptionRole) { return priv->describe(rec); } + else if (role == AddressRole) + { + return QString::fromStdString(rec->address); + } + else if (role == LabelRole) + { + return walletModel->getAddressTableModel()->labelForAddress(QString::fromStdString(rec->address)); + } + else if (role == AbsoluteAmountRole) + { + return llabs(rec->credit + rec->debit); + } + else if (role == TxIDRole) + { + return QString::fromStdString(rec->getTxID()); + } + else if (role == ConfirmedRole) + { + return rec->status.status == TransactionStatus::HaveConfirmations; + } + else if (role == FormattedAmountRole) + { + return formatTxAmount(rec, false); + } return QVariant(); } @@ -528,15 +576,15 @@ QVariant TransactionTableModel::headerData(int section, Qt::Orientation orientat switch(section) { case Status: - return tr("Transaction status. Hover over this field to show number of transactions."); + return tr("Transaction status. Hover over this field to show number of confirmations."); 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."); + case Type: + return tr("Type of transaction."); + case ToAddress: + return tr("Destination address of transaction."); + case Amount: + return tr("Amount removed from or added to balance."); } } }