Skip to content

Commit 1dbe3ee

Browse files
committed
qml: Introduce Tooltip for the BlockClock navbar button
The Tooltip will appear when hovering over the BlockClock tab button in the desktop navigation bar. It will show the current state of IBD.
1 parent 085805f commit 1dbe3ee

File tree

11 files changed

+166
-64
lines changed

11 files changed

+166
-64
lines changed

src/Makefile.qt.include

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,9 @@ QML_RES_ICONS = \
336336
qml/res/icons/shutdown.png \
337337
qml/res/icons/singlesig-wallet.png \
338338
qml/res/icons/storage-dark.png \
339-
qml/res/icons/storage-light.png
339+
qml/res/icons/storage-light.png \
340+
qml/res/icons/tooltip-arrow-dark.png \
341+
qml/res/icons/tooltip-arrow-light.png
340342

341343
QML_QRC_CPP = qml/qrc_bitcoin.cpp
342344
QML_QRC = qml/bitcoin_qml.qrc
@@ -360,6 +362,7 @@ QML_RES_QML = \
360362
qml/components/StorageSettings.qml \
361363
qml/components/ThemeSettings.qml \
362364
qml/components/TotalBytesIndicator.qml \
365+
qml/components/Tooltip.qml \
363366
qml/controls/ContinueButton.qml \
364367
qml/controls/CoreText.qml \
365368
qml/controls/ExternalLink.qml \
@@ -381,6 +384,7 @@ QML_RES_QML = \
381384
qml/controls/TextButton.qml \
382385
qml/controls/Theme.qml \
383386
qml/controls/ToggleButton.qml \
387+
qml/controls/utils.js \
384388
qml/controls/ValueInput.qml \
385389
qml/pages/initerrormessage.qml \
386390
qml/pages/main.qml \

src/qml/bitcoin_qml.qrc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
<file>components/StorageSettings.qml</file>
2020
<file>components/ThemeSettings.qml</file>
2121
<file>components/TotalBytesIndicator.qml</file>
22+
<file>components/Tooltip.qml</file>
2223
<file>controls/ContinueButton.qml</file>
2324
<file>controls/CoreText.qml</file>
2425
<file>controls/ExternalLink.qml</file>
@@ -41,6 +42,7 @@
4142
<file>controls/TextButton.qml</file>
4243
<file>controls/Theme.qml</file>
4344
<file>controls/ToggleButton.qml</file>
45+
<file>controls/utils.js</file>
4446
<file>controls/ValueInput.qml</file>
4547
<file>pages/initerrormessage.qml</file>
4648
<file>pages/main.qml</file>
@@ -88,6 +90,8 @@
8890
<file alias="singlesig-wallet">res/icons/singlesig-wallet.png</file>
8991
<file alias="storage-dark">res/icons/storage-dark.png</file>
9092
<file alias="storage-light">res/icons/storage-light.png</file>
93+
<file alias="tooltip-arrow-dark">res/icons/tooltip-arrow-dark.png</file>
94+
<file alias="tooltip-arrow-light">res/icons/tooltip-arrow-light.png</file>
9195
</qresource>
9296
<qresource prefix="/fonts">
9397
<file alias="inter/regular">res/fonts/Inter-Regular.otf</file>

src/qml/components/BlockClock.qml

Lines changed: 2 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import Qt.labs.settings 1.0
1010
import org.bitcoincore.qt 1.0
1111

1212
import "../controls"
13+
import "../controls/utils.js" as Utils
1314

