Browse Source

Merge pull request #2951 from laanwj/2013_08_addressbook_purpose

[Qt] Handle address purpose in incremental updates
0.10
Wladimir J. van der Laan 11 years ago
parent
commit
1537d174d7
  1. 38
      src/qt/addresstablemodel.cpp
  2. 2
      src/qt/addresstablemodel.h
  3. 10
      src/qt/transactiontablemodel.cpp
  4. 17
      src/qt/walletmodel.cpp
  5. 2
      src/qt/walletmodel.h
  6. 8
      src/wallet.cpp
  7. 8
      src/wallet.h

38
src/qt/addresstablemodel.cpp

@ -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),
@ -85,7 +92,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(
@ -95,7 +102,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)
{ {
@ -324,10 +331,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)

2
src/qt/addresstablemodel.h

@ -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;
}; };

10
src/qt/transactiontablemodel.cpp

@ -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

17
src/qt/walletmodel.cpp

@ -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));
} }

2
src/qt/walletmodel.h

@ -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();
}; };

8
src/wallet.cpp

@ -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());

8
src/wallet.h

@ -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…
Cancel
Save