Skip to content

Commit 320b3d4

Browse files
committed
Merge #448: Introduce Coin Selection page
c9bf7ae qml: Don't allow Coin selection if there are none available (johnny9) c31ac8c qml: Initialize total amount in CoinsListModel (johnny9) a0ee146 qml: Put CoinSelection ListView in a ScrollView (johnny9) dee3530 qml: Move CoinSelection list header outside of ListView (johnny9) 7d34aaf qml: Return 0 when recipient amount QString is empty (johnny9) 1868185 qml: Introduce the CoinSelection page (johnny9) 44276f8 qml: Add CoinsListModel to WalletQmlModel (johnny9) 99d6fb7 qml: Introduce Ellipsis icon (johnny9) 6519ad6 qml: Introduce Lock icon (johnny9) 4d65a74 qml: Simplify imageprovider (johnny9) 098bb4b qml: Update triangle-up/down icons (johnny9) Pull request description: This is the first iteration of the Coin Selection menu The option to open the Coin Selection menu is a QSetting that is toggled on/off in the ellipsis menu on the Send page. When enabled, the user can click on the Select inputs button and the Coin Selection menu will be push on the stack from below. The Coin Selection menu will list possible inputs and a checkbox is used to select the coins. Locked coins are not selectable and instead of a check box, they have a locked icon. https://github.com/user-attachments/assets/f148d231-d9e9-4923-91f3-8e422049bbf5 ACKs for top commit: hebasto: ACK c9bf7ae, I have skimmed through the code and it looks OK. Tree-SHA512: 463770f9438e7db5cd092982a207900db86c83db1d0e25245eed25f448a36a53f9146e4de46f7406598eba611cfd24ecb7d804580a951304e90a6152184205fb
2 parents 3423fb8 + c9bf7ae commit 320b3d4

24 files changed

+969
-329
lines changed