1415
Item {
1516
id: root
@@ -28,7 +29,7 @@ Item {
2829
property bool synced: nodeModel.verificationProgress > 0.999
2930
property string syncProgress: formatProgressPercentage(nodeModel.verificationProgress * 100)
3031
property bool paused: false
31-
property var syncState: formatRemainingSyncTime(nodeModel.remainingSyncTime)
32+
property var syncState: Utils.formatRemainingSyncTime(nodeModel.remainingSyncTime)
3233
property string syncTime: syncState.text
3334
property bool estimating: syncState.estimating
3435

@@ -234,65 +235,4 @@ Item {
234235
return "0%"
235236
}
236237
}
237-
238-
function formatRemainingSyncTime(milliseconds) {
239-
var minutes = Math.floor(milliseconds / 60000);
240-
var seconds = Math.floor((milliseconds % 60000) / 1000);
241-
var weeks = Math.floor(minutes / 10080);
242-
minutes %= 10080;
243-
var days = Math.floor(minutes / 1440);
244-
minutes %= 1440;
245-
var hours = Math.floor(minutes / 60);
246-
minutes %= 60;
247-
var result = "";
248-
var estimatingStatus = false;
249-
250-
if (weeks > 0) {
251-
return {
252-
text: "~" + weeks + (weeks === 1 ? " week" : " weeks") + " left",
253-
estimating: false
254-
};
255-
}
256-
if (days > 0) {
257-
return {
258-
text: "~" + days + (days === 1 ? " day" : " days") + " left",
259-
estimating: false
260-
};
261-
}
262-
if (hours >= 5) {
263-
return {
264-
text: "~" + hours + (hours === 1 ? " hour" : " hours") + " left",
265-
estimating: false
266-
};
267-
}
268-
if (hours > 0) {
269-
return {
270-
text: "~" + hours + "h " + minutes + "m" + " left",
271-
estimating: false
272-
};
273-
}
274-
if (minutes >= 5) {
275-
return {
276-
text: "~" + minutes + (minutes === 1 ? " minute" : " minutes") + " left",
277-
estimating: false
278-
};
279-
}
280-
if (minutes > 0) {
281-
return {
282-
text: "~" + minutes + "m " + seconds + "s" + " left",
283-
estimating: false
284-
};
285-
}
286-
if (seconds > 0) {
287-
return {
288-
text: "~" + seconds + (seconds === 1 ? " second" : " seconds") + " left",
289-
estimating: false
290-
};
291-
} else {
292-
return {
293-
text: "Estimating",
294-
estimating: true
295-
};
296-
}
297-
}
298238
}

src/qml/components/Tooltip.qml

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
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+
8+
import "../controls"
9+
10+
Item {
11+
id: root
12+
13+
property alias text: tooltipText.text
14+
15+
Rectangle {
16+
id: tooltipBg
17+
color: Theme.color.neutral0
18+
border.color: Theme.color.neutral4
19+
radius: 5
20+
border.width: 1
21+
width: tooltipText.width + 30
22+
height: tooltipText.height + 20
23+
anchors.top: arrow.bottom
24+
anchors.right: arrow.right
25+
anchors.rightMargin: -10
26+
anchors.topMargin: -1
27+
}
28+
29+
Image {
30+
id: arrow
31+
source: Theme.image.tooltipArrow
32+
width: 22
33+
height: 10
34+
anchors.horizontalCenter: root.horizontalCenter
35+
anchors.top: root.top
36+
}
37+
38+
CoreText {
39+
id: tooltipText
40+
text: ""
41+
wrapMode: Text.NoWrap
42+
anchors.centerIn: tooltipBg
43+
}
44+
}

