Skip to content

Commit d155eed

Browse files
committed
qml: Introduce WalletModel and loadWallet functionality
When a user selects a wallet from the WalletSelect menu the wallet controller can now load the wallet data in and the name and balance will appear in the WalletBadge
1 parent e7bea2d commit d155eed

13 files changed

+221
-150
lines changed

src/Makefile.qt.include

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ QT_MOC_CPP = \
4343
qml/models/moc_options_model.cpp \
4444
qml/models/moc_peerlistsortproxy.cpp \
4545
qml/models/moc_walletlistmodel.cpp \
46+
qml/models/moc_walletqmlmodel.cpp \
4647
qml/moc_appmode.cpp \
47-
qml/moc_walletcontroller.cpp \
48+
qml/moc_walletqmlcontroller.cpp \
4849
qt/moc_addressbookpage.cpp \
4950
qt/moc_addresstablemodel.cpp \
5051
qt/moc_askpassphrasedialog.cpp \
@@ -124,12 +125,13 @@ BITCOIN_QT_H = \
124125
qml/models/options_model.h \
125126
qml/models/peerlistsortproxy.h \
126127
qml/models/walletlistmodel.h \
128+
qml/models/walletqmlmodel.h \
127129
qml/appmode.h \
128130
qml/bitcoin.h \
129131
qml/guiconstants.h \
130132
qml/imageprovider.h \
131133
qml/util.h \
132-
qml/walletcontroller.h \
134+
qml/walletqmlcontroller.h \
133135
qt/addressbookpage.h \
134136
qt/addresstablemodel.h \
135137
qt/askpassphrasedialog.h \
@@ -314,9 +316,10 @@ BITCOIN_QML_BASE_CPP = \
314316
qml/models/options_model.cpp \
315317
qml/models/peerlistsortproxy.cpp \
316318
qml/models/walletlistmodel.cpp \
319+
qml/models/walletqmlmodel.cpp \
317320
qml/imageprovider.cpp \
318321
qml/util.cpp \
319-
qml/walletcontroller.cpp
322+
qml/walletqmlcontroller.cpp
320323

321324
QML_RES_FONTS = \
322325
qml/res/fonts/Inter-Regular.otf \

src/qml/bitcoin.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@
2727
#include <qml/models/options_model.h>
2828
#include <qml/models/peerlistsortproxy.h>
2929
#include <qml/models/walletlistmodel.h>
30+
#include <qml/models/walletqmlmodel.h>
3031
#include <qml/imageprovider.h>
3132
#include <qml/util.h>
32-
#include <qml/walletcontroller.h>
33+
#include <qml/walletqmlcontroller.h>
3334
#include <qt/guiutil.h>
3435
#include <qt/initexecutor.h>
3536
#include <qt/networkstyle.h>
@@ -258,8 +259,17 @@ int QmlGuiMain(int argc, char* argv[])
258259

259260
NodeModel node_model{*node};
260261
InitExecutor init_executor{*node};
262+
#ifdef ENABLE_WALLET
263+
WalletQmlController wallet_controller(*node);
264+
QObject::connect(&init_executor, &InitExecutor::initializeResult, &wallet_controller, &WalletQmlController::initialize);
265+
#endif
261266
QObject::connect(&node_model, &NodeModel::requestedInitialize, &init_executor, &InitExecutor::initialize);
262-
QObject::connect(&node_model, &NodeModel::requestedShutdown, &init_executor, &InitExecutor::shutdown);
267+
QObject::connect(&node_model, &NodeModel::requestedShutdown, [&] {
268+
#ifdef ENABLE_WALLET
269+
wallet_controller.unloadWallets();
270+
#endif
271+
init_executor.shutdown();
272+
});
263273
QObject::connect(&init_executor, &InitExecutor::initializeResult, &node_model, &NodeModel::initializeResult);
264274
QObject::connect(&init_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection);
265275
// QObject::connect(&init_executor, &InitExecutor::runawayException, &node_model, &NodeModel::handleRunawayException);
@@ -276,8 +286,12 @@ int QmlGuiMain(int argc, char* argv[])
276286
QObject::connect(&node_model, &NodeModel::setTimeRatioList, &chain_model, &ChainModel::setTimeRatioList);
277287
QObject::connect(&node_model, &NodeModel::setTimeRatioListInitial, &chain_model, &ChainModel::setTimeRatioListInitial);
278288

289+
279290
qGuiApp->setQuitOnLastWindowClosed(false);
280291
QObject::connect(qGuiApp, &QGuiApplication::lastWindowClosed, [&] {
292+
#ifdef ENABLE_WALLET
293+
wallet_controller.unloadWallets();
294+
#endif
281295
node->startShutdown();
282296
});
283297

@@ -288,8 +302,6 @@ int QmlGuiMain(int argc, char* argv[])
288302
GUIUtil::LoadFont(":/fonts/inter/regular");
289303
GUIUtil::LoadFont(":/fonts/inter/semibold");
290304