src/Makefile.qt.include

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ QT_MOC_CPP = \
3939
qml/controls/moc_linegraph.cpp \
4040
qml/models/moc_activitylistmodel.cpp \
4141
qml/models/moc_chainmodel.cpp \
42+
qml/models/moc_coinslistmodel.cpp \
4243
qml/models/moc_networktraffictower.cpp \
4344
qml/models/moc_nodemodel.cpp \
4445
qml/models/moc_options_model.cpp \
@@ -129,6 +130,7 @@ BITCOIN_QT_H = \
129130
qml/controls/linegraph.h \
130131
qml/models/activitylistmodel.h \
131132
qml/models/chainmodel.h \
133+
qml/models/coinslistmodel.h \
132134
qml/models/networktraffictower.h \
133135
qml/models/nodemodel.h \
134136
qml/models/options_model.h \
@@ -328,6 +330,7 @@ BITCOIN_QML_BASE_CPP = \
328330
qml/controls/linegraph.cpp \
329331
qml/models/activitylistmodel.cpp \
330332
qml/models/chainmodel.cpp \
333+
qml/models/coinslistmodel.cpp \
331334
qml/models/networktraffictower.cpp \
332335
qml/models/nodemodel.cpp \
333336
qml/models/options_model.cpp \
@@ -361,13 +364,15 @@ QML_RES_ICONS = \
361364
qml/res/icons/copy.png \
362365
qml/res/icons/coinbase.png \
363366
qml/res/icons/cross.png \
367+
qml/res/icons/ellipsis.png \
364368
qml/res/icons/error.png \
365369
qml/res/icons/export.png \
366370
qml/res/icons/flip-vertical.png \
367371
qml/res/icons/gear.png \
368372
qml/res/icons/gear-outline.png \
369373
qml/res/icons/hidden.png \
370374
qml/res/icons/info.png \
375+
qml/res/icons/lock.png \
371376
qml/res/icons/minus.png \
372377
qml/res/icons/network-dark.png \
373378
qml/res/icons/network-light.png \
@@ -395,9 +400,10 @@ QML_RES_QML = \
395400
qml/components/ConnectionSettings.qml \
396401
qml/components/DeveloperOptions.qml \
397402
qml/components/ExternalPopup.qml \
398-
qml/components/PeersIndicator.qml \
399403
qml/components/NetworkTrafficGraph.qml \
400404
qml/components/NetworkIndicator.qml \
405+
qml/components/OptionPopup.qml \
406+
qml/components/PeersIndicator.qml \
401407
qml/components/ProxySettings.qml \
402408
qml/components/Separator.qml \
403409
qml/components/StorageLocations.qml \
@@ -409,8 +415,11 @@ QML_RES_QML = \
409415
qml/controls/AddWalletButton.qml \
410416
qml/controls/CaretRightIcon.qml \
411417
qml/controls/ContinueButton.qml \
418+
qml/controls/CoreCheckBox.qml \
412419
qml/controls/CoreText.qml \
413420
qml/controls/CoreTextField.qml \
421+
qml/controls/EllipsisMenuButton.qml \
422+
qml/controls/EllipsisMenuToggleItem.qml \
414423
qml/controls/ExternalLink.qml \
415424
qml/controls/FocusBorder.qml \
416425
qml/controls/Header.qml \
@@ -419,6 +428,7 @@ QML_RES_QML = \
419428
qml/controls/IPAddressValueInput.qml \
420429
qml/controls/KeyValueRow.qml \
421430
qml/controls/LabeledTextInput.qml \
431+
qml/controls/LabeledCoinControlButton.qml \
422432
qml/controls/NavButton.qml \
423433
qml/controls/NavigationBar.qml \
424434
qml/controls/NavigationBar2.qml \
@@ -431,6 +441,7 @@ QML_RES_QML = \
431441
qml/controls/ProgressIndicator.qml \
432442
qml/controls/qmldir \
433443
qml/controls/Setting.qml \
444+
qml/controls/SendOptionsPopup.qml \
434445
qml/controls/TextButton.qml \
435446
qml/controls/Theme.qml \
436447
qml/controls/ToggleButton.qml \
@@ -461,6 +472,7 @@ QML_RES_QML = \
461472
qml/pages/settings/SettingsTheme.qml \
462473
qml/pages/wallet/Activity.qml \
463474
qml/pages/wallet/ActivityDetails.qml \
475+
qml/pages/wallet/CoinSelection.qml \
464476
qml/pages/wallet/CreateBackup.qml \
465477
qml/pages/wallet/CreateConfirm.qml \
466478
qml/pages/wallet/CreateIntro.qml \

