diff --git a/src/qt/addresstablemodel.h b/src/qt/addresstablemodel.h --- a/src/qt/addresstablemodel.h +++ b/src/qt/addresstablemodel.h @@ -83,11 +83,18 @@ QString addRow(const QString &type, const QString &label, const QString &address, const OutputType address_type); - /* Look up label for address in address book, if not found return empty + /** + * Look up label for address in address book, if not found return empty * string. */ QString labelForAddress(const QString &address) const; + /** + * Look up purpose for address in address book, if not found return empty + * string. + */ + QString purposeForAddress(const QString &address) const; + /* Look up row index of an address in the model. Return -1 if not found. */ @@ -103,6 +110,10 @@ QStringList columns; EditStatus editStatus; + /** Look up address book data given an address string. */ + bool getAddressData(const QString &address, std::string *name, + std::string *purpose) const; + /** Notify listeners that data changed. */ void emitDataChanged(int index); diff --git a/src/qt/addresstablemodel.cpp b/src/qt/addresstablemodel.cpp --- a/src/qt/addresstablemodel.cpp +++ b/src/qt/addresstablemodel.cpp @@ -385,20 +385,31 @@ return true; } -/* Look up label for address in address book, if not found return empty string. - */ QString AddressTableModel::labelForAddress(const QString &address) const { - CTxDestination destination = - DecodeDestination(address.toStdString(), walletModel->getChainParams()); std::string name; - if (walletModel->wallet().getAddress(destination, &name, - /* is_mine= */ nullptr, - /* purpose= */ nullptr)) { + if (getAddressData(address, &name, /* purpose= */ nullptr)) { return QString::fromStdString(name); } return QString(); } +QString AddressTableModel::purposeForAddress(const QString &address) const { + std::string purpose; + if (getAddressData(address, /* name= */ nullptr, &purpose)) { + return QString::fromStdString(purpose); + } + return QString(); +} + +bool AddressTableModel::getAddressData(const QString &address, + std::string *name, + std::string *purpose) const { + CTxDestination destination = + DecodeDestination(address.toStdString(), walletModel->getChainParams()); + return walletModel->wallet().getAddress(destination, name, + /* is_mine= */ nullptr, purpose); +} + int AddressTableModel::lookupAddress(const QString &address) const { QModelIndexList lst = match(index(0, Address, QModelIndex()), Qt::EditRole, address, 1, Qt::MatchExactly); diff --git a/src/qt/editaddressdialog.h b/src/qt/editaddressdialog.h --- a/src/qt/editaddressdialog.h +++ b/src/qt/editaddressdialog.h @@ -46,6 +46,12 @@ private: bool saveCurrentRow(); + /** + * Return a descriptive string when adding an already-existing address + * fails. + */ + QString getDuplicateAddressWarning() const; + Ui::EditAddressDialog *ui; QDataWidgetMapper *mapper; Mode mode; diff --git a/src/qt/editaddressdialog.cpp b/src/qt/editaddressdialog.cpp --- a/src/qt/editaddressdialog.cpp +++ b/src/qt/editaddressdialog.cpp @@ -104,9 +104,7 @@ break; case AddressTableModel::DUPLICATE_ADDRESS: QMessageBox::warning(this, windowTitle(), - tr("The entered address \"%1\" is already " - "in the address book.") - .arg(ui->addressEdit->text()), + getDuplicateAddressWarning(), QMessageBox::Ok, QMessageBox::Ok); break; case AddressTableModel::WALLET_UNLOCK_FAILURE: @@ -125,6 +123,25 @@ QDialog::accept(); } +QString EditAddressDialog::getDuplicateAddressWarning() const { + QString dup_address = ui->addressEdit->text(); + QString existing_label = model->labelForAddress(dup_address); + QString existing_purpose = model->purposeForAddress(dup_address); + + if (existing_purpose == "receive" && + (mode == NewSendingAddress || mode == EditSendingAddress)) { + return tr("Address \"%1\" already exists as a receiving address with " + "label " + "\"%2\" and so cannot be added as a sending address.") + .arg(dup_address) + .arg(existing_label); + } + return tr("The entered address \"%1\" is already in the address book with " + "label \"%2\".") + .arg(dup_address) + .arg(existing_label); +} + QString EditAddressDialog::getAddress() const { return address; }