work on transaction list model
This commit is contained in:
parent
213f763630
commit
0856c1a03e
5 changed files with 375 additions and 84 deletions
|
@ -54,7 +54,8 @@ HEADERS += gui/include/bitcoingui.h \
|
||||||
json/include/json/json_spirit.h \
|
json/include/json/json_spirit.h \
|
||||||
core/include/rpc.h \
|
core/include/rpc.h \
|
||||||
gui/src/clientmodel.h \
|
gui/src/clientmodel.h \
|
||||||
gui/include/clientmodel.h
|
gui/include/clientmodel.h \
|
||||||
|
gui/include/guiutil.h
|
||||||
SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
|
SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
|
||||||
gui/src/transactiontablemodel.cpp \
|
gui/src/transactiontablemodel.cpp \
|
||||||
gui/src/addresstablemodel.cpp \
|
gui/src/addresstablemodel.cpp \
|
||||||
|
@ -78,7 +79,8 @@ SOURCES += gui/src/bitcoin.cpp gui/src/bitcoingui.cpp \
|
||||||
json/src/json_spirit_writer.cpp \
|
json/src/json_spirit_writer.cpp \
|
||||||
json/src/json_spirit_value.cpp \
|
json/src/json_spirit_value.cpp \
|
||||||
json/src/json_spirit_reader.cpp \
|
json/src/json_spirit_reader.cpp \
|
||||||
gui/src/clientmodel.cpp
|
gui/src/clientmodel.cpp \
|
||||||
|
gui/src/guiutil.cpp
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
gui/bitcoin.qrc
|
gui/bitcoin.qrc
|
||||||
|
|
8
gui/include/guiutil.h
Normal file
8
gui/include/guiutil.h
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
#ifndef GUIUTIL_H
|
||||||
|
#define GUIUTIL_H
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
QString DateTimeStr(qint64 nTime);
|
||||||
|
|
||||||
|
#endif // GUIUTIL_H
|
|
@ -26,10 +26,11 @@ public:
|
||||||
TypeRole = Qt::UserRole
|
TypeRole = Qt::UserRole
|
||||||
} RoleIndex;
|
} RoleIndex;
|
||||||
|
|
||||||
/* Transaction type */
|
/* TypeRole values */
|
||||||
static const QString Sent;
|
static const QString Sent;
|
||||||
static const QString Received;
|
static const QString Received;
|
||||||
static const QString Generated;
|
static const QString Generated;
|
||||||
|
static const QString Other;
|
||||||
|
|
||||||
int rowCount(const QModelIndex &parent) const;
|
int rowCount(const QModelIndex &parent) const;
|
||||||
int columnCount(const QModelIndex &parent) const;
|
int columnCount(const QModelIndex &parent) const;
|
||||||
|
|
9
gui/src/guiutil.cpp
Normal file
9
gui/src/guiutil.cpp
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
#include "guiutil.h"
|
||||||
|
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
QString DateTimeStr(qint64 nTime)
|
||||||
|
{
|
||||||
|
QDateTime date = QDateTime::fromMSecsSinceEpoch(nTime*1000);
|
||||||
|
return date.toString(Qt::DefaultLocaleShortDate) + QString(" ") + date.toString("hh:mm");
|
||||||
|
}
|
|
@ -1,4 +1,5 @@
|
||||||
#include "transactiontablemodel.h"
|
#include "transactiontablemodel.h"
|
||||||
|
#include "guiutil.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include <QLocale>
|
#include <QLocale>
|
||||||
|
@ -8,67 +9,320 @@
|
||||||
const QString TransactionTableModel::Sent = "s";
|
const QString TransactionTableModel::Sent = "s";
|
||||||
const QString TransactionTableModel::Received = "r";
|
const QString TransactionTableModel::Received = "r";
|
||||||
const QString TransactionTableModel::Generated = "g";
|
const QString TransactionTableModel::Generated = "g";
|
||||||
|
const QString TransactionTableModel::Other = "o";
|
||||||
|
|
||||||
/* Separate transaction record format from core.
|
/* TODO: look up address in address book
|
||||||
* When the GUI is going to communicate with the core through the network,
|
when showing.
|
||||||
* we'll need our own internal formats anyway.
|
Color based on confirmation status.
|
||||||
|
(fConfirmed ? wxColour(0,0,0) : wxColour(128,128,128))
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
class TransactionStatus
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
TransactionStatus():
|
||||||
|
confirmed(false), sortKey(""), maturity(Mature),
|
||||||
|
matures_in(0), status(Offline), depth(0), open_for(0)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
enum Maturity
|
||||||
|
{
|
||||||
|
Immature,
|
||||||
|
Mature,
|
||||||
|
MaturesIn,
|
||||||
|
MaturesWarning, /* Will probably not mature because no nodes have confirmed */
|
||||||
|
NotAccepted
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Status {
|
||||||
|
OpenUntilDate,
|
||||||
|
OpenUntilBlock,
|
||||||
|
Offline,
|
||||||
|
Unconfirmed,
|
||||||
|
HaveConfirmations
|
||||||
|
};
|
||||||
|
|
||||||
|
bool confirmed;
|
||||||
|
std::string sortKey;
|
||||||
|
|
||||||
|
/* For "Generated" transactions */
|
||||||
|
Maturity maturity;
|
||||||
|
int matures_in;
|
||||||
|
|
||||||
|
/* Reported status */
|
||||||
|
Status status;
|
||||||
|
int64 depth;
|
||||||
|
int64 open_for; /* Timestamp if status==OpenUntilDate, otherwise number of blocks */
|
||||||
|
};
|
||||||
|
|
||||||
class TransactionRecord
|
class TransactionRecord
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/* Information that never changes for the life of the transaction
|
enum Type
|
||||||
*/
|
{
|
||||||
|
Other,
|
||||||
|
Generated,
|
||||||
|
SendToAddress,
|
||||||
|
SendToIP,
|
||||||
|
RecvFromAddress,
|
||||||
|
RecvFromIP,
|
||||||
|
SendToSelf
|
||||||
|
};
|
||||||
|
|
||||||
|
TransactionRecord():
|
||||||
|
hash(), time(0), type(Other), address(""), debit(0), credit(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionRecord(uint256 hash, int64 time, const TransactionStatus &status):
|
||||||
|
hash(hash), time(time), type(Other), address(""), debit(0),
|
||||||
|
credit(0), status(status)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
TransactionRecord(uint256 hash, int64 time, const TransactionStatus &status,
|
||||||
|
Type type, const std::string &address,
|
||||||
|
int64 debit, int64 credit):
|
||||||
|
hash(hash), time(time), type(type), address(address), debit(debit), credit(credit),
|
||||||
|
status(status)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fixed */
|
||||||
uint256 hash;
|
uint256 hash;
|
||||||
int64 time;
|
int64 time;
|
||||||
int64 credit;
|
Type type;
|
||||||
|
std::string address;
|
||||||
int64 debit;
|
int64 debit;
|
||||||
int64 change;
|
int64 credit;
|
||||||
int64 lockTime;
|
|
||||||
int64 timeReceived;
|
|
||||||
bool isCoinBase;
|
|
||||||
int blockIndex;
|
|
||||||
|
|
||||||
/* Properties that change based on changes in block chain that come in
|
/* Status: can change with block chain update */
|
||||||
over the network.
|
TransactionStatus status;
|
||||||
*/
|
|
||||||
bool confirmed;
|
|
||||||
int depthInMainChain;
|
|
||||||
bool final;
|
|
||||||
int requestCount;
|
|
||||||
|
|
||||||
TransactionRecord(const CWalletTx &tx)
|
|
||||||
{
|
|
||||||
/* Copy immutable properties.
|
|
||||||
*/
|
|
||||||
hash = tx.GetHash();
|
|
||||||
time = tx.GetTxTime();
|
|
||||||
credit = tx.GetCredit(true);
|
|
||||||
debit = tx.GetDebit();
|
|
||||||
change = tx.GetChange();
|
|
||||||
isCoinBase = tx.IsCoinBase();
|
|
||||||
lockTime = tx.nLockTime;
|
|
||||||
timeReceived = tx.nTimeReceived;
|
|
||||||
|
|
||||||
/* Find the block the tx is in, store the index
|
|
||||||
*/
|
|
||||||
CBlockIndex* pindex = NULL;
|
|
||||||
std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(tx.hashBlock);
|
|
||||||
if (mi != mapBlockIndex.end())
|
|
||||||
pindex = (*mi).second;
|
|
||||||
blockIndex = (pindex ? pindex->nHeight : INT_MAX);
|
|
||||||
|
|
||||||
update(tx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void update(const CWalletTx &tx)
|
|
||||||
{
|
|
||||||
confirmed = tx.IsConfirmed();
|
|
||||||
depthInMainChain = tx.GetDepthInMainChain();
|
|
||||||
final = tx.IsFinal();
|
|
||||||
requestCount = tx.GetRequestCount();
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Return positive answer if transaction should be shown in list.
|
||||||
|
*/
|
||||||
|
bool showTransaction(const CWalletTx &wtx)
|
||||||
|
{
|
||||||
|
if (wtx.IsCoinBase())
|
||||||
|
{
|
||||||
|
// Don't show generated coin until confirmed by at least one block after it
|
||||||
|
// so we don't get the user's hopes up until it looks like it's probably accepted.
|
||||||
|
//
|
||||||
|
// It is not an error when generated blocks are not accepted. By design,
|
||||||
|
// some percentage of blocks, like 10% or more, will end up not accepted.
|
||||||
|
// This is the normal mechanism by which the network copes with latency.
|
||||||
|
//
|
||||||
|
// We display regular transactions right away before any confirmation
|
||||||
|
// because they can always get into some block eventually. Generated coins
|
||||||
|
// are special because if their block is not accepted, they are not valid.
|
||||||
|
//
|
||||||
|
if (wtx.GetDepthInMainChain() < 2)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decompose CWallet transaction to model transaction records.
|
||||||
|
*/
|
||||||
|
QList<TransactionRecord> decomposeTransaction(const CWalletTx &wtx)
|
||||||
|
{
|
||||||
|
QList<TransactionRecord> parts;
|
||||||
|
int64 nTime = wtx.nTimeDisplayed = wtx.GetTxTime();
|
||||||
|
int64 nCredit = wtx.GetCredit(true);
|
||||||
|
int64 nDebit = wtx.GetDebit();
|
||||||
|
int64 nNet = nCredit - nDebit;
|
||||||
|
uint256 hash = wtx.GetHash();
|
||||||
|
std::map<std::string, std::string> mapValue = wtx.mapValue;
|
||||||
|
|
||||||
|
// Find the block the tx is in
|
||||||
|
CBlockIndex* pindex = NULL;
|
||||||
|
std::map<uint256, CBlockIndex*>::iterator mi = mapBlockIndex.find(wtx.hashBlock);
|
||||||
|
if (mi != mapBlockIndex.end())
|
||||||
|
pindex = (*mi).second;
|
||||||
|
|
||||||
|
// Determine transaction status
|
||||||
|
TransactionStatus status;
|
||||||
|
// Sort order, unrecorded transactions sort to the top
|
||||||
|
status.sortKey = strprintf("%010d-%01d-%010u",
|
||||||
|
(pindex ? pindex->nHeight : INT_MAX),
|
||||||
|
(wtx.IsCoinBase() ? 1 : 0),
|
||||||
|
wtx.nTimeReceived);
|
||||||
|
status.confirmed = wtx.IsConfirmed();
|
||||||
|
status.depth = wtx.GetDepthInMainChain();
|
||||||
|
|
||||||
|
if (!wtx.IsFinal())
|
||||||
|
{
|
||||||
|
if (wtx.nLockTime < 500000000)
|
||||||
|
{
|
||||||
|
status.status = TransactionStatus::OpenUntilBlock;
|
||||||
|
status.open_for = nBestHeight - wtx.nLockTime;
|
||||||
|
} else {
|
||||||
|
status.status = TransactionStatus::OpenUntilDate;
|
||||||
|
status.open_for = wtx.nLockTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
||||||
|
{
|
||||||
|
status.status = TransactionStatus::Offline;
|
||||||
|
} else if (status.depth < 6)
|
||||||
|
{
|
||||||
|
status.status = TransactionStatus::Unconfirmed;
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
status.status = TransactionStatus::HaveConfirmations;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showTransaction(wtx))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (nNet > 0 || wtx.IsCoinBase())
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Credit
|
||||||
|
//
|
||||||
|
TransactionRecord sub(hash, nTime, status);
|
||||||
|
|
||||||
|
sub.credit = nNet;
|
||||||
|
|
||||||
|
if (wtx.IsCoinBase())
|
||||||
|
{
|
||||||
|
// Generated
|
||||||
|
sub.type = TransactionRecord::Generated;
|
||||||
|
|
||||||
|
if (nCredit == 0)
|
||||||
|
{
|
||||||
|
sub.status.maturity = TransactionStatus::Immature;
|
||||||
|
|
||||||
|
int64 nUnmatured = 0;
|
||||||
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
|
nUnmatured += txout.GetCredit();
|
||||||
|
sub.credit = nUnmatured;
|
||||||
|
|
||||||
|
if (wtx.IsInMainChain())
|
||||||
|
{
|
||||||
|
sub.status.maturity = TransactionStatus::MaturesIn;
|
||||||
|
sub.status.matures_in = wtx.GetBlocksToMaturity();
|
||||||
|
|
||||||
|
// Check if the block was requested by anyone
|
||||||
|
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
||||||
|
sub.status.maturity = TransactionStatus::MaturesWarning;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sub.status.maturity = TransactionStatus::NotAccepted;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!mapValue["from"].empty() || !mapValue["message"].empty())
|
||||||
|
{
|
||||||
|
// Received by IP connection
|
||||||
|
sub.type = TransactionRecord::RecvFromIP;
|
||||||
|
if (!mapValue["from"].empty())
|
||||||
|
sub.address = mapValue["from"];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Received by Bitcoin Address
|
||||||
|
sub.type = TransactionRecord::RecvFromAddress;
|
||||||
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
|
{
|
||||||
|
if (txout.IsMine())
|
||||||
|
{
|
||||||
|
std::vector<unsigned char> vchPubKey;
|
||||||
|
if (ExtractPubKey(txout.scriptPubKey, true, vchPubKey))
|
||||||
|
{
|
||||||
|
sub.address = PubKeyToAddress(vchPubKey);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
parts.append(sub);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bool fAllFromMe = true;
|
||||||
|
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||||
|
fAllFromMe = fAllFromMe && txin.IsMine();
|
||||||
|
|
||||||
|
bool fAllToMe = true;
|
||||||
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
|
fAllToMe = fAllToMe && txout.IsMine();
|
||||||
|
|
||||||
|
if (fAllFromMe && fAllToMe)
|
||||||
|
{
|
||||||
|
// Payment to self
|
||||||
|
int64 nChange = wtx.GetChange();
|
||||||
|
|
||||||
|
parts.append(TransactionRecord(hash, nTime, status, TransactionRecord::SendToSelf, "",
|
||||||
|
-(nDebit - nChange), nCredit - nChange));
|
||||||
|
}
|
||||||
|
else if (fAllFromMe)
|
||||||
|
{
|
||||||
|
//
|
||||||
|
// Debit
|
||||||
|
//
|
||||||
|
int64 nTxFee = nDebit - wtx.GetValueOut();
|
||||||
|
|
||||||
|
for (int nOut = 0; nOut < wtx.vout.size(); nOut++)
|
||||||
|
{
|
||||||
|
const CTxOut& txout = wtx.vout[nOut];
|
||||||
|
TransactionRecord sub(hash, nTime, status);
|
||||||
|
|
||||||
|
if (txout.IsMine())
|
||||||
|
{
|
||||||
|
// Sent to self
|
||||||
|
sub.type = TransactionRecord::SendToSelf;
|
||||||
|
sub.credit = txout.nValue;
|
||||||
|
} else if (!mapValue["to"].empty())
|
||||||
|
{
|
||||||
|
// Sent to IP
|
||||||
|
sub.type = TransactionRecord::SendToIP;
|
||||||
|
sub.address = mapValue["to"];
|
||||||
|
} else {
|
||||||
|
// Sent to Bitcoin Address
|
||||||
|
sub.type = TransactionRecord::SendToAddress;
|
||||||
|
uint160 hash160;
|
||||||
|
if (ExtractHash160(txout.scriptPubKey, hash160))
|
||||||
|
sub.address = Hash160ToAddress(hash160);
|
||||||
|
}
|
||||||
|
|
||||||
|
int64 nValue = txout.nValue;
|
||||||
|
/* Add fee to first output */
|
||||||
|
if (nTxFee > 0)
|
||||||
|
{
|
||||||
|
nValue += nTxFee;
|
||||||
|
nTxFee = 0;
|
||||||
|
}
|
||||||
|
sub.debit = nValue;
|
||||||
|
sub.status.sortKey += strprintf("-%d", nOut);
|
||||||
|
|
||||||
|
parts.append(sub);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//
|
||||||
|
// Mixed debit transaction, can't break down payees
|
||||||
|
//
|
||||||
|
bool fAllMine = true;
|
||||||
|
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||||
|
fAllMine = fAllMine && txout.IsMine();
|
||||||
|
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||||
|
fAllMine = fAllMine && txin.IsMine();
|
||||||
|
|
||||||
|
parts.append(TransactionRecord(hash, nTime, status, TransactionRecord::Other, "", nNet, 0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts;
|
||||||
|
}
|
||||||
|
|
||||||
/* Internal implementation */
|
/* Internal implementation */
|
||||||
class TransactionTableImpl
|
class TransactionTableImpl
|
||||||
{
|
{
|
||||||
|
@ -93,7 +347,7 @@ public:
|
||||||
/* TODO: Make note of new and removed transactions */
|
/* TODO: Make note of new and removed transactions */
|
||||||
/* insertedIndices */
|
/* insertedIndices */
|
||||||
/* removedIndices */
|
/* removedIndices */
|
||||||
cachedWallet.append(TransactionRecord(it->second));
|
cachedWallet.append(decomposeTransaction(it->second));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* beginInsertRows(QModelIndex(), first, last) */
|
/* beginInsertRows(QModelIndex(), first, last) */
|
||||||
|
@ -146,14 +400,6 @@ TransactionTableModel::~TransactionTableModel()
|
||||||
int TransactionTableModel::rowCount(const QModelIndex &parent) const
|
int TransactionTableModel::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
Q_UNUSED(parent);
|
Q_UNUSED(parent);
|
||||||
/*
|
|
||||||
int retval = 0;
|
|
||||||
CRITICAL_BLOCK(cs_mapWallet)
|
|
||||||
{
|
|
||||||
retval = mapWallet.size();
|
|
||||||
}
|
|
||||||
return retval;
|
|
||||||
*/
|
|
||||||
return impl->size();
|
return impl->size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -165,32 +411,37 @@ int TransactionTableModel::columnCount(const QModelIndex &parent) const
|
||||||
|
|
||||||
QVariant TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) const
|
QVariant TransactionTableModel::formatTxStatus(const TransactionRecord *wtx) const
|
||||||
{
|
{
|
||||||
return QVariant(QString("Test"));
|
QString status;
|
||||||
#if 0
|
switch(wtx->status.status)
|
||||||
// Status
|
|
||||||
if (!wtx.IsFinal())
|
|
||||||
{
|
{
|
||||||
if (wtx.nLockTime < 500000000)
|
case TransactionStatus::OpenUntilBlock:
|
||||||
return strprintf(_("Open for %d blocks"), nBestHeight - wtx.nLockTime);
|
status = tr("Open for %n block(s)","",wtx->status.open_for);
|
||||||
else
|
break;
|
||||||
return strprintf(_("Open until %s"), DateTimeStr(wtx.nLockTime).c_str());
|
case TransactionStatus::OpenUntilDate:
|
||||||
|
status = tr("Open until ") + DateTimeStr(wtx->status.open_for);
|
||||||
|
break;
|
||||||
|
case TransactionStatus::Offline:
|
||||||
|
status = tr("%1/offline").arg(wtx->status.depth);
|
||||||
|
break;
|
||||||
|
case TransactionStatus::Unconfirmed:
|
||||||
|
status = tr("%1/unconfirmed").arg(wtx->status.depth);
|
||||||
|
break;
|
||||||
|
case TransactionStatus::HaveConfirmations:
|
||||||
|
status = tr("%1 confirmations").arg(wtx->status.depth);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
return QVariant(status);
|
||||||
int nDepth = wtx.GetDepthInMainChain();
|
|
||||||
if (GetAdjustedTime() - wtx.nTimeReceived > 2 * 60 && wtx.GetRequestCount() == 0)
|
|
||||||
return strprintf(_("%d/offline?"), nDepth);
|
|
||||||
else if (nDepth < 6)
|
|
||||||
return strprintf(_("%d/unconfirmed"), nDepth);
|
|
||||||
else
|
|
||||||
return strprintf(_("%d confirmations"), nDepth);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const
|
QVariant TransactionTableModel::formatTxDate(const TransactionRecord *wtx) const
|
||||||
{
|
{
|
||||||
return QVariant();
|
if(wtx->time)
|
||||||
|
{
|
||||||
|
return QVariant(DateTimeStr(wtx->time));
|
||||||
|
} else {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TransactionTableModel::formatTxDescription(const TransactionRecord *wtx) const
|
QVariant TransactionTableModel::formatTxDescription(const TransactionRecord *wtx) const
|
||||||
|
@ -200,12 +451,32 @@ QVariant TransactionTableModel::formatTxDescription(const TransactionRecord *wtx
|
||||||
|
|
||||||
QVariant TransactionTableModel::formatTxDebit(const TransactionRecord *wtx) const
|
QVariant TransactionTableModel::formatTxDebit(const TransactionRecord *wtx) const
|
||||||
{
|
{
|
||||||
return QVariant();
|
if(wtx->debit)
|
||||||
|
{
|
||||||
|
QString str = QString::fromStdString(FormatMoney(wtx->debit));
|
||||||
|
if(!wtx->status.confirmed)
|
||||||
|
{
|
||||||
|
str = QString("[") + str + QString("]");
|
||||||
|
}
|
||||||
|
return QVariant(str);
|
||||||
|
} else {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TransactionTableModel::formatTxCredit(const TransactionRecord *wtx) const
|
QVariant TransactionTableModel::formatTxCredit(const TransactionRecord *wtx) const
|
||||||
{
|
{
|
||||||
return QVariant();
|
if(wtx->credit)
|
||||||
|
{
|
||||||
|
QString str = QString::fromStdString(FormatMoney(wtx->credit));
|
||||||
|
if(!wtx->status.confirmed)
|
||||||
|
{
|
||||||
|
str = QString("[") + str + QString("]");
|
||||||
|
}
|
||||||
|
return QVariant(str);
|
||||||
|
} else {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
|
QVariant TransactionTableModel::data(const QModelIndex &index, int role) const
|
||||||
|
|
Loading…
Reference in a new issue