qt: Handle address purpose in incremental updates
Correctly use the purpose of addresses that are added after the start of the client. Addresses with purpose "refund" and "change" should not be visible in the GUI. This is now handled correctly.
This commit is contained in:
parent
ff33a3470d
commit
dcd0b0775e
7 changed files with 54 additions and 33 deletions
|
@ -15,7 +15,8 @@ struct AddressTableEntry
|
||||||
{
|
{
|
||||||
enum Type {
|
enum Type {
|
||||||
Sending,
|
Sending,
|
||||||
Receiving
|
Receiving,
|
||||||
|
Hidden /* QSortFilterProxyModel will filter these out */
|
||||||
};
|
};
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
|
@ -43,6 +44,20 @@ struct AddressTableEntryLessThan
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/* Determine address type from address purpose */
|
||||||
|
static AddressTableEntry::Type translateTransactionType(const QString &strPurpose, bool isMine)
|
||||||
|
{
|
||||||
|
AddressTableEntry::Type addressType = AddressTableEntry::Hidden;
|
||||||
|
// "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all.
|
||||||
|
if (strPurpose == "send")
|
||||||
|
addressType = AddressTableEntry::Sending;
|
||||||
|
else if (strPurpose == "receive")
|
||||||
|
addressType = AddressTableEntry::Receiving;
|
||||||
|
else if (strPurpose == "unknown" || strPurpose == "") // if purpose not set, guess
|
||||||
|
addressType = (isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending);
|
||||||
|
return addressType;
|
||||||
|
}
|
||||||
|
|
||||||
// Private implementation
|
// Private implementation
|
||||||
class AddressTablePriv
|
class AddressTablePriv
|
||||||
{
|
{
|
||||||
|
@ -62,17 +77,9 @@ public:
|
||||||
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
|
BOOST_FOREACH(const PAIRTYPE(CTxDestination, CAddressBookData)& item, wallet->mapAddressBook)
|
||||||
{
|
{
|
||||||
const CBitcoinAddress& address = item.first;
|
const CBitcoinAddress& address = item.first;
|
||||||
|
|
||||||
AddressTableEntry::Type addressType;
|
|
||||||
const std::string& strPurpose = item.second.purpose;
|
|
||||||
if (strPurpose == "send") addressType = AddressTableEntry::Sending;
|
|
||||||
else if (strPurpose == "receive") addressType = AddressTableEntry::Receiving;
|
|
||||||
else if (strPurpose == "unknown") {
|
|
||||||
bool fMine = IsMine(*wallet, address.Get());
|
bool fMine = IsMine(*wallet, address.Get());
|
||||||
addressType = (fMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending);
|
AddressTableEntry::Type addressType = translateTransactionType(
|
||||||
}
|
QString::fromStdString(item.second.purpose), fMine);
|
||||||
else continue; // "refund" addresses aren't shown, and change addresses aren't in mapAddressBook at all.
|
|
||||||
|
|
||||||
const std::string& strName = item.second.name;
|
const std::string& strName = item.second.name;
|
||||||
cachedAddressTable.append(AddressTableEntry(addressType,
|
cachedAddressTable.append(AddressTableEntry(addressType,
|
||||||
QString::fromStdString(strName),
|
QString::fromStdString(strName),
|
||||||
|
@ -83,7 +90,7 @@ public:
|
||||||
qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
|
qSort(cachedAddressTable.begin(), cachedAddressTable.end(), AddressTableEntryLessThan());
|
||||||
}
|
}
|
||||||
|
|
||||||
void updateEntry(const QString &address, const QString &label, bool isMine, int status)
|
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status)
|
||||||
{
|
{
|
||||||
// Find address / label in model
|
// Find address / label in model
|
||||||
QList<AddressTableEntry>::iterator lower = qLowerBound(
|
QList<AddressTableEntry>::iterator lower = qLowerBound(
|
||||||
|
@ -93,7 +100,7 @@ public:
|
||||||
int lowerIndex = (lower - cachedAddressTable.begin());
|
int lowerIndex = (lower - cachedAddressTable.begin());
|
||||||
int upperIndex = (upper - cachedAddressTable.begin());
|
int upperIndex = (upper - cachedAddressTable.begin());
|
||||||
bool inModel = (lower != upper);
|
bool inModel = (lower != upper);
|
||||||
AddressTableEntry::Type newEntryType = isMine ? AddressTableEntry::Receiving : AddressTableEntry::Sending;
|
AddressTableEntry::Type newEntryType = translateTransactionType(purpose, isMine);
|
||||||
|
|
||||||
switch(status)
|
switch(status)
|
||||||
{
|
{
|
||||||
|
@ -322,10 +329,11 @@ QModelIndex AddressTableModel::index(int row, int column, const QModelIndex &par
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AddressTableModel::updateEntry(const QString &address, const QString &label, bool isMine, int status)
|
void AddressTableModel::updateEntry(const QString &address,
|
||||||
|
const QString &label, bool isMine, const QString &purpose, int status)
|
||||||
{
|
{
|
||||||
// Update address book model from Bitcoin core
|
// Update address book model from Bitcoin core
|
||||||
priv->updateEntry(address, label, isMine, status);
|
priv->updateEntry(address, label, isMine, purpose, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
|
QString AddressTableModel::addRow(const QString &type, const QString &label, const QString &address)
|
||||||
|
|
|
@ -85,7 +85,7 @@ signals:
|
||||||
public slots:
|
public slots:
|
||||||
/* Update address list from core.
|
/* Update address list from core.
|
||||||
*/
|
*/
|
||||||
void updateEntry(const QString &address, const QString &label, bool isMine, int status);
|
void updateEntry(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
|
||||||
|
|
||||||
friend class AddressTablePriv;
|
friend class AddressTablePriv;
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,11 +20,11 @@
|
||||||
|
|
||||||
// Amount column is right-aligned it contains numbers
|
// Amount column is right-aligned it contains numbers
|
||||||
static int column_alignments[] = {
|
static int column_alignments[] = {
|
||||||
Qt::AlignLeft|Qt::AlignVCenter,
|
Qt::AlignLeft|Qt::AlignVCenter, /* status */
|
||||||
Qt::AlignLeft|Qt::AlignVCenter,
|
Qt::AlignLeft|Qt::AlignVCenter, /* date */
|
||||||
Qt::AlignLeft|Qt::AlignVCenter,
|
Qt::AlignLeft|Qt::AlignVCenter, /* type */
|
||||||
Qt::AlignLeft|Qt::AlignVCenter,
|
Qt::AlignLeft|Qt::AlignVCenter, /* address */
|
||||||
Qt::AlignRight|Qt::AlignVCenter
|
Qt::AlignRight|Qt::AlignVCenter /* amount */
|
||||||
};
|
};
|
||||||
|
|
||||||
// Comparison operator for sort/binary search of model tx list
|
// Comparison operator for sort/binary search of model tx list
|
||||||
|
|
|
@ -112,10 +112,11 @@ void WalletModel::updateTransaction(const QString &hash, int status)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WalletModel::updateAddressBook(const QString &address, const QString &label, bool isMine, int status)
|
void WalletModel::updateAddressBook(const QString &address, const QString &label,
|
||||||
|
bool isMine, const QString &purpose, int status)
|
||||||
{
|
{
|
||||||
if(addressTableModel)
|
if(addressTableModel)
|
||||||
addressTableModel->updateEntry(address, label, isMine, status);
|
addressTableModel->updateEntry(address, label, isMine, purpose, status);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WalletModel::validateAddress(const QString &address)
|
bool WalletModel::validateAddress(const QString &address)
|
||||||
|
@ -351,13 +352,17 @@ static void NotifyKeyStoreStatusChanged(WalletModel *walletmodel, CCryptoKeyStor
|
||||||
QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
|
QMetaObject::invokeMethod(walletmodel, "updateStatus", Qt::QueuedConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status)
|
static void NotifyAddressBookChanged(WalletModel *walletmodel, CWallet *wallet,
|
||||||
|
const CTxDestination &address, const std::string &label, bool isMine,
|
||||||
|
const std::string &purpose, ChangeType status)
|
||||||
{
|
{
|
||||||
OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i status=%i\n", CBitcoinAddress(address).ToString().c_str(), label.c_str(), isMine, status);
|
OutputDebugStringF("NotifyAddressBookChanged %s %s isMine=%i purpose=%s status=%i\n",
|
||||||
|
CBitcoinAddress(address).ToString().c_str(), label.c_str(), isMine, purpose.c_str(), status);
|
||||||
QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(walletmodel, "updateAddressBook", Qt::QueuedConnection,
|
||||||
Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())),
|
Q_ARG(QString, QString::fromStdString(CBitcoinAddress(address).ToString())),
|
||||||
Q_ARG(QString, QString::fromStdString(label)),
|
Q_ARG(QString, QString::fromStdString(label)),
|
||||||
Q_ARG(bool, isMine),
|
Q_ARG(bool, isMine),
|
||||||
|
Q_ARG(QString, QString::fromStdString(purpose)),
|
||||||
Q_ARG(int, status));
|
Q_ARG(int, status));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -373,7 +378,7 @@ void WalletModel::subscribeToCoreSignals()
|
||||||
{
|
{
|
||||||
// Connect signals to wallet
|
// Connect signals to wallet
|
||||||
wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
wallet->NotifyStatusChanged.connect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
||||||
wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
|
wallet->NotifyAddressBookChanged.connect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
|
||||||
wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
wallet->NotifyTransactionChanged.connect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,7 +386,7 @@ void WalletModel::unsubscribeFromCoreSignals()
|
||||||
{
|
{
|
||||||
// Disconnect signals from wallet
|
// Disconnect signals from wallet
|
||||||
wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
wallet->NotifyStatusChanged.disconnect(boost::bind(&NotifyKeyStoreStatusChanged, this, _1));
|
||||||
wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5));
|
wallet->NotifyAddressBookChanged.disconnect(boost::bind(NotifyAddressBookChanged, this, _1, _2, _3, _4, _5, _6));
|
||||||
wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
wallet->NotifyTransactionChanged.disconnect(boost::bind(NotifyTransactionChanged, this, _1, _2, _3));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ public slots:
|
||||||
/* New transaction, or transaction changed status */
|
/* New transaction, or transaction changed status */
|
||||||
void updateTransaction(const QString &hash, int status);
|
void updateTransaction(const QString &hash, int status);
|
||||||
/* New, updated or removed address book entry */
|
/* New, updated or removed address book entry */
|
||||||
void updateAddressBook(const QString &address, const QString &label, bool isMine, int status);
|
void updateAddressBook(const QString &address, const QString &label, bool isMine, const QString &purpose, int status);
|
||||||
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
|
/* Current, immature or unconfirmed balance might have changed - emit 'balanceChanged' if so */
|
||||||
void pollBalanceChanged();
|
void pollBalanceChanged();
|
||||||
};
|
};
|
||||||
|
|
|
@ -1461,7 +1461,11 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
|
||||||
{
|
{
|
||||||
std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
|
std::map<CTxDestination, CAddressBookData>::iterator mi = mapAddressBook.find(address);
|
||||||
mapAddressBook[address].name = strName;
|
mapAddressBook[address].name = strName;
|
||||||
NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address), (mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
|
if (!strPurpose.empty()) /* update purpose only if requested */
|
||||||
|
mapAddressBook[address].purpose = strPurpose;
|
||||||
|
NotifyAddressBookChanged(this, address, strName, ::IsMine(*this, address),
|
||||||
|
mapAddressBook[address].purpose,
|
||||||
|
(mi == mapAddressBook.end()) ? CT_NEW : CT_UPDATED);
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
return false;
|
return false;
|
||||||
if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
|
if (!strPurpose.empty() && !CWalletDB(strWalletFile).WritePurpose(CBitcoinAddress(address).ToString(), strPurpose))
|
||||||
|
@ -1472,7 +1476,7 @@ bool CWallet::SetAddressBook(const CTxDestination& address, const string& strNam
|
||||||
bool CWallet::DelAddressBook(const CTxDestination& address)
|
bool CWallet::DelAddressBook(const CTxDestination& address)
|
||||||
{
|
{
|
||||||
mapAddressBook.erase(address);
|
mapAddressBook.erase(address);
|
||||||
NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), CT_DELETED);
|
NotifyAddressBookChanged(this, address, "", ::IsMine(*this, address), "", CT_DELETED);
|
||||||
if (!fFileBacked)
|
if (!fFileBacked)
|
||||||
return false;
|
return false;
|
||||||
CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
|
CWalletDB(strWalletFile).ErasePurpose(CBitcoinAddress(address).ToString());
|
||||||
|
|
|
@ -335,12 +335,16 @@ public:
|
||||||
/** Address book entry changed.
|
/** Address book entry changed.
|
||||||
* @note called with lock cs_wallet held.
|
* @note called with lock cs_wallet held.
|
||||||
*/
|
*/
|
||||||
boost::signals2::signal<void (CWallet *wallet, const CTxDestination &address, const std::string &label, bool isMine, ChangeType status)> NotifyAddressBookChanged;
|
boost::signals2::signal<void (CWallet *wallet, const CTxDestination
|
||||||
|
&address, const std::string &label, bool isMine,
|
||||||
|
const std::string &purpose,
|
||||||
|
ChangeType status)> NotifyAddressBookChanged;
|
||||||
|
|
||||||
/** Wallet transaction added, removed or updated.
|
/** Wallet transaction added, removed or updated.
|
||||||
* @note called with lock cs_wallet held.
|
* @note called with lock cs_wallet held.
|
||||||
*/
|
*/
|
||||||
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx, ChangeType status)> NotifyTransactionChanged;
|
boost::signals2::signal<void (CWallet *wallet, const uint256 &hashTx,
|
||||||
|
ChangeType status)> NotifyTransactionChanged;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** A key allocated from the key pool. */
|
/** A key allocated from the key pool. */
|
||||||
|
|
Loading…
Reference in a new issue