##// END OF EJS Templates
Move Common MIME types constants in a Definition file in core module.
trabillard -
r850:3715d1ed451c
parent child
Show More
@@ -0,0 +1,18
1 #ifndef SCIQLOP_MIMETYPESDEF_H
2 #define SCIQLOP_MIMETYPESDEF_H
3
4 #include "CoreGlobal.h"
5
6 #include <QString>
7
8 // ////////////////// //
9 // SciQlop Mime Types //
10 // ////////////////// //
11
12 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_GRAPH;
13 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE;
14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
16
17
18 #endif // SCIQLOP_MIMETYPESDEF_H
@@ -0,0 +1,6
1 #include "Common/MimeTypesDef.h"
2
3 const QString MIME_TYPE_GRAPH = QStringLiteral("scqlop/graph");
4 const QString MIME_TYPE_ZONE = QStringLiteral("scqlop/zone");
5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("scqlop/var-list");
6 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("scqlop/time-range");
@@ -1,230 +1,227
1 #include "DragDropHelper.h"
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragWidget.h"
3 #include "Visualization/VisualizationDragWidget.h"
4
4
5 #include <QDir>
5 #include <QDir>
6 #include <QDragEnterEvent>
6 #include <QDragEnterEvent>
7 #include <QDragMoveEvent>
7 #include <QDragMoveEvent>
8 #include <QScrollArea>
8 #include <QScrollArea>
9 #include <QScrollBar>
9 #include <QScrollBar>
10 #include <QTimer>
10 #include <QTimer>
11 #include <QVBoxLayout>
11 #include <QVBoxLayout>
12
12
13 const QString DragDropHelper::MIME_TYPE_GRAPH = "scqlop/graph";
14 const QString DragDropHelper::MIME_TYPE_ZONE = "scqlop/zone";
15
16 const int SCROLL_SPEED = 5;
13 const int SCROLL_SPEED = 5;
17 const int SCROLL_ZONE_SIZE = 50;
14 const int SCROLL_ZONE_SIZE = 50;
18
15
19 struct DragDropScroller::DragDropScrollerPrivate {
16 struct DragDropScroller::DragDropScrollerPrivate {
20
17
21 QList<QScrollArea *> m_ScrollAreas;
18 QList<QScrollArea *> m_ScrollAreas;
22 QScrollArea *m_CurrentScrollArea = nullptr;
19 QScrollArea *m_CurrentScrollArea = nullptr;
23 std::unique_ptr<QTimer> m_Timer = nullptr;
20 std::unique_ptr<QTimer> m_Timer = nullptr;
24
21
25
22
26 enum class ScrollDirection { up, down, unknown };
23 enum class ScrollDirection { up, down, unknown };
27 ScrollDirection m_Direction = ScrollDirection::unknown;
24 ScrollDirection m_Direction = ScrollDirection::unknown;
28
25
29 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
26 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
30 {
27 {
31 m_Timer->setInterval(0);
28 m_Timer->setInterval(0);
32 }
29 }
33 };
30 };
34
31
35 DragDropScroller::DragDropScroller(QObject *parent)
32 DragDropScroller::DragDropScroller(QObject *parent)
36 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
33 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
37 {
34 {
38 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
35 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
39 }
36 }
40
37
41 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
38 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
42 {
39 {
43 impl->m_ScrollAreas << scrollArea;
40 impl->m_ScrollAreas << scrollArea;
44 scrollArea->viewport()->setAcceptDrops(true);
41 scrollArea->viewport()->setAcceptDrops(true);
45 }
42 }
46
43
47 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
44 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
48 {
45 {
49 impl->m_ScrollAreas.removeAll(scrollArea);
46 impl->m_ScrollAreas.removeAll(scrollArea);
50 scrollArea->viewport()->setAcceptDrops(false);
47 scrollArea->viewport()->setAcceptDrops(false);
51 }
48 }
52
49
53 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
50 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
54 {
51 {
55 if (event->type() == QEvent::DragMove) {
52 if (event->type() == QEvent::DragMove) {
56 auto w = static_cast<QWidget *>(obj);
53 auto w = static_cast<QWidget *>(obj);
57
54
58 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
55 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
59 auto moveEvent = static_cast<QDragMoveEvent *>(event);
56 auto moveEvent = static_cast<QDragMoveEvent *>(event);
60
57
61 auto pos = moveEvent->pos();
58 auto pos = moveEvent->pos();
62 if (impl->m_CurrentScrollArea->viewport() != w) {
59 if (impl->m_CurrentScrollArea->viewport() != w) {
63 auto globalPos = w->mapToGlobal(moveEvent->pos());
60 auto globalPos = w->mapToGlobal(moveEvent->pos());
64 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
61 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
65 }
62 }
66
63
67 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
64 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
68 - SCROLL_ZONE_SIZE;
65 - SCROLL_ZONE_SIZE;
69 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
66 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
70
67
71 if (!isInTopZone && !isInBottomZone) {
68 if (!isInTopZone && !isInBottomZone) {
72 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
69 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
73 impl->m_Timer->stop();
70 impl->m_Timer->stop();
74 }
71 }
75 else if (!impl->m_Timer->isActive()) {
72 else if (!impl->m_Timer->isActive()) {
76 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
73 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
77 : DragDropScrollerPrivate::ScrollDirection::down;
74 : DragDropScrollerPrivate::ScrollDirection::down;
78 impl->m_Timer->start();
75 impl->m_Timer->start();
79 }
76 }
80 }
77 }
81 }
78 }
82 else if (event->type() == QEvent::DragEnter) {
79 else if (event->type() == QEvent::DragEnter) {
83 auto w = static_cast<QWidget *>(obj);
80 auto w = static_cast<QWidget *>(obj);
84
81
85 for (auto scrollArea : impl->m_ScrollAreas) {
82 for (auto scrollArea : impl->m_ScrollAreas) {
86 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
83 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
87 auto enterEvent = static_cast<QDragEnterEvent *>(event);
84 auto enterEvent = static_cast<QDragEnterEvent *>(event);
88 enterEvent->acceptProposedAction();
85 enterEvent->acceptProposedAction();
89 enterEvent->setDropAction(Qt::IgnoreAction);
86 enterEvent->setDropAction(Qt::IgnoreAction);
90 impl->m_CurrentScrollArea = scrollArea;
87 impl->m_CurrentScrollArea = scrollArea;
91 break;
88 break;
92 }
89 }
93 }
90 }
94 }
91 }
95 else if (event->type() == QEvent::DragLeave) {
92 else if (event->type() == QEvent::DragLeave) {
96 if (impl->m_CurrentScrollArea) {
93 if (impl->m_CurrentScrollArea) {
97 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
94 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
98 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
95 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
99 impl->m_CurrentScrollArea = nullptr;
96 impl->m_CurrentScrollArea = nullptr;
100 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
97 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
101 impl->m_Timer->stop();
98 impl->m_Timer->stop();
102 }
99 }
103 }
100 }
104 }
101 }
105 else if (event->type() == QEvent::Drop) {
102 else if (event->type() == QEvent::Drop) {
106 if (impl->m_CurrentScrollArea) {
103 if (impl->m_CurrentScrollArea) {
107 impl->m_CurrentScrollArea = nullptr;
104 impl->m_CurrentScrollArea = nullptr;
108 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
105 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
109 impl->m_Timer->stop();
106 impl->m_Timer->stop();
110 }
107 }
111 }
108 }
112
109
113 return false;
110 return false;
114 }
111 }
115
112
116 void DragDropScroller::onTimer()
113 void DragDropScroller::onTimer()
117 {
114 {
118 if (impl->m_CurrentScrollArea) {
115 if (impl->m_CurrentScrollArea) {
119 auto mvt = 0;
116 auto mvt = 0;
120 switch (impl->m_Direction) {
117 switch (impl->m_Direction) {
121 case DragDropScrollerPrivate::ScrollDirection::up:
118 case DragDropScrollerPrivate::ScrollDirection::up:
122 mvt = SCROLL_SPEED;
119 mvt = SCROLL_SPEED;
123 break;
120 break;
124 case DragDropScrollerPrivate::ScrollDirection::down:
121 case DragDropScrollerPrivate::ScrollDirection::down:
125 mvt = -SCROLL_SPEED;
122 mvt = -SCROLL_SPEED;
126 break;
123 break;
127 default:
124 default:
128 break;
125 break;
129 }
126 }
130
127
131 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
128 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
132 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
129 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
133 }
130 }
134 }
131 }
135
132
136 struct DragDropHelper::DragDropHelperPrivate {
133 struct DragDropHelper::DragDropHelperPrivate {
137
134
138 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
135 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
139 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
136 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
140 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
137 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
141 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
138 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
142 // QTemporaryFile to have a name which is not generated.
139 // QTemporaryFile to have a name which is not generated.
143
140
144 explicit DragDropHelperPrivate()
141 explicit DragDropHelperPrivate()
145 : m_PlaceHolder{std::make_unique<QWidget>()},
142 : m_PlaceHolder{std::make_unique<QWidget>()},
146 m_DragDropScroller{std::make_unique<DragDropScroller>()}
143 m_DragDropScroller{std::make_unique<DragDropScroller>()}
147 {
144 {
148 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
145 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
149 sqpApp->installEventFilter(m_DragDropScroller.get());
146 sqpApp->installEventFilter(m_DragDropScroller.get());
150
147
151
148
152 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
149 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
153 }
150 }
154
151
155 void preparePlaceHolder() const
152 void preparePlaceHolder() const
156 {
153 {
157 if (m_CurrentDragWidget) {
154 if (m_CurrentDragWidget) {
158 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
155 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
159 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
156 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
160 }
157 }
161 else {
158 else {
162 m_PlaceHolder->setMinimumSize(200, 200);
159 m_PlaceHolder->setMinimumSize(200, 200);
163 }
160 }
164 }
161 }
165 };
162 };
166
163
167
164
168 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
165 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
169 {
166 {
170 }
167 }
171
168
172 DragDropHelper::~DragDropHelper()
169 DragDropHelper::~DragDropHelper()
173 {
170 {
174 QFile::remove(impl->m_ImageTempUrl);
171 QFile::remove(impl->m_ImageTempUrl);
175 }
172 }
176
173
177 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
174 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
178 {
175 {
179 impl->m_CurrentDragWidget = dragWidget;
176 impl->m_CurrentDragWidget = dragWidget;
180 }
177 }
181
178
182 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
179 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
183 {
180 {
184 return impl->m_CurrentDragWidget;
181 return impl->m_CurrentDragWidget;
185 }
182 }
186
183
187
184
188 QWidget &DragDropHelper::placeHolder() const
185 QWidget &DragDropHelper::placeHolder() const
189 {
186 {
190 return *impl->m_PlaceHolder;
187 return *impl->m_PlaceHolder;
191 }
188 }
192
189
193 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
190 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
194 {
191 {
195 removePlaceHolder();
192 removePlaceHolder();
196 impl->preparePlaceHolder();
193 impl->preparePlaceHolder();
197 layout->insertWidget(index, impl->m_PlaceHolder.get());
194 layout->insertWidget(index, impl->m_PlaceHolder.get());
198 impl->m_PlaceHolder->show();
195 impl->m_PlaceHolder->show();
199 }
196 }
200
197
201 void DragDropHelper::removePlaceHolder()
198 void DragDropHelper::removePlaceHolder()
202 {
199 {
203 auto parentWidget = impl->m_PlaceHolder->parentWidget();
200 auto parentWidget = impl->m_PlaceHolder->parentWidget();
204 if (parentWidget) {
201 if (parentWidget) {
205 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
202 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
206 impl->m_PlaceHolder->setParent(nullptr);
203 impl->m_PlaceHolder->setParent(nullptr);
207 impl->m_PlaceHolder->hide();
204 impl->m_PlaceHolder->hide();
208 }
205 }
209 }
206 }
210
207
211 bool DragDropHelper::isPlaceHolderSet() const
208 bool DragDropHelper::isPlaceHolderSet() const
212 {
209 {
213 return impl->m_PlaceHolder->parentWidget();
210 return impl->m_PlaceHolder->parentWidget();
214 }
211 }
215
212
216 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
213 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
217 {
214 {
218 impl->m_DragDropScroller->addScrollArea(scrollArea);
215 impl->m_DragDropScroller->addScrollArea(scrollArea);
219 }
216 }
220
217
221 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
218 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
222 {
219 {
223 impl->m_DragDropScroller->removeScrollArea(scrollArea);
220 impl->m_DragDropScroller->removeScrollArea(scrollArea);
224 }
221 }
225
222
226 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
223 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
227 {
224 {
228 image.save(impl->m_ImageTempUrl);
225 image.save(impl->m_ImageTempUrl);
229 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
226 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
230 }
227 }
@@ -1,384 +1,385
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Common/MimeTypesDef.h>
9 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
10 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
11 #include <DragDropHelper.h>
12 #include <DragDropHelper.h>
12 #include <Settings/SqpSettingsDefs.h>
13 #include <Settings/SqpSettingsDefs.h>
13 #include <SqpApplication.h>
14 #include <SqpApplication.h>
14 #include <Variable/Variable.h>
15 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
16 #include <Variable/VariableController.h>
16
17
17 #include <unordered_map>
18 #include <unordered_map>
18
19
19 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
20 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
20
21
21 namespace {
22 namespace {
22
23
23 /// Key pressed to enable zoom on horizontal axis
24 /// Key pressed to enable zoom on horizontal axis
24 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
25 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
25
26
26 /// Key pressed to enable zoom on vertical axis
27 /// Key pressed to enable zoom on vertical axis
27 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
28 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
28
29
29 } // namespace
30 } // namespace
30
31
31 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
32 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
32
33
33 explicit VisualizationGraphWidgetPrivate(const QString &name)
34 explicit VisualizationGraphWidgetPrivate(const QString &name)
34 : m_Name{name},
35 : m_Name{name},
35 m_DoAcquisition{true},
36 m_DoAcquisition{true},
36 m_IsCalibration{false},
37 m_IsCalibration{false},
37 m_RenderingDelegate{nullptr}
38 m_RenderingDelegate{nullptr}
38 {
39 {
39 }
40 }
40
41
41 QString m_Name;
42 QString m_Name;
42 // 1 variable -> n qcpplot
43 // 1 variable -> n qcpplot
43 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
44 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
44 bool m_DoAcquisition;
45 bool m_DoAcquisition;
45 bool m_IsCalibration;
46 bool m_IsCalibration;
46 QCPItemTracer *m_TextTracer;
47 QCPItemTracer *m_TextTracer;
47 /// Delegate used to attach rendering features to the plot
48 /// Delegate used to attach rendering features to the plot
48 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 };
50 };
50
51
51 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 : VisualizationDragWidget{parent},
53 : VisualizationDragWidget{parent},
53 ui{new Ui::VisualizationGraphWidget},
54 ui{new Ui::VisualizationGraphWidget},
54 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 {
56 {
56 ui->setupUi(this);
57 ui->setupUi(this);
57
58
58 // 'Close' options : widget is deleted when closed
59 // 'Close' options : widget is deleted when closed
59 setAttribute(Qt::WA_DeleteOnClose);
60 setAttribute(Qt::WA_DeleteOnClose);
60
61
61 // Set qcpplot properties :
62 // Set qcpplot properties :
62 // - Drag (on x-axis) and zoom are enabled
63 // - Drag (on x-axis) and zoom are enabled
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66
67
67 // The delegate must be initialized after the ui as it uses the plot
68 // The delegate must be initialized after the ui as it uses the plot
68 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69
70
70 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 &VisualizationGraphWidget::onMouseRelease);
73 &VisualizationGraphWidget::onMouseRelease);
73 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 &QCPAxis::rangeChanged),
77 &QCPAxis::rangeChanged),
77 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
78
79
79 // Activates menu when right clicking on the graph
80 // Activates menu when right clicking on the graph
80 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
81 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
82 &VisualizationGraphWidget::onGraphMenuRequested);
83 &VisualizationGraphWidget::onGraphMenuRequested);
83
84
84 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
85 &VariableController::onRequestDataLoading);
86 &VariableController::onRequestDataLoading);
86
87
87 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
88 &VisualizationGraphWidget::onUpdateVarDisplaying);
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
89 }
90 }
90
91
91
92
92 VisualizationGraphWidget::~VisualizationGraphWidget()
93 VisualizationGraphWidget::~VisualizationGraphWidget()
93 {
94 {
94 delete ui;
95 delete ui;
95 }
96 }
96
97
97 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 {
99 {
99 auto parent = parentWidget();
100 auto parent = parentWidget();
100 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 parent = parent->parentWidget();
102 parent = parent->parentWidget();
102 }
103 }
103
104
104 return qobject_cast<VisualizationZoneWidget *>(parent);
105 return qobject_cast<VisualizationZoneWidget *>(parent);
105 }
106 }
106
107
107 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 {
109 {
109 impl->m_DoAcquisition = enable;
110 impl->m_DoAcquisition = enable;
110 }
111 }
111
112
112 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
113 {
114 {
114 // Uses delegate to create the qcpplot components according to the variable
115 // Uses delegate to create the qcpplot components according to the variable
115 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
117
118
118 // Set axes properties according to the units of the data series
119 // Set axes properties according to the units of the data series
119 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
120 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
120 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
121 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
121 auto xAxisUnit = Unit{};
122 auto xAxisUnit = Unit{};
122 auto valuesUnit = Unit{};
123 auto valuesUnit = Unit{};
123
124
124 if (auto dataSeries = variable->dataSeries()) {
125 if (auto dataSeries = variable->dataSeries()) {
125 dataSeries->lockRead();
126 dataSeries->lockRead();
126 xAxisUnit = dataSeries->xAxisUnit();
127 xAxisUnit = dataSeries->xAxisUnit();
127 valuesUnit = dataSeries->valuesUnit();
128 valuesUnit = dataSeries->valuesUnit();
128 dataSeries->unlock();
129 dataSeries->unlock();
129 }
130 }
130 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
131
132
132 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
133
134
134 this->enableAcquisition(false);
135 this->enableAcquisition(false);
135 this->setGraphRange(range);
136 this->setGraphRange(range);
136 this->enableAcquisition(true);
137 this->enableAcquisition(true);
137
138
138 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
139
140
140 emit variableAdded(variable);
141 emit variableAdded(variable);
141 }
142 }
142
143
143 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
144 {
145 {
145 // Each component associated to the variable :
146 // Each component associated to the variable :
146 // - is removed from qcpplot (which deletes it)
147 // - is removed from qcpplot (which deletes it)
147 // - is no longer referenced in the map
148 // - is no longer referenced in the map
148 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
149 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
150 emit variableAboutToBeRemoved(variable);
151 emit variableAboutToBeRemoved(variable);
151
152
152 auto &plottablesMap = variableIt->second;
153 auto &plottablesMap = variableIt->second;
153
154
154 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
155 plottableIt != plottableEnd;) {
156 plottableIt != plottableEnd;) {
156 ui->widget->removePlottable(plottableIt->second);
157 ui->widget->removePlottable(plottableIt->second);
157 plottableIt = plottablesMap.erase(plottableIt);
158 plottableIt = plottablesMap.erase(plottableIt);
158 }
159 }
159
160
160 impl->m_VariableToPlotMultiMap.erase(variableIt);
161 impl->m_VariableToPlotMultiMap.erase(variableIt);
161 }
162 }
162
163
163 // Updates graph
164 // Updates graph
164 ui->widget->replot();
165 ui->widget->replot();
165 }
166 }
166
167
167 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
168 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
168 {
169 {
169 auto variables = QList<std::shared_ptr<Variable> >{};
170 auto variables = QList<std::shared_ptr<Variable> >{};
170 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
171 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
172 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
172 variables << it->first;
173 variables << it->first;
173 }
174 }
174
175
175 return variables;
176 return variables;
176 }
177 }
177
178
178 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 {
180 {
180 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 }
182 }
182
183
183 SqpRange VisualizationGraphWidget::graphRange() const noexcept
184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
184 {
185 {
185 auto graphRange = ui->widget->xAxis->range();
186 auto graphRange = ui->widget->xAxis->range();
186 return SqpRange{graphRange.lower, graphRange.upper};
187 return SqpRange{graphRange.lower, graphRange.upper};
187 }
188 }
188
189
189 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
190 {
191 {
191 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
192 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
193 ui->widget->replot();
194 ui->widget->replot();
194 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
195 }
196 }
196
197
197 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
198 {
199 {
199 if (visitor) {
200 if (visitor) {
200 visitor->visit(this);
201 visitor->visit(this);
201 }
202 }
202 else {
203 else {
203 qCCritical(LOG_VisualizationGraphWidget())
204 qCCritical(LOG_VisualizationGraphWidget())
204 << tr("Can't visit widget : the visitor is null");
205 << tr("Can't visit widget : the visitor is null");
205 }
206 }
206 }
207 }
207
208
208 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
209 {
210 {
210 /// @todo : for the moment, a graph can always accomodate a variable
211 /// @todo : for the moment, a graph can always accomodate a variable
211 Q_UNUSED(variable);
212 Q_UNUSED(variable);
212 return true;
213 return true;
213 }
214 }
214
215
215 bool VisualizationGraphWidget::contains(const Variable &variable) const
216 bool VisualizationGraphWidget::contains(const Variable &variable) const
216 {
217 {
217 // Finds the variable among the keys of the map
218 // Finds the variable among the keys of the map
218 auto variablePtr = &variable;
219 auto variablePtr = &variable;
219 auto findVariable
220 auto findVariable
220 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
221
222
222 auto end = impl->m_VariableToPlotMultiMap.cend();
223 auto end = impl->m_VariableToPlotMultiMap.cend();
223 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
224 return it != end;
225 return it != end;
225 }
226 }
226
227
227 QString VisualizationGraphWidget::name() const
228 QString VisualizationGraphWidget::name() const
228 {
229 {
229 return impl->m_Name;
230 return impl->m_Name;
230 }
231 }
231
232
232 QMimeData *VisualizationGraphWidget::mimeData() const
233 QMimeData *VisualizationGraphWidget::mimeData() const
233 {
234 {
234 auto mimeData = new QMimeData;
235 auto mimeData = new QMimeData;
235 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
236 mimeData->setData(MIME_TYPE_GRAPH, QByteArray());
236
237
237 return mimeData;
238 return mimeData;
238 }
239 }
239
240
240 bool VisualizationGraphWidget::isDragAllowed() const
241 bool VisualizationGraphWidget::isDragAllowed() const
241 {
242 {
242 return true;
243 return true;
243 }
244 }
244
245
245 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
246 {
247 {
247 Q_UNUSED(event);
248 Q_UNUSED(event);
248
249
249 // Prevents that all variables will be removed from graph when it will be closed
250 // Prevents that all variables will be removed from graph when it will be closed
250 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
251 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
251 emit variableAboutToBeRemoved(variableEntry.first);
252 emit variableAboutToBeRemoved(variableEntry.first);
252 }
253 }
253 }
254 }
254
255
255 void VisualizationGraphWidget::enterEvent(QEvent *event)
256 void VisualizationGraphWidget::enterEvent(QEvent *event)
256 {
257 {
257 Q_UNUSED(event);
258 Q_UNUSED(event);
258 impl->m_RenderingDelegate->showGraphOverlay(true);
259 impl->m_RenderingDelegate->showGraphOverlay(true);
259 }
260 }
260
261
261 void VisualizationGraphWidget::leaveEvent(QEvent *event)
262 void VisualizationGraphWidget::leaveEvent(QEvent *event)
262 {
263 {
263 Q_UNUSED(event);
264 Q_UNUSED(event);
264 impl->m_RenderingDelegate->showGraphOverlay(false);
265 impl->m_RenderingDelegate->showGraphOverlay(false);
265 }
266 }
266
267
267 QCustomPlot &VisualizationGraphWidget::plot() noexcept
268 QCustomPlot &VisualizationGraphWidget::plot() noexcept
268 {
269 {
269 return *ui->widget;
270 return *ui->widget;
270 }
271 }
271
272
272 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
273 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
273 {
274 {
274 QMenu graphMenu{};
275 QMenu graphMenu{};
275
276
276 // Iterates on variables (unique keys)
277 // Iterates on variables (unique keys)
277 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
278 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
278 end = impl->m_VariableToPlotMultiMap.cend();
279 end = impl->m_VariableToPlotMultiMap.cend();
279 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
280 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
280 // 'Remove variable' action
281 // 'Remove variable' action
281 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
282 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
282 [ this, var = it->first ]() { removeVariable(var); });
283 [ this, var = it->first ]() { removeVariable(var); });
283 }
284 }
284
285
285 if (!graphMenu.isEmpty()) {
286 if (!graphMenu.isEmpty()) {
286 graphMenu.exec(QCursor::pos());
287 graphMenu.exec(QCursor::pos());
287 }
288 }
288 }
289 }
289
290
290 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
291 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
291 {
292 {
292 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
293 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
293 << QThread::currentThread()->objectName() << "DoAcqui"
294 << QThread::currentThread()->objectName() << "DoAcqui"
294 << impl->m_DoAcquisition;
295 << impl->m_DoAcquisition;
295
296
296 auto graphRange = SqpRange{t1.lower, t1.upper};
297 auto graphRange = SqpRange{t1.lower, t1.upper};
297 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
298 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
298
299
299 if (impl->m_DoAcquisition) {
300 if (impl->m_DoAcquisition) {
300 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
301 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
301
302
302 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
303 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
303 end = impl->m_VariableToPlotMultiMap.end();
304 end = impl->m_VariableToPlotMultiMap.end();
304 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
305 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
305 variableUnderGraphVector.push_back(it->first);
306 variableUnderGraphVector.push_back(it->first);
306 }
307 }
307 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
308 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
308 !impl->m_IsCalibration);
309 !impl->m_IsCalibration);
309
310
310 if (!impl->m_IsCalibration) {
311 if (!impl->m_IsCalibration) {
311 qCDebug(LOG_VisualizationGraphWidget())
312 qCDebug(LOG_VisualizationGraphWidget())
312 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
313 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
313 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
314 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
314 emit synchronize(graphRange, oldGraphRange);
315 emit synchronize(graphRange, oldGraphRange);
315 }
316 }
316 }
317 }
317 }
318 }
318
319
319 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
320 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
320 {
321 {
321 // Handles plot rendering when mouse is moving
322 // Handles plot rendering when mouse is moving
322 impl->m_RenderingDelegate->onMouseMove(event);
323 impl->m_RenderingDelegate->onMouseMove(event);
323
324
324 VisualizationDragWidget::mouseMoveEvent(event);
325 VisualizationDragWidget::mouseMoveEvent(event);
325 }
326 }
326
327
327 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
328 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
328 {
329 {
329 auto zoomOrientations = QFlags<Qt::Orientation>{};
330 auto zoomOrientations = QFlags<Qt::Orientation>{};
330
331
331 // Lambda that enables a zoom orientation if the key modifier related to this orientation
332 // Lambda that enables a zoom orientation if the key modifier related to this orientation
332 // has
333 // has
333 // been pressed
334 // been pressed
334 auto enableOrientation
335 auto enableOrientation
335 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
336 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
336 auto orientationEnabled = event->modifiers().testFlag(modifier);
337 auto orientationEnabled = event->modifiers().testFlag(modifier);
337 zoomOrientations.setFlag(orientation, orientationEnabled);
338 zoomOrientations.setFlag(orientation, orientationEnabled);
338 };
339 };
339 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
340 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
340 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
341 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
341
342
342 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
343 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
343 }
344 }
344
345
345 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
346 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
346 {
347 {
347 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
348 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
348
349
349 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
350 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
350
351
351 VisualizationDragWidget::mousePressEvent(event);
352 VisualizationDragWidget::mousePressEvent(event);
352 }
353 }
353
354
354 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
355 {
356 {
356 impl->m_IsCalibration = false;
357 impl->m_IsCalibration = false;
357 }
358 }
358
359
359 void VisualizationGraphWidget::onDataCacheVariableUpdated()
360 void VisualizationGraphWidget::onDataCacheVariableUpdated()
360 {
361 {
361 auto graphRange = ui->widget->xAxis->range();
362 auto graphRange = ui->widget->xAxis->range();
362 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
363 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
363
364
364 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
365 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
365 auto variable = variableEntry.first;
366 auto variable = variableEntry.first;
366 qCDebug(LOG_VisualizationGraphWidget())
367 qCDebug(LOG_VisualizationGraphWidget())
367 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
368 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
368 qCDebug(LOG_VisualizationGraphWidget())
369 qCDebug(LOG_VisualizationGraphWidget())
369 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
370 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
371 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
371 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
372 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
372 variable->range());
373 variable->range());
373 }
374 }
374 }
375 }
375 }
376 }
376
377
377 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
378 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
378 const SqpRange &range)
379 const SqpRange &range)
379 {
380 {
380 auto it = impl->m_VariableToPlotMultiMap.find(variable);
381 auto it = impl->m_VariableToPlotMultiMap.find(variable);
381 if (it != impl->m_VariableToPlotMultiMap.end()) {
382 if (it != impl->m_VariableToPlotMultiMap.end()) {
382 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
383 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
383 }
384 }
384 }
385 }
@@ -1,219 +1,220
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Variable/VariableController.h"
8 #include "Variable/VariableController.h"
9
9
10 #include "Common/MimeTypesDef.h"
11
10 #include "DragDropHelper.h"
12 #include "DragDropHelper.h"
11 #include "SqpApplication.h"
13 #include "SqpApplication.h"
12
14
13 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
14
16
15 namespace {
17 namespace {
16
18
17 /// Generates a default name for a new zone, according to the number of zones already displayed in
19 /// Generates a default name for a new zone, according to the number of zones already displayed in
18 /// the tab
20 /// the tab
19 QString defaultZoneName(const QLayout &layout)
21 QString defaultZoneName(const QLayout &layout)
20 {
22 {
21 auto count = 0;
23 auto count = 0;
22 for (auto i = 0; i < layout.count(); ++i) {
24 for (auto i = 0; i < layout.count(); ++i) {
23 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
25 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
24 count++;
26 count++;
25 }
27 }
26 }
28 }
27
29
28 return QObject::tr("Zone %1").arg(count + 1);
30 return QObject::tr("Zone %1").arg(count + 1);
29 }
31 }
30
32
31 /**
33 /**
32 * Applies a function to all zones of the tab represented by its layout
34 * Applies a function to all zones of the tab represented by its layout
33 * @param layout the layout that contains zones
35 * @param layout the layout that contains zones
34 * @param fun the function to apply to each zone
36 * @param fun the function to apply to each zone
35 */
37 */
36 template <typename Fun>
38 template <typename Fun>
37 void processZones(QLayout &layout, Fun fun)
39 void processZones(QLayout &layout, Fun fun)
38 {
40 {
39 for (auto i = 0; i < layout.count(); ++i) {
41 for (auto i = 0; i < layout.count(); ++i) {
40 if (auto item = layout.itemAt(i)) {
42 if (auto item = layout.itemAt(i)) {
41 if (auto visualizationZoneWidget
43 if (auto visualizationZoneWidget
42 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
44 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
43 fun(*visualizationZoneWidget);
45 fun(*visualizationZoneWidget);
44 }
46 }
45 }
47 }
46 }
48 }
47 }
49 }
48
50
49 } // namespace
51 } // namespace
50
52
51 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
53 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
52 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
53
55
54 QString m_Name;
56 QString m_Name;
55 };
57 };
56
58
57 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
59 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
58 : QWidget{parent},
60 : QWidget{parent},
59 ui{new Ui::VisualizationTabWidget},
61 ui{new Ui::VisualizationTabWidget},
60 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
62 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
61 {
63 {
62 ui->setupUi(this);
64 ui->setupUi(this);
63
65
64 ui->dragDropContainer->setAcceptedMimeTypes(
66 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_ZONE});
65 {DragDropHelper::MIME_TYPE_GRAPH, DragDropHelper::MIME_TYPE_ZONE});
66 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
67 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
67 &VisualizationTabWidget::dropMimeData);
68 &VisualizationTabWidget::dropMimeData);
68 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
69 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
69
70
70 // Widget is deleted when closed
71 // Widget is deleted when closed
71 setAttribute(Qt::WA_DeleteOnClose);
72 setAttribute(Qt::WA_DeleteOnClose);
72 }
73 }
73
74
74 VisualizationTabWidget::~VisualizationTabWidget()
75 VisualizationTabWidget::~VisualizationTabWidget()
75 {
76 {
76 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
77 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
77 delete ui;
78 delete ui;
78 }
79 }
79
80
80 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
81 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
81 {
82 {
82 ui->dragDropContainer->addDragWidget(zoneWidget);
83 ui->dragDropContainer->addDragWidget(zoneWidget);
83 }
84 }
84
85
85 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
86 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
86 {
87 {
87 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
88 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
88 }
89 }
89
90
90 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
91 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
91 {
92 {
92 return createZone({variable}, -1);
93 return createZone({variable}, -1);
93 }
94 }
94
95
95 VisualizationZoneWidget *
96 VisualizationZoneWidget *
96 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
97 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
97 {
98 {
98 auto zoneWidget = createEmptyZone(index);
99 auto zoneWidget = createEmptyZone(index);
99
100
100 // Creates a new graph into the zone
101 // Creates a new graph into the zone
101 zoneWidget->createGraph(variables, index);
102 zoneWidget->createGraph(variables, index);
102
103
103 return zoneWidget;
104 return zoneWidget;
104 }
105 }
105
106
106 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
107 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
107 {
108 {
108 auto zoneWidget
109 auto zoneWidget
109 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
110 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
110 this->insertZone(index, zoneWidget);
111 this->insertZone(index, zoneWidget);
111
112
112 return zoneWidget;
113 return zoneWidget;
113 }
114 }
114
115
115 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
116 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
116 {
117 {
117 if (visitor) {
118 if (visitor) {
118 visitor->visitEnter(this);
119 visitor->visitEnter(this);
119
120
120 // Apply visitor to zone children: widgets different from zones are not visited (no action)
121 // Apply visitor to zone children: widgets different from zones are not visited (no action)
121 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
122 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
122 zoneWidget.accept(visitor);
123 zoneWidget.accept(visitor);
123 });
124 });
124
125
125 visitor->visitLeave(this);
126 visitor->visitLeave(this);
126 }
127 }
127 else {
128 else {
128 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
129 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
129 }
130 }
130 }
131 }
131
132
132 bool VisualizationTabWidget::canDrop(const Variable &variable) const
133 bool VisualizationTabWidget::canDrop(const Variable &variable) const
133 {
134 {
134 // A tab can always accomodate a variable
135 // A tab can always accomodate a variable
135 Q_UNUSED(variable);
136 Q_UNUSED(variable);
136 return true;
137 return true;
137 }
138 }
138
139
139 bool VisualizationTabWidget::contains(const Variable &variable) const
140 bool VisualizationTabWidget::contains(const Variable &variable) const
140 {
141 {
141 Q_UNUSED(variable);
142 Q_UNUSED(variable);
142 return false;
143 return false;
143 }
144 }
144
145
145 QString VisualizationTabWidget::name() const
146 QString VisualizationTabWidget::name() const
146 {
147 {
147 return impl->m_Name;
148 return impl->m_Name;
148 }
149 }
149
150
150 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
151 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
151 {
152 {
152 // Closes zones in the tab
153 // Closes zones in the tab
153 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
154 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
154
155
155 QWidget::closeEvent(event);
156 QWidget::closeEvent(event);
156 }
157 }
157
158
158 QLayout &VisualizationTabWidget::tabLayout() const noexcept
159 QLayout &VisualizationTabWidget::tabLayout() const noexcept
159 {
160 {
160 return *ui->dragDropContainer->layout();
161 return *ui->dragDropContainer->layout();
161 }
162 }
162
163
163 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
164 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
164 {
165 {
165 auto &helper = sqpApp->dragDropHelper();
166 auto &helper = sqpApp->dragDropHelper();
166 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
167 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
167 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
168 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
168 auto parentDragDropContainer
169 auto parentDragDropContainer
169 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
170 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
170 Q_ASSERT(parentDragDropContainer);
171 Q_ASSERT(parentDragDropContainer);
171
172
172 auto nbGraph = parentDragDropContainer->countDragWidget();
173 auto nbGraph = parentDragDropContainer->countDragWidget();
173
174
174 const auto &variables = graphWidget->variables();
175 const auto &variables = graphWidget->variables();
175
176
176 if (!variables.isEmpty()) {
177 if (!variables.isEmpty()) {
177 // Abort the requests for the variables (if any)
178 // Abort the requests for the variables (if any)
178 // Commented, because it's not sure if it's needed or not
179 // Commented, because it's not sure if it's needed or not
179 // for (const auto& var : variables)
180 // for (const auto& var : variables)
180 //{
181 //{
181 // sqpApp->variableController().onAbortProgressRequested(var);
182 // sqpApp->variableController().onAbortProgressRequested(var);
182 //}
183 //}
183
184
184 if (nbGraph == 1) {
185 if (nbGraph == 1) {
185 // This is the only graph in the previous zone, close the zone
186 // This is the only graph in the previous zone, close the zone
186 graphWidget->parentZoneWidget()->close();
187 graphWidget->parentZoneWidget()->close();
187 }
188 }
188 else {
189 else {
189 // Close the graph
190 // Close the graph
190 graphWidget->close();
191 graphWidget->close();
191 }
192 }
192
193
193 createZone(variables, index);
194 createZone(variables, index);
194 }
195 }
195 else {
196 else {
196 // The graph is empty, create an empty zone and move the graph inside
197 // The graph is empty, create an empty zone and move the graph inside
197
198
198 auto parentZoneWidget = graphWidget->parentZoneWidget();
199 auto parentZoneWidget = graphWidget->parentZoneWidget();
199
200
200 parentDragDropContainer->layout()->removeWidget(graphWidget);
201 parentDragDropContainer->layout()->removeWidget(graphWidget);
201
202
202 auto zoneWidget = createEmptyZone(index);
203 auto zoneWidget = createEmptyZone(index);
203 zoneWidget->addGraph(graphWidget);
204 zoneWidget->addGraph(graphWidget);
204
205
205 // Close the old zone if it was the only graph inside
206 // Close the old zone if it was the only graph inside
206 if (nbGraph == 1) {
207 if (nbGraph == 1) {
207 parentZoneWidget->close();
208 parentZoneWidget->close();
208 }
209 }
209 }
210 }
210 }
211 }
211 else if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_ZONE)) {
212 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
212 // Simple move of the zone, no variable operation associated
213 // Simple move of the zone, no variable operation associated
213 auto zoneWidget = static_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
214 auto zoneWidget = static_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
214 auto parentDragDropContainer = zoneWidget->parentWidget();
215 auto parentDragDropContainer = zoneWidget->parentWidget();
215 parentDragDropContainer->layout()->removeWidget(zoneWidget);
216 parentDragDropContainer->layout()->removeWidget(zoneWidget);
216
217
217 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
218 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
218 }
219 }
219 }
220 }
@@ -1,410 +1,411
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
7
7
8 #include "Common/MimeTypesDef.h"
8 #include <Data/SqpRange.h>
9 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
11 #include <Variable/VariableController.h>
11
12
12 #include <DragDropHelper.h>
13 #include <DragDropHelper.h>
13 #include <QUuid>
14 #include <QUuid>
14 #include <SqpApplication.h>
15 #include <SqpApplication.h>
15 #include <cmath>
16 #include <cmath>
16
17
17 #include <QLayout>
18 #include <QLayout>
18
19
19 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
20 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
20
21
21 namespace {
22 namespace {
22
23
23 /// Minimum height for graph added in zones (in pixels)
24 /// Minimum height for graph added in zones (in pixels)
24 const auto GRAPH_MINIMUM_HEIGHT = 300;
25 const auto GRAPH_MINIMUM_HEIGHT = 300;
25
26
26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
27 /// Generates a default name for a new graph, according to the number of graphs already displayed in
27 /// the zone
28 /// the zone
28 QString defaultGraphName(const QLayout &layout)
29 QString defaultGraphName(const QLayout &layout)
29 {
30 {
30 auto count = 0;
31 auto count = 0;
31 for (auto i = 0; i < layout.count(); ++i) {
32 for (auto i = 0; i < layout.count(); ++i) {
32 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
33 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
33 count++;
34 count++;
34 }
35 }
35 }
36 }
36
37
37 return QObject::tr("Graph %1").arg(count + 1);
38 return QObject::tr("Graph %1").arg(count + 1);
38 }
39 }
39
40
40 /**
41 /**
41 * Applies a function to all graphs of the zone represented by its layout
42 * Applies a function to all graphs of the zone represented by its layout
42 * @param layout the layout that contains graphs
43 * @param layout the layout that contains graphs
43 * @param fun the function to apply to each graph
44 * @param fun the function to apply to each graph
44 */
45 */
45 template <typename Fun>
46 template <typename Fun>
46 void processGraphs(QLayout &layout, Fun fun)
47 void processGraphs(QLayout &layout, Fun fun)
47 {
48 {
48 for (auto i = 0; i < layout.count(); ++i) {
49 for (auto i = 0; i < layout.count(); ++i) {
49 if (auto item = layout.itemAt(i)) {
50 if (auto item = layout.itemAt(i)) {
50 if (auto visualizationGraphWidget
51 if (auto visualizationGraphWidget
51 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
52 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
52 fun(*visualizationGraphWidget);
53 fun(*visualizationGraphWidget);
53 }
54 }
54 }
55 }
55 }
56 }
56 }
57 }
57
58
58 } // namespace
59 } // namespace
59
60
60 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
61 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
61
62
62 explicit VisualizationZoneWidgetPrivate()
63 explicit VisualizationZoneWidgetPrivate()
63 : m_SynchronisationGroupId{QUuid::createUuid()},
64 : m_SynchronisationGroupId{QUuid::createUuid()},
64 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
65 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
65 {
66 {
66 }
67 }
67 QUuid m_SynchronisationGroupId;
68 QUuid m_SynchronisationGroupId;
68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
69 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
69 };
70 };
70
71
71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
72 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
72 : VisualizationDragWidget{parent},
73 : VisualizationDragWidget{parent},
73 ui{new Ui::VisualizationZoneWidget},
74 ui{new Ui::VisualizationZoneWidget},
74 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
75 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
75 {
76 {
76 ui->setupUi(this);
77 ui->setupUi(this);
77
78
78 ui->zoneNameLabel->setText(name);
79 ui->zoneNameLabel->setText(name);
79
80
80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
81 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH});
81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
82 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
82 &VisualizationZoneWidget::dropMimeData);
83 &VisualizationZoneWidget::dropMimeData);
83
84
84 // 'Close' options : widget is deleted when closed
85 // 'Close' options : widget is deleted when closed
85 setAttribute(Qt::WA_DeleteOnClose);
86 setAttribute(Qt::WA_DeleteOnClose);
86 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
87 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
87 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
88 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
88
89
89 // Synchronisation id
90 // Synchronisation id
90 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
91 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
91 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
92 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
92 }
93 }
93
94
94 VisualizationZoneWidget::~VisualizationZoneWidget()
95 VisualizationZoneWidget::~VisualizationZoneWidget()
95 {
96 {
96 delete ui;
97 delete ui;
97 }
98 }
98
99
99 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
100 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
100 {
101 {
101 // Synchronize new graph with others in the zone
102 // Synchronize new graph with others in the zone
102 impl->m_Synchronizer->addGraph(*graphWidget);
103 impl->m_Synchronizer->addGraph(*graphWidget);
103
104
104 ui->dragDropContainer->addDragWidget(graphWidget);
105 ui->dragDropContainer->addDragWidget(graphWidget);
105 }
106 }
106
107
107 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
108 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
108 {
109 {
109 // Synchronize new graph with others in the zone
110 // Synchronize new graph with others in the zone
110 impl->m_Synchronizer->addGraph(*graphWidget);
111 impl->m_Synchronizer->addGraph(*graphWidget);
111
112
112 ui->dragDropContainer->insertDragWidget(index, graphWidget);
113 ui->dragDropContainer->insertDragWidget(index, graphWidget);
113 }
114 }
114
115
115 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
116 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
116 {
117 {
117 return createGraph(variable, -1);
118 return createGraph(variable, -1);
118 }
119 }
119
120
120 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
121 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
121 int index)
122 int index)
122 {
123 {
123 auto graphWidget
124 auto graphWidget
124 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
125 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
125
126
126
127
127 // Set graph properties
128 // Set graph properties
128 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
129 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
129 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
130 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
130
131
131
132
132 // Lambda to synchronize zone widget
133 // Lambda to synchronize zone widget
133 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
134 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
134 const SqpRange &oldGraphRange) {
135 const SqpRange &oldGraphRange) {
135
136
136 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
137 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
137 auto frameLayout = ui->dragDropContainer->layout();
138 auto frameLayout = ui->dragDropContainer->layout();
138 for (auto i = 0; i < frameLayout->count(); ++i) {
139 for (auto i = 0; i < frameLayout->count(); ++i) {
139 auto graphChild
140 auto graphChild
140 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
141 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
141 if (graphChild && (graphChild != graphWidget)) {
142 if (graphChild && (graphChild != graphWidget)) {
142
143
143 auto graphChildRange = graphChild->graphRange();
144 auto graphChildRange = graphChild->graphRange();
144 switch (zoomType) {
145 switch (zoomType) {
145 case AcquisitionZoomType::ZoomIn: {
146 case AcquisitionZoomType::ZoomIn: {
146 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
147 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
147 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
148 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
148 graphChildRange.m_TStart += deltaLeft;
149 graphChildRange.m_TStart += deltaLeft;
149 graphChildRange.m_TEnd -= deltaRight;
150 graphChildRange.m_TEnd -= deltaRight;
150 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
152 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
152 << deltaLeft;
153 << deltaLeft;
153 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
154 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
154 << deltaRight;
155 << deltaRight;
155 qCDebug(LOG_VisualizationZoneWidget())
156 qCDebug(LOG_VisualizationZoneWidget())
156 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
157 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
157
158
158 break;
159 break;
159 }
160 }
160
161
161 case AcquisitionZoomType::ZoomOut: {
162 case AcquisitionZoomType::ZoomOut: {
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
163 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
164 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
164 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
165 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
166 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
166 << deltaLeft;
167 << deltaLeft;
167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
168 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
168 << deltaRight;
169 << deltaRight;
169 qCDebug(LOG_VisualizationZoneWidget())
170 qCDebug(LOG_VisualizationZoneWidget())
170 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
171 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
171 graphChildRange.m_TStart -= deltaLeft;
172 graphChildRange.m_TStart -= deltaLeft;
172 graphChildRange.m_TEnd += deltaRight;
173 graphChildRange.m_TEnd += deltaRight;
173 break;
174 break;
174 }
175 }
175 case AcquisitionZoomType::PanRight: {
176 case AcquisitionZoomType::PanRight: {
176 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
177 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
177 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
178 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
178 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
179 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
179 graphChildRange.m_TStart += deltaLeft;
180 graphChildRange.m_TStart += deltaLeft;
180 graphChildRange.m_TEnd += deltaRight;
181 graphChildRange.m_TEnd += deltaRight;
181 qCDebug(LOG_VisualizationZoneWidget())
182 qCDebug(LOG_VisualizationZoneWidget())
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 break;
184 break;
184 }
185 }
185 case AcquisitionZoomType::PanLeft: {
186 case AcquisitionZoomType::PanLeft: {
186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
187 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
188 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
188 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
189 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
189 graphChildRange.m_TStart -= deltaLeft;
190 graphChildRange.m_TStart -= deltaLeft;
190 graphChildRange.m_TEnd -= deltaRight;
191 graphChildRange.m_TEnd -= deltaRight;
191 break;
192 break;
192 }
193 }
193 case AcquisitionZoomType::Unknown: {
194 case AcquisitionZoomType::Unknown: {
194 qCDebug(LOG_VisualizationZoneWidget())
195 qCDebug(LOG_VisualizationZoneWidget())
195 << tr("Impossible to synchronize: zoom type unknown");
196 << tr("Impossible to synchronize: zoom type unknown");
196 break;
197 break;
197 }
198 }
198 default:
199 default:
199 qCCritical(LOG_VisualizationZoneWidget())
200 qCCritical(LOG_VisualizationZoneWidget())
200 << tr("Impossible to synchronize: zoom type not take into account");
201 << tr("Impossible to synchronize: zoom type not take into account");
201 // No action
202 // No action
202 break;
203 break;
203 }
204 }
204 graphChild->enableAcquisition(false);
205 graphChild->enableAcquisition(false);
205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
206 << graphChild->graphRange();
207 << graphChild->graphRange();
207 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
208 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
208 << graphChildRange;
209 << graphChildRange;
209 qCDebug(LOG_VisualizationZoneWidget())
210 qCDebug(LOG_VisualizationZoneWidget())
210 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
211 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
211 graphChild->setGraphRange(graphChildRange);
212 graphChild->setGraphRange(graphChildRange);
212 graphChild->enableAcquisition(true);
213 graphChild->enableAcquisition(true);
213 }
214 }
214 }
215 }
215 };
216 };
216
217
217 // connection for synchronization
218 // connection for synchronization
218 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
219 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
219 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
220 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
220 &VisualizationZoneWidget::onVariableAdded);
221 &VisualizationZoneWidget::onVariableAdded);
221 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
222 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
222 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
223 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
223
224
224 auto range = SqpRange{};
225 auto range = SqpRange{};
225
226
226 // Apply visitor to graph children
227 // Apply visitor to graph children
227 auto layout = ui->dragDropContainer->layout();
228 auto layout = ui->dragDropContainer->layout();
228 if (layout->count() > 0) {
229 if (layout->count() > 0) {
229 // Case of a new graph in a existant zone
230 // Case of a new graph in a existant zone
230 if (auto visualizationGraphWidget
231 if (auto visualizationGraphWidget
231 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
232 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
232 range = visualizationGraphWidget->graphRange();
233 range = visualizationGraphWidget->graphRange();
233 }
234 }
234 }
235 }
235 else {
236 else {
236 // Case of a new graph as the first of the zone
237 // Case of a new graph as the first of the zone
237 range = variable->range();
238 range = variable->range();
238 }
239 }
239
240
240 this->insertGraph(index, graphWidget);
241 this->insertGraph(index, graphWidget);
241
242
242 graphWidget->addVariable(variable, range);
243 graphWidget->addVariable(variable, range);
243
244
244 // get y using variable range
245 // get y using variable range
245 if (auto dataSeries = variable->dataSeries()) {
246 if (auto dataSeries = variable->dataSeries()) {
246 dataSeries->lockRead();
247 dataSeries->lockRead();
247 auto valuesBounds
248 auto valuesBounds
248 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
249 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
249 auto end = dataSeries->cend();
250 auto end = dataSeries->cend();
250 if (valuesBounds.first != end && valuesBounds.second != end) {
251 if (valuesBounds.first != end && valuesBounds.second != end) {
251 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
252 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
252
253
253 auto minValue = rangeValue(valuesBounds.first->minValue());
254 auto minValue = rangeValue(valuesBounds.first->minValue());
254 auto maxValue = rangeValue(valuesBounds.second->maxValue());
255 auto maxValue = rangeValue(valuesBounds.second->maxValue());
255
256
256 graphWidget->setYRange(SqpRange{minValue, maxValue});
257 graphWidget->setYRange(SqpRange{minValue, maxValue});
257 }
258 }
258 dataSeries->unlock();
259 dataSeries->unlock();
259 }
260 }
260
261
261 return graphWidget;
262 return graphWidget;
262 }
263 }
263
264
264 VisualizationGraphWidget *
265 VisualizationGraphWidget *
265 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
266 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
266 {
267 {
267 if (variables.isEmpty()) {
268 if (variables.isEmpty()) {
268 return nullptr;
269 return nullptr;
269 }
270 }
270
271
271 auto graphWidget = createGraph(variables.first(), index);
272 auto graphWidget = createGraph(variables.first(), index);
272 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
273 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
273 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
274 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
274 }
275 }
275
276
276 return graphWidget;
277 return graphWidget;
277 }
278 }
278
279
279 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
280 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
280 {
281 {
281 if (visitor) {
282 if (visitor) {
282 visitor->visitEnter(this);
283 visitor->visitEnter(this);
283
284
284 // Apply visitor to graph children: widgets different from graphs are not visited (no
285 // Apply visitor to graph children: widgets different from graphs are not visited (no
285 // action)
286 // action)
286 processGraphs(
287 processGraphs(
287 *ui->dragDropContainer->layout(),
288 *ui->dragDropContainer->layout(),
288 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
289 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
289
290
290 visitor->visitLeave(this);
291 visitor->visitLeave(this);
291 }
292 }
292 else {
293 else {
293 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
294 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
294 }
295 }
295 }
296 }
296
297
297 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
298 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
298 {
299 {
299 // A tab can always accomodate a variable
300 // A tab can always accomodate a variable
300 Q_UNUSED(variable);
301 Q_UNUSED(variable);
301 return true;
302 return true;
302 }
303 }
303
304
304 bool VisualizationZoneWidget::contains(const Variable &variable) const
305 bool VisualizationZoneWidget::contains(const Variable &variable) const
305 {
306 {
306 Q_UNUSED(variable);
307 Q_UNUSED(variable);
307 return false;
308 return false;
308 }
309 }
309
310
310 QString VisualizationZoneWidget::name() const
311 QString VisualizationZoneWidget::name() const
311 {
312 {
312 return ui->zoneNameLabel->text();
313 return ui->zoneNameLabel->text();
313 }
314 }
314
315
315 QMimeData *VisualizationZoneWidget::mimeData() const
316 QMimeData *VisualizationZoneWidget::mimeData() const
316 {
317 {
317 auto mimeData = new QMimeData;
318 auto mimeData = new QMimeData;
318 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
319 mimeData->setData(MIME_TYPE_ZONE, QByteArray());
319
320
320 return mimeData;
321 return mimeData;
321 }
322 }
322
323
323 bool VisualizationZoneWidget::isDragAllowed() const
324 bool VisualizationZoneWidget::isDragAllowed() const
324 {
325 {
325 return true;
326 return true;
326 }
327 }
327
328
328 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
329 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
329 {
330 {
330 // Closes graphs in the zone
331 // Closes graphs in the zone
331 processGraphs(*ui->dragDropContainer->layout(),
332 processGraphs(*ui->dragDropContainer->layout(),
332 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
333 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
333
334
334 // Delete synchronization group from variable controller
335 // Delete synchronization group from variable controller
335 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
336 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
336 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
337 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
337
338
338 QWidget::closeEvent(event);
339 QWidget::closeEvent(event);
339 }
340 }
340
341
341 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
342 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
342 {
343 {
343 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
344 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
344 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
345 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
345 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
346 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
346 }
347 }
347
348
348 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
349 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
349 {
350 {
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
351 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
351 Q_ARG(std::shared_ptr<Variable>, variable),
352 Q_ARG(std::shared_ptr<Variable>, variable),
352 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
353 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
353 }
354 }
354
355
355 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
356 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
356 {
357 {
357 auto &helper = sqpApp->dragDropHelper();
358 auto &helper = sqpApp->dragDropHelper();
358 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
359 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
359 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
360 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
360 auto parentDragDropContainer
361 auto parentDragDropContainer
361 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
362 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
362 Q_ASSERT(parentDragDropContainer);
363 Q_ASSERT(parentDragDropContainer);
363
364
364 const auto &variables = graphWidget->variables();
365 const auto &variables = graphWidget->variables();
365
366
366 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
367 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
367 // The drop didn't occur in the same zone
368 // The drop didn't occur in the same zone
368
369
369 // Abort the requests for the variables (if any)
370 // Abort the requests for the variables (if any)
370 // Commented, because it's not sure if it's needed or not
371 // Commented, because it's not sure if it's needed or not
371 // for (const auto& var : variables)
372 // for (const auto& var : variables)
372 //{
373 //{
373 // sqpApp->variableController().onAbortProgressRequested(var);
374 // sqpApp->variableController().onAbortProgressRequested(var);
374 //}
375 //}
375
376
376 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
377 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
377 auto nbGraph = parentDragDropContainer->countDragWidget();
378 auto nbGraph = parentDragDropContainer->countDragWidget();
378 if (nbGraph == 1) {
379 if (nbGraph == 1) {
379 // This is the only graph in the previous zone, close the zone
380 // This is the only graph in the previous zone, close the zone
380 previousParentZoneWidget->close();
381 previousParentZoneWidget->close();
381 }
382 }
382 else {
383 else {
383 // Close the graph
384 // Close the graph
384 graphWidget->close();
385 graphWidget->close();
385 }
386 }
386
387
387 // Creates the new graph in the zone
388 // Creates the new graph in the zone
388 createGraph(variables, index);
389 createGraph(variables, index);
389 }
390 }
390 else {
391 else {
391 // The drop occurred in the same zone or the graph is empty
392 // The drop occurred in the same zone or the graph is empty
392 // Simple move of the graph, no variable operation associated
393 // Simple move of the graph, no variable operation associated
393 parentDragDropContainer->layout()->removeWidget(graphWidget);
394 parentDragDropContainer->layout()->removeWidget(graphWidget);
394
395
395 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
396 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
396 // The graph is empty and dropped in a different zone.
397 // The graph is empty and dropped in a different zone.
397 // Take the range of the first graph in the zone (if existing).
398 // Take the range of the first graph in the zone (if existing).
398 auto layout = ui->dragDropContainer->layout();
399 auto layout = ui->dragDropContainer->layout();
399 if (layout->count() > 0) {
400 if (layout->count() > 0) {
400 if (auto visualizationGraphWidget
401 if (auto visualizationGraphWidget
401 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
402 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
402 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
403 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
403 }
404 }
404 }
405 }
405 }
406 }
406
407
407 ui->dragDropContainer->insertDragWidget(index, graphWidget);
408 ui->dragDropContainer->insertDragWidget(index, graphWidget);
408 }
409 }
409 }
410 }
410 }
411 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

You need to be logged in to leave comments. Login now