Skip to content

Commit

Permalink
Merge #401: Introduce Wallet Select Dropdown
Browse files Browse the repository at this point in the history
0939f2b qml: Introduce the WalletSelect component (johnny9)
5906e69 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 [0939f2b](0939f2b) on WSL Ubuntu 22.04

Tree-SHA512: 19b877ca1be7488c54e79dba28720818711ab9f9f8de34cdb4f540daa150dc6debb8d78d9e0ba14b8a246f88497f6a04b089bcd3e4dca433afe49990201439d9
  • Loading branch information
hebasto committed Aug 12, 2024
2 parents a73577b + 0939f2b commit 8c19122
Show file tree
Hide file tree
Showing 12 changed files with 458 additions and 20 deletions.
8 changes: 7 additions & 1 deletion src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ QT_MOC_CPP = \
qml/models/moc_nodemodel.cpp \
qml/models/moc_options_model.cpp \
qml/models/moc_peerlistsortproxy.cpp \
qml/models/moc_walletlistmodel.cpp \
qml/moc_appmode.cpp \
qml/moc_walletcontroller.cpp \
qt/moc_addressbookpage.cpp \
Expand Down Expand Up @@ -122,6 +123,7 @@ BITCOIN_QT_H = \
qml/models/nodemodel.h \
qml/models/options_model.h \
qml/models/peerlistsortproxy.h \
qml/models/walletlistmodel.h \
qml/appmode.h \
qml/bitcoin.h \
qml/guiconstants.h \
Expand Down Expand Up @@ -311,6 +313,7 @@ BITCOIN_QML_BASE_CPP = \
qml/models/nodemodel.cpp \
qml/models/options_model.cpp \
qml/models/peerlistsortproxy.cpp \
qml/models/walletlistmodel.cpp \
qml/imageprovider.cpp \
qml/util.cpp \
qml/walletcontroller.cpp
Expand Down Expand Up @@ -339,6 +342,7 @@ QML_RES_ICONS = \
qml/res/icons/info.png \
qml/res/icons/network-dark.png \
qml/res/icons/network-light.png \
qml/res/icons/plus.png \
qml/res/icons/shutdown.png \
qml/res/icons/singlesig-wallet.png \
qml/res/icons/storage-dark.png \
Expand Down Expand Up @@ -423,7 +427,9 @@ QML_RES_QML = \
qml/pages/wallet/CreateIntro.qml \
qml/pages/wallet/CreateName.qml \
qml/pages/wallet/CreatePassword.qml \
qml/pages/wallet/DesktopWallets.qml
qml/pages/wallet/DesktopWallets.qml \
qml/pages/wallet/WalletBadge.qml \
qml/pages/wallet/WalletSelect.qml

if TARGET_ANDROID
BITCOIN_QT_H += qml/androidnotifier.h
Expand Down
4 changes: 4 additions & 0 deletions src/qml/bitcoin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include <qml/models/nodemodel.h>
#include <qml/models/options_model.h>
#include <qml/models/peerlistsortproxy.h>
#include <qml/models/walletlistmodel.h>
#include <qml/imageprovider.h>
#include <qml/util.h>
#include <qml/walletcontroller.h>
Expand Down Expand Up @@ -295,12 +296,15 @@ int QmlGuiMain(int argc, char* argv[])
assert(!network_style.isNull());
engine.addImageProvider(QStringLiteral("images"), new ImageProvider{network_style.data()});

WalletListModel wallet_list_model{*node, nullptr};

engine.rootContext()->setContextProperty("networkTrafficTower", &network_traffic_tower);
engine.rootContext()->setContextProperty("nodeModel", &node_model);
engine.rootContext()->setContextProperty("chainModel", &chain_model);
engine.rootContext()->setContextProperty("peerTableModel", &peer_model);
engine.rootContext()->setContextProperty("peerListModelProxy", &peer_model_sort_proxy);
engine.rootContext()->setContextProperty("walletController", &wallet_controller);
engine.rootContext()->setContextProperty("walletListModel", &wallet_list_model);

