diff --git a/src/Makefile.qt.include b/src/Makefile.qt.include
index f371a5b5aa..31106bd1d7 100644
--- a/src/Makefile.qt.include
+++ b/src/Makefile.qt.include
@@ -335,6 +335,7 @@ QML_RES_ICONS = \
qml/res/icons/caret-right.png \
qml/res/icons/check.png \
qml/res/icons/cross.png \
+ qml/res/icons/error.png \
qml/res/icons/export.png \
qml/res/icons/gear.png \
qml/res/icons/gear-outline.png \
diff --git a/src/qml/bitcoin_qml.qrc b/src/qml/bitcoin_qml.qrc
index 3d20c0109d..c745a9ce59 100644
--- a/src/qml/bitcoin_qml.qrc
+++ b/src/qml/bitcoin_qml.qrc
@@ -90,6 +90,7 @@
res/icons/caret-right.png
res/icons/check.png
res/icons/cross.png
+ res/icons/error.png
res/icons/export.png
res/icons/gear.png
res/icons/gear-outline.png
diff --git a/src/qml/components/BlockClock.qml b/src/qml/components/BlockClock.qml
index dcb2d2d7b6..51b02afe51 100644
--- a/src/qml/components/BlockClock.qml
+++ b/src/qml/components/BlockClock.qml
@@ -32,6 +32,7 @@ Item {
property var syncState: Utils.formatRemainingSyncTime(nodeModel.remainingSyncTime)
property string syncTime: syncState.text
property bool estimating: syncState.estimating
+ property bool faulted: nodeModel.faulted
activeFocusOnTab: true
@@ -50,7 +51,7 @@ Item {
penWidth: dial.width / 50
timeRatioList: chainModel.timeRatioList
verificationProgress: nodeModel.verificationProgress
- paused: root.paused
+ paused: root.paused || root.faulted
connected: root.connected
synced: nodeModel.verificationProgress > 0.999
backgroundColor: Theme.color.neutral2
@@ -143,7 +144,7 @@ Item {
maxNumOutboundPeers: nodeModel.maxNumOutboundPeers
indicatorDimensions: dial.width * (3/200)
indicatorSpacing: dial.width / 40
- paused: root.paused
+ paused: root.paused || root.faulted
}
NetworkIndicator {
@@ -156,10 +157,13 @@ Item {
MouseArea {
anchors.fill: dial
- cursorShape: Qt.PointingHandCursor
+ cursorShape: root.faulted ? Qt.ArrowCursor : Qt.PointingHandCursor
+ enabled: !root.faulted
onClicked: {
- root.paused = !root.paused
- nodeModel.pause = root.paused
+ if (!root.faulted) {
+ root.paused = !root.paused
+ nodeModel.pause = root.paused
+ }
}
FocusBorder {
visible: root.activeFocus
@@ -175,6 +179,7 @@ Item {
subText: root.syncTime
}
},
+
State {
name: "BLOCKCLOCK"; when: synced && !paused && connected
PropertyChanges {
@@ -186,7 +191,7 @@ Item {
},
State {
- name: "PAUSE"; when: paused
+ name: "PAUSE"; when: paused && !faulted
PropertyChanges {
target: root
header: "Paused"
@@ -204,6 +209,20 @@ Item {
}
},
+ State {
+ name: "ERROR"; when: faulted
+ PropertyChanges {
+ target: root
+ header: "Error"
+ headerSize: dial.width * (3/25)
+ }
+ PropertyChanges {
+ target: bitcoinIcon
+ anchors.bottomMargin: dial.width / 40
+ icon.source: "image://images/error"
+ }
+ },
+
State {
name: "CONNECTING"; when: !paused && !connected
PropertyChanges {
@@ -224,6 +243,7 @@ Item {
}
]
+
function formatProgressPercentage(progress) {
if (progress >= 1) {
return Math.round(progress) + "%"
diff --git a/src/qml/imageprovider.cpp b/src/qml/imageprovider.cpp
index f00168acec..254df95ef7 100644
--- a/src/qml/imageprovider.cpp
+++ b/src/qml/imageprovider.cpp
@@ -82,6 +82,11 @@ QPixmap ImageProvider::requestPixmap(const QString& id, QSize* size, const QSize
return QIcon(":/icons/cross").pixmap(requested_size);
}
+ if (id == "error") {
+ *size = requested_size;
+ return QIcon(":/icons/error").pixmap(requested_size);
+ }
+
if (id == "export") {
*size = requested_size;
return QIcon(":/icons/export").pixmap(requested_size);
diff --git a/src/qml/models/nodemodel.cpp b/src/qml/models/nodemodel.cpp
index a699376d1a..521e5fa1c5 100644
--- a/src/qml/models/nodemodel.cpp
+++ b/src/qml/models/nodemodel.cpp
@@ -15,6 +15,7 @@
#include
#include
#include
+#include
NodeModel::NodeModel(interfaces::Node& node)
: m_node{node}
@@ -93,6 +94,14 @@ void NodeModel::setPause(bool new_pause)
}
}
+void NodeModel::setErrorState(bool faulted)
+{
+ if (m_faulted != faulted) {
+ m_faulted = faulted;
+ Q_EMIT errorStateChanged(faulted);
+ }
+}
+
void NodeModel::startNodeInitializionThread()
{
Q_EMIT requestedInitialize();
@@ -103,9 +112,11 @@ void NodeModel::requestShutdown()
Q_EMIT requestedShutdown();
}
-void NodeModel::initializeResult([[maybe_unused]] bool success, interfaces::BlockAndHeaderTipInfo tip_info)
+void NodeModel::initializeResult(bool success, interfaces::BlockAndHeaderTipInfo tip_info)
{
- // TODO: Handle the `success` parameter,
+ if (!success) {
+ setErrorState(true);
+ }
setBlockTipHeight(tip_info.block_height);
setVerificationProgress(tip_info.verification_progress);
diff --git a/src/qml/models/nodemodel.h b/src/qml/models/nodemodel.h
index 442a0becf3..a17f9b0833 100644
--- a/src/qml/models/nodemodel.h
+++ b/src/qml/models/nodemodel.h
@@ -33,6 +33,7 @@ class NodeModel : public QObject
Q_PROPERTY(int remainingSyncTime READ remainingSyncTime NOTIFY remainingSyncTimeChanged)
Q_PROPERTY(double verificationProgress READ verificationProgress NOTIFY verificationProgressChanged)
Q_PROPERTY(bool pause READ pause WRITE setPause NOTIFY pauseChanged)
+ Q_PROPERTY(bool faulted READ errorState WRITE setErrorState NOTIFY errorStateChanged)
public:
explicit NodeModel(interfaces::Node& node);
@@ -49,6 +50,8 @@ class NodeModel : public QObject
void setVerificationProgress(double new_progress);
bool pause() const { return m_pause; }
void setPause(bool new_pause);
+ bool errorState() const { return m_faulted; }
+ void setErrorState(bool new_error);
Q_INVOKABLE float getTotalBytesReceived() const { return (float)m_node.getTotalBytesRecv(); }
Q_INVOKABLE float getTotalBytesSent() const { return (float)m_node.getTotalBytesSent(); }
@@ -70,6 +73,7 @@ public Q_SLOTS:
void requestedShutdown();
void verificationProgressChanged();
void pauseChanged(bool new_pause);
+ void errorStateChanged(bool new_error_state);
void setTimeRatioList(int new_time);
void setTimeRatioListInitial();
@@ -85,6 +89,7 @@ public Q_SLOTS:
int m_remaining_sync_time{0};
double m_verification_progress{0.0};
bool m_pause{false};
+ bool m_faulted{false};
int m_shutdown_polling_timer_id{0};
diff --git a/src/qml/res/icons/error.png b/src/qml/res/icons/error.png
new file mode 100644
index 0000000000..cf60fada2d
Binary files /dev/null and b/src/qml/res/icons/error.png differ
diff --git a/src/qml/res/src/error.svg b/src/qml/res/src/error.svg
new file mode 100644
index 0000000000..c8bc7128f4
--- /dev/null
+++ b/src/qml/res/src/error.svg
@@ -0,0 +1,4 @@
+