@ -9,6 +9,7 @@
# include "bitcoinunits.h"
# include "bitcoinunits.h"
# include "wallet.h"
# include "wallet.h"
# include "ui_interface.h"
# include <QLocale>
# include <QLocale>
# include <QList>
# include <QList>
@ -66,14 +67,13 @@ public:
*/
*/
void refreshWallet ( )
void refreshWallet ( )
{
{
# ifdef WALLET_UPDATE_DEBUG
OutputDebugStringF ( " refreshWallet \n " ) ;
qDebug ( ) < < " refreshWallet " ;
# endif
cachedWallet . clear ( ) ;
cachedWallet . clear ( ) ;
{
{
LOCK ( wallet - > cs_wallet ) ;
LOCK ( wallet - > cs_wallet ) ;
for ( std : : map < uint256 , CWalletTx > : : iterator it = wallet - > mapWallet . begin ( ) ; it ! = wallet - > mapWallet . end ( ) ; + + it )
for ( std : : map < uint256 , CWalletTx > : : iterator it = wallet - > mapWallet . begin ( ) ; it ! = wallet - > mapWallet . end ( ) ; + + it )
{
{
if ( TransactionRecord : : showTransaction ( it - > second ) )
cachedWallet . append ( TransactionRecord : : decomposeTransaction ( wallet , it - > second ) ) ;
cachedWallet . append ( TransactionRecord : : decomposeTransaction ( wallet , it - > second ) ) ;
}
}
}
}
@ -82,28 +82,18 @@ public:
/* Update our model of the wallet incrementally, to synchronize our model of the wallet
/* Update our model of the wallet incrementally, to synchronize our model of the wallet
with that of the core .
with that of the core .
Call with list of hashes of transactions that were added , removed or changed .
Call with transaction that was added , removed or changed .
*/
*/
void updateWallet ( const QList < uint256 > & updated )
void updateWallet ( const uint256 & hash , int status )
{
{
// Walk through updated transactions, update model as needed.
OutputDebugStringF ( " updateWallet %s %i \n " , hash . ToString ( ) . c_str ( ) , status ) ;
# ifdef WALLET_UPDATE_DEBUG
qDebug ( ) < < " updateWallet " ;
# 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 ) ;
{
{
LOCK ( wallet - > cs_wallet ) ;
LOCK ( wallet - > cs_wallet ) ;
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
// Find transaction in wallet
std : : map < uint256 , CWalletTx > : : iterator mi = wallet - > mapWallet . find ( hash ) ;
std : : map < uint256 , CWalletTx > : : iterator mi = wallet - > mapWallet . find ( hash ) ;
bool inWallet = mi ! = wallet - > mapWallet . end ( ) ;
bool inWallet = mi ! = wallet - > mapWallet . end ( ) ;
// Find bounds of this transaction in model
// Find bounds of this transaction in model
QList < TransactionRecord > : : iterator lower = qLowerBound (
QList < TransactionRecord > : : iterator lower = qLowerBound (
cachedWallet . begin ( ) , cachedWallet . end ( ) , hash , TxLessThan ( ) ) ;
cachedWallet . begin ( ) , cachedWallet . end ( ) , hash , TxLessThan ( ) ) ;
@ -111,20 +101,36 @@ public:
cachedWallet . begin ( ) , cachedWallet . end ( ) , hash , TxLessThan ( ) ) ;
cachedWallet . begin ( ) , cachedWallet . end ( ) , hash , TxLessThan ( ) ) ;
int lowerIndex = ( lower - cachedWallet . begin ( ) ) ;
int lowerIndex = ( lower - cachedWallet . begin ( ) ) ;
int upperIndex = ( upper - cachedWallet . begin ( ) ) ;
int upperIndex = ( upper - cachedWallet . begin ( ) ) ;
bool inModel = ( lower ! = upper ) ;
// Determine if transaction is in model already
// Determine whether to show transaction or not
bool inModel = false ;
bool showTransaction = ( inWallet & & TransactionRecord : : showTransaction ( mi - > second ) ) ;
if ( lower ! = upper )
if ( status = = CT_UPDATED )
{
{
inModel = true ;
if ( showTransaction & & ! inModel )
status = CT_NEW ; /* Not in model, but want to show, treat as new */
if ( ! showTransaction & & inModel )
status = CT_DELETED ; /* In model, but want to hide, treat as deleted */
}
}
# ifdef WALLET_UPDATE_DEBUG
OutputDebugStringF ( " inWallet=%i inModel=%i Index=%i-%i showTransaction=%i derivedStatus=%i \n " ,
qDebug ( ) < < " " < < QString : : fromStdString ( hash . ToString ( ) ) < < inWallet < < " " < < inModel
inWallet , inModel , lowerIndex , upperIndex , showTransaction , status ) ;
< < lowerIndex < < " - " < < upperIndex ;
# endif
if ( inWallet & & ! inModel )
switch ( status )
{
case CT_NEW :
if ( inModel )
{
OutputDebugStringF ( " Warning: updateWallet: Got CT_NEW, but transaction is already in model \n " ) ;
break ;
}
if ( ! inWallet )
{
OutputDebugStringF ( " Warning: updateWallet: Got CT_NEW, but transaction is not in wallet \n " ) ;
break ;
}
if ( showTransaction )
{
{
// Added -- insert at the right position
// Added -- insert at the right position
QList < TransactionRecord > toInsert =
QList < TransactionRecord > toInsert =
@ -141,17 +147,22 @@ public:
parent - > endInsertRows ( ) ;
parent - > endInsertRows ( ) ;
}
}
}
}
else if ( ! inWallet & & inModel )
break ;
case CT_DELETED :
if ( ! inModel )
{
{
OutputDebugStringF ( " Warning: updateWallet: Got CT_DELETED, but transaction is not in model \n " ) ;
break ;
}
// Removed -- remove entire transaction from table
// Removed -- remove entire transaction from table
parent - > beginRemoveRows ( QModelIndex ( ) , lowerIndex , upperIndex - 1 ) ;
parent - > beginRemoveRows ( QModelIndex ( ) , lowerIndex , upperIndex - 1 ) ;
cachedWallet . erase ( lower , upper ) ;
cachedWallet . erase ( lower , upper ) ;
parent - > endRemoveRows ( ) ;
parent - > endRemoveRows ( ) ;
}
break ;
else if ( inWallet & & inModel )
case CT_UPDATED :
{
// Miscellaneous updates -- nothing to do, status update will take care of this, and is only computed for
// Updated -- nothing to do, status update will take care of this
// visible transactions.
}
break ;
}
}
}
}
}
}
@ -209,14 +220,15 @@ TransactionTableModel::TransactionTableModel(CWallet* wallet, WalletModel *paren
QAbstractTableModel ( parent ) ,
QAbstractTableModel ( parent ) ,
wallet ( wallet ) ,
wallet ( wallet ) ,
walletModel ( parent ) ,
walletModel ( parent ) ,
priv ( new TransactionTablePriv ( wallet , this ) )
priv ( new TransactionTablePriv ( wallet , this ) ) ,
cachedNumBlocks ( 0 )
{
{
columns < < QString ( ) < < tr ( " Date " ) < < tr ( " Type " ) < < tr ( " Address " ) < < tr ( " Amount " ) ;
columns < < QString ( ) < < tr ( " Date " ) < < tr ( " Type " ) < < tr ( " Address " ) < < tr ( " Amount " ) ;
priv - > refreshWallet ( ) ;
priv - > refreshWallet ( ) ;
QTimer * timer = new QTimer ( this ) ;
QTimer * timer = new QTimer ( this ) ;
connect ( timer , SIGNAL ( timeout ( ) ) , this , SLOT ( update ( ) ) ) ;
connect ( timer , SIGNAL ( timeout ( ) ) , this , SLOT ( updateConfirmations ( ) ) ) ;
timer - > start ( MODEL_UPDATE_DELAY ) ;
timer - > start ( MODEL_UPDATE_DELAY ) ;
}
}
@ -225,29 +237,23 @@ TransactionTableModel::~TransactionTableModel()
delete priv ;
delete priv ;
}
}
void TransactionTableModel : : update ( )
void TransactionTableModel : : updateTransaction ( const QString & hash , int status )
{
{
QList < uint256 > updated ;
uint256 updated ;
updated . SetHex ( hash . toStdString ( ) ) ;
// Check if there are changes to wallet map
priv - > updateWallet ( updated , status ) ;
{
TRY_LOCK ( wallet - > cs_wallet , lockWallet ) ;
if ( lockWallet & & ! wallet - > vWalletUpdated . empty ( ) )
{
BOOST_FOREACH ( uint256 hash , wallet - > vWalletUpdated )
{
updated . append ( hash ) ;
}
wallet - > vWalletUpdated . clear ( ) ;
}
}
}
if ( ! updated . empty ( ) )
void TransactionTableModel : : updateConfirmations ( )
{
{
priv - > updateWallet ( updated ) ;
if ( nBestHeight ! = cachedNumBlocks )
{
// Status (number of confirmations) and (possibly) description
cachedNumBlocks = nBestHeight ;
// columns changed for all rows.
// Blocks came in since last poll.
// Invalidate status (number of confirmations) and (possibly) description
// for all rows. Qt is smart enough to only actually request the data for the
// visible rows.
emit dataChanged ( index ( 0 , Status ) , index ( priv - > size ( ) - 1 , Status ) ) ;
emit dataChanged ( index ( 0 , Status ) , index ( priv - > size ( ) - 1 , Status ) ) ;
emit dataChanged ( index ( 0 , ToAddress ) , index ( priv - > size ( ) - 1 , ToAddress ) ) ;
emit dataChanged ( index ( 0 , ToAddress ) , index ( priv - > size ( ) - 1 , ToAddress ) ) ;
}
}