291-
WalletController wallet_controller(*node);
292-
293305
QQmlApplicationEngine engine;
294306

295307
QScopedPointer<const NetworkStyle> network_style{NetworkStyle::instantiate(Params().GetChainType())};
@@ -316,6 +328,9 @@ int QmlGuiMain(int argc, char* argv[])
316328
qmlRegisterType<BlockClockDial>("org.bitcoincore.qt", 1, 0, "BlockClockDial");
317329
qmlRegisterType<LineGraph>("org.bitcoincore.qt", 1, 0, "LineGraph");
318330

331+
qmlRegisterUncreatableType<WalletQmlModel>("org.bitcoincore.qt", 1, 0, "WalletQmlModel",
332+
"WalletQmlModel cannot be instantiated from QML");
333+
319334
engine.load(QUrl(QStringLiteral("qrc:///qml/pages/main.qml")));
320335
if (engine.rootObjects().isEmpty()) {
321336
return EXIT_FAILURE;

src/qml/models/walletlistmodel.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ WalletListModel::WalletListModel(interfaces::Node& node, QObject *parent)
1212
: QAbstractListModel(parent)
1313
, m_node(node)
1414
{
15-
setSelectedWallet("Singlesig Wallet");
1615
}
1716

1817
void WalletListModel::listWalletDir()
@@ -32,19 +31,6 @@ void WalletListModel::listWalletDir()
3231
}
3332
}
3433

