Skip to content

Commit a07c7f2

Browse files
committed
qml: Introduce the Desktop Wallet Activity Page
1 parent b4bebc3 commit a07c7f2

14 files changed

+959
-3
lines changed

Diff for: src/Makefile.qt.include

+6
Original file line numberDiff line numberDiff line change
@@ -37,12 +37,14 @@ QT_FORMS_UI = \
3737
QT_MOC_CPP = \
3838
qml/components/moc_blockclockdial.cpp \
3939
qml/controls/moc_linegraph.cpp \
40+
qml/models/moc_activitylistmodel.cpp \
4041
qml/models/moc_chainmodel.cpp \
4142
qml/models/moc_networktraffictower.cpp \
4243
qml/models/moc_nodemodel.cpp \
4344
qml/models/moc_options_model.cpp \
4445
qml/models/moc_peerdetailsmodel.cpp \
4546
qml/models/moc_peerlistsortproxy.cpp \
47+
qml/models/moc_transaction.cpp \
4648
qml/models/moc_walletlistmodel.cpp \
4749
qml/models/moc_walletqmlmodel.cpp \
4850
qml/moc_appmode.cpp \
@@ -120,12 +122,14 @@ QT_QRC_LOCALE = qt/bitcoin_locale.qrc
120122
BITCOIN_QT_H = \
121123
qml/components/blockclockdial.h \
122124
qml/controls/linegraph.h \
125+
qml/models/activitylistmodel.h \
123126
qml/models/chainmodel.h \
124127
qml/models/networktraffictower.h \
125128
qml/models/nodemodel.h \
126129
qml/models/options_model.h \
127130
qml/models/peerdetailsmodel.h \
128131
qml/models/peerlistsortproxy.h \
132+
qml/models/transaction.h \
129133
qml/models/walletlistmodel.h \
130134
qml/models/walletqmlmodel.h \
131135
qml/appmode.h \
@@ -312,12 +316,14 @@ BITCOIN_QML_BASE_CPP = \
312316
qml/bitcoin.cpp \
313317
qml/components/blockclockdial.cpp \
314318
qml/controls/linegraph.cpp \
319+
qml/models/activitylistmodel.cpp \
315320
qml/models/chainmodel.cpp \
316321
qml/models/networktraffictower.cpp \
317322
qml/models/nodemodel.cpp \
318323
qml/models/options_model.cpp \
319324
qml/models/peerdetailsmodel.cpp \
320325
qml/models/peerlistsortproxy.cpp \
326+
qml/models/transaction.cpp \
321327
qml/models/walletlistmodel.cpp \
322328
qml/models/walletqmlmodel.cpp \
323329
qml/imageprovider.cpp \

Diff for: src/qml/bitcoin.cpp

+4
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <qml/components/blockclockdial.h>
2222
#include <qml/controls/linegraph.h>
2323
#include <qml/guiconstants.h>
24+
#include <qml/models/activitylistmodel.h>
2425
#include <qml/models/chainmodel.h>
2526
#include <qml/models/networktraffictower.h>
2627
#include <qml/models/nodemodel.h>
@@ -318,6 +319,9 @@ int QmlGuiMain(int argc, char* argv[])
318319
WalletListModel wallet_list_model{*node, nullptr};
319320
engine.rootContext()->setContextProperty("walletController", &wallet_controller);
320321
engine.rootContext()->setContextProperty("walletListModel", &wallet_list_model);
322+
323+
ActivityListModel actitvity_list_model{nullptr};
324+
engine.rootContext()->setContextProperty("activityListModel", &actitvity_list_model);
321325
#endif
322326

323327
OptionsQmlModel options_model(*node, !need_onboarding.toBool());

Diff for: src/qml/components/Activity.qml

Whitespace-only changes.

Diff for: src/qml/models/activitylistmodel.cpp

