Skip to content

Commit

Permalink
Merge bitcoin-core#400: Introduce Tooltip for the BlockClock navbar b…
Browse files Browse the repository at this point in the history
…utton

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
  • Loading branch information
hebasto committed May 27, 2024
2 parents cf820e5 + 8f8341f commit a7ccfc3
Show file tree
Hide file tree
Showing 13 changed files with 172 additions and 64 deletions.
6 changes: 5 additions & 1 deletion src/Makefile.qt.include
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,9 @@ QML_RES_ICONS = \
qml/res/icons/shutdown.png \
qml/res/icons/singlesig-wallet.png \
qml/res/icons/storage-dark.png \
qml/res/icons/storage-light.png
qml/res/icons/storage-light.png \
qml/res/icons/tooltip-arrow-dark.png \
qml/res/icons/tooltip-arrow-light.png

QML_QRC_CPP = qml/qrc_bitcoin.cpp
QML_QRC = qml/bitcoin_qml.qrc
Expand All @@ -361,6 +363,7 @@ QML_RES_QML = \
qml/components/StorageSettings.qml \
qml/components/ThemeSettings.qml \
qml/components/TotalBytesIndicator.qml \
qml/components/Tooltip.qml \
qml/controls/ContinueButton.qml \
qml/controls/CoreText.qml \
qml/controls/ExternalLink.qml \
Expand All @@ -383,6 +386,7 @@ QML_RES_QML = \
qml/controls/TextButton.qml \
qml/controls/Theme.qml \
qml/controls/ToggleButton.qml \
qml/controls/utils.js \
qml/controls/ValueInput.qml \
qml/pages/initerrormessage.qml \
qml/pages/main.qml \
Expand Down
4 changes: 4 additions & 0 deletions src/qml/bitcoin_qml.qrc
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<file>components/StorageSettings.qml</file>
<file>components/ThemeSettings.qml</file>
<file>components/TotalBytesIndicator.qml</file>
<file>components/Tooltip.qml</file>
<file>controls/ContinueButton.qml</file>
<file>controls/CoreText.qml</file>
<file>controls/ExternalLink.qml</file>
Expand All @@ -41,6 +42,7 @@
<file>controls/TextButton.qml</file>
<file>controls/Theme.qml</file>
<file>controls/ToggleButton.qml</file>
<file>controls/utils.js</file>
<file>controls/ValueInput.qml</file>
<file>pages/initerrormessage.qml</file>
<file>pages/main.qml</file>
Expand Down Expand Up @@ -88,6 +90,8 @@
<file alias="singlesig-wallet">res/icons/singlesig-wallet.png</file>
<file alias="storage-dark">res/icons/storage-dark.png</file>
<file alias="storage-light">res/icons/storage-light.png</file>
<file alias="tooltip-arrow-dark">res/icons/tooltip-arrow-dark.png</file>
<file alias="tooltip-arrow-light">res/icons/tooltip-arrow-light.png</file>
</qresource>
<qresource prefix="/fonts">
<file alias="inter/regular">res/fonts/Inter-Regular.otf</file>
Expand Down
64 changes: 2 additions & 62 deletions src/qml/components/BlockClock.qml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import Qt.labs.settings 1.0
import org.bitcoincore.qt 1.0

import "../controls"
import "../controls/utils.js" as Utils

Item {
id: root
Expand All @@ -28,7 +29,7 @@ Item {
property bool synced: nodeModel.verificationProgress > 0.999
property string syncProgress: formatProgressPercentage(nodeModel.verificationProgress * 100)
property bool paused: false
property var syncState: formatRemainingSyncTime(nodeModel.remainingSyncTime)
property var syncState: Utils.formatRemainingSyncTime(nodeModel.remainingSyncTime)
property string syncTime: syncState.text
property bool estimating: syncState.estimating

Expand Down Expand Up @@ -234,65 +235,4 @@ Item {
return "0%"
}
}

function formatRemainingSyncTime(milliseconds) {
var minutes = Math.floor(milliseconds / 60000);
var seconds = Math.floor((milliseconds % 60000) / 1000);
var weeks = Math.floor(minutes / 10080);
minutes %= 10080;
var days = Math.floor(minutes / 1440);
minutes %= 1440;
var hours = Math.floor(minutes / 60);
minutes %= 60;
var result = "";
var estimatingStatus = false;

if (weeks > 0) {
return {
text: "~" + weeks + (weeks === 1 ? " week" : " weeks") + " left",
estimating: false
};
}
if (days > 0) {
return {
text: "~" + days + (days === 1 ? " day" : " days") + " left",
estimating: false
};
}
if (hours >= 5) {
return {
text: "~" + hours + (hours === 1 ? " hour" : " hours") + " left",
estimating: false
};
}
if (hours > 0) {
return {
text: "~" + hours + "h " + minutes + "m" + " left",
estimating: false
};
}
if (minutes >= 5) {
return {
text: "~" + minutes + (minutes === 1 ? " minute" : " minutes") + " left",
estimating: false
};
}
if (minutes > 0) {
return {
text: "~" + minutes + "m " + seconds + "s" + " left",
estimating: false
};
}
if (seconds > 0) {
return {
text: "~" + seconds + (seconds === 1 ? " second" : " seconds") + " left",
estimating: false
};
} else {
return {
text: "Estimating",
estimating: true
};
}
}
}
44 changes: 44 additions & 0 deletions src/qml/components/Tooltip.qml
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Copyright (c) 2024 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

import QtQuick 2.15
import QtQuick.Controls 2.15

import "../controls"

