Bitcoin Core 30.99.0
P2P Digital Currency
recentrequeststablemodel.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-present The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
6
7#include <qt/bitcoinunits.h>
8#include <qt/guiutil.h>
9#include <qt/optionsmodel.h>
10#include <qt/walletmodel.h>
11
12#include <clientversion.h>
13#include <interfaces/wallet.h>
14#include <key_io.h>
15#include <streams.h>
16#include <util/string.h>
17
18#include <utility>
19
20#include <QLatin1Char>
21#include <QLatin1String>
22
23using util::ToString;
24
26 QAbstractTableModel(parent), walletModel(parent)
27{
28 // Load entries from wallet
29 for (const std::string& request : parent->wallet().getAddressReceiveRequests()) {
30 addNewRequest(request);
31 }
32
33 /* These columns must match the indices in the ColumnIndex enumeration */
34 columns << tr("Date") << tr("Label") << tr("Message") << getAmountTitle();
35
37}
38
40
41int RecentRequestsTableModel::rowCount(const QModelIndex &parent) const
42{
43 if (parent.isValid()) {
44 return 0;
45 }
46 return list.length();
47}
48
49int RecentRequestsTableModel::columnCount(const QModelIndex &parent) const
50{
51 if (parent.isValid()) {
52 return 0;
53 }
54 return columns.length();
55}
56
57QVariant RecentRequestsTableModel::data(const QModelIndex &index, int role) const
58{
59 if(!index.isValid() || index.row() >= list.length())
60 return QVariant();
61
62 if(role == Qt::DisplayRole || role == Qt::EditRole)
63 {
64 const RecentRequestEntry *rec = &list[index.row()];
65 switch(index.column())
66 {
67 case Date:
68 return GUIUtil::dateTimeStr(rec->date);
69 case Label:
70 if(rec->recipient.label.isEmpty() && role == Qt::DisplayRole)
71 {
72 return tr("(no label)");
73 }
74 else
75 {
76 return rec->recipient.label;
77 }
78 case Message:
79 if(rec->recipient.message.isEmpty() && role == Qt::DisplayRole)
80 {
81 return tr("(no message)");
82 }
83 else
84 {
85 return rec->recipient.message;
86 }
87 case Amount:
88 if (rec->recipient.amount == 0 && role == Qt::DisplayRole)
89 return tr("(no amount requested)");
90 else if (role == Qt::EditRole)
92 else
94 }
95 }
96 else if (role == Qt::TextAlignmentRole)
97 {
98 if (index.column() == Amount)
99 return (int)(Qt::AlignRight|Qt::AlignVCenter);
100 }
101 return QVariant();
102}
103
104bool RecentRequestsTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
105{
106 return true;
107}
108
109QVariant RecentRequestsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
110{
111 if(orientation == Qt::Horizontal)
112 {
113 if(role == Qt::DisplayRole && section < columns.size())
114 {
115 return columns[section];
116 }
117 }
118 return QVariant();
119}
120
123{
125 Q_EMIT headerDataChanged(Qt::Horizontal,Amount,Amount);
126}
127
130{
131 if (!walletModel->getOptionsModel()) return {};
132 return tr("Requested") +
133 QLatin1String(" (") +
135 QLatin1Char(')');
136}
137
138QModelIndex RecentRequestsTableModel::index(int row, int column, const QModelIndex &parent) const
139{
140 Q_UNUSED(parent);
141
142 return createIndex(row, column);
143}
144
145bool RecentRequestsTableModel::removeRows(int row, int count, const QModelIndex &parent)
146{
147 Q_UNUSED(parent);
148
149 if(count > 0 && row >= 0 && (row+count) <= list.size())
150 {
151 for (int i = 0; i < count; ++i)
152 {
153 const RecentRequestEntry* rec = &list[row+i];
155 return false;
156 }
157
158 beginRemoveRows(parent, row, row + count - 1);
159 list.erase(list.begin() + row, list.begin() + row + count);
160 endRemoveRows();
161 return true;
162 } else {
163 return false;
164 }
165}
166
167Qt::ItemFlags RecentRequestsTableModel::flags(const QModelIndex &index) const
168{
169 return Qt::ItemIsSelectable | Qt::ItemIsEnabled;
170}
171
172// called when adding a request from the GUI
174{
175 RecentRequestEntry newEntry;
176 newEntry.id = ++nReceiveRequestsMaxId;
177 newEntry.date = QDateTime::currentDateTime();
178 newEntry.recipient = recipient;
179
180 DataStream ss{};
181 ss << newEntry;
182
183 if (!walletModel->wallet().setAddressReceiveRequest(DecodeDestination(recipient.address.toStdString()), ToString(newEntry.id), ss.str()))
184 return;
185
186 addNewRequest(newEntry);
187}
188
189// called from ctor when loading from wallet
190void RecentRequestsTableModel::addNewRequest(const std::string &recipient)
191{
192 SpanReader ss{MakeByteSpan(recipient)};
193
195 ss >> entry;
196
197 if (entry.id == 0) // should not happen
198 return;
199
202
204}
205
206// actually add to table in GUI
208{
209 beginInsertRows(QModelIndex(), 0, 0);
210 list.prepend(recipient);
211 endInsertRows();
212}
213
214void RecentRequestsTableModel::sort(int column, Qt::SortOrder order)
215{
216 std::sort(list.begin(), list.end(), RecentRequestEntryLessThan(column, order));
217 Q_EMIT dataChanged(index(0, 0, QModelIndex()), index(list.size() - 1, NUMBER_OF_COLUMNS - 1, QModelIndex()));
218}
219
221{
223}
224
226{
227 const RecentRequestEntry* pLeft = &left;
228 const RecentRequestEntry* pRight = &right;
229 if (order == Qt::DescendingOrder)
230 std::swap(pLeft, pRight);
231
232 switch(column)
233 {
235 return pLeft->date.toSecsSinceEpoch() < pRight->date.toSecsSinceEpoch();
237 return pLeft->recipient.label < pRight->recipient.label;
239 return pLeft->recipient.message < pRight->recipient.message;
241 return pLeft->recipient.amount < pRight->recipient.amount;
242 default:
243 return pLeft->id < pRight->id;
244 }
245}
static QString format(Unit unit, const CAmount &amount, bool plussign=false, SeparatorStyle separators=SeparatorStyle::STANDARD, bool justify=false)
Format as string.
static QString shortName(Unit unit)
Short name.
Double ended buffer combining vector and stream-like interfaces.
Definition: streams.h:133
void displayUnitChanged(BitcoinUnit unit)
BitcoinUnit getDisplayUnit() const
Definition: optionsmodel.h:103
int64_t id
SendCoinsRecipient recipient
QDateTime date
Qt::SortOrder order
bool operator()(const RecentRequestEntry &left, const RecentRequestEntry &right) const
int column
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex()) override
QVariant headerData(int section, Qt::Orientation orientation, int role) const override
bool setData(const QModelIndex &index, const QVariant &value, int role) override
QModelIndex index(int row, int column, const QModelIndex &parent=QModelIndex()) const override
QVariant data(const QModelIndex &index, int role) const override
const RecentRequestEntry & entry(int row) const
void sort(int column, Qt::SortOrder order=Qt::AscendingOrder) override
QList< RecentRequestEntry > list
int rowCount(const QModelIndex &parent) const override
void updateAmountColumnTitle()
Updates the column title to "Amount (DisplayUnit)" and emits headerDataChanged() signal for table hea...
QString getAmountTitle()
Gets title for amount column including current display unit if optionsModel reference available.
Qt::ItemFlags flags(const QModelIndex &index) const override
void addNewRequest(const SendCoinsRecipient &recipient)
RecentRequestsTableModel(WalletModel *parent)
int columnCount(const QModelIndex &parent) const override
Minimal stream for reading from an existing byte array by std::span.
Definition: streams.h:83
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:49
interfaces::Wallet & wallet() const
Definition: walletmodel.h:138
OptionsModel * getOptionsModel() const
virtual bool setAddressReceiveRequest(const CTxDestination &dest, const std::string &id, const std::string &value)=0
Save or remove receive request.
virtual std::vector< std::string > getAddressReceiveRequests()=0
Get receive requests.
CTxDestination DecodeDestination(const std::string &str, std::string &error_msg, std::vector< int > *error_locations)
Definition: key_io.cpp:299
QString dateTimeStr(const QDateTime &date)
Definition: guiutil.cpp:90
std::string ToString(const T &t)
Locale-independent version of std::to_string.
Definition: string.h:246
auto MakeByteSpan(const V &v) noexcept
Definition: span.h:84
static int count