+140
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
// Copyright (c) 2024 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+
5+
#include <qml/models/activitylistmodel.h>
6+
7+
#include <qml/models/walletqmlmodel.h>
8+
9+
ActivityListModel::ActivityListModel(WalletQmlModel *parent)
10+
: QAbstractListModel(parent)
11+
, m_wallet_model(parent)
12+
{
13+
if (m_wallet_model != nullptr) {
14+
refreshWallet();
15+
}
16+
}
17+
18+
int ActivityListModel::rowCount(const QModelIndex &parent) const
19+
{
20+
Q_UNUSED(parent)
21+
return m_transactions.size();
22+
}
23+
24+
void ActivityListModel::updateTransactionStatus(QSharedPointer<Transaction> tx) const
25+
{
26+
if (m_wallet_model == nullptr) {
27+
return;
28+
}
29+
interfaces::WalletTxStatus wtx;
30+
int num_blocks;
31+
int64_t block_time;
32+
if (m_wallet_model->tryGetTxStatus(tx->hash, wtx, num_blocks, block_time)) {
33+
tx->updateStatus(wtx, num_blocks, block_time);
34+
} else {
35+
tx->status = Transaction::Status::NotAccepted;
36+
}
37+
}
38+
39+
QVariant ActivityListModel::data(const QModelIndex &index, int role) const
40+
{
41+
if (!index.isValid() || index.row() < 0 || index.row() >= m_transactions.size())
42+
return QVariant();
43+
44+
QSharedPointer<Transaction> tx = m_transactions.at(index.row());
45+
updateTransactionStatus(tx);
46+
47+
switch (role) {
48+
case AmountRole:
49+
return tx->prettyAmount();
50+
case AddressRole:
51+
return tx->address;
52+
case LabelRole:
53+
return tx->label;
54+
case DateTimeRole:
55+
return tx->dateTimeString();
56+
case StatusRole:
57+
return tx->status;
58+
case TypeRole:
59+
return tx->type;
60+
case DepthRole:
61+
return tx->depth;
62+
default:
63+
return QVariant();
64+
}
65+
}
66+
67+
QHash<int, QByteArray> ActivityListModel::roleNames() const
68+
{
69+
QHash<int, QByteArray> roles;
70+
roles[AmountRole] = "amount";
71+
roles[AddressRole] = "address";
72+
roles[LabelRole] = "label";
73+
roles[DateTimeRole] = "date";
74+
roles[StatusRole] = "status";
75+
roles[TypeRole] = "type";
76+
roles[DepthRole] = "depth";
77+
return roles;
78+
}
79+
80+
void ActivityListModel::refreshWallet()
81+
{
82+
if (m_wallet_model == nullptr) {
83+
return;
84+
}
85+
for (const auto &tx : m_wallet_model->getWalletTxs()) {
86+
auto transactions = Transaction::fromWalletTx(tx);
87+
m_transactions.append(transactions);
88+
for (const auto &transaction : transactions) {
89+
updateTransactionStatus(transaction);
90+
}
91+
}
92+
std::sort(m_transactions.begin(), m_transactions.end(),
93+
[](const QSharedPointer<Transaction> &a, const QSharedPointer<Transaction> &b) {
94+
return a->depth < b->depth;
95+
});
96+
}
97+
98+
void ActivityListModel::updateTransaction(const uint256& hash, const interfaces::WalletTxStatus& wtx, int num_blocks, int64_t block_time)
99+
{
100+
int index = findTransactionIndex(hash);
101+
if (index != -1) {
102+
QSharedPointer<Transaction> tx = m_transactions.at(index);
103+
tx->updateStatus(wtx, num_blocks, block_time);
104+
Q_EMIT dataChanged(this->index(index), this->index(index));
105+
}
106+
}
107+
108+
109+
int ActivityListModel::findTransactionIndex(const uint256& hash) const
110+
{
111+
auto it = std::find_if(m_transactions.begin(), m_transactions.end(),
112+
[&hash](const QSharedPointer<Transaction>& tx) {
113+
return tx->hash == hash;
114+
});
115+
if (it != m_transactions.end()) {
116+
return std::distance(m_transactions.begin(), it);
117+
}
118+
return -1;
119+
}
120+
121+
void ActivityListModel::subsctribeToCoreSignals()
122+
{
123+
// Connect signals to wallet
124+
m_handler_transaction_changed = m_wallet_model->handleTransactionChanged([this](const uint256& hash, ChangeType status) {
125+
interfaces::WalletTxStatus wtx;
126+
int num_blocks;
127+
int64_t block_time;
128+
if (m_wallet_model->tryGetTxStatus(hash, wtx, num_blocks, block_time)) {
129+
updateTransaction(hash, wtx, num_blocks, block_time);
130+
}
131+
});
132+
}
133+
134+
void ActivityListModel::unsubscribeFromCoreSignals()
135+
{
136+
// Disconnect signals from wallet
137+
if (m_handler_transaction_changed) {
138+
m_handler_transaction_changed->disconnect();
139+
}
140+
}

Diff for: src/qml/models/activitylistmodel.h

+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
// Copyright (c) 2024 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+
5+
#ifndef BITCOIN_QML_MODELS_ACTIVITYLISTMODEL_H
6+
#define BITCOIN_QML_MODELS_ACTIVITYLISTMODEL_H
7+
8+
#include <interfaces/handler.h>
9+
#include <interfaces/wallet.h>
10+
11+
#include <qml/models/walletqmlmodel.h>
12+
#include <qml/models/transaction.h>
13+
14+
#include <QAbstractListModel>
15+
#include <QList>
16+
#include <QSharedPointer>
17+
#include <QString>
18+
19+
#include <memory>
20+
21+
class WalletQmlModel;
22+
23+
class ActivityListModel : public QAbstractListModel
24+
{
25+
Q_OBJECT
26+
27+
public:
28+
explicit ActivityListModel(WalletQmlModel * parent = nullptr);
29+
30+
enum TransactionRoles {
31+
AmountRole = Qt::UserRole + 1,
32+
AddressRole,
33+
LabelRole,
34+
DateTimeRole,
35+
StatusRole,
36+
TypeRole,
37+
DepthRole
38+
};
39+
40+
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
41+
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
42+
QHash<int, QByteArray> roleNames() const override;
43+
44+
private:
45+
void refreshWallet();
46+
void updateTransactionStatus(QSharedPointer<Transaction> tx) const;
47+
void subsctribeToCoreSignals();
48+
void unsubscribeFromCoreSignals();
49+
void updateTransaction(const uint256& hash, const interfaces::WalletTxStatus& wtx,
50+
int num_blocks, int64_t block_time);
51+
int findTransactionIndex(const uint256& hash) const;
52+
53+
QList<QSharedPointer<Transaction>> m_transactions;
54+
WalletQmlModel* m_wallet_model;
55+
std::unique_ptr<interfaces::Handler> m_handler_transaction_changed;
56+
std::unique_ptr<interfaces::Handler> m_handler_show_progress;
57+
};
58+
59+
#endif // BITCOIN_QML_MODELS_ACTIVITYLISTMODEL_H

Diff for: src/qml/models/activitymodel.cpp

Whitespace-only changes.

Diff for: src/qml/models/activitymodel.h

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
// Copyright (c) 2024 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.

0 commit comments

Comments
 (0)