Skip to content

Commit fab547e

Browse files
committed
qml: Introduce the WalletBadge component
The WalletBadge is an Item that shows a wallet's name, type and balance. The WalletBadge balance shows all of the decimal places for a whole bitcoin and highlights the satoshis available. The component can be configured to not show the Icon or the Balance.
1 parent af8a090 commit fab547e

File tree

4 files changed

+158
-22
lines changed

4 files changed

+158
-22
lines changed

src/Makefile.qt.include

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -407,7 +407,8 @@ QML_RES_QML = \
407407
qml/pages/settings/SettingsProxy.qml \
408408
qml/pages/settings/SettingsStorage.qml \
409409
qml/pages/settings/SettingsTheme.qml \
410-
qml/pages/wallet/DesktopWallets.qml
410+
qml/pages/wallet/DesktopWallets.qml \
411+
qml/pages/wallet/WalletBadge.qml
411412

412413
if TARGET_ANDROID
413414
BITCOIN_QT_H += qml/androidnotifier.h

src/qml/bitcoin_qml.qrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
<file>pages/settings/SettingsStorage.qml</file>
6767
<file>pages/settings/SettingsTheme.qml</file>
6868
<file>pages/wallet/DesktopWallets.qml</file>
69+
<file>pages/wallet/WalletBadge.qml</file>
6970
</qresource>
7071
<qresource prefix="/icons">
7172
<file alias="arrow-down">res/icons/arrow-down.png</file>

src/qml/pages/wallet/DesktopWallets.qml

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -21,27 +21,10 @@ 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
43-
}
44-
}
24+
leftItem: WalletBadge {
25+
implicitWidth: 164
26+
implicitHeight: 60
27+
text: qsTr("Singlesig Wallet")
4528
}
4629
centerItem: RowLayout {
4730
NavigationTab {

src/qml/pages/wallet/WalletBadge.qml

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
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+
import QtQuick 2.15
6+
import QtQuick.Controls 2.15
7+
import QtQuick.Layouts 1.15
8+
9+
import org.bitcoincore.qt 1.0
10+
11+
import "../../controls"
12+
13+
Button {
14+
id: root
15+
16+
function formatSatoshis(satoshis) {
17+
// Convert satoshis to bitcoins
18+
var bitcoins = satoshis / 100000000;
19+
20+
// Format bitcoins to a fixed 8 decimal places string
21+
var bitcoinStr = bitcoins.toFixed(8);
22+
23+
// Split the bitcoin string into integer and fractional parts
24+
var parts = bitcoinStr.split('.');
25+
26+
// Add spaces for every 3 digits in the integer part
27+
parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
28+
29+
// Highlight the first significant digit and all following digits in the integer part
30+
var significantFound = false;
31+
parts[0] = parts[0].replace(/(\d)/g, function(match) {
32+
if (!significantFound && match !== '0') {
33+
significantFound = true;
34+
}
35+
if (significantFound) {
36+
return '<font color="' + Theme.color.neutral9 + '">' + match + '</font>';
37+
}
38+
return match;
39+
});
40+
41+
// Add spaces for every 3 digits in the decimal part
42+
parts[1] = parts[1].replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
43+
if (significantFound) {
44+
parts[1] = '<font color="' + Theme.color.neutral9 + '">' + parts[1] + '</font>';
45+
} else {
46+
// Highlight the first significant digit and all following digits in the fractional part
47+
significantFound = false;
48+
parts[1] = parts[1].replace(/(\d)/g, function(match) {
49+
if (!significantFound && match !== '0') {
50+
significantFound = true;
51+
}
52+
if (significantFound) {
53+
return '<font color="' + Theme.color.neutral9 + '">' + match + '</font>';
54+
}
55+
return match;
56+
});
57+
}
58+
59+
// Concatenate the parts back together
60+
var formattedBitcoins = parts.join('.');
61+
62+
// Format the text with the Bitcoin symbol
63+
var formattedText = `<font color="${Theme.color.neutral9}">₿</font> ${formattedBitcoins}`;
64+
65+
// Highlight zero in a different color if satoshis are zero
66+
if (satoshis === 0) {
67+
formattedText = `<font color="${Theme.color.neutral7}">₿ 0.00</font>`;
68+
}
69+
70+
return formattedText;
71+
}
72+
73+
property color bgActiveColor: Theme.color.neutral2
74+
property color textColor: Theme.color.neutral7
75+
property color textHoverColor: Theme.color.neutral9
76+
property color textActiveColor: Theme.color.orange
77+
property color iconColor: "transparent"
78+
property string iconSource: ""
79+
property bool showBalance: true
80+
property bool showIcon: true
81+
82+
checkable: true
83+
hoverEnabled: AppMode.isDesktop
84+
implicitHeight: 60
85+
implicitWidth: 220
86+
bottomPadding: 0
87+
topPadding: 0
88+
89+
contentItem: RowLayout {
90+
anchors.fill: parent
91+
anchors.leftMargin: 10
92+
spacing: 5
93+
Icon {
94+
id: icon
95+
visible: root.showIcon
96+
source: "image://images/singlesig-wallet"
97+
color: Theme.color.neutral8
98+
Layout.preferredWidth: 30
99+
Layout.preferredHeight: 30
100+
}
101+
Column {
102+
Layout.fillWidth: true
103+
spacing: 2
104+
CoreText {
105+
id: buttonText
106+
font.pixelSize: 13
107+
text: root.text
108+
color: root.textColor
109+
bold: true
110+
visible: root.text !== ""
111+
}
112+
CoreText {
113+
id: balanceText
114+
visible: root.showBalance
115+
text: formatSatoshis(12300)
116+
color: Theme.color.neutral7
117+
}
118+
}
119+
}
120+
121+
background: Rectangle {
122+
id: bg
123+
height: root.height
124+
width: root.width
125+
radius: 5
126+
color: Theme.color.neutral3
127+
visible: root.hovered || root.checked
128+
129+
FocusBorder {
130+
visible: root.visualFocus
131+
}
132+
133+
Behavior on color {
134+
ColorAnimation { duration: 150 }
135+
}
136+
}
137+
138+
states: [
139+
State {
140+
name: "CHECKED"; when: root.checked
141+
PropertyChanges { target: buttonText; color: root.textActiveColor }
142+
PropertyChanges { target: icon; color: root.textActiveColor }
143+
},
144+
State {
145+
name: "HOVER"; when: root.hovered
146+
PropertyChanges { target: buttonText; color: root.textHoverColor }
147+
PropertyChanges { target: icon; color: root.textHoverColor }
148+
PropertyChanges { target: balanceText; color: root.textHoverColor }
149+
}
150+
]
151+
}

0 commit comments

Comments
 (0)