Skip to content

Commit a7ccfc3

Browse files
committed
Merge #400: Introduce Tooltip for the BlockClock navbar button
8f8341f qml: Introduce Tooltip for the BlockClock navbar button (johnny9) Pull request description: The Tooltip will appear when hovering over the BlockClock tab button in the desktop navigation bar. It will show the current state of IBD. Two things are different than the figma. The wording for remaining blocks matches what is shown on the BlockClock instead of what the figma shows and After sync, Blockheight is shown instead. Looking for opinions on both during review. ![vlcsnap-2024-05-01-20h05m06s361](https://github.com/bitcoin-core/gui-qml/assets/985648/fb4b6da1-ac76-4e82-b515-977f09caee51) [![Build Artifacts](https://img.shields.io/badge/Build%20Artifacts-green )](https://github.com/bitcoin-core/gui-qml/actions/runs/9012143092?pr=400) ACKs for top commit: D33r-Gee: tACK 8f8341f on WSL Ubuntu 22.04 LGTM pablomartin4btc: re-tACK 8f8341f Tree-SHA512: c61980b31eed9d4a632dbccc59e4b7ef3effb019e70eea06597f908ba59f83322e49d9cd1c57ec51267e9af32976d63c8ce9deea8b2b89b5c3858ea5f81f0223
2 parents cf820e5 + 8f8341f commit a7ccfc3

13 files changed

+172
-64
lines changed

src/Makefile.qt.include

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

342344
QML_QRC_CPP = qml/qrc_bitcoin.cpp
343345
QML_QRC = qml/bitcoin_qml.qrc
@@ -361,6 +363,7 @@ QML_RES_QML = \
361363
qml/components/StorageSettings.qml \
362364
qml/components/ThemeSettings.qml \
363365
qml/components/TotalBytesIndicator.qml \
366+
qml/components/Tooltip.qml \
364367
qml/controls/ContinueButton.qml \
365368
qml/controls/CoreText.qml \
366369
qml/controls/ExternalLink.qml \
@@ -383,6 +386,7 @@ QML_RES_QML = \
383386
qml/controls/TextButton.qml \
384387
qml/controls/Theme.qml \
385388
qml/controls/ToggleButton.qml \
389+
qml/controls/utils.js \
386390
qml/controls/ValueInput.qml \
387391
qml/pages/initerrormessage.qml \
388392
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: 29 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,36 @@ 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+
property bool paused: nodeModel.pause
84+
property bool connected: nodeModel.numOutboundPeers > 0
85+
86+
anchors.top: blockClockTabButton.bottom
87+
anchors.topMargin: -5
88+
anchors.horizontalCenter: blockClockTabButton.horizontalCenter
89+
90+
visible: blockClockTabButton.hovered
91+
text: {
92+
if (paused) {
93+
qsTr("Paused")
94+
} else if (connected && synced) {
95+
qsTr("Blocktime\n" + Number(nodeModel.blockTipHeight).toLocaleString(Qt.locale(), 'f', 0))
96+
} else if (connected){
97+
qsTr("Downloading blocks\n" + syncState.text)
98+
} else {
99+
qsTr("Connecting")
100+
}
101+
}
102+
}
74103
}
75104
NavigationTab {
76105
iconSource: "image://images/gear-outline"
2.05 KB
Loading
1.23 KB
Loading
Lines changed: 4 additions & 0 deletions
Loading
Lines changed: 4 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)