Skip to content

Commit 7175d02

Browse files
committed
Merge #401: Introduce Wallet Select Dropdown
2c1433d qml: Introduce the WalletSelect component (johnny9) d61b861 qml: Introduce the WalletBadge component (johnny9) Pull request description: WalletSelect is a Popup that appears after clicking the main WalletBadge in the DesktopNavigation bar. It contains a ListView that allows the user to select one of the wallets listed in the wallet directory. This PR uses the arrow icon that is shared with the Tooltip so it is based off of that commit. [![Build Artifacts](https://img.shields.io/badge/Build%20Artifacts-green )](https://github.com/bitcoin-core/gui-qml/actions/runs/9263281845) ACKs for top commit: D33r-Gee: tACK [2c1433d](2c1433d) on WSL Ubuntu 22.04 Tree-SHA512: 19b877ca1be7488c54e79dba28720818711ab9f9f8de34cdb4f540daa150dc6debb8d78d9e0ba14b8a246f88497f6a04b089bcd3e4dca433afe49990201439d9
2 parents 6df72f8 + 2c1433d commit 7175d02

File tree

11 files changed

+451
-19
lines changed

11 files changed

+451
-19
lines changed

qml/bitcoin.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include <qml/models/nodemodel.h>
2727
#include <qml/models/options_model.h>
2828
#include <qml/models/peerlistsortproxy.h>
29+
#include <qml/models/walletlistmodel.h>
2930
#include <qml/imageprovider.h>
3031
#include <qml/util.h>
3132
#include <qml/walletcontroller.h>
@@ -295,12 +296,15 @@ int QmlGuiMain(int argc, char* argv[])
295296
assert(!network_style.isNull());
296297
engine.addImageProvider(QStringLiteral("images"), new ImageProvider{network_style.data()});
297298

299+
WalletListModel wallet_list_model{*node, nullptr};
300+
298301
engine.rootContext()->setContextProperty("networkTrafficTower", &network_traffic_tower);
299302
engine.rootContext()->setContextProperty("nodeModel", &node_model);
300303
engine.rootContext()->setContextProperty("chainModel", &chain_model);
301304
engine.rootContext()->setContextProperty("peerTableModel", &peer_model);
302305
engine.rootContext()->setContextProperty("peerListModelProxy", &peer_model_sort_proxy);
303306
engine.rootContext()->setContextProperty("walletController", &wallet_controller);
307+
engine.rootContext()->setContextProperty("walletListModel", &wallet_list_model);
304308

305309
OptionsQmlModel options_model(*node, !need_onboarding.toBool());
306310
engine.rootContext()->setContextProperty("optionsModel", &options_model);

qml/bitcoin_qml.qrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,8 @@
7373
<file>pages/wallet/CreateName.qml</file>
7474
<file>pages/wallet/CreatePassword.qml</file>
7575
<file>pages/wallet/DesktopWallets.qml</file>
76+
<file>pages/wallet/WalletBadge.qml</file>
77+
<file>pages/wallet/WalletSelect.qml</file>
7678
</qresource>
7779
<qresource prefix="/icons">
7880
<file alias="add-wallet-dark">res/icons/add-wallet-dark.png</file>
@@ -95,6 +97,7 @@
9597
<file alias="info">res/icons/info.png</file>
9698
<file alias="network-dark">res/icons/network-dark.png</file>
9799
<file alias="network-light">res/icons/network-light.png</file>
100+
<file alias="plus">res/icons/plus.png</file>
98101
<file alias="shutdown">res/icons/shutdown.png</file>
99102
<file alias="singlesig-wallet">res/icons/singlesig-wallet.png</file>
100103
<file alias="storage-dark">res/icons/storage-dark.png</file>

qml/controls/Icon.qml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import QtQuick.Controls 2.15
77

88
Button {
99
id: root
10+
width: icon.width
11+
height: icon.height
1012
required property color color
1113
required property url source
1214
property int size: 32

qml/imageprovider.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,5 +162,9 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
162162
return QIcon(":/icons/hidden").pixmap(requested_size);
163163
}
164164

165+
if (id == "plus") {
166+
*size = requested_size;
167+
return QIcon(":/icons/plus").pixmap(requested_size);
168+
}
165169
return {};
166170
}

qml/models/walletlistmodel.cpp

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
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/walletlistmodel.h>
6+
7+
#include <interfaces/node.h>
8+
9+
#include <QSet>
10+
11+
WalletListModel::WalletListModel(interfaces::Node& node, QObject *parent)
12+
: QAbstractListModel(parent)
13+
, m_node(node)
14+
{
15+
setSelectedWallet("Singlesig Wallet");
16+
}
17+
18+
void WalletListModel::listWalletDir()
19+
{
20+
QSet<QString> existing_names;
21+
for (int i = 0; i < rowCount(); ++i) {
22+
QModelIndex index = this->index(i, 0);
23+
QString name = data(index, NameRole).toString();
24+
existing_names.insert(name);
25+
}
26+
27+
for (const std::string &name : m_node.walletLoader().listWalletDir()) {
28+
QString qname = QString::fromStdString(name);
29+
if (!existing_names.contains(qname)) {
30+
addItem({ qname });
31+
}
32+
}
33+
}
34+
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+
48+
int WalletListModel::rowCount(const QModelIndex &parent) const
49+
{
50+
Q_UNUSED(parent);
51+
return m_items.size();
52+
}
53+
54+
QVariant WalletListModel::data(const QModelIndex &index, int role) const
55+
{
56+
if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size())
57+
return QVariant();
58+
59+
const auto &item = m_items[index.row()];
60+
switch (role) {
61+
case Qt::DisplayRole:
62+
case NameRole:
63+
return item.name;
64+
default:
65+
return QVariant();
66+
}
67+
}
68+
69+
QHash<int, QByteArray> WalletListModel::roleNames() const
70+
{
71+
QHash<int, QByteArray> roles;
72+
roles[NameRole] = "name";
73+
return roles;
74+
}
75+
76+
void WalletListModel::addItem(const Item &item)
77+
{
78+
beginInsertRows(QModelIndex(), rowCount(), rowCount());
79+
m_items.append(item);
80+
endInsertRows();
81+
}

