-
Notifications
You must be signed in to change notification settings - Fork 50
Introduce the BlockClock control #148
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -312,6 +312,7 @@ QML_RES_QML = \ | |||
qml/components/StorageLocations.qml \ | |||
qml/components/StorageOptions.qml \ | |||
qml/components/StorageSettings.qml \ | |||
qml/controls/BlockClock.qml \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is a component. not a control
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The next update of my PR intends to make the BlockClock.qml
file a purely abstract structure and introduce a component file that uses it to paint different states of the block clock as needed. So I think moving BlockClock.qml
to components now would be a wasted effort.
Should you still think I shall move the BlockClock.qml
to controls, or if there is a better approach for achieving the final BlockClock state, I would love to hear that.
} | ||
} | ||
|
||
Canvas { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
instead of canvas, this should be the simpler ShapePath: https://doc.qt.io/qt-6/qml-qtquick-shapes-shapepath.html
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I looked through using the ShapePath to paint the BlockClock. However, using this would require us to introduce a new dependency, qml-module-qtquick-shapes
for building the GUI.
So I think this suggestion needs further discussion before implementing it.
A friendly ping, @hebasto
What do you think about this suggestion?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately, from my experiments, ShapePath
and related items have issues. The most annoying issue happens with small curves where tessellation yields bad curve smoothness. Another issue is that with complex drawings you end up with lots of items and bindings everywhere (especially with Repeaters), which is also not that performant.
Going forward a stack/composition of Canvas is the best option, like photoshop layers. For instance, the Canvas on the bottom could be static or updated less often than the one on the top.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, @promag, for sharing your thoughts and suggestion for using Canvas.
For instance, the Canvas on the bottom could be static or updated less often than the one on the top.
I think this would be good optimization. However, I might be putting a temporary hold on this optimization suggestion for now, as I am currently getting the Block Clock to display the block tracker, which involves some significant changes to the Canvas as well. So I shall be taking up this suggestion along with the other suggestion that shall come forth with the updated branch.
96311e3
to
621eae1
Compare
Updated from 96311e3 to 055e0c0 (pr148.01 -> pr148.02) Changes:
Note: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Branch doesn't build
src/qml/nodemodel.cpp
Outdated
|
||
const CBlockIndex* tip; | ||
node::NodeContext* context = m_node.context(); | ||
ChainstateManager* chainman = context->chainman.get(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is too low level of an object to be handling here when we have interfaces::chain
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me take a look into replacing this low-level object handling with interfaces::chain
src/qml/nodemodel.h
Outdated
double verificationProgress() const { return m_verification_progress; } | ||
void setVerificationProgress(double new_progress); | ||
QVariantList blockTimeList() const { return m_block_time_list; } | ||
bool setBlockTimeList(int new_block_time); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why should the nodemodel, a proxy class for our internal node, keep something like a blocklist?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering your previous suggestion about using the interfaces::chain
, I think I can create a separate .cpp file handling chain-related parameters such as blockTimeList
import QtQuick.Controls 2.15 | ||
import QtQuick.Layouts 1.15 | ||
|
||
Item { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the implementation of the block clock, and the file residing at src/qml/components/BlockClockComponent.qml
is just a controller for this. A better architecture is to have a controller that loads the different states the block clock can be in.
You'd be able to split up this file, as it is very long, between a simple circular progress bar that shows the verification progress while in IBD, then another dial like progress bar for the blocks. Then load these into the controller.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me try rephrasing your suggestion to ensure I understood it correctly.
You suggest I create a separate component
file for each block clock state, create a controller file in qml/control
, and switch to loading different block clock component files based on the requirement.
Have I understood it correctly?
src/qml/controls/BlockClock.qml
Outdated
sourceSize.height: 30 | ||
Layout.bottomMargin: 15 | ||
} | ||
Text { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isn't this recreating our header component?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it is. Thanks for pointing that out. I shall fix this with the next update of the PR.
src/qml/nodemodel.cpp
Outdated
return true; | ||
} | ||
|
||
void NodeModel::setBlockTimeListInitial(const CBlockIndex* pblockindex) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is definitely too low level for us to be passing around here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let me experiment with interfaces::chain
and devise an approach that avoids low-level object handling.
621eae1
to
1f134fd
Compare
1f134fd
to
23f8a83
Compare
Updated from 23f8a83 to 621eae1 (pr148.03 -> pr148.04) Changes:
Here is the demo of the latest iteration of the block clock: Block_Clock_demo.mov |
23f8a83
to
2a5e998
Compare
Updated from 621eae1 to 2a5e998 (pr148.04 -> pr148.05) Changes:
Demo: Screen.Recording.2022-12-12.at.7.21.57.PM.mov |
Thanks for the updates. It looks like the artifacts are not building due a lint issue (the Android build is only 22 bytes). Could you please address this? I'd love to get hands-on with this update. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To fix the lint task, suggesting the patch as follows:
diff --git a/src/qml/chainmodel.h b/src/qml/chainmodel.h
index 9ab25f35c..2943c9c16 100644
--- a/src/qml/chainmodel.h
+++ b/src/qml/chainmodel.h
@@ -2,8 +2,8 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
-#ifndef BITCOIN_QML_CHAIN_MODEL_H
-#define BITCOIN_QML_CHAIN_MODEL_H
+#ifndef BITCOIN_QML_CHAINMODEL_H
+#define BITCOIN_QML_CHAINMODEL_H
#include <interfaces/chain.h>
@@ -47,4 +47,4 @@ private:
interfaces::Chain& m_chain;
};
-#endif // BITCOIN_QML_CHAIN_MODEL_H
\ No newline at end of file
+#endif // BITCOIN_QML_CHAINMODEL_H
2a5e998
to
0f5461e
Compare
Updated from 2a5e998 to 0f5461e (pr148.05 -> pr148.06) Addressed @hebasto @jarolrod @GBKS comments. Changes:
Screenshots:
|
0f5461e
to
0fbe6c8
Compare
0fbe6c8
to
29f019e
Compare
29f019e
to
8173bf6
Compare
Updated from 29f019e to 8173bf6 (pr148.08 -> pr148.09)
Differences as explained in #212 Description:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Views look nice and render correctly. Tested pause/unpause as well as a full sync on signet at got the following results.
![]() |
![]() |
![]() |
![]() |
![]() |
---|
A few QML errors when running that need to be resolved before merging. I've left comments for those errors at the corresponding line numbers.
tail -f debug.log | grep GUI
to watch for issues when running bitcoin-qt.
8173bf6
to
bcbc80b
Compare
Updated from 8173bf6 to bcbc80b (pr148.09 -> pr148.10) Addressed @johnny9 comments. Changes:
|
The CI lint task error:
looks a bit weird as I failed to find a branch the c4e1ce2 commit belongs to. I hope rebasing will help. @shaavan And please make sure your local branch does not contain any merge commits. |
- This method would allow to get the blocktime value of the block at the given height.
bcbc80b
to
68fa33b
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
QML error when going into the paused state still exists. Other issues are resolved.
Updated from 68fa33b to 20b4ed5 (pr148.11 -> pr148.12, diff) Addressed @johnny9 comment.
Explaination: For example, for the block count of 122010, difference:
|
20b4ed5
to
abb0bef
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good work on this Shashwat. All of the QML errors appear to be resolved now. Views render as expected
int64_t getBlockTime(int height) override | ||
{ | ||
LOCK(::cs_main); | ||
return Assert(chainman().ActiveChain()[height])->GetBlockTime(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In Chain
interface, probably better to use a type-safe CBlockIndex::Time()
Lines 279 to 282 in fd4e57f
NodeSeconds Time() const | |
{ | |
return NodeSeconds{std::chrono::seconds{nTime}}; | |
} |
Anyway, it will take a broader discussion when it will about to merge into the main repo.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, let me look through it.
it will take a broader discussion when it will about to merge into the main repo.
Let me include that, along with other future suggestions for this file.
src/qml/chainmodel.cpp
Outdated
timer = new QTimer(); | ||
connect(timer, &QTimer::timeout, this, &ChainModel::setCurrentTimeRatio); | ||
timer->start(1000); | ||
|
||
QThread* timer_thread = new QThread; | ||
timer->moveToThread(timer_thread); | ||
timer_thread->start(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry, if I missed any previous discussion about that, but why is calling of ChainModel::setCurrentTimeRatio
implemented like that?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The currentTimeRatio represents the ratio of 12 hours that has been passed.
So, for example, at 4 am or pm, the currenTimeRatio would be 0.3.
We need to update this information in the blockClock each second so that the blockClock always shows the correct blockTime.
So that's why I created a separate 1-sec timer thread to call this function each second and update the currentTimeRatio.
- This file allowing using of Chain interfaces to get information about the blockchain. - This class declares and defines the function that will be used in for the Block Clock.
1. Added a new Q_PROPERTY to track the remaining time till the IBD completioni. 2. Added two signals to later connect to the chainmodel class function. 3. Added new member variable, m_pause, which will keep track of if the block clock is in paused state or not, and will accordingly disconnect or reconnect the user to network.
- Also made appropriate connections with the nodemodel signals
- This property will later be used for the BlockClock.qml file
- The BlockClock.qml files provides the control for BlockClock and determines how the elements would be displayed. - The BlockClockComponent.qml file uses the aforementioned control to display the value, and determines what will be displayed.
abb0bef
to
67d12a6
Compare
Closing in favor of #220. |
6701ad2 qml: introduce the BlockClock (johnny9) 60bd8cb qml: introduce ChainModel (johnny9) eb945ac qml: add sync time related properties to NodeModel (johnny9) 8db7f0f qml: add additional properties in Header (johnny9) 094a2c4 qml: add ability to pause NodeModel (johnny9) 1fce853 Add getBlockTime interface method in src/interfaces/chain.h (shaavan) Pull request description: This is a continuation of #148. The goal of this PR is to get the working features from #148 merged in using a QQuickPainterItem implementation of the dial instead of the javascript canvas. Connection state as well as the animating icon will be implemented in a later PR. Refactoring and clean up from the removal of the Canvas code still remains. [](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/win64/insecure_win_gui.zip?branch=pull/220) [](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos/insecure_mac_gui.zip?branch=pull/220) [](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/macos_arm64/insecure_mac_arm64_gui.zip?branch=pull/220) [](https://api.cirrus-ci.com/v1/artifact/github/bitcoin-core/gui-qml/android/insecure_android_apk.zip?branch=pull/220) ACKs for top commit: jarolrod: ACK 6701ad2 Tree-SHA512: 43b99d1fd69b67b285e91e05d3864c7044917cd6feae97b4c226f3a7b499ca24f6e786575dbc700461b1f6c58c0273746e4ea5834c554fa4dc916868199698df
Screenshot:
Things to note for the current implementation:
Since this is the prototype for the Block clock, I focused on the implementation part and took some liberties with the nuances, which I would like to document here.
PeersIndicator
component #127 introduces an implementation of the peer indicator and has a largely positive review. This PR could be updated with IntroducePeersIndicator
component #127's implementation when that gets merged.