Skip to content

Commit c57705b

Browse files
committed
qml: Introduce UI Flow for Loading Snapshot
This introduce the UI flow to load a AssumeUTXO snapshot into the Bitcoin Core App. It modifies the connection settings and adds a SnapshotSettings file, Icon, and modified progress bar. It has been rebased
1 parent 2e7bef0 commit c57705b

17 files changed

+407
-1
lines changed

src/Makefile.qt.include

+5
Original file line numberDiff line numberDiff line change
@@ -360,12 +360,15 @@ QML_RES_ICONS = \
360360
qml/res/icons/check.png \
361361
qml/res/icons/copy.png \
362362
qml/res/icons/coinbase.png \
363+
qml/res/icons/circle-file.png \
364+
qml/res/icons/circle-green-check.png \
363365
qml/res/icons/cross.png \
364366
qml/res/icons/error.png \
365367
qml/res/icons/export.png \
366368
qml/res/icons/flip-vertical.png \
367369
qml/res/icons/gear.png \
368370
qml/res/icons/gear-outline.png \
371+
qml/res/icons/green-check.png \
369372
qml/res/icons/hidden.png \
370373
qml/res/icons/info.png \
371374
qml/res/icons/minus.png \
@@ -400,6 +403,7 @@ QML_RES_QML = \
400403
qml/components/NetworkIndicator.qml \
401404
qml/components/ProxySettings.qml \
402405
qml/components/Separator.qml \
406+
qml/components/SnapshotSettings.qml \
403407
qml/components/StorageLocations.qml \
404408
qml/components/StorageOptions.qml \
405409
qml/components/StorageSettings.qml \
@@ -457,6 +461,7 @@ QML_RES_QML = \
457461
qml/pages/settings/SettingsDeveloper.qml \
458462
qml/pages/settings/SettingsDisplay.qml \
459463
qml/pages/settings/SettingsProxy.qml \
464+
qml/pages/settings/SettingsSnapshot.qml \
460465
qml/pages/settings/SettingsStorage.qml \
461466
qml/pages/settings/SettingsTheme.qml \
462467
qml/pages/wallet/Activity.qml \

src/qml/bitcoin_qml.qrc

+6
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
<file>components/ProxySettings.qml</file>
1616
<file>components/StorageLocations.qml</file>
1717
<file>components/Separator.qml</file>
18+
<file>components/SnapshotSettings.qml</file>
1819
<file>components/StorageOptions.qml</file>
1920
<file>components/StorageSettings.qml</file>
2021
<file>components/ThemeSettings.qml</file>
@@ -26,6 +27,7 @@
2627
<file>controls/CoreTextField.qml</file>
2728
<file>controls/ExternalLink.qml</file>
2829
<file>controls/FocusBorder.qml</file>
30+
<file>controls/GreenCheckIcon.qml</file>
2931
<file>controls/Header.qml</file>
3032
<file>controls/Icon.qml</file>
3133
<file>controls/InformationPage.qml</file>
@@ -70,6 +72,7 @@
7072
<file>pages/settings/SettingsDeveloper.qml</file>
7173
<file>pages/settings/SettingsDisplay.qml</file>
7274
<file>pages/settings/SettingsProxy.qml</file>
75+
<file>pages/settings/SettingsSnapshot.qml</file>
7376
<file>pages/settings/SettingsStorage.qml</file>
7477
<file>pages/settings/SettingsTheme.qml</file>
7578
<file>pages/wallet/Activity.qml</file>
@@ -103,12 +106,15 @@
103106
<file alias="check">res/icons/check.png</file>
104107
<file alias="copy">res/icons/copy.png</file>
105108
<file alias="coinbase">res/icons/coinbase.png</file>
109+
<file alias="circle-file">res/icons/circle-file.png</file>
110+
<file alias="circle-green-check">res/icons/circle-green-check.png</file>
106111
<file alias="cross">res/icons/cross.png</file>
107112
<file alias="error">res/icons/error.png</file>
108113
<file alias="export">res/icons/export.png</file>
109114
<file alias="flip-vertical">res/icons/flip-vertical.png</file>
110115
<file alias="gear">res/icons/gear.png</file>
111116
<file alias="gear-outline">res/icons/gear-outline.png</file>
117+
<file alias="green-check">res/icons/green-check.png</file>
112118
<file alias="hidden">res/icons/hidden.png</file>
113119
<file alias="info">res/icons/info.png</file>
114120
<file alias="minus">res/icons/minus.png</file>

src/qml/components/ConnectionSettings.qml