src/qml/controls/CoreText.qml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import QtQuick.Controls 2.15
88
Text {
99
property bool bold: false
1010
property bool wrap: true
11-
color: Theme.color.white
11+
color: Theme.color.neutral9
1212
font.family: "Inter"
1313
font.styleName: bold ? "Semi Bold" : "Regular"
1414
font.pixelSize: 13

src/qml/controls/Theme.qml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ Control {
4444
required property url blocktime
4545
required property url network
4646
required property url storage
47+
required property url tooltipArrow
4748
}
4849

4950
ColorSet {
@@ -115,13 +116,15 @@ Control {
115116
blocktime: "image://images/blocktime-dark"
116117
network: "image://images/network-dark"
117118
storage: "image://images/storage-dark"
119+
tooltipArrow: "qrc:/icons/tooltip-arrow-dark"
118120
}
119121

120122
ImageSet {
121123
id: lightImageSet
122124
blocktime: "image://images/blocktime-light"
123125
network: "image://images/network-light"
124126
storage: "image://images/storage-light"
127+
tooltipArrow: "qrc:/icons/tooltip-arrow-light"
125128
}
126129

127130
function toggleDark() {

src/qml/controls/utils.js

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
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+
// utils.js
6+
7+
function formatRemainingSyncTime(milliseconds) {
8+
var minutes = Math.floor(milliseconds / 60000);
9+
var seconds = Math.floor((milliseconds % 60000) / 1000);
10+
var weeks = Math.floor(minutes / 10080);
11+
minutes %= 10080;
12+
var days = Math.floor(minutes / 1440);
13+
minutes %= 1440;
14+
var hours = Math.floor(minutes / 60);
15+
minutes %= 60;
16+
var result = "";
17+
var estimatingStatus = false;
18+
19+
if (weeks > 0) {
20+
return {
21+
text: "~" + weeks + (weeks === 1 ? " week" : " weeks") + " left",
22+
estimating: false
23+
};
24+
}
25+
if (days > 0) {
26+
return {
27+
text: "~" + days + (days === 1 ? " day" : " days") + " left",
28+
estimating: false
29+
};
30+
}
31+
if (hours >= 5) {
32+
return {
33+
text: "~" + hours + (hours === 1 ? " hour" : " hours") + " left",
34+
estimating: false
35+
};
36+
}
37+
if (hours > 0) {
38+
return {
39+
text: "~" + hours + "h " + minutes + "m" + " left",
40+
estimating: false
41+
};
42+
}
43+
if (minutes >= 5) {
44+
return {
45+
text: "~" + minutes + (minutes === 1 ? " minute" : " minutes") + " left",
46+
estimating: false
47+
};
48+
}
49+
if (minutes > 0) {
50+
return {
51+
text: "~" + minutes + "m " + seconds + "s" + " left",
52+
estimating: false
53+
};
54+
}
55+
if (seconds > 0) {
56+
return {
57+
text: "~" + seconds + (seconds === 1 ? " second" : " seconds") + " left",
58+
estimating: false
59+
};
60+
} else {
61+
return {
62+
text: "Estimating",
63+
estimating: true
64+
};
65+
}
66+
}

src/qml/imageprovider.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,5 +132,15 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
132132
return QIcon(":/icons/storage-light").pixmap(requested_size);
133133
}
134134

135+
if (id == "tooltip-arrow-dark") {
136+
*size = requested_size;
137+
return QIcon(":/icons/tooltip-arrow-dark").pixmap(requested_size);
138+
}
139+
140+
if (id == "tooltip-arrow-light") {
141+
*size = requested_size;
142+
return QIcon(":/icons/tooltip-arrow-light").pixmap(requested_size);
143+
}
144+
135145
return {};
136146
}

src/qml/pages/wallet/DesktopWallets.qml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,11 @@
55
import QtQuick 2.15
66
import QtQuick.Controls 2.15
77
import QtQuick.Layouts 1.15
8+
89
import org.bitcoincore.qt 1.0
10+
911
import "../../controls"
12+
import "../../controls/utils.js" as Utils
1013
import "../../components"
1114
import "../node"
1215

@@ -67,10 +70,30 @@ Page {
6770
shorten: true
6871
}
6972
NavigationTab {
73+
id: blockClockTabButton
7074
Layout.preferredWidth: 30
7175
Layout.rightMargin: 10
7276
property int index: 3
7377
ButtonGroup.group: navigationTabs
78+
79+
Tooltip {
80+
id: blockClockTooltip
81+
property var syncState: Utils.formatRemainingSyncTime(nodeModel.remainingSyncTime)
82+
property bool synced: nodeModel.verificationProgress > 0.9999
83+
84+
anchors.top: blockClockTabButton.bottom
85+
anchors.topMargin: -5
86+
anchors.horizontalCenter: blockClockTabButton.horizontalCenter
87+
88+
visible: blockClockTabButton.hovered
89+
text: {
90+
if (synced) {
91+
qsTr("Blocktime\n" + Number(nodeModel.blockTipHeight).toLocaleString(Qt.locale(), 'f', 0))
92+
} else {
93+
qsTr("Downloading blocks\n" + syncState.text)
94+
}
95+
}
96+
}
7497
}
7598
NavigationTab {
7699
iconSource: "image://images/gear-outline"
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)