Skip to content

Commit 0da49e0

Browse files
johnny9shaavan
authored andcommitted
qml: introduce ChainModel
The ChainModel is responsible for managing the block information that the gui components need to show. In this case, the ChainModel will provide a list of ratios for the block times of the last 12 hours to be rendered on the block clock's dial. Github-Pull: #220 Rebased-From: 60bd8cb Co-authored-by: shaavan <shaavan.github@gmail.com>
1 parent 600bef6 commit 0da49e0

File tree

4 files changed

+155
-0
lines changed

4 files changed

+155
-0
lines changed

src/qml/BitcoinApp/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ qt6_add_qml_module(bitcoin_qml
99
SOURCES
1010
appmode.h
1111
bitcoin.cpp
12+
chainmodel.cpp
1213
imageprovider.cpp
1314
nodemodel.cpp
1415
options_model.cpp

src/qml/BitcoinApp/bitcoin.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,15 @@
88
#include <common/args.h>
99
#include <common/system.h>
1010
#include <init.h>
11+
#include <interfaces/chain.h>
1112
#include <interfaces/node.h>
1213
#include <interfaces/init.h>
1314
#include <logging.h>
1415
#include <node/interface_ui.h>
1516
#include <node/context.h>
1617
#include <noui.h>
1718
#include <qml/BitcoinApp/appmode.h>
19+
#include <qml/BitcoinApp/chainmodel.h>
1820
#include <qml/BitcoinApp/imageprovider.h>
1921
#include <qml/BitcoinApp/nodemodel.h>
2022
#include <qml/BitcoinApp/options_model.h>
@@ -131,6 +133,7 @@ int QmlGuiMain(int argc, char* argv[])
131133
InitParameterInteraction(gArgs);
132134

133135
std::unique_ptr<interfaces::Node> node = init->makeNode();
136+
std::unique_ptr<interfaces::Chain> chain = init->makeChain();
134137
if (!node->baseInitialize()) {
135138
// A dialog with detailed error will have been shown by InitError().
136139
return EXIT_FAILURE;
@@ -146,6 +149,11 @@ int QmlGuiMain(int argc, char* argv[])
146149
QObject::connect(&init_executor, &InitExecutor::shutdownResult, qGuiApp, &QGuiApplication::quit, Qt::QueuedConnection);
147150
// QObject::connect(&init_executor, &InitExecutor::runawayException, &node_model, &NodeModel::handleRunawayException);
148151

152+
ChainModel chain_model{*chain};
153+
154+
QObject::connect(&node_model, &NodeModel::setTimeRatioList, &chain_model, &ChainModel::setTimeRatioList);
155+
QObject::connect(&node_model, &NodeModel::setTimeRatioListInitial, &chain_model, &ChainModel::setTimeRatioListInitial);
156+
149157
qGuiApp->setQuitOnLastWindowClosed(false);
150158
QObject::connect(qGuiApp, &QGuiApplication::lastWindowClosed, [&] {
151159
node->startShutdown();
@@ -162,6 +170,7 @@ int QmlGuiMain(int argc, char* argv[])
162170
engine.addImageProvider(QStringLiteral("images"), new ImageProvider{network_style.data()});
163171

164172
engine.rootContext()->setContextProperty("nodeModel", &node_model);
173+
engine.rootContext()->setContextProperty("chainModel", &chain_model);
165174

166175
OptionsQmlModel options_model{*node};
167176
engine.rootContext()->setContextProperty("optionsModel", &options_model);

src/qml/BitcoinApp/chainmodel.cpp

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright (c) 2022 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+
#include <qml/BitcoinApp/chainmodel.h>
6+
7+
#include <QDateTime>
8+
#include <QThread>
9+
#include <QTime>
10+
#include <interfaces/chain.h>
11+
12+
ChainModel::ChainModel(interfaces::Chain& chain)
13+
: m_chain{chain}
14+
{
15+
QTimer* timer = new QTimer();
16+
connect(timer, &QTimer::timeout, this, &ChainModel::setCurrentTimeRatio);
17+
timer->start(1000);
18+
19+
QThread* timer_thread = new QThread;
20+
timer->moveToThread(timer_thread);
21+
timer_thread->start();
22+
}
23+
24+
void ChainModel::setTimeRatioList(int new_time)
25+
{
26+
if (m_time_ratio_list.isEmpty()) {
27+
setTimeRatioListInitial();
28+
}
29+
int time_at_meridian = timestampAtMeridian();
30+
31+
if (new_time < time_at_meridian) {
32+
return;
33+
}
34+
m_time_ratio_list.push_back(double(new_time - time_at_meridian) / SECS_IN_12_HOURS);
35+
36+
Q_EMIT timeRatioListChanged();
37+
}
38+
39+
int ChainModel::timestampAtMeridian()
40+
{
41+
int secs_since_meridian = (QTime::currentTime().msecsSinceStartOfDay() / 1000) % SECS_IN_12_HOURS;
42+
int current_timestamp = QDateTime::currentSecsSinceEpoch();
43+
44+
return current_timestamp - secs_since_meridian;
45+
}
46+
47+
void ChainModel::setTimeRatioListInitial()
48+
{
49+
int time_at_meridian = timestampAtMeridian();
50+
m_time_ratio_list.clear();
51+
/* m_time_ratio_list[0] = current_time_ratio
52+
* m_time_ratio_list[1] = 0
53+
* These two positions remain fixed for these
54+
* values in m_time_ratio_list */
55+
m_time_ratio_list.push_back(double(QDateTime::currentSecsSinceEpoch() - time_at_meridian) / SECS_IN_12_HOURS);
56+
m_time_ratio_list.push_back(0);
57+
58+
int first_block_height;
59+
int active_chain_height = m_chain.getHeight().value();
60+
bool success = m_chain.findFirstBlockWithTimeAndHeight(/*min_time=*/time_at_meridian, /*min_height=*/0, interfaces::FoundBlock().height(first_block_height));
61+
62+
if (!success) {
63+
Q_EMIT timeRatioListChanged();
64+
return;
65+
}
66+
67+
for (int height = first_block_height; height < active_chain_height + 1; height++) {
68+
m_time_ratio_list.push_back(double(m_chain.getBlockTime(height) - time_at_meridian) / SECS_IN_12_HOURS);
69+
}
70+
71+
Q_EMIT timeRatioListChanged();
72+
}
73+
74+
void ChainModel::setCurrentTimeRatio()
75+
{
76+
int secs_since_meridian = (QTime::currentTime().msecsSinceStartOfDay() / 1000) % SECS_IN_12_HOURS;
77+
double current_time_ratio = double(secs_since_meridian) / SECS_IN_12_HOURS;
78+
79+
if (current_time_ratio < m_time_ratio_list[0].toDouble()) { // That means time has crossed a meridian
80+
m_time_ratio_list.clear();
81+
}
82+
83+
if (m_time_ratio_list.isEmpty()) {
84+
m_time_ratio_list.push_back(current_time_ratio);
85+
m_time_ratio_list.push_back(0);
86+
} else {
87+
m_time_ratio_list[0] = current_time_ratio;
88+
}
89+
90+
Q_EMIT timeRatioListChanged();
91+
}

src/qml/BitcoinApp/chainmodel.h

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
// Copyright (c) 2022 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+
#ifndef BITCOIN_QML_CHAINMODEL_H
6+
#define BITCOIN_QML_CHAINMODEL_H
7+
8+
#include <interfaces/chain.h>
9+
10+
#include <QObject>
11+
#include <QTimer>
12+
#include <QVariant>
13+
14+
namespace interfaces {
15+
class FoundBlock;
16+
class Chain;
17+
} // namespace interfaces
18+
19+
static const int SECS_IN_12_HOURS = 43200;
20+
21+
class ChainModel : public QObject
22+
{
23+
Q_OBJECT
24+
Q_PROPERTY(QVariantList timeRatioList READ timeRatioList NOTIFY timeRatioListChanged)
25+
26+
public:
27+
explicit ChainModel(interfaces::Chain& chain);
28+
29+
QVariantList timeRatioList() const { return m_time_ratio_list; };
30+
31+
int timestampAtMeridian();
32+
33+
void setCurrentTimeRatio();
34+
35+
public Q_SLOTS:
36+
void setTimeRatioList(int new_time);
37+
void setTimeRatioListInitial();
38+
39+
Q_SIGNALS:
40+
void timeRatioListChanged();
41+
42+
private:
43+
/* time_ratio: Ratio between the time at which an event
44+
* happened and 12 hours. So, for example, if a block is
45+
* found at 4 am or pm, the time_ratio would be 0.3.
46+
* The m_time_ratio_list stores the time ratio value for
47+
* the current_time and the time at which the blocks in
48+
* the last 12 hours were mined. */
49+
QVariantList m_time_ratio_list{0.0};
50+
51+
interfaces::Chain& m_chain;
52+
};
53+
54+
#endif // BITCOIN_QML_CHAINMODEL_H

0 commit comments

Comments
 (0)