35-
void WalletListModel::setSelectedWallet(QString wallet_name)
36-
{
37-
if (m_selected_wallet != wallet_name) {
38-
m_selected_wallet = wallet_name;
39-
Q_EMIT selectedWalletChanged();
40-
}
41-
}
42-
43-
QString WalletListModel::selectedWallet() const
44-
{
45-
return m_selected_wallet;
46-
}
47-
4834
int WalletListModel::rowCount(const QModelIndex &parent) const
4935
{
5036
Q_UNUSED(parent);

src/qml/models/walletlistmodel.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ class Node;
1616
class WalletListModel : public QAbstractListModel
1717
{
1818
Q_OBJECT
19-
Q_PROPERTY(QString selectedWallet READ selectedWallet WRITE setSelectedWallet NOTIFY selectedWalletChanged)
2019

2120
public:
2221
WalletListModel(interfaces::Node& node, QObject *parent = nullptr);
@@ -30,15 +29,9 @@ class WalletListModel : public QAbstractListModel
3029
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
3130
QHash<int, QByteArray> roleNames() const override;
3231

33-
void setSelectedWallet(QString wallet_name);
34-
QString selectedWallet() const;
35-
3632
public Q_SLOTS:
3733
void listWalletDir();
3834

39-
Q_SIGNALS:
40-
void selectedWalletChanged();
41-
4235
private:
4336
struct Item {
4437
QString name;
@@ -48,8 +41,6 @@ public Q_SLOTS:
4841

4942
QList<Item> m_items;
5043
interfaces::Node& m_node;
51-
QString m_selected_wallet;
52-
5344
};
5445

5546
#endif // BITCOIN_QML_MODELS_WALLETLISTMODEL_H

src/qml/models/walletqmlmodel.cpp

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
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/walletqmlmodel.h>
6+
7+
#include <qt/bitcoinunits.h>
8+
9+
#include <QTimer>
10+
11+
WalletQmlModel::WalletQmlModel(std::unique_ptr<interfaces::Wallet> wallet, QObject *parent)
12+
: QObject(parent)
13+
{
14+
m_wallet = std::move(wallet);
15+
}
16+
17+
WalletQmlModel::WalletQmlModel(QObject *parent)
18+
: QObject(parent)
19+
{
20+
}
21+
22+
QString WalletQmlModel::balance() const
23+
{
24+
if (!m_wallet) {
25+
return "0";
26+
}
27+
return BitcoinUnits::format(BitcoinUnits::Unit::BTC, m_wallet->getBalance());
28+
}
29+
30+
QString WalletQmlModel::name() const
31+
{
32+
if (!m_wallet) {
33+
return QString();
34+
}
35+
return QString::fromStdString(m_wallet->getWalletName());
36+
}

src/qml/models/walletqmlmodel.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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_WALLETQMLMODEL_H
6+
#define BITCOIN_QML_MODELS_WALLETQMLMODEL_H
7+
8+
#include <interfaces/wallet.h>
9+
10+
#include <QObject>
11+
12+
class WalletQmlModel : public QObject
13+
{
14+
Q_OBJECT
15+
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
16+
Q_PROPERTY(QString balance READ balance NOTIFY balanceChanged)
17+
18+
public:
19+
WalletQmlModel(std::unique_ptr<interfaces::Wallet> wallet, QObject *parent = nullptr);
20+
WalletQmlModel(QObject *parent = nullptr);
21+
~WalletQmlModel() = default;
22+
23+
QString name() const;
24+
QString balance() const;
25+
26+
Q_SIGNALS:
27+
void nameChanged();
28+
void balanceChanged();
29+
30+
private:
31+
std::unique_ptr<interfaces::Wallet> m_wallet;
32+
};
33+
34+
#endif // BITCOIN_QML_MODELS_WALLETQMLMODEL_H

src/qml/pages/wallet/DesktopWallets.qml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,8 @@ Page {
2424
leftItem: WalletBadge {
2525
implicitWidth: 154
2626
implicitHeight: 46
27-
text: walletListModel.selectedWallet
27+
text: walletController.selectedWallet.name
28+
balance: walletController.selectedWallet.balance
2829

2930
MouseArea {
3031
anchors.fill: parent

src/qml/pages/wallet/WalletBadge.qml

Lines changed: 3 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -13,70 +13,6 @@ import "../../controls"
1313
Button {
1414
id: root
1515

16-
function formatSatoshis(satoshis) {
17-
var highlightColor = Theme.color.neutral9
18-
var zeroColor = Theme.color.neutral7
19-
20-
if (root.checked || root.hovered) {
21-
highlightColor = zeroColor = Theme.color.orange
22-
}
23-
24-
// Convert satoshis to bitcoins
25-
var bitcoins = satoshis / 100000000;
26-
27-
// Format bitcoins to a fixed 8 decimal places string
28-
var bitcoinStr = bitcoins.toFixed(8);
29-
30-
// Split the bitcoin string into integer and fractional parts
31-
var parts = bitcoinStr.split('.');
32-
33-
// Add spaces for every 3 digits in the integer part
34-
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
35-
36-
// Highlight the first significant digit and all following digits in the integer part
37-
var significantFound = false;
38-
parts[0] = parts[0].replace(/(\d)/g, function(match) {
39-
if (!significantFound && match !== '0') {
40-
significantFound = true;
41-
}
42-
if (significantFound) {
43-
return '<font color="' + highlightColor + '">' + match + '</font>';
44-
}
45-
return match;
46-
});
47-
48-
// Add spaces for every 3 digits in the decimal part
49-
parts[1] = parts[1].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
50-
if (significantFound) {
51-
parts[1] = '<font color="' + highlightColor + '">' + parts[1] + '</font>';
52-
} else {
53-
// Highlight the first significant digit and all following digits in the fractional part
54-
significantFound = false;
55-
parts[1] = parts[1].replace(/(\d)/g, function(match) {
56-
if (!significantFound && match !== '0') {
57-
significantFound = true;
58-
}
59-
if (significantFound) {
60-
return '<font color="' + highlightColor + '">' + match + '</font>';
61-
}
62-
return match;
63-
});
64-
}
65-
66-
// Concatenate the parts back together
67-
var formattedBitcoins = parts.join('.');
68-
69-
// Format the text with the Bitcoin symbol
70-
var formattedText = `<font color="${highlightColor}">₿</font> ${formattedBitcoins}`;
71-
72-
// Highlight zero in a different color if satoshis are zero
73-
if (satoshis === 0) {
74-
formattedText = `<font color="${zeroColor}">₿ 0.00</font>`;
75-
}
76-
77-
return formattedText;
78-
}
79-
8016
property color bgActiveColor: Theme.color.neutral2
8117
property color textColor: Theme.color.neutral7
8218
property color textHoverColor: Theme.color.orange
@@ -85,17 +21,17 @@ Button {
8521
property string iconSource: ""
8622
property bool showBalance: true
8723
property bool showIcon: true
24+
property string balance: "0.0 000 000"
8825

8926
checkable: true
9027
hoverEnabled: AppMode.isDesktop
9128
implicitHeight: 60
92-
implicitWidth: 220
29+
implicitWidth: contentItem.width
9330
bottomPadding: 0
9431
topPadding: 0
9532
clip: true
9633

9734
contentItem: RowLayout {
98-
anchors.fill: parent
9935
anchors.leftMargin: 5
10036
anchors.rightMargin: 5
10137
clip: true
@@ -126,7 +62,7 @@ Button {
12662
CoreText {
12763
id: balanceText
12864
visible: root.showBalance
129-
text: formatSatoshis(12300)
65+
text: "" + root.balance
13066
color: Theme.color.neutral7
13167
}
13268
}

src/qml/pages/wallet/WalletSelect.qml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,12 @@ Popup {
7777
width: 220
7878
height: 32
7979
text: name
80+
checked: walletController.selectedWallet.name == name
8081
ButtonGroup.group: buttonGroup
8182
showBalance: false
8283
showIcon: false
8384
onClicked: {
84-
walletListModel.selectedWallet = name
85+
walletController.setSelectedWallet(name)
8586
root.close()
8687
}
8788
}

src/qml/walletcontroller.cpp

Lines changed: 0 additions & 25 deletions
This file was deleted.

0 commit comments

Comments
 (0)