src/qml/bitcoin_qml.qrc

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
<file>components/BlockClock.qml</file>
55
<file>components/BlockClockDisplayMode.qml</file>
66
<file>components/BlockCounter.qml</file>
7-
<file>controls/CaretRightIcon.qml</file>
87
<file>components/ConnectionOptions.qml</file>
98
<file>components/ConnectionSettings.qml</file>
10-
<file>components/PeersIndicator.qml</file>
119
<file>components/DeveloperOptions.qml</file>
1210
<file>components/ExternalPopup.qml</file>
1311
<file>components/NetworkTrafficGraph.qml</file>
1412
<file>components/NetworkIndicator.qml</file>
13+
<file>components/OptionPopup.qml</file>
14+
<file>components/PeersIndicator.qml</file>
1515
<file>components/ProxySettings.qml</file>
1616
<file>components/StorageLocations.qml</file>
1717
<file>components/Separator.qml</file>
@@ -21,7 +21,9 @@
2121
<file>components/TotalBytesIndicator.qml</file>
2222
<file>components/Tooltip.qml</file>
2323
<file>controls/AddWalletButton.qml</file>
24+
<file>controls/CaretRightIcon.qml</file>
2425
<file>controls/ContinueButton.qml</file>
26+
<file>controls/CoreCheckBox.qml</file>
2527
<file>controls/CoreText.qml</file>
2628
<file>controls/CoreTextField.qml</file>
2729
<file>controls/ExternalLink.qml</file>
@@ -32,6 +34,9 @@
3234
<file>controls/IPAddressValueInput.qml</file>
3335
<file>controls/KeyValueRow.qml</file>
3436
<file>controls/LabeledTextInput.qml</file>
37+
<file>controls/LabeledCoinControlButton.qml</file>
38+
<file>controls/EllipsisMenuButton.qml</file>
39+
<file>controls/EllipsisMenuToggleItem.qml</file>
3540
<file>controls/NavButton.qml</file>
3641
<file>controls/NavigationBar.qml</file>
3742
<file>controls/NavigationBar2.qml</file>
@@ -43,6 +48,7 @@
4348
<file>controls/PageStack.qml</file>
4449
<file>controls/ProgressIndicator.qml</file>
4550
<file>controls/qmldir</file>
51+
<file>controls/SendOptionsPopup.qml</file>
4652
<file>controls/Setting.qml</file>
4753
<file>controls/TextButton.qml</file>
4854
<file>controls/Theme.qml</file>
@@ -74,6 +80,7 @@
7480
<file>pages/settings/SettingsTheme.qml</file>
7581
<file>pages/wallet/Activity.qml</file>
7682
<file>pages/wallet/ActivityDetails.qml</file>
83+
<file>pages/wallet/CoinSelection.qml</file>
7784
<file>pages/wallet/CreateBackup.qml</file>
7885
<file>pages/wallet/CreateConfirm.qml</file>
7986
<file>pages/wallet/CreateIntro.qml</file>
@@ -104,13 +111,15 @@
104111
<file alias="copy">res/icons/copy.png</file>
105112
<file alias="coinbase">res/icons/coinbase.png</file>
106113
<file alias="cross">res/icons/cross.png</file>
114+
<file alias="ellipsis">res/icons/ellipsis.png</file>
107115
<file alias="error">res/icons/error.png</file>
108116
<file alias="export">res/icons/export.png</file>
109117
<file alias="flip-vertical">res/icons/flip-vertical.png</file>
110118
<file alias="gear">res/icons/gear.png</file>
111119
<file alias="gear-outline">res/icons/gear-outline.png</file>
112120
<file alias="hidden">res/icons/hidden.png</file>
113121
<file alias="info">res/icons/info.png</file>
122+
<file alias="lock">res/icons/lock.png</file>
114123
<file alias="minus">res/icons/minus.png</file>
115124
<file alias="network-dark">res/icons/network-dark.png</file>
116125
<file alias="network-light">res/icons/network-light.png</file>

src/qml/components/OptionPopup.qml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Copyright (c) 2025 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 "../controls"
10+
11+
Popup {
12+
id: root
13+
14+
background: Item {
15+
anchors.fill: parent
16+
Rectangle {
17+
color: Theme.color.neutral0
18+
border.color: Theme.color.neutral4
19+
radius: 5
20+
border.width: 1
21+
anchors.fill: parent
22+
}
23+
}
24+
}

