mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-02-13 08:58:52 +00:00
f5ba424cd44619d9b9be88b8593d69a7ba96db26 wallet: Add IsAddressUsed / SetAddressUsed methods (Russell Yanofsky)
62252c95e5aa55f33a5ef22292d5d8161fcb892a interfaces: Stop exposing wallet destdata to gui (Russell Yanofsky)
985430d9b2e183c1f59a34472e413a8d00a7e6da test: Add gui test for wallet receive requests (Russell Yanofsky)
Pull request description:
Stop giving GUI access to destdata rows in database. Replace with narrow API just for saving and reading receive request information.
This simplifies code and should prevent the GUI from interfering with other destdata like address-used status. It also adds some more GUI test coverage.
There are no changes in behavior.
ACKs for top commit:
jarolrod:
tACK f5ba424cd44619d9b9be88b8593d69a7ba96db26
laanwj:
Code review ACK f5ba424cd44619d9b9be88b8593d69a7ba96db26
Tree-SHA512: 5423df4786e537a59013cb5bfb9e1bc29a7ca4b8835360c00cc2165a59f925fdc355907a4ceb8bca0285bb4946ba235bffa7645537a951ad03fd3b4cee17b6b0
248 lines
7.4 KiB
C++
248 lines
7.4 KiB
C++
// Copyright (c) 2011-2020 The Bitcoin Core developers
|
|
// Distributed under the MIT software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include <qt/recentrequeststablemodel.h>
|
|
|
|
#include <qt/bitcoinunits.h>
|
|
#include <qt/guiutil.h>
|
|
#include <qt/optionsmodel.h>
|
|
#include <qt/walletmodel.h>
|
|
|
|
#include <clientversion.h>
|
|
#include <interfaces/wallet.h>
|
|
#include <key_io.h>
|
|
#include <streams.h>
|
|
#include <util/string.h>
|
|
|
|
#include <utility>
|
|
|
|
#include <QLatin1Char>
|
|
#include <QLatin1String>
|
|
|
|
RecentRequestsTableModel::RecentRequestsTableModel(WalletModel *parent) :
|
|
QAbstractTableModel(parent), walletModel(parent)
|
|
{
|
|
// Load entries from wallet
|
|
for (const std::string& request : parent->wallet().getAddressReceiveRequests()) {
|
|
addNewRequest(request);
|
|
}
|
|
|
|
/* These columns must match the indices in the ColumnIndex enumeration */
|
|
columns << tr("Date") << tr("Label") << tr("Message") << getAmountTitle();
|
|
|
|
connect(walletModel->getOptionsModel(), &OptionsModel::displayUnitChanged, this, &RecentRequestsTableModel::updateDisplayUnit);
|
|
}
|
|
|
|
RecentRequestsTableModel::~RecentRequestsTableModel()
|
|
{
|
|
/* Intentionally left empty */
|
|
}
|
|
|
|
int RecentRequestsTableModel::rowCount(const QModelIndex &parent) const
|
|
{
|
|
if (parent.isValid()) {
|
|
return 0;
|
|
}
|
|
return list.length();
|
|
}
|
|
|
|
int RecentRequestsTableModel::columnCount(const QModelIndex &parent) const
|
|
{
|
|
if (parent.isValid()) {
|
|
return 0;
|
|
}
|
|
return columns.length();
|
|
}
|
|
|
|
QVariant RecentRequestsTableModel::data(const QModelIndex &index, int role) const
|
|
{
|
|
if(!index.isValid() || index.row() >= list.length())
|
|
return QVariant();
|
|
|
|
if(role == Qt::DisplayRole || role == Qt::EditRole)
|
|
{
|
|
const RecentRequestEntry *rec = &list[index.row()];
|
|
switch(index.column())
|
|
{
|
|
case Date:
|
|
return GUIUtil::dateTimeStr(rec->date);
|
|
case Label:
|
|
if(rec->recipient.label.isEmpty() && role == Qt::DisplayRole)
|
|
{
|
|
return tr("(no label)");
|
|
}
|
|
else
|
|
{
|
|
return rec->recipient.label;
|
|
}
|
|
case Message:
|
|
if(rec->recipient.message.isEmpty() && role == Qt::DisplayRole)
|
|
{
|
|
return tr("(no message)");
|
|
}
|
|
else
|
|
{
|
|
return rec->recipient.message;
|
|
}
|
|
case Amount:
|
|
if (rec->recipient.amount == 0 && role == Qt::DisplayRole)
|
|
return tr("(no amount requested)");
|
|
else if (role == Qt::EditRole)
|
|
return BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), rec->recipient.amount, false, BitcoinUnits::SeparatorStyle::NEVER);
|
|
else
|
|
return BitcoinUnits::format(walletModel->getOptionsModel()->getDisplayUnit(), rec->recipient.amount);
|
|
}
|
|
}
|
|
else if (role == Qt::TextAlignmentRole)
|
|
{
|
|
if (index.column() == Amount)
|
|
return (int)(Qt::AlignRight|Qt::AlignVCenter);
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
bool RecentRequestsTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
|
{
|
|
return true;
|
|
}
|
|
|
|
QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
|
{
|
|
if(orientation == Qt::Horizontal)
|
|
{
|
|
if(role == Qt::DisplayRole && section < columns.size())
|
|
{
|
|
return columns[section];
|
|
}
|
|
}
|
|
return QVariant();
|
|
}
|
|
|
|
/** Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table headers to react. */
|
|
void RecentRequestsTableModel::updateAmountColumnTitle()
|
|
{
|
|
columns[Amount] = getAmountTitle();
|
|
Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
|
|
}
|
|
|
|
/** Gets title for amount column including current display unit if optionsModel reference available. */
|
|
QString RecentRequestsTableModel::getAmountTitle()
|
|
{
|
|
if (!walletModel->getOptionsModel()) return {};
|
|
return tr("Requested") +
|
|
QLatin1String(" (") +
|
|
BitcoinUnits::shortName(this->walletModel->getOptionsModel()->getDisplayUnit()) +
|
|
QLatin1Char(')');
|
|
}
|
|
|
|
QModelIndex RecentRequestsTableModel::index(int row, int column, const QModelIndex &parent) const
|
|
{
|
|
Q_UNUSED(parent);
|
|
|
|
return createIndex(row, column);
|
|
}
|
|
|
|
bool RecentRequestsTableModel::removeRows(int row, int count, const QModelIndex &parent)
|
|
{
|
|
Q_UNUSED(parent);
|
|
|
|
if(count > 0 && row >= 0 && (row+count) <= list.size())
|
|
{
|
|
for (int i = 0; i < count; ++i)
|
|
{
|
|
const RecentRequestEntry* rec = &list[row+i];
|
|
if (!walletModel->wallet().setAddressReceiveRequest(DecodeDestination(rec->recipient.address.toStdString()), ToString(rec->id), ""))
|
|
return false;
|
|
}
|
|
|
|
beginRemoveRows(parent, row, row + count - 1);
|
|
list.erase(list.begin() + row, list.begin() + row + count);
|
|
endRemoveRows();
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
Qt::ItemFlags RecentRequestsTableModel::flags(const QModelIndex &index) const
|
|
{
|
|
return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
|
|
}
|
|
|
|
// called when adding a request from the GUI
|
|
void RecentRequestsTableModel::addNewRequest(const SendCoinsRecipient &recipient)
|
|
{
|
|
RecentRequestEntry newEntry;
|
|
newEntry.id = ++nReceiveRequestsMaxId;
|
|
newEntry.date = QDateTime::currentDateTime();
|
|
newEntry.recipient = recipient;
|
|
|
|
CDataStream ss(SER_DISK, CLIENT_VERSION);
|
|
ss << newEntry;
|
|
|
|
if (!walletModel->wallet().setAddressReceiveRequest(DecodeDestination(recipient.address.toStdString()), ToString(newEntry.id), ss.str()))
|
|
return;
|
|
|
|
addNewRequest(newEntry);
|
|
}
|
|
|
|
// called from ctor when loading from wallet
|
|
void RecentRequestsTableModel::addNewRequest(const std::string &recipient)
|
|
{
|
|
std::vector<uint8_t> data(recipient.begin(), recipient.end());
|
|
CDataStream ss(data, SER_DISK, CLIENT_VERSION);
|
|
|
|
RecentRequestEntry entry;
|
|
ss >> entry;
|
|
|
|
if (entry.id == 0) // should not happen
|
|
return;
|
|
|
|
if (entry.id > nReceiveRequestsMaxId)
|
|
nReceiveRequestsMaxId = entry.id;
|
|
|
|
addNewRequest(entry);
|
|
}
|
|
|
|
// actually add to table in GUI
|
|
void RecentRequestsTableModel::addNewRequest(RecentRequestEntry &recipient)
|
|
{
|
|
beginInsertRows(QModelIndex(), 0, 0);
|
|
list.prepend(recipient);
|
|
endInsertRows();
|
|
}
|
|
|
|
void RecentRequestsTableModel::sort(int column, Qt::SortOrder order)
|
|
{
|
|
std::sort(list.begin(), list.end(), RecentRequestEntryLessThan(column, order));
|
|
Q_EMIT dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex()));
|
|
}
|
|
|
|
void RecentRequestsTableModel::updateDisplayUnit()
|
|
{
|
|
updateAmountColumnTitle();
|
|
}
|
|
|
|
bool RecentRequestEntryLessThan::operator()(const RecentRequestEntry& left, const RecentRequestEntry& right) const
|
|
{
|
|
const RecentRequestEntry* pLeft = &left;
|
|
const RecentRequestEntry* pRight = &right;
|
|
if (order == Qt::DescendingOrder)
|
|
std::swap(pLeft, pRight);
|
|
|
|
switch(column)
|
|
{
|
|
case RecentRequestsTableModel::Date:
|
|
return pLeft->date.toTime_t() < pRight->date.toTime_t();
|
|
case RecentRequestsTableModel::Label:
|
|
return pLeft->recipient.label < pRight->recipient.label;
|
|
case RecentRequestsTableModel::Message:
|
|
return pLeft->recipient.message < pRight->recipient.message;
|
|
case RecentRequestsTableModel::Amount:
|
|
return pLeft->recipient.amount < pRight->recipient.amount;
|
|
default:
|
|
return pLeft->id < pRight->id;
|
|
}
|
|
}
|