OptionsQmlModel options_model(*node, !need_onboarding.toBool());
engine.rootContext()->setContextProperty("optionsModel", &options_model);
Expand Down
3 changes: 3 additions & 0 deletions src/qml/bitcoin_qml.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@
<file>pages/wallet/CreateName.qml</file>
<file>pages/wallet/CreatePassword.qml</file>
<file>pages/wallet/DesktopWallets.qml</file>
<file>pages/wallet/WalletBadge.qml</file>
<file>pages/wallet/WalletSelect.qml</file>
</qresource>
<qresource prefix="/icons">
<file alias="add-wallet-dark">res/icons/add-wallet-dark.png</file>
Expand All @@ -95,6 +97,7 @@
<file alias="info">res/icons/info.png</file>
<file alias="network-dark">res/icons/network-dark.png</file>
<file alias="network-light">res/icons/network-light.png</file>
<file alias="plus">res/icons/plus.png</file>
<file alias="shutdown">res/icons/shutdown.png</file>
<file alias="singlesig-wallet">res/icons/singlesig-wallet.png</file>
<file alias="storage-dark">res/icons/storage-dark.png</file>
Expand Down
2 changes: 2 additions & 0 deletions src/qml/controls/Icon.qml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import QtQuick.Controls 2.15

Button {
id: root
width: icon.width
height: icon.height
required property color color
required property url source
property int size: 32
Expand Down
4 changes: 4 additions & 0 deletions src/qml/imageprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -162,5 +162,9 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
return QIcon(":/icons/hidden").pixmap(requested_size);
}

if (id == "plus") {
*size = requested_size;
return QIcon(":/icons/plus").pixmap(requested_size);
}
return {};
}
81 changes: 81 additions & 0 deletions src/qml/models/walletlistmodel.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// 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/walletlistmodel.h>

#include <interfaces/node.h>

#include <QSet>

WalletListModel::WalletListModel(interfaces::Node& node, QObject *parent)
: QAbstractListModel(parent)
, m_node(node)
{
setSelectedWallet("Singlesig Wallet");
}

void WalletListModel::listWalletDir()
{
QSet<QString> existing_names;
for (int i = 0; i < rowCount(); ++i) {
QModelIndex index = this->index(i, 0);
QString name = data(index, NameRole).toString();
existing_names.insert(name);
}

for (const std::string &name : m_node.walletLoader().listWalletDir()) {
QString qname = QString::fromStdString(name);
if (!existing_names.contains(qname)) {
addItem({ qname });
}
}
}

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);
return m_items.size();
}

QVariant WalletListModel::data(const QModelIndex &index, int role) const
{
if (!index.isValid() || index.row() < 0 || index.row() >= m_items.size())
return QVariant();

const auto &item = m_items[index.row()];
switch (role) {
case Qt::DisplayRole:
case NameRole:
return item.name;
default:
return QVariant();
}
}

QHash<int, QByteArray> WalletListModel::roleNames() const
{
QHash<int, QByteArray> roles;
roles[NameRole] = "name";
return roles;
}

void WalletListModel::addItem(const Item &item)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_items.append(item);
endInsertRows();
}
55 changes: 55 additions & 0 deletions src/qml/models/walletlistmodel.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
// 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_WALLETLISTMODEL_H
#define BITCOIN_QML_MODELS_WALLETLISTMODEL_H

#include <interfaces/wallet.h>
#include <QAbstractListModel>
#include <QList>

namespace interfaces {
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);
~WalletListModel() = default;

enum Roles {
NameRole = Qt::UserRole + 1
};

int rowCount(const QModelIndex &parent = QModelIndex()) const override;
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;
};

void addItem(const Item &item);

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

};

#endif // BITCOIN_QML_MODELS_WALLETLISTMODEL_H
37 changes: 18 additions & 19 deletions src/qml/pages/wallet/DesktopWallets.qml
Original file line number Diff line number Diff line change
Expand Up @@ -21,27 +21,26 @@ Page {

header: NavigationBar2 {
id: navBar
leftItem: RowLayout {
spacing: 5
Icon {
source: "image://images/singlesig-wallet"
color: Theme.color.neutral8
Layout.preferredWidth: 30
Layout.preferredHeight: 30
Layout.leftMargin: 10
}
Column {
spacing: 2
CoreText {
text: "Singlesig Wallet"
color: Theme.color.neutral7
bold: true
}
CoreText {
text: "<font color=\""+Theme.color.white+"\">₿</font> 0.00 <font color=\""+Theme.color.white+"\">167 599</font>"
color: Theme.color.neutral7
leftItem: WalletBadge {
implicitWidth: 154
implicitHeight: 46
text: walletListModel.selectedWallet

MouseArea {
anchors.fill: parent
onClicked: {
walletListModel.listWalletDir()
walletSelect.opened ? walletSelect.close() : walletSelect.open()
}
}

WalletSelect {
id: walletSelect
model: walletListModel
closePolicy: Popup.CloseOnPressOutside
x: 0
y: parent.height
}
}
centerItem: RowLayout {
NavigationTab {
Expand Down
Loading

0 comments on commit 8c19122

Please sign in to comment.