src/qml/controls/CoreCheckBox.qml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Copyright (c) 2025 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+
8+
AbstractButton {
9+
id: root
10+
implicitWidth: 20
11+
implicitHeight: 20
12+
13+
property color borderColor: Theme.color.neutral9
14+
property color fillColor: Theme.color.neutral9
15+
16+
background: null
17+
18+
checkable: true
19+
hoverEnabled: AppMode.isDesktop
20+
21+
contentItem: Rectangle {
22+
radius: 3
23+
border.color: root.checked ? root.fillColor : root.borderColor
24+
border.width: 1
25+
color: root.checked ? root.fillColor : "transparent"
26+
}
27+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
// Copyright (c) 2025 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+
Button {
12+
id: root
13+
14+
property color hoverColor: Theme.color.orange
15+
property color activeColor: Theme.color.orange
16+
17+
hoverEnabled: AppMode.isDesktop
18+
implicitHeight: 35
19+
implicitWidth: 35
20+
21+
MouseArea {
22+
anchors.fill: parent
23+
enabled: false
24+
hoverEnabled: true
25+
cursorShape: Qt.PointingHandCursor
26+
}
27+
28+
background: null
29+
30+
contentItem: Icon {
31+
id: ellipsisIcon
32+
anchors.fill: parent
33+
source: "image://images/ellipsis"
34+
color: Theme.color.neutral9
35+
size: 35
36+
}
37+
38+
states: [
39+
State {
40+
name: "CHECKED"; when: root.checked
41+
PropertyChanges { target: ellipsisIcon; color: activeColor }
42+
},
43+
State {
44+
name: "HOVER"; when: root.hovered
45+
PropertyChanges { target: ellipsisIcon; color: hoverColor }
46+
}
47+
]
48+
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright (c) 2025 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+
import org.bitcoincore.qt 1.0
9+
10+
Button {
11+
property int bgRadius: 5
12+
property color bgDefaultColor: "transparent"
13+
property color bgHoverColor: Theme.color.neutral2
14+
property color textColor: Theme.color.neutral7
15+
property color textHoverColor: Theme.color.neutral9
16+
property color textActiveColor: Theme.color.neutral7
17+
18+
id: root
19+
checkable: true
20+
checked: optionSwitch.checked
21+
hoverEnabled: AppMode.isDesktop
22+
23+
implicitWidth: 280
24+
25+
MouseArea {
26+
anchors.fill: parent
27+
enabled: false
28+
hoverEnabled: true
29+
cursorShape: Qt.PointingHandCursor
30+
}
31+
32+
onClicked: {
33+
optionSwitch.checked = !optionSwitch.checked
34+
}
35+
36+
contentItem: RowLayout {
37+
spacing: 7
38+
anchors.fill: parent
39+
anchors.centerIn: parent
40+
anchors.margins: 10
41+
CoreText {
42+
Layout.fillWidth: true
43+
Layout.alignment: Qt.AlignVCenter
44+
horizontalAlignment: Text.AlignLeft
45+
font.pixelSize: 15
46+
text: root.text
47+
}
48+
OptionSwitch {
49+
id: optionSwitch
50+
Layout.alignment: Qt.AlignVCenter
51+
Layout.preferredWidth: 40
52+
Layout.preferredHeight: 24
53+
checked: root.checked
54+
}
55+
}
56+
57+
background: Rectangle {
58+
id: bg
59+
color: root.bgDefaultColor
60+
radius: root.bgRadius
61+
62+
Behavior on color {
63+
ColorAnimation { duration: 150 }
64+
}
65+
}
66+
67+
states: [
68+
State {
69+
name: "HOVER"; when: root.hovered
70+
PropertyChanges { target: bg; color: root.bgHoverColor }
71+
PropertyChanges { target: buttonText; color: root.textHoverColor }
72+
}
73+
]
74+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// Copyright (c) 2025 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+
Item {
10+
property int coinsSelected: 0
11+
property int coinCount: 0
12+
13+
signal openCoinControl
14+
15+
id: root
16+
implicitHeight: label.height
17+
18+
CoreText {
19+
id: label
20+
anchors.left: parent.left
21+
anchors.verticalCenter: parent.verticalCenter
22+
horizontalAlignment: Text.AlignLeft
23+
width: 110
24+
color: Theme.color.neutral9
25+
font.pixelSize: 18
26+
text: qsTr("Inputs")
27+
}
28+
29+
CoreText {
30+
anchors.left: label.right
31+
anchors.verticalCenter: parent.verticalCenter
32+
horizontalAlignment: Text.AlignLeft
33+
color: Theme.color.orangeLight1
34+
font.pixelSize: 18
35+
text: {
36+
if (coinCount === 0) {
37+
qsTr("No coins available")
38+
} else if (coinsSelected === 0) {
39+
qsTr("Select")
40+
} else {
41+
qsTr("%1 input%2 selected")
42+
.arg(coinsSelected)
43+
.arg(coinsSelected === 1 ? "" : "s")
44+
}
45+
}
46+
47+
MouseArea {
48+
anchors.fill: parent
49+
onClicked: {
50+
if (coinCount > 0) {
51+
root.openCoinControl()
52+
}
53+
}
54+
cursorShape: Qt.PointingHandCursor
55+
}
56+
}
57+
}

0 commit comments

Comments
 (0)