Skip to content

Commit bcb0b35

Browse files
Gabrielnmdstatatupig-abilio
authored
Adds progress value display feature. (#505)
* adds version to Catch2 due to compatibility issues * Updates from upstream * Solve conflicts * Improve progress value size and alignment * solve conflicts * solve conflicts * add ProgressValue case to switch * solve conflicts * remove undesirable statement * change the way in which the progress label was displayed --------- Co-authored-by: Taiguara Tupinambás <tatatupi@gmail.com> Co-authored-by: g-abilio <gabrielabiliobferreira2@gmail.com> Co-authored-by: Gabriel Abílio <150153171+g-abilio@users.noreply.github.com>
1 parent 163ed49 commit bcb0b35

File tree

9 files changed

+131
-44
lines changed

9 files changed

+131
-44
lines changed

examples/calculator/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ set(CALC_HEADER_FILES
1313
NumberDisplayDataModel.hpp
1414
NumberSourceDataModel.hpp
1515
SubtractionModel.hpp
16+
LongProcessingRandomNumber.hpp
1617
)
1718

1819
add_executable(calculator
Lines changed: 78 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,72 @@
11
#pragma once
22

3-
#include <QtNodes/NodeDelegateModel>
43
#include <QTimer>
4+
#include <QtCore/QElapsedTimer>
55
#include <QtCore/QObject>
6-
#include <QtWidgets/QLabel>
76
#include <QtCore/QRandomGenerator64>
7+
#include <QtNodes/NodeDelegateModel>
8+
#include <QtWidgets/QLabel>
89

9-
#include "MathOperationDataModel.hpp"
1010
#include "DecimalData.hpp"
11+
#include "MathOperationDataModel.hpp"
1112

12-
/// The model generates a random value in a long processing schema,
13-
/// as it should demonstrate the usage of the NodeProcessingStatus.
13+
/// The model generates a random value in a long processing schema, as it should demonstrate
14+
/// the usage of the NodeProcessingStatus and the ProgressValue functionality.
1415
/// The random number is generate in the [n1, n2] interval.
15-
class RandomNumberModel : public MathOperationDataModel
16+
class LongProcessingRandomNumber : public MathOperationDataModel
1617
{
1718
public:
18-
RandomNumberModel()
19-
: _timer(new QTimer(this))
19+
LongProcessingRandomNumber()
2020
{
2121
this->setNodeProcessingStatus(QtNodes::NodeProcessingStatus::Empty);
2222

2323
QObject::connect(this, &NodeDelegateModel::computingStarted, this, [this]() {
24-
if (_number1.lock() && _number2.lock()) {
25-
this->setNodeProcessingStatus(QtNodes::NodeProcessingStatus::Processing);
24+
this->setNodeProcessingStatus(QtNodes::NodeProcessingStatus::Processing);
25+
26+
setProgressValue(QString{"0%"});
27+
emit requestNodeUpdate();
28+
29+
_elapsedTimer.start();
30+
31+
if (!_progressTimer) {
32+
_progressTimer = new QTimer(this);
33+
connect(_progressTimer, &QTimer::timeout, this, [this]() {
34+
qint64 elapsed = _elapsedTimer.elapsed();
35+
int percent = static_cast<int>((double(elapsed) / _totalDurationMs) * 100.0);
36+
37+
if (percent > 100)
38+
percent = 100;
39+
40+
setProgressValue(QString::number(percent) + "%");
41+
emit requestNodeUpdate();
42+
});
2643
}
44+
45+
_progressTimer->start(_progressUpdateIntervalMs);
46+
2747
emit requestNodeUpdate();
2848
});
49+
2950
QObject::connect(this, &NodeDelegateModel::computingFinished, this, [this]() {
51+
if (_progressTimer) {
52+
_progressTimer->stop();
53+
}
54+
55+
setProgressValue(QString());
56+
3057
this->setNodeProcessingStatus(QtNodes::NodeProcessingStatus::Updated);
58+
3159
emit requestNodeUpdate();
3260
});
3361
}
34-
virtual ~RandomNumberModel() {}
62+
63+
virtual ~LongProcessingRandomNumber()
64+
{
65+
if (_progressTimer) {
66+
_progressTimer->stop();
67+
delete _progressTimer;
68+
}
69+
}
3570

3671
public:
3772
QString caption() const override { return QStringLiteral("Random Number"); }
@@ -41,47 +76,50 @@ class RandomNumberModel : public MathOperationDataModel
4176
private:
4277
void compute() override
4378
{
44-
// Stop any previous computation
45-
_timer->stop();
46-
_timer->disconnect();
79+
auto n1 = _number1.lock();
80+
auto n2 = _number2.lock();
81+
82+
if (!n1 || !n2) {
83+
return;
84+
}
4785

4886
Q_EMIT computingStarted();
4987
PortIndex const outPortIndex = 0;
5088

51-
auto n1 = _number1.lock();
52-
auto n2 = _number2.lock();
89+
QTimer::singleShot(_totalDurationMs, this, [this, n1, n2]() {
90+
if (n1 && n2) {
91+
double a = n1->number();
92+
double b = n2->number();
93+
94+
if (a > b) {
95+
setNodeProcessingStatus(QtNodes::NodeProcessingStatus::Failed);
5396

54-
_secondsRemaining = 3;
55-
_timer->start(1000);
56-
connect(_timer, &QTimer::timeout, this, [this, n1, n2, outPortIndex]() {
57-
if (--_secondsRemaining <= 0) {
58-
_timer->stop();
59-
if (n1 && n2) {
60-
double a = n1->number();
61-
double b = n2->number();
62-
63-
if (a > b) {
64-
setNodeProcessingStatus(QtNodes::NodeProcessingStatus::Failed);
65-
emit requestNodeUpdate();
66-
return;
97+
if (_progressTimer) {
98+
_progressTimer->stop();
6799
}
68100

69-
double upper = std::nextafter(b, std::numeric_limits<double>::max());
70-
double randomValue = QRandomGenerator::global()->generateDouble() * (upper - a)
71-
+ a;
101+
setProgressValue(QString());
72102

73-
_result = std::make_shared<DecimalData>(randomValue);
74-
Q_EMIT computingFinished();
75-
} else {
76-
_result.reset();
103+
emit requestNodeUpdate();
104+
return;
77105
}
78106

79-
Q_EMIT dataUpdated(outPortIndex);
107+
double upper = std::nextafter(b, std::numeric_limits<double>::max());
108+
double randomValue = QRandomGenerator::global()->generateDouble() * (upper - a) + a;
109+
110+
_result = std::make_shared<DecimalData>(randomValue);
111+
emit computingFinished();
112+
} else {
113+
_result.reset();
80114
}
115+
116+
Q_EMIT dataUpdated(outPortIndex);
81117
});
82118
}
83119

84-
private:
85-
QTimer *_timer;
86-
int _secondsRemaining = 0;
120+
QTimer *_progressTimer = nullptr;
121+
QElapsedTimer _elapsedTimer;
122+
123+
const int _totalDurationMs = 3000;
124+
const int _progressUpdateIntervalMs = 50;
87125
};

examples/calculator/headless_main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ static std::shared_ptr<NodeDelegateModelRegistry> registerDataModels()
2828

2929
ret->registerModel<DivisionModel>("Operators");
3030

31-
ret->registerModel<RandomNumberModel>("Operators");
31+
ret->registerModel<LongProcessingRandomNumber>("Operators");
3232

3333
return ret;
3434
}

examples/calculator/main.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ static std::shared_ptr<NodeDelegateModelRegistry> registerDataModels()
4141

4242
ret->registerModel<DivisionModel>("Operators");
4343

44-
ret->registerModel<RandomNumberModel>("Operators");
44+
ret->registerModel<LongProcessingRandomNumber>("Operators");
4545

4646
return ret;
4747
}

include/QtNodes/internal/DefaultNodePainter.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class NODE_EDITOR_PUBLIC DefaultNodePainter : public AbstractNodePainter
3737

3838
void drawValidationIcon(QPainter *painter, NodeGraphicsObject &ngo) const;
3939

40+
void drawProgressValue(QPainter *painter, NodeGraphicsObject &ngo) const;
41+
4042
private:
4143
QIcon _toolTipIcon{":/info-tooltip.svg"};
4244
};

include/QtNodes/internal/Definitions.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,11 @@ Q_NAMESPACE_EXPORT(NODE_EDITOR_PUBLIC)
3535
ValidationState = 11, ///< Enum NodeValidationState of the node
3636
LabelVisible = 12, ///< `bool` for label visibility.
3737
ProcessingStatus = 13, ///< Enum NodeProcessingStatus of the node
38-
Label = 14, ///< `QString` for node label.
39-
LabelEditable = 15, ///< `bool` to indicate label editing support.
38+
ProgressValue = 14, ///< 'QString' for the progress value
39+
Label = 15, ///< `QString` for node label.
40+
LabelEditable = 16, ///< `bool` to indicate label editing support.
4041
};
42+
4143
Q_ENUM_NS(NodeRole)
4244

4345
/**

include/QtNodes/internal/NodeDelegateModel.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ class NODE_EDITOR_PUBLIC NodeDelegateModel
9090
/// Returns the curent processing status
9191
virtual NodeProcessingStatus processingStatus() const { return _processingStatus; }
9292

93+
/// Progress is used in GUI
94+
virtual QString progressValue() const { return _progressValue; }
95+
96+
public:
9397
QJsonObject save() const override;
9498

9599
void load(QJsonObject const &) override;
@@ -118,6 +122,8 @@ class NODE_EDITOR_PUBLIC NodeDelegateModel
118122

119123
void setStatusIconStyle(ProcessingIconStyle const &style);
120124

125+
void setProgressValue(QString new_progress) { _progressValue = new_progress; }
126+
121127
public:
122128
virtual void setInData(std::shared_ptr<NodeData> nodeData, PortIndex const portIndex) = 0;
123129

@@ -199,6 +205,8 @@ public Q_SLOTS:
199205
NodeValidationState _nodeValidationState;
200206

201207
NodeProcessingStatus _processingStatus{NodeProcessingStatus::NoStatus};
208+
209+
QString _progressValue{QString()};
202210
};
203211

204212
} // namespace QtNodes

src/DataFlowGraphModel.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -321,6 +321,10 @@ QVariant DataFlowGraphModel::nodeData(NodeId nodeId, NodeRole role) const
321321
auto processingStatus = model->processingStatus();
322322
result = QVariant::fromValue(processingStatus);
323323
} break;
324+
325+
case NodeRole::ProgressValue:
326+
result = model->progressValue();
327+
break;
324328
}
325329

326330
return result;
@@ -415,6 +419,9 @@ bool DataFlowGraphModel::setNodeData(NodeId nodeId, NodeRole role, QVariant valu
415419

416420
case NodeRole::LabelEditable:
417421
break;
422+
423+
case NodeRole::ProgressValue:
424+
break;
418425
}
419426

420427
return result;

src/DefaultNodePainter.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ void DefaultNodePainter::paint(QPainter *painter, NodeGraphicsObject &ngo) const
4040
drawNodeLabel(painter, ngo);
4141

4242
drawValidationIcon(painter, ngo);
43+
44+
drawProgressValue(painter, ngo);
4345
}
4446

4547
void DefaultNodePainter::drawNodeRect(QPainter *painter, NodeGraphicsObject &ngo) const
@@ -431,4 +433,31 @@ void DefaultNodePainter::drawValidationIcon(QPainter *painter, NodeGraphicsObjec
431433
pixmap);
432434
}
433435

436+
void DefaultNodePainter::drawProgressValue(QPainter *painter, NodeGraphicsObject &ngo) const
437+
{
438+
AbstractGraphModel &model = ngo.graphModel();
439+
NodeId const nodeId = ngo.nodeId();
440+
AbstractNodeGeometry &geometry = ngo.nodeScene()->nodeGeometry();
441+
442+
QString const nodeProgress = model.nodeData(nodeId, NodeRole::ProgressValue).toString();
443+
444+
QFont font = painter->font();
445+
font.setBold(true);
446+
font.setPointSize(7);
447+
auto rect = QFontMetrics(font).boundingRect(nodeProgress);
448+
449+
QSize size = geometry.size(nodeId);
450+
QPointF position(rect.width() / 1.5, size.height() - 1.0 * rect.height());
451+
452+
QJsonDocument json = QJsonDocument::fromVariant(model.nodeData(nodeId, NodeRole::Style));
453+
NodeStyle nodeStyle(json.object());
454+
455+
painter->setFont(font);
456+
painter->setPen(nodeStyle.FontColor);
457+
painter->drawText(position, nodeProgress);
458+
459+
font.setBold(false);
460+
painter->setFont(font);
461+
}
462+
434463
} // namespace QtNodes

0 commit comments

Comments
 (0)