Skip to content

Commit

Permalink
qml: Introduce WalletModel and loadWallet functionality
Browse files Browse the repository at this point in the history
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
  • Loading branch information
johnny9 committed Sep 23, 2024
1 parent e7bea2d commit 26b5ef9
Show file tree
Hide file tree
Showing 13 changed files with 216 additions and 149 deletions.
9 changes: 6 additions & 3 deletions src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ QT_MOC_CPP = \
qml/models/moc_options_model.cpp \
qml/models/moc_peerlistsortproxy.cpp \
qml/models/moc_walletlistmodel.cpp \
qml/models/moc_walletqmlmodel.cpp \
qml/moc_appmode.cpp \
qml/moc_walletcontroller.cpp \
qml/moc_walletqmlcontroller.cpp \
qt/moc_addressbookpage.cpp \
qt/moc_addresstablemodel.cpp \
qt/moc_askpassphrasedialog.cpp \
Expand Down Expand Up @@ -124,12 +125,13 @@ BITCOIN_QT_H = \
qml/models/options_model.h \
qml/models/peerlistsortproxy.h \
qml/models/walletlistmodel.h \
qml/models/walletqmlmodel.h \
qml/appmode.h \
qml/bitcoin.h \
qml/guiconstants.h \
qml/imageprovider.h \
qml/util.h \
qml/walletcontroller.h \
qml/walletqmlcontroller.h \
qt/addressbookpage.h \
qt/addresstablemodel.h \
qt/askpassphrasedialog.h \
Expand Down Expand Up @@ -314,9 +316,10 @@ BITCOIN_QML_BASE_CPP = \
qml/models/options_model.cpp \
qml/models/peerlistsortproxy.cpp \
qml/models/walletlistmodel.cpp \
qml/models/walletqmlmodel.cpp \
qml/imageprovider.cpp \
qml/util.cpp \
qml/walletcontroller.cpp
qml/walletqmlcontroller.cpp

QML_RES_FONTS = \
qml/res/fonts/Inter-Regular.otf \
Expand Down
17 changes: 14 additions & 3 deletions src/qml/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,10 @@
#include <qml/models/options_model.h>
#include <qml/models/peerlistsortproxy.h>
#include <qml/models/walletlistmodel.h>
#include <qml/models/walletqmlmodel.h>
#include <qml/imageprovider.h>
#include <qml/util.h>
#include <qml/walletcontroller.h>
#include <qml/walletqmlcontroller.h>
#include <qt/guiutil.h>
#include <qt/initexecutor.h>
#include <qt/networkstyle.h>
Expand Down Expand Up @@ -276,8 +277,17 @@ int QmlGuiMain(int argc, char* argv[])
QObject::connect(&node_model, &NodeModel::setTimeRatioList, &chain_model, &ChainModel::setTimeRatioList);
QObject::connect(&node_model, &NodeModel::setTimeRatioListInitial, &chain_model, &ChainModel::setTimeRatioListInitial);


#ifdef ENABLE_WALLET
WalletQmlController wallet_controller(*node);
QObject::connect(&init_executor, &InitExecutor::initializeResult, &wallet_controller, &WalletQmlController::initialize);
#endif

qGuiApp->setQuitOnLastWindowClosed(false);
QObject::connect(qGuiApp, &QGuiApplication::lastWindowClosed, [&] {
#ifdef ENABLE_WALLET
wallet_controller.unloadWallets();
#endif
node->startShutdown();
});

Expand All @@ -288,8 +298,6 @@ int QmlGuiMain(int argc, char* argv[])
GUIUtil::LoadFont(":/fonts/inter/regular");
GUIUtil::LoadFont(":/fonts/inter/semibold");

WalletController wallet_controller(*node);

QQmlApplicationEngine engine;

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

qmlRegisterUncreatableType<WalletQmlModel>("org.bitcoincore.qt", 1, 0, "WalletQmlModel",
"WalletQmlModel cannot be instantiated from QML");