Item {
id: root

property alias text: tooltipText.text

Rectangle {
id: tooltipBg
color: Theme.color.neutral0
border.color: Theme.color.neutral4
radius: 5
border.width: 1
width: tooltipText.width + 30
height: tooltipText.height + 20
anchors.top: arrow.bottom
anchors.right: arrow.right
anchors.rightMargin: -10
anchors.topMargin: -1
}

Image {
id: arrow
source: Theme.image.tooltipArrow
width: 22
height: 10
anchors.horizontalCenter: root.horizontalCenter
anchors.top: root.top
}

CoreText {
id: tooltipText
text: ""
wrapMode: Text.NoWrap
anchors.centerIn: tooltipBg
}
}
2 changes: 1 addition & 1 deletion src/qml/controls/CoreText.qml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import QtQuick.Controls 2.15
Text {
property bool bold: false
property bool wrap: true
color: Theme.color.white
color: Theme.color.neutral9
font.family: "Inter"
font.styleName: bold ? "Semi Bold" : "Regular"
font.pixelSize: 13
Expand Down
3 changes: 3 additions & 0 deletions src/qml/controls/Theme.qml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Control {
required property url blocktime
required property url network
required property url storage
required property url tooltipArrow
}

ColorSet {
Expand Down Expand Up @@ -115,13 +116,15 @@ Control {
blocktime: "image://images/blocktime-dark"
network: "image://images/network-dark"
storage: "image://images/storage-dark"
tooltipArrow: "qrc:/icons/tooltip-arrow-dark"
}

ImageSet {
id: lightImageSet
blocktime: "image://images/blocktime-light"
network: "image://images/network-light"
storage: "image://images/storage-light"
tooltipArrow: "qrc:/icons/tooltip-arrow-light"
}

function toggleDark() {
Expand Down
66 changes: 66 additions & 0 deletions src/qml/controls/utils.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// Copyright (c) 2024 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

// utils.js

function formatRemainingSyncTime(milliseconds) {
var minutes = Math.floor(milliseconds / 60000);
var seconds = Math.floor((milliseconds % 60000) / 1000);
var weeks = Math.floor(minutes / 10080);
minutes %= 10080;
var days = Math.floor(minutes / 1440);
minutes %= 1440;
var hours = Math.floor(minutes / 60);
minutes %= 60;
var result = "";
var estimatingStatus = false;

if (weeks > 0) {
return {
text: "~" + weeks + (weeks === 1 ? " week" : " weeks") + " left",
estimating: false
};
}
if (days > 0) {
return {
text: "~" + days + (days === 1 ? " day" : " days") + " left",
estimating: false
};
}
if (hours >= 5) {
return {
text: "~" + hours + (hours === 1 ? " hour" : " hours") + " left",
estimating: false
};
}
if (hours > 0) {
return {
text: "~" + hours + "h " + minutes + "m" + " left",
estimating: false
};
}
if (minutes >= 5) {
return {
text: "~" + minutes + (minutes === 1 ? " minute" : " minutes") + " left",
estimating: false
};
}
if (minutes > 0) {
return {
text: "~" + minutes + "m " + seconds + "s" + " left",
estimating: false
};
}
if (seconds > 0) {
return {
text: "~" + seconds + (seconds === 1 ? " second" : " seconds") + " left",
estimating: false
};
} else {
return {
text: "Estimating",
estimating: true
};
}
}
10 changes: 10 additions & 0 deletions src/qml/imageprovider.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,5 +132,15 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
return QIcon(":/icons/storage-light").pixmap(requested_size);
}

if (id == "tooltip-arrow-dark") {
*size = requested_size;
return QIcon(":/icons/tooltip-arrow-dark").pixmap(requested_size);
}

if (id == "tooltip-arrow-light") {
*size = requested_size;
return QIcon(":/icons/tooltip-arrow-light").pixmap(requested_size);
}

return {};
}
29 changes: 29 additions & 0 deletions src/qml/pages/wallet/DesktopWallets.qml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15

import org.bitcoincore.qt 1.0

import "../../controls"
import "../../controls/utils.js" as Utils
import "../../components"
import "../node"

Expand Down Expand Up @@ -67,10 +70,36 @@ Page {
shorten: true
}
NavigationTab {
id: blockClockTabButton
Layout.preferredWidth: 30
Layout.rightMargin: 10
property int index: 3
ButtonGroup.group: navigationTabs

Tooltip {
id: blockClockTooltip
property var syncState: Utils.formatRemainingSyncTime(nodeModel.remainingSyncTime)
property bool synced: nodeModel.verificationProgress > 0.9999
property bool paused: nodeModel.pause
property bool connected: nodeModel.numOutboundPeers > 0

anchors.top: blockClockTabButton.bottom
anchors.topMargin: -5
anchors.horizontalCenter: blockClockTabButton.horizontalCenter

visible: blockClockTabButton.hovered
text: {
if (paused) {
qsTr("Paused")
} else if (connected && synced) {
qsTr("Blocktime\n" + Number(nodeModel.blockTipHeight).toLocaleString(Qt.locale(), 'f', 0))
} else if (connected){
qsTr("Downloading blocks\n" + syncState.text)
} else {
qsTr("Connecting")
}
}
}
}
NavigationTab {
iconSource: "image://images/gear-outline"
Expand Down
Binary file added src/qml/res/icons/tooltip-arrow-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added src/qml/res/icons/tooltip-arrow-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/qml/res/src/tooltip-arrow-dark.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions src/qml/res/src/tooltip-arrow-light.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit a7ccfc3

Please sign in to comment.