qml/models/walletlistmodel.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
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_WALLETLISTMODEL_H
6+
#define BITCOIN_QML_MODELS_WALLETLISTMODEL_H
7+
8+
#include <interfaces/wallet.h>
9+
#include <QAbstractListModel>
10+
#include <QList>
11+
12+
namespace interfaces {
13+
class Node;
14+
}
15+
16+
class WalletListModel : public QAbstractListModel
17+
{
18+
Q_OBJECT
19+
Q_PROPERTY(QString selectedWallet READ selectedWallet WRITE setSelectedWallet NOTIFY selectedWalletChanged)
20+
21+
public:
22+
WalletListModel(interfaces::Node& node, QObject *parent = nullptr);
23+
~WalletListModel() = default;
24+
25+
enum Roles {
26+
NameRole = Qt::UserRole + 1
27+
};
28+
29+
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
30+
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
31+
QHash<int, QByteArray> roleNames() const override;
32+
33+
void setSelectedWallet(QString wallet_name);
34+
QString selectedWallet() const;
35+
36+
public Q_SLOTS:
37+
void listWalletDir();
38+
39+
Q_SIGNALS:
40+
void selectedWalletChanged();
41+
42+
private:
43+
struct Item {
44+
QString name;
45+
};
46+
47+
void addItem(const Item &item);
48+
49+
QList<Item> m_items;
50+
interfaces::Node& m_node;
51+
QString m_selected_wallet;
52+
53+
};
54+
55+
#endif // BITCOIN_QML_MODELS_WALLETLISTMODEL_H

qml/pages/wallet/DesktopWallets.qml

Lines changed: 18 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,26 @@ Page {
2121

2222
header: NavigationBar2 {
2323
id: navBar
24-
leftItem: RowLayout {
25-
spacing: 5
26-
Icon {
27-
source: "image://images/singlesig-wallet"
28-
color: Theme.color.neutral8
29-
Layout.preferredWidth: 30
30-
Layout.preferredHeight: 30
31-
Layout.leftMargin: 10
32-
}
33-
Column {
34-
spacing: 2
35-
CoreText {
36-
text: "Singlesig Wallet"
37-
color: Theme.color.neutral7
38-
bold: true
39-
}
40-
CoreText {
41-
text: "<font color=\""+Theme.color.white+"\">₿</font> 0.00 <font color=\""+Theme.color.white+"\">167 599</font>"
42-
color: Theme.color.neutral7
24+
leftItem: WalletBadge {
25+
implicitWidth: 154
26+
implicitHeight: 46
27+
text: walletListModel.selectedWallet
28+
29+
MouseArea {
30+
anchors.fill: parent
31+
onClicked: {
32+
walletListModel.listWalletDir()
33+
walletSelect.opened ? walletSelect.close() : walletSelect.open()
4334
}
4435
}
36+
37+
WalletSelect {
38+
id: walletSelect
39+
model: walletListModel
40+
closePolicy: Popup.CloseOnPressOutside
41+
x: 0
42+
y: parent.height
43+
}
4544
}
4645
centerItem: RowLayout {
4746
NavigationTab {

0 commit comments

Comments
 (0)