engine.load(QUrl(QStringLiteral("qrc:///qml/pages/main.qml")));
if (engine.rootObjects().isEmpty()) {
return EXIT_FAILURE;
Expand Down
14 changes: 0 additions & 14 deletions src/qml/models/walletlistmodel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ WalletListModel::WalletListModel(interfaces::Node& node, QObject *parent)
: QAbstractListModel(parent)
, m_node(node)
{
setSelectedWallet("Singlesig Wallet");
}

void WalletListModel::listWalletDir()
Expand All @@ -32,19 +31,6 @@ void WalletListModel::listWalletDir()
}
}

void WalletListModel::setSelectedWallet(QString wallet_name)
{
if (m_selected_wallet != wallet_name) {
m_selected_wallet = wallet_name;
Q_EMIT selectedWalletChanged();
}
}

QString WalletListModel::selectedWallet() const
{
return m_selected_wallet;
}

int WalletListModel::rowCount(const QModelIndex &parent) const
{
Q_UNUSED(parent);
Expand Down
9 changes: 0 additions & 9 deletions src/qml/models/walletlistmodel.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ class Node;
class WalletListModel : public QAbstractListModel
{
Q_OBJECT
Q_PROPERTY(QString selectedWallet READ selectedWallet WRITE setSelectedWallet NOTIFY selectedWalletChanged)

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

void setSelectedWallet(QString wallet_name);
QString selectedWallet() const;

public Q_SLOTS:
void listWalletDir();

Q_SIGNALS:
void selectedWalletChanged();

private:
struct Item {
QString name;
Expand All @@ -48,8 +41,6 @@ public Q_SLOTS:

QList<Item> m_items;
interfaces::Node& m_node;
QString m_selected_wallet;

};

#endif // BITCOIN_QML_MODELS_WALLETLISTMODEL_H
36 changes: 36 additions & 0 deletions src/qml/models/walletqmlmodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright (c) 2024 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 <qml/models/walletqmlmodel.h>

#include <qt/bitcoinunits.h>

#include <QTimer>

WalletQmlModel::WalletQmlModel(std::unique_ptr<interfaces::Wallet> wallet, QObject *parent)
: QObject(parent)
{
m_wallet = std::move(wallet);
}

WalletQmlModel::WalletQmlModel(QObject *parent)
: QObject(parent)
{
}

QString WalletQmlModel::balance() const
{
if (!m_wallet) {
return "0";
}
return BitcoinUnits::format(BitcoinUnits::Unit::BTC, m_wallet->getBalance());
}

QString WalletQmlModel::name() const
{
if (!m_wallet) {
return QString();
}
return QString::fromStdString(m_wallet->getWalletName());
}
34 changes: 34 additions & 0 deletions src/qml/models/walletqmlmodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// Copyright (c) 2024 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#ifndef BITCOIN_QML_MODELS_WALLETQMLMODEL_H
#define BITCOIN_QML_MODELS_WALLETQMLMODEL_H

#include <interfaces/wallet.h>

#include <QObject>

class WalletQmlModel : public QObject
{
Q_OBJECT
Q_PROPERTY(QString name READ name NOTIFY nameChanged)
Q_PROPERTY(QString balance READ balance NOTIFY balanceChanged)

public:
WalletQmlModel(std::unique_ptr<interfaces::Wallet> wallet, QObject *parent = nullptr);
WalletQmlModel(QObject *parent = nullptr);
~WalletQmlModel() = default;

QString name() const;
QString balance() const;

Q_SIGNALS:
void nameChanged();
void balanceChanged();

private:
std::unique_ptr<interfaces::Wallet> m_wallet;
};

#endif // BITCOIN_QML_MODELS_WALLETQMLMODEL_H
3 changes: 2 additions & 1 deletion src/qml/pages/wallet/DesktopWallets.qml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ Page {
leftItem: WalletBadge {
implicitWidth: 154
implicitHeight: 46
text: walletListModel.selectedWallet
text: walletController.selectedWallet.name
balance: walletController.selectedWallet.balance

MouseArea {
anchors.fill: parent
Expand Down
70 changes: 3 additions & 67 deletions src/qml/pages/wallet/WalletBadge.qml
Original file line number Diff line number Diff line change
Expand Up @@ -13,70 +13,6 @@ import "../../controls"
Button {
id: root

function formatSatoshis(satoshis) {
var highlightColor = Theme.color.neutral9
var zeroColor = Theme.color.neutral7

if (root.checked || root.hovered) {
highlightColor = zeroColor = Theme.color.orange
}

// Convert satoshis to bitcoins
var bitcoins = satoshis / 100000000;

// Format bitcoins to a fixed 8 decimal places string
var bitcoinStr = bitcoins.toFixed(8);

// Split the bitcoin string into integer and fractional parts
var parts = bitcoinStr.split('.');

// Add spaces for every 3 digits in the integer part
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');

// Highlight the first significant digit and all following digits in the integer part
var significantFound = false;
parts[0] = parts[0].replace(/(\d)/g, function(match) {
if (!significantFound && match !== '0') {
significantFound = true;
}
if (significantFound) {
return '<font color="' + highlightColor + '">' + match + '</font>';
}
return match;
});

// Add spaces for every 3 digits in the decimal part
parts[1] = parts[1].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
if (significantFound) {
parts[1] = '<font color="' + highlightColor + '">' + parts[1] + '</font>';
} else {
// Highlight the first significant digit and all following digits in the fractional part
significantFound = false;
parts[1] = parts[1].replace(/(\d)/g, function(match) {
if (!significantFound && match !== '0') {
significantFound = true;
}
if (significantFound) {
return '<font color="' + highlightColor + '">' + match + '</font>';
}
return match;
});
}

// Concatenate the parts back together
var formattedBitcoins = parts.join('.');

// Format the text with the Bitcoin symbol
var formattedText = `<font color="${highlightColor}">₿</font> ${formattedBitcoins}`;

// Highlight zero in a different color if satoshis are zero
if (satoshis === 0) {
formattedText = `<font color="${zeroColor}">₿ 0.00</font>`;
}

return formattedText;
}

property color bgActiveColor: Theme.color.neutral2
property color textColor: Theme.color.neutral7
property color textHoverColor: Theme.color.orange
Expand All @@ -85,17 +21,17 @@ Button {
property string iconSource: ""
property bool showBalance: true
property bool showIcon: true
property string balance: "0.0 000 000"

checkable: true
hoverEnabled: AppMode.isDesktop
implicitHeight: 60
implicitWidth: 220
implicitWidth: contentItem.width
bottomPadding: 0
topPadding: 0
clip: true

contentItem: RowLayout {
anchors.fill: parent
anchors.leftMargin: 5
anchors.rightMargin: 5
clip: true
Expand Down Expand Up @@ -126,7 +62,7 @@ Button {
CoreText {
id: balanceText
visible: root.showBalance
text: formatSatoshis(12300)
text: "" + root.balance
color: Theme.color.neutral7
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/qml/pages/wallet/WalletSelect.qml
Original file line number Diff line number Diff line change
Expand Up @@ -77,11 +77,12 @@ Popup {
width: 220
height: 32
text: name
checked: walletController.selectedWallet.name == name
ButtonGroup.group: buttonGroup
showBalance: false
showIcon: false
onClicked: {
walletListModel.selectedWallet = name
walletController.setSelectedWallet(name)
root.close()
}
}
Expand Down
25 changes: 0 additions & 25 deletions src/qml/walletcontroller.cpp

This file was deleted.

26 changes: 0 additions & 26 deletions src/qml/walletcontroller.h

This file was deleted.

Loading

0 comments on commit 26b5ef9

Please sign in to comment.