+30
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,37 @@ import "../controls"
1010
ColumnLayout {
1111
id: root
1212
signal next
13+
signal gotoSnapshot
14+
property bool onboarding: false
15+
property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
1316
spacing: 4
17+
Setting {
18+
id: gotoSnapshot
19+
visible: !root.onboarding && !snapshotImportCompleted
20+
Layout.fillWidth: true
21+
header: qsTr("Load snapshot")
22+
description: qsTr("Instant use with background sync")
23+
actionItem: Item {
24+
width: 26
25+
height: 26
26+
CaretRightIcon {
27+
anchors.centerIn: parent
28+
visible: !snapshotImportCompleted
29+
color: gotoSnapshot.stateColor
30+
}
31+
GreenCheckIcon {
32+
anchors.centerIn: parent
33+
visible: snapshotImportCompleted
34+
color: Theme.color.transparent
35+
size: 30
36+
}
37+
}
38+
onClicked: root.gotoSnapshot()
39+
}
40+
Separator {
41+
visible: !root.onboarding && !snapshotImportCompleted
42+
Layout.fillWidth: true
43+
}
1444
Setting {
1545
Layout.fillWidth: true
1646
header: qsTr("Enable listening")
+229
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
// Copyright (c) 2023-present 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 QtQuick.Dialogs 1.3
9+
10+
import "../controls"
11+
12+
ColumnLayout {
13+
id: columnLayout
14+
signal back
15+
property bool snapshotLoading: nodeModel.snapshotLoading
16+
property bool snapshotLoaded: nodeModel.isSnapshotLoaded
17+
property bool snapshotImportCompleted: onboarding ? false : chainModel.isSnapshotActive
18+
property bool onboarding: false
19+
property bool snapshotVerified: onboarding ? false : chainModel.isSnapshotActive
20+
property string snapshotFileName: ""
21+
property var snapshotInfo: (snapshotVerified || snapshotLoaded) ? chainModel.getSnapshotInfo() : ({})
22+
property string selectedFile: ""
23+
property bool headersSynced: nodeModel.headersSynced
24+
25+
width: Math.min(parent.width, 450)
26+
anchors.horizontalCenter: parent.horizontalCenter
27+
28+
StackLayout {
29+
id: settingsStack
30+
currentIndex: onboarding ? 0 : snapshotLoaded ? 2 : snapshotVerified ? 2 : snapshotLoading ? 1 : 0
31+
32+
ColumnLayout {
33+
Layout.alignment: Qt.AlignHCenter
34+
Layout.preferredWidth: Math.min(parent.width, 450)
35+
36+
Image {
37+
Layout.alignment: Qt.AlignCenter
38+
source: "image://images/circle-file"
39+
40+
sourceSize.width: 200
41+
sourceSize.height: 200
42+
}
43+
44+
Header {
45+
Layout.fillWidth: true
46+
Layout.topMargin: 20
47+
headerBold: true
48+
header: qsTr("Load snapshot")
49+
descriptionBold: false
50+
descriptionColor: Theme.color.neutral6
51+
descriptionSize: 17
52+
descriptionLineHeight: 1.1
53+
description: qsTr("You can start using the application more quickly by loading a recent transaction snapshot." +
54+
" It will be automatically verified in the background.")
55+
}
56+
57+
CoreText {
58+
Layout.fillWidth: true
59+
Layout.topMargin: 20
60+
color: Theme.color.neutral6
61+
font.pixelSize: 17
62+
visible: !headersSynced
63+
text: !headersSynced
64+
? qsTr("Please wait for headers to sync before loading a snapshot.")
65+
: qsTr("")
66+
wrap: true
67+
wrapMode: Text.WordWrap
68+
}
69+
70+
ContinueButton {
71+
Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
72+
Layout.topMargin: 40
73+
Layout.leftMargin: 20
74+
Layout.rightMargin: Layout.leftMargin
75+
Layout.bottomMargin: 20
76+
Layout.alignment: Qt.AlignCenter
77+
text: qsTr("Choose snapshot file")
78+
enabled: headersSynced
79+
onClicked: fileDialog.open()
80+
}
81+
82+
FileDialog {
83+
id: fileDialog
84+
folder: shortcuts.home
85+
selectMultiple: false
86+
selectExisting: true
87+
nameFilters: ["Snapshot files (*.dat)", "All files (*)"]
88+
onAccepted: {
89+
selectedFile = fileUrl.toString()
90+
snapshotFileName = selectedFile
91+
nodeModel.snapshotLoadThread(snapshotFileName)
92+
}
93+
}
94+
// TODO: Handle file error signal
95+
}
96+
97+
ColumnLayout {
98+
Layout.alignment: Qt.AlignHCenter
99+
Layout.preferredWidth: Math.min(parent.width, 450)
100+
101+
Image {
102+
Layout.alignment: Qt.AlignCenter
103+
source: "image://images/circle-file"
104+
105+
sourceSize.width: 200
106+
sourceSize.height: 200
107+
}
108+
109+
Header {
110+
Layout.fillWidth: true
111+
Layout.topMargin: 20
112+
Layout.leftMargin: 20
113+
Layout.rightMargin: 20
114+
header: qsTr("Loading Snapshot")
115+
description: qsTr("This might take a while...")
116+
}
117+
118+
ProgressIndicator {
119+
id: progressIndicator
120+
Layout.topMargin: 20
121+
width: 200
122+
height: 20
123+
progress: nodeModel.snapshotProgress
124+
Layout.alignment: Qt.AlignCenter
125+
progressColor: Theme.color.blue
126+
}
127+
}
128+
129+
ColumnLayout {
130+
id: loadedSnapshotColumn
131+
Layout.alignment: Qt.AlignHCenter
132+
Layout.preferredWidth: Math.min(parent.width, 450)
133+
134+
Image {
135+
Layout.alignment: Qt.AlignCenter
136+
source: "image://images/circle-green-check"
137+
138+
sourceSize.width: 60
139+
sourceSize.height: 60
140+
}
141+
142+
Header {
143+
Layout.fillWidth: true
144+
Layout.topMargin: 20
145+
headerBold: true
146+
header: qsTr("Snapshot Loaded")
147+
descriptionBold: false
148+
descriptionColor: Theme.color.neutral6
149+
descriptionSize: 17
150+
descriptionLineHeight: 1.1
151+
description: snapshotInfo && snapshotInfo["date"] ?
152+
qsTr("It contains unspent transactions up to %1. Next, transactions will be verified and newer transactions downloaded.").arg(snapshotInfo["date"]) :
153+
qsTr("It contains transactions up to DEBUG. Newer transactions still need to be downloaded." +
154+
" The data will be verified in the background.")
155+
}
156+
157+
ContinueButton {
158+
Layout.preferredWidth: Math.min(300, columnLayout.width - 2 * Layout.leftMargin)
159+
Layout.topMargin: 40
160+
Layout.alignment: Qt.AlignCenter
161+
text: qsTr("Done")
162+
onClicked: {
163+
chainModel.isSnapshotActiveChanged()
164+
back()
165+
}
166+
}
167+
168+
Setting {
169+
id: viewDetails
170+
Layout.alignment: Qt.AlignCenter
171+
header: qsTr("View details")
172+
actionItem: CaretRightIcon {
173+
id: caretIcon
174+
color: viewDetails.stateColor
175+
rotation: viewDetails.expanded ? 90 : 0
176+
Behavior on rotation { NumberAnimation { duration: 200 } }
177+
}
178+
179+
property bool expanded: false
180+
181+
onClicked: {
182+
expanded = !expanded
183+
}
184+
}
185+
186+
ColumnLayout {
187+
id: detailsContent
188+
visible: viewDetails.expanded
189+
Layout.preferredWidth: Math.min(300, parent.width - 2 * Layout.leftMargin)
190+
Layout.alignment: Qt.AlignCenter
191+
Layout.leftMargin: 80
192+
Layout.rightMargin: 80
193+
Layout.topMargin: 10
194+
spacing: 10
195+
// TODO: make sure the block height number aligns right
196+
RowLayout {
197+
CoreText {
198+
text: qsTr("Block Height:")
199+
Layout.alignment: Qt.AlignLeft
200+
font.pixelSize: 14
201+
}
202+
CoreText {
203+
text: snapshotInfo && snapshotInfo["height"] ?
204+
snapshotInfo["height"] : qsTr("DEBUG")
205+
Layout.alignment: Qt.AlignRight
206+
font.pixelSize: 14
207+
}
208+
}
209+
Separator { Layout.fillWidth: true }
210+
ColumnLayout {
211+
Layout.fillWidth: true
212+
spacing: 5
213+
CoreText {
214+
text: qsTr("Hash:")
215+
font.pixelSize: 14
216+
}
217+
CoreText {
218+
text: snapshotInfo && snapshotInfo["hashSerializedFirstHalf"] ?
219+
snapshotInfo["hashSerializedFirstHalf"] + "\n" + snapshotInfo["hashSerializedSecondHalf"] :
220+
qsTr("DEBUG")
221+
Layout.fillWidth: true
222+
font.pixelSize: 14
223+
textFormat: Text.PlainText
224+
}
225+
}
226+
}
227+
}
228+
}
229+
}

src/qml/controls/GreenCheckIcon.qml

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Copyright (c) 2023 - present 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+
Icon {
9+
source: "image://images/green-check"
10+
size: 30
11+
}

src/qml/controls/Header.qml

+2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ ColumnLayout {
2525
property int subtextSize: 15
2626
property color subtextColor: Theme.color.neutral9
2727
property bool wrap: true
28+
property real descriptionLineHeight: 1
2829

2930
spacing: 0
3031
Loader {
@@ -60,6 +61,7 @@ ColumnLayout {
6061
text: root.description
6162
horizontalAlignment: root.center ? Text.AlignHCenter : Text.AlignLeft
6263
wrapMode: wrap ? Text.WordWrap : Text.NoWrap
64+
lineHeight: root.descriptionLineHeight
6365

6466
Behavior on color {
6567
ColorAnimation { duration: 150 }

src/qml/controls/ProgressIndicator.qml

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import QtQuick.Controls 2.15
77

88
Control {
99
property real progress: 0
10+
property color progressColor: Theme.color.orange
1011
Behavior on progress {
1112
NumberAnimation {
1213
easing.type: Easing.Bezier
@@ -26,7 +27,7 @@ Control {
2627
width: contentItem.width
2728
height: contentItem.height
2829
radius: contentItem.radius
29-
color: Theme.color.orange
30+
color: progressColor
3031
}
3132
}
3233
}

0 commit comments

Comments
 (0)