##// END OF EJS Templates
Fixes for review
trabillard -
r846:3f7ba55eb4d2
parent child
Show More
@@ -1,42 +1,42
1 #ifndef VISUALIZATIONDRAGDROPCONTAINER_H
2 #define VISUALIZATIONDRAGDROPCONTAINER_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QMimeData>
6 6 #include <QVBoxLayout>
7 7 #include <QWidget>
8 8
9 9 class VisualizationDragWidget;
10 10
11 11 class VisualizationDragDropContainer : public QWidget {
12 12 Q_OBJECT
13 13
14 14 signals:
15 15 void dropOccured(int dropIndex, const QMimeData *mimeData);
16 16
17 17 public:
18 18 VisualizationDragDropContainer(QWidget *parent = nullptr);
19 19
20 20 void addDragWidget(VisualizationDragWidget *dragWidget);
21 21 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
22 22
23 23 void setAcceptedMimeTypes(const QStringList &mimeTypes);
24 24 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
25 25
26 26 int countDragWidget() const;
27 27
28 28 protected:
29 29 void dragEnterEvent(QDragEnterEvent *event);
30 30 void dragLeaveEvent(QDragLeaveEvent *event);
31 31 void dragMoveEvent(QDragMoveEvent *event);
32 32 void dropEvent(QDropEvent *event);
33 33
34 34 private:
35 35 class VisualizationDragDropContainerPrivate;
36 36 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
37 37
38 38 private slots:
39 39 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
40 40 };
41 41
42 #endif // VISUALIZATIONDRAGDROPCONTAINER_H
42 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,29 +1,29
1 #ifndef VISUALIZATIONDRAGWIDGET_H
2 #define VISUALIZATIONDRAGWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGWIDGET_H
2 #define SCIQLOP_VISUALIZATIONDRAGWIDGET_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QMimeData>
6 6 #include <QWidget>
7 7
8 8 class VisualizationDragWidget : public QWidget {
9 9 Q_OBJECT
10 10
11 11 public:
12 12 VisualizationDragWidget(QWidget *parent = nullptr);
13 13
14 14 virtual QMimeData *mimeData() const = 0;
15 15 virtual bool isDragAllowed() const = 0;
16 16
17 17 protected:
18 18 virtual void mousePressEvent(QMouseEvent *event) override;
19 19 virtual void mouseMoveEvent(QMouseEvent *event) override;
20 20
21 21 private:
22 22 class VisualizationDragWidgetPrivate;
23 23 spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl;
24 24
25 25 signals:
26 26 void dragDetected(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
27 27 };
28 28
29 #endif // VISUALIZATIONDRAGWIDGET_H
29 #endif // SCIQLOP_VISUALIZATIONDRAGWIDGET_H
@@ -1,302 +1,302
1 1 #include "Visualization/VisualizationDragDropContainer.h"
2 2 #include "DragDropHelper.h"
3 3 #include "SqpApplication.h"
4 4 #include "Visualization/VisualizationDragWidget.h"
5 5
6 6 #include <QDrag>
7 7 #include <QDragEnterEvent>
8 8 #include <QVBoxLayout>
9 9
10 10 #include <cmath>
11 11 #include <memory>
12 12
13 13 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
14 14
15 15 QVBoxLayout *m_Layout;
16 16 QStringList m_AcceptedMimeTypes;
17 17 QStringList m_MergeAllowedMimeTypes;
18 18
19 19 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
20 20 {
21 21 m_Layout = new QVBoxLayout(widget);
22 22 m_Layout->setContentsMargins(0, 0, 0, 0);
23 23 }
24 24
25 25 bool acceptMimeData(const QMimeData *data) const
26 26 {
27 27 for (const auto &type : m_AcceptedMimeTypes) {
28 28 if (data->hasFormat(type)) {
29 29 return true;
30 30 }
31 31 }
32 32
33 33 return false;
34 34 }
35 35
36 36 bool allowMergeMimeData(const QMimeData *data) const
37 37 {
38 38 for (const auto &type : m_MergeAllowedMimeTypes) {
39 39 if (data->hasFormat(type)) {
40 40 return true;
41 41 }
42 42 }
43 43
44 44 return false;
45 45 }
46 46
47 47 bool hasPlaceHolder() const
48 48 {
49 49 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
50 50 }
51 51
52 52 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
53 53 {
54 54 VisualizationDragWidget *dragWidget = nullptr;
55 55
56 56 for (auto child : parent->children()) {
57 57 auto widget = qobject_cast<VisualizationDragWidget *>(child);
58 58 if (widget && widget->isVisible()) {
59 59 if (widget->frameGeometry().contains(pos)) {
60 60 dragWidget = widget;
61 61 break;
62 62 }
63 63 }
64 64 }
65 65
66 66 return dragWidget;
67 67 }
68 68
69 69 bool cursorIsInContainer(QWidget *container) const
70 70 {
71 71 auto adustNum = 18; // to be safe, in case of scrollbar on the side
72 72 auto containerRect = QRect(QPoint(), container->contentsRect().size())
73 73 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
74 qDebug() << containerRect << container->mapFromGlobal(QCursor::pos());
75 74 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
76 75 }
77 76 };
78 77
79 78 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
80 79 : QWidget{parent},
81 80 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
82 81 {
83 82 setAcceptDrops(true);
84 83 }
85 84
86 85 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
87 86 {
88 87 impl->m_Layout->addWidget(dragWidget);
89 88 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
90 89 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
91 90 &VisualizationDragDropContainer::startDrag);
92 91 }
93 92
94 93 void VisualizationDragDropContainer::insertDragWidget(int index,
95 94 VisualizationDragWidget *dragWidget)
96 95 {
97 96 impl->m_Layout->insertWidget(index, dragWidget);
98 97 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
99 98 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
100 99 &VisualizationDragDropContainer::startDrag);
101 100 }
102 101
103 102 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
104 103 {
105 104 impl->m_AcceptedMimeTypes = mimeTypes;
106 105 }
107 106
108 107 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
109 108 {
110 109 impl->m_MergeAllowedMimeTypes = mimeTypes;
111 110 }
112 111
113 112 int VisualizationDragDropContainer::countDragWidget() const
114 113 {
115 114 auto nbGraph = 0;
116 115 for (auto child : children()) {
117 auto widget = qobject_cast<VisualizationDragWidget *>(child);
118 if (widget) {
116 if (qobject_cast<VisualizationDragWidget *>(child)) {
119 117 nbGraph += 1;
120 118 }
121 119 }
122 120
123 121 return nbGraph;
124 122 }
125 123
126 124 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
127 125 const QPoint &dragPosition)
128 126 {
129 127 auto &helper = sqpApp->dragDropHelper();
130 128
131 129 // Note: The management of the drag object is done by Qt
132 auto *drag = new QDrag{dragWidget};
130 auto drag = new QDrag{dragWidget};
133 131 drag->setHotSpot(dragPosition);
134 132
135 133 auto mimeData = dragWidget->mimeData();
136 134 drag->setMimeData(mimeData);
137 135
138 136 auto pixmap = QPixmap(dragWidget->size());
139 137 dragWidget->render(&pixmap);
140 138 drag->setPixmap(pixmap);
141 139
142 140 auto image = pixmap.toImage();
143 141 mimeData->setImageData(image);
144 142 mimeData->setUrls({helper.imageTemporaryUrl(image)});
145 143
146 144 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
147 145 helper.setCurrentDragWidget(dragWidget);
148 146
149 147 if (impl->cursorIsInContainer(this)) {
150 148 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
151 149 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
152 150 dragWidget->setVisible(false);
153 151 }
154 152 }
155 153
156 154 // Note: The exec() is blocking on windows but not on linux and macOS
157 155 drag->exec(Qt::MoveAction | Qt::CopyAction);
158 156 }
159 157
160 158 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
161 159 {
162 160 if (impl->acceptMimeData(event->mimeData())) {
163 161 event->acceptProposedAction();
164 162
165 163 auto &helper = sqpApp->dragDropHelper();
166 164
167 165 if (!impl->hasPlaceHolder()) {
168 166 auto dragWidget = helper.getCurrentDragWidget();
169 167 auto parentWidget
170 168 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
171 169 if (parentWidget) {
172 170 dragWidget->setVisible(false);
173 171 }
174 172
175 173 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
176 174
177 175 if (dragWidgetHovered) {
178 176 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
179 177 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
180 178 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
181 179 hoveredWidgetIndex
182 180 += 1; // Correction of the index if the drop occurs in the same container
183 181 }
184 182
185 183 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
186 184 }
187 185 else {
188 186 helper.insertPlaceHolder(impl->m_Layout, 0);
189 187 }
190 188 }
191 189 }
192 else
190 else {
193 191 event->ignore();
192 }
194 193
195 194 QWidget::dragEnterEvent(event);
196 195 }
197 196
198 197 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
199 198 {
200 199 Q_UNUSED(event);
201 200
202 201 auto &helper = sqpApp->dragDropHelper();
203 202
204 203 if (!impl->cursorIsInContainer(this)) {
205 204 helper.removePlaceHolder();
206 205
207 206 bool isInternal = true;
208 207 if (isInternal) {
209 // Only if the drag is strated from the visualization
208 // Only if the drag is started from the visualization
210 209 // Show the drag widget at its original place
211 210 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
212 211 // drop zone (It is not possible to catch a drop event outside of the application)
213 212
214 213 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
215 214 if (dragWidget) {
216 215 dragWidget->setVisible(true);
217 216 }
218 217 }
219 218 }
220 219
221 220 QWidget::dragLeaveEvent(event);
222 221 }
223 222
224 223 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
225 224 {
226 225 if (impl->acceptMimeData(event->mimeData())) {
227 226 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
228 227 if (dragWidgetHovered) {
229 228 auto canMerge = impl->allowMergeMimeData(event->mimeData());
230 229
231 230 auto nbDragWidget = countDragWidget();
232 231 if (nbDragWidget > 0) {
233 232 auto graphHeight = size().height() / nbDragWidget;
234 233 auto dropIndex = floor(event->pos().y() / graphHeight);
235 234 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
236 235
237 236 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
238 237 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
239 238
240 239 auto &helper = sqpApp->dragDropHelper();
241 240 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
242 241
243 242 if (isOnTop || isOnBottom) {
244 243 if (isOnBottom) {
245 244 dropIndex += 1;
246 245 }
247 246
248 247 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
249 248 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
250 249 dropIndex += 1; // Correction of the index if the drop occurs in the same
251 250 // container
252 251 }
253 252
254 253 if (dropIndex != placeHolderIndex) {
255 254 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
256 255 }
257 256 }
258 257 else if (canMerge) {
259 258 // drop on the middle -> merge
260 259 if (impl->hasPlaceHolder()) {
261 260 helper.removePlaceHolder();
262 261 }
263 262 }
264 263 }
265 264 }
266 265 }
267 else
266 else {
268 267 event->ignore();
268 }
269 269
270 270 QWidget::dragMoveEvent(event);
271 271 }
272 272
273 273 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
274 274 {
275 275 if (impl->acceptMimeData(event->mimeData())) {
276 276 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
277 277 if (impl->hasPlaceHolder() && dragWidget) {
278 278 auto &helper = sqpApp->dragDropHelper();
279 279
280 280 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
281 281
282 282 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
283 283 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
284 284 droppedIndex
285 285 -= 1; // Correction of the index if the drop occurs in the same container
286 286 }
287 287
288 288 dragWidget->setVisible(true);
289 dragWidget->setStyleSheet("");
290 289
291 290 event->acceptProposedAction();
292 291
293 292 helper.removePlaceHolder();
294 293
295 294 emit dropOccured(droppedIndex, event->mimeData());
296 295 }
297 296 }
298 else
297 else {
299 298 event->ignore();
299 }
300 300
301 301 QWidget::dropEvent(event);
302 302 }
@@ -1,384 +1,384
1 1 #include "Visualization/VisualizationGraphWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationDefs.h"
4 4 #include "Visualization/VisualizationGraphHelper.h"
5 5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7 #include "ui_VisualizationGraphWidget.h"
8 8
9 9 #include <Data/ArrayData.h>
10 10 #include <Data/IDataSeries.h>
11 11 #include <DragDropHelper.h>
12 12 #include <Settings/SqpSettingsDefs.h>
13 13 #include <SqpApplication.h>
14 14 #include <Variable/Variable.h>
15 15 #include <Variable/VariableController.h>
16 16
17 17 #include <unordered_map>
18 18
19 19 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
20 20
21 21 namespace {
22 22
23 23 /// Key pressed to enable zoom on horizontal axis
24 24 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
25 25
26 26 /// Key pressed to enable zoom on vertical axis
27 27 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
28 28
29 29 } // namespace
30 30
31 31 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
32 32
33 33 explicit VisualizationGraphWidgetPrivate(const QString &name)
34 34 : m_Name{name},
35 35 m_DoAcquisition{true},
36 36 m_IsCalibration{false},
37 37 m_RenderingDelegate{nullptr}
38 38 {
39 39 }
40 40
41 41 QString m_Name;
42 42 // 1 variable -> n qcpplot
43 43 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
44 44 bool m_DoAcquisition;
45 45 bool m_IsCalibration;
46 46 QCPItemTracer *m_TextTracer;
47 47 /// Delegate used to attach rendering features to the plot
48 48 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 49 };
50 50
51 51 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 52 : VisualizationDragWidget{parent},
53 53 ui{new Ui::VisualizationGraphWidget},
54 54 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 55 {
56 56 ui->setupUi(this);
57 57
58 58 // 'Close' options : widget is deleted when closed
59 59 setAttribute(Qt::WA_DeleteOnClose);
60 60
61 61 // Set qcpplot properties :
62 62 // - Drag (on x-axis) and zoom are enabled
63 63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66 66
67 67 // The delegate must be initialized after the ui as it uses the plot
68 68 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69 69
70 70 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 71 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 72 &VisualizationGraphWidget::onMouseRelease);
73 73 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 74 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 75 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 76 &QCPAxis::rangeChanged),
77 77 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
78 78
79 79 // Activates menu when right clicking on the graph
80 80 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
81 81 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
82 82 &VisualizationGraphWidget::onGraphMenuRequested);
83 83
84 84 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
85 85 &VariableController::onRequestDataLoading);
86 86
87 87 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
88 88 &VisualizationGraphWidget::onUpdateVarDisplaying);
89 89 }
90 90
91 91
92 92 VisualizationGraphWidget::~VisualizationGraphWidget()
93 93 {
94 94 delete ui;
95 95 }
96 96
97 97 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
98 98 {
99 99 auto parent = parentWidget();
100 do {
100 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
101 101 parent = parent->parentWidget();
102 } while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent));
102 }
103 103
104 104 return qobject_cast<VisualizationZoneWidget *>(parent);
105 105 }
106 106
107 107 void VisualizationGraphWidget::enableAcquisition(bool enable)
108 108 {
109 109 impl->m_DoAcquisition = enable;
110 110 }
111 111
112 112 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
113 113 {
114 114 // Uses delegate to create the qcpplot components according to the variable
115 115 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
116 116 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
117 117
118 118 // Set axes properties according to the units of the data series
119 119 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
120 120 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
121 121 auto xAxisUnit = Unit{};
122 122 auto valuesUnit = Unit{};
123 123
124 124 if (auto dataSeries = variable->dataSeries()) {
125 125 dataSeries->lockRead();
126 126 xAxisUnit = dataSeries->xAxisUnit();
127 127 valuesUnit = dataSeries->valuesUnit();
128 128 dataSeries->unlock();
129 129 }
130 130 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
131 131
132 132 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
133 133
134 134 this->enableAcquisition(false);
135 135 this->setGraphRange(range);
136 136 this->enableAcquisition(true);
137 137
138 138 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
139 139
140 140 emit variableAdded(variable);
141 141 }
142 142
143 143 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
144 144 {
145 145 // Each component associated to the variable :
146 146 // - is removed from qcpplot (which deletes it)
147 147 // - is no longer referenced in the map
148 148 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
149 149 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
150 150 emit variableAboutToBeRemoved(variable);
151 151
152 152 auto &plottablesMap = variableIt->second;
153 153
154 154 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
155 155 plottableIt != plottableEnd;) {
156 156 ui->widget->removePlottable(plottableIt->second);
157 157 plottableIt = plottablesMap.erase(plottableIt);
158 158 }
159 159
160 160 impl->m_VariableToPlotMultiMap.erase(variableIt);
161 161 }
162 162
163 163 // Updates graph
164 164 ui->widget->replot();
165 165 }
166 166
167 167 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
168 168 {
169 169 auto variables = QList<std::shared_ptr<Variable> >{};
170 170 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
171 171 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
172 172 variables << it->first;
173 173 }
174 174
175 175 return variables;
176 176 }
177 177
178 178 void VisualizationGraphWidget::setYRange(const SqpRange &range)
179 179 {
180 180 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
181 181 }
182 182
183 183 SqpRange VisualizationGraphWidget::graphRange() const noexcept
184 184 {
185 185 auto graphRange = ui->widget->xAxis->range();
186 186 return SqpRange{graphRange.lower, graphRange.upper};
187 187 }
188 188
189 189 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
190 190 {
191 191 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
192 192 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
193 193 ui->widget->replot();
194 194 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
195 195 }
196 196
197 197 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
198 198 {
199 199 if (visitor) {
200 200 visitor->visit(this);
201 201 }
202 202 else {
203 203 qCCritical(LOG_VisualizationGraphWidget())
204 204 << tr("Can't visit widget : the visitor is null");
205 205 }
206 206 }
207 207
208 208 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
209 209 {
210 210 /// @todo : for the moment, a graph can always accomodate a variable
211 211 Q_UNUSED(variable);
212 212 return true;
213 213 }
214 214
215 215 bool VisualizationGraphWidget::contains(const Variable &variable) const
216 216 {
217 217 // Finds the variable among the keys of the map
218 218 auto variablePtr = &variable;
219 219 auto findVariable
220 220 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
221 221
222 222 auto end = impl->m_VariableToPlotMultiMap.cend();
223 223 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
224 224 return it != end;
225 225 }
226 226
227 227 QString VisualizationGraphWidget::name() const
228 228 {
229 229 return impl->m_Name;
230 230 }
231 231
232 232 QMimeData *VisualizationGraphWidget::mimeData() const
233 233 {
234 auto *mimeData = new QMimeData;
234 auto mimeData = new QMimeData;
235 235 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
236 236
237 237 return mimeData;
238 238 }
239 239
240 240 bool VisualizationGraphWidget::isDragAllowed() const
241 241 {
242 242 return true;
243 243 }
244 244
245 245 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
246 246 {
247 247 Q_UNUSED(event);
248 248
249 249 // Prevents that all variables will be removed from graph when it will be closed
250 250 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
251 251 emit variableAboutToBeRemoved(variableEntry.first);
252 252 }
253 253 }
254 254
255 255 void VisualizationGraphWidget::enterEvent(QEvent *event)
256 256 {
257 257 Q_UNUSED(event);
258 258 impl->m_RenderingDelegate->showGraphOverlay(true);
259 259 }
260 260
261 261 void VisualizationGraphWidget::leaveEvent(QEvent *event)
262 262 {
263 263 Q_UNUSED(event);
264 264 impl->m_RenderingDelegate->showGraphOverlay(false);
265 265 }
266 266
267 267 QCustomPlot &VisualizationGraphWidget::plot() noexcept
268 268 {
269 269 return *ui->widget;
270 270 }
271 271
272 272 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
273 273 {
274 274 QMenu graphMenu{};
275 275
276 276 // Iterates on variables (unique keys)
277 277 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
278 278 end = impl->m_VariableToPlotMultiMap.cend();
279 279 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
280 280 // 'Remove variable' action
281 281 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
282 282 [ this, var = it->first ]() { removeVariable(var); });
283 283 }
284 284
285 285 if (!graphMenu.isEmpty()) {
286 286 graphMenu.exec(QCursor::pos());
287 287 }
288 288 }
289 289
290 290 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
291 291 {
292 292 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
293 293 << QThread::currentThread()->objectName() << "DoAcqui"
294 294 << impl->m_DoAcquisition;
295 295
296 296 auto graphRange = SqpRange{t1.lower, t1.upper};
297 297 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
298 298
299 299 if (impl->m_DoAcquisition) {
300 300 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
301 301
302 302 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
303 303 end = impl->m_VariableToPlotMultiMap.end();
304 304 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
305 305 variableUnderGraphVector.push_back(it->first);
306 306 }
307 307 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
308 308 !impl->m_IsCalibration);
309 309
310 310 if (!impl->m_IsCalibration) {
311 311 qCDebug(LOG_VisualizationGraphWidget())
312 312 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
313 313 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
314 314 emit synchronize(graphRange, oldGraphRange);
315 315 }
316 316 }
317 317 }
318 318
319 319 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
320 320 {
321 321 // Handles plot rendering when mouse is moving
322 322 impl->m_RenderingDelegate->onMouseMove(event);
323 323
324 324 VisualizationDragWidget::mouseMoveEvent(event);
325 325 }
326 326
327 327 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
328 328 {
329 329 auto zoomOrientations = QFlags<Qt::Orientation>{};
330 330
331 331 // Lambda that enables a zoom orientation if the key modifier related to this orientation
332 332 // has
333 333 // been pressed
334 334 auto enableOrientation
335 335 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
336 336 auto orientationEnabled = event->modifiers().testFlag(modifier);
337 337 zoomOrientations.setFlag(orientation, orientationEnabled);
338 338 };
339 339 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
340 340 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
341 341
342 342 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
343 343 }
344 344
345 345 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
346 346 {
347 347 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
348 348
349 349 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
350 350
351 351 VisualizationDragWidget::mousePressEvent(event);
352 352 }
353 353
354 354 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
355 355 {
356 356 impl->m_IsCalibration = false;
357 357 }
358 358
359 359 void VisualizationGraphWidget::onDataCacheVariableUpdated()
360 360 {
361 361 auto graphRange = ui->widget->xAxis->range();
362 362 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
363 363
364 364 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
365 365 auto variable = variableEntry.first;
366 366 qCDebug(LOG_VisualizationGraphWidget())
367 367 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
368 368 qCDebug(LOG_VisualizationGraphWidget())
369 369 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
370 370 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
371 371 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
372 372 variable->range());
373 373 }
374 374 }
375 375 }
376 376
377 377 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
378 378 const SqpRange &range)
379 379 {
380 380 auto it = impl->m_VariableToPlotMultiMap.find(variable);
381 381 if (it != impl->m_VariableToPlotMultiMap.end()) {
382 382 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
383 383 }
384 384 }
@@ -1,410 +1,410
1 1 #include "Visualization/VisualizationZoneWidget.h"
2 2
3 3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 4 #include "Visualization/QCustomPlotSynchronizer.h"
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "ui_VisualizationZoneWidget.h"
7 7
8 8 #include <Data/SqpRange.h>
9 9 #include <Variable/Variable.h>
10 10 #include <Variable/VariableController.h>
11 11
12 12 #include <DragDropHelper.h>
13 13 #include <QUuid>
14 14 #include <SqpApplication.h>
15 15 #include <cmath>
16 16
17 17 #include <QLayout>
18 18
19 19 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
20 20
21 21 namespace {
22 22
23 23 /// Minimum height for graph added in zones (in pixels)
24 24 const auto GRAPH_MINIMUM_HEIGHT = 300;
25 25
26 26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
27 27 /// the zone
28 28 QString defaultGraphName(const QLayout &layout)
29 29 {
30 30 auto count = 0;
31 31 for (auto i = 0; i < layout.count(); ++i) {
32 32 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
33 33 count++;
34 34 }
35 35 }
36 36
37 37 return QObject::tr("Graph %1").arg(count + 1);
38 38 }
39 39
40 40 /**
41 41 * Applies a function to all graphs of the zone represented by its layout
42 42 * @param layout the layout that contains graphs
43 43 * @param fun the function to apply to each graph
44 44 */
45 45 template <typename Fun>
46 46 void processGraphs(QLayout &layout, Fun fun)
47 47 {
48 48 for (auto i = 0; i < layout.count(); ++i) {
49 49 if (auto item = layout.itemAt(i)) {
50 50 if (auto visualizationGraphWidget
51 51 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
52 52 fun(*visualizationGraphWidget);
53 53 }
54 54 }
55 55 }
56 56 }
57 57
58 58 } // namespace
59 59
60 60 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
61 61
62 62 explicit VisualizationZoneWidgetPrivate()
63 63 : m_SynchronisationGroupId{QUuid::createUuid()},
64 64 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
65 65 {
66 66 }
67 67 QUuid m_SynchronisationGroupId;
68 68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
69 69 };
70 70
71 71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
72 72 : VisualizationDragWidget{parent},
73 73 ui{new Ui::VisualizationZoneWidget},
74 74 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
75 75 {
76 76 ui->setupUi(this);
77 77
78 78 ui->zoneNameLabel->setText(name);
79 79
80 80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
81 81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
82 82 &VisualizationZoneWidget::dropMimeData);
83 83
84 84 // 'Close' options : widget is deleted when closed
85 85 setAttribute(Qt::WA_DeleteOnClose);
86 86 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
87 87 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
88 88
89 89 // Synchronisation id
90 90 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
91 91 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
92 92 }
93 93
94 94 VisualizationZoneWidget::~VisualizationZoneWidget()
95 95 {
96 96 delete ui;
97 97 }
98 98
99 99 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
100 100 {
101 101 // Synchronize new graph with others in the zone
102 102 impl->m_Synchronizer->addGraph(*graphWidget);
103 103
104 104 ui->dragDropContainer->addDragWidget(graphWidget);
105 105 }
106 106
107 107 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
108 108 {
109 109 // Synchronize new graph with others in the zone
110 110 impl->m_Synchronizer->addGraph(*graphWidget);
111 111
112 112 ui->dragDropContainer->insertDragWidget(index, graphWidget);
113 113 }
114 114
115 115 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
116 116 {
117 117 return createGraph(variable, -1);
118 118 }
119 119
120 120 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
121 121 int index)
122 122 {
123 123 auto graphWidget
124 124 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
125 125
126 126
127 127 // Set graph properties
128 128 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
129 129 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
130 130
131 131
132 132 // Lambda to synchronize zone widget
133 133 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
134 134 const SqpRange &oldGraphRange) {
135 135
136 136 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
137 137 auto frameLayout = ui->dragDropContainer->layout();
138 138 for (auto i = 0; i < frameLayout->count(); ++i) {
139 139 auto graphChild
140 140 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
141 141 if (graphChild && (graphChild != graphWidget)) {
142 142
143 143 auto graphChildRange = graphChild->graphRange();
144 144 switch (zoomType) {
145 145 case AcquisitionZoomType::ZoomIn: {
146 146 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
147 147 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
148 148 graphChildRange.m_TStart += deltaLeft;
149 149 graphChildRange.m_TEnd -= deltaRight;
150 150 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
151 151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
152 152 << deltaLeft;
153 153 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
154 154 << deltaRight;
155 155 qCDebug(LOG_VisualizationZoneWidget())
156 156 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
157 157
158 158 break;
159 159 }
160 160
161 161 case AcquisitionZoomType::ZoomOut: {
162 162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
163 163 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
164 164 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
165 165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
166 166 << deltaLeft;
167 167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
168 168 << deltaRight;
169 169 qCDebug(LOG_VisualizationZoneWidget())
170 170 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
171 171 graphChildRange.m_TStart -= deltaLeft;
172 172 graphChildRange.m_TEnd += deltaRight;
173 173 break;
174 174 }
175 175 case AcquisitionZoomType::PanRight: {
176 176 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
177 177 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
178 178 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
179 179 graphChildRange.m_TStart += deltaLeft;
180 180 graphChildRange.m_TEnd += deltaRight;
181 181 qCDebug(LOG_VisualizationZoneWidget())
182 182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 183 break;
184 184 }
185 185 case AcquisitionZoomType::PanLeft: {
186 186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
187 187 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
188 188 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
189 189 graphChildRange.m_TStart -= deltaLeft;
190 190 graphChildRange.m_TEnd -= deltaRight;
191 191 break;
192 192 }
193 193 case AcquisitionZoomType::Unknown: {
194 194 qCDebug(LOG_VisualizationZoneWidget())
195 195 << tr("Impossible to synchronize: zoom type unknown");
196 196 break;
197 197 }
198 198 default:
199 199 qCCritical(LOG_VisualizationZoneWidget())
200 200 << tr("Impossible to synchronize: zoom type not take into account");
201 201 // No action
202 202 break;
203 203 }
204 204 graphChild->enableAcquisition(false);
205 205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
206 206 << graphChild->graphRange();
207 207 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
208 208 << graphChildRange;
209 209 qCDebug(LOG_VisualizationZoneWidget())
210 210 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
211 211 graphChild->setGraphRange(graphChildRange);
212 212 graphChild->enableAcquisition(true);
213 213 }
214 214 }
215 215 };
216 216
217 217 // connection for synchronization
218 218 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
219 219 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
220 220 &VisualizationZoneWidget::onVariableAdded);
221 221 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
222 222 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
223 223
224 224 auto range = SqpRange{};
225 225
226 226 // Apply visitor to graph children
227 227 auto layout = ui->dragDropContainer->layout();
228 228 if (layout->count() > 0) {
229 229 // Case of a new graph in a existant zone
230 230 if (auto visualizationGraphWidget
231 231 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
232 232 range = visualizationGraphWidget->graphRange();
233 233 }
234 234 }
235 235 else {
236 236 // Case of a new graph as the first of the zone
237 237 range = variable->range();
238 238 }
239 239
240 240 this->insertGraph(index, graphWidget);
241 241
242 242 graphWidget->addVariable(variable, range);
243 243
244 244 // get y using variable range
245 245 if (auto dataSeries = variable->dataSeries()) {
246 246 dataSeries->lockRead();
247 247 auto valuesBounds
248 248 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
249 249 auto end = dataSeries->cend();
250 250 if (valuesBounds.first != end && valuesBounds.second != end) {
251 251 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
252 252
253 253 auto minValue = rangeValue(valuesBounds.first->minValue());
254 254 auto maxValue = rangeValue(valuesBounds.second->maxValue());
255 255
256 256 graphWidget->setYRange(SqpRange{minValue, maxValue});
257 257 }
258 258 dataSeries->unlock();
259 259 }
260 260
261 261 return graphWidget;
262 262 }
263 263
264 264 VisualizationGraphWidget *
265 265 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
266 266 {
267 267 if (variables.isEmpty()) {
268 268 return nullptr;
269 269 }
270 270
271 271 auto graphWidget = createGraph(variables.first(), index);
272 272 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
273 273 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
274 274 }
275 275
276 276 return graphWidget;
277 277 }
278 278
279 279 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
280 280 {
281 281 if (visitor) {
282 282 visitor->visitEnter(this);
283 283
284 284 // Apply visitor to graph children: widgets different from graphs are not visited (no
285 285 // action)
286 286 processGraphs(
287 287 *ui->dragDropContainer->layout(),
288 288 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
289 289
290 290 visitor->visitLeave(this);
291 291 }
292 292 else {
293 293 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
294 294 }
295 295 }
296 296
297 297 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
298 298 {
299 299 // A tab can always accomodate a variable
300 300 Q_UNUSED(variable);
301 301 return true;
302 302 }
303 303
304 304 bool VisualizationZoneWidget::contains(const Variable &variable) const
305 305 {
306 306 Q_UNUSED(variable);
307 307 return false;
308 308 }
309 309
310 310 QString VisualizationZoneWidget::name() const
311 311 {
312 312 return ui->zoneNameLabel->text();
313 313 }
314 314
315 315 QMimeData *VisualizationZoneWidget::mimeData() const
316 316 {
317 auto *mimeData = new QMimeData;
317 auto mimeData = new QMimeData;
318 318 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
319 319
320 320 return mimeData;
321 321 }
322 322
323 323 bool VisualizationZoneWidget::isDragAllowed() const
324 324 {
325 325 return true;
326 326 }
327 327
328 328 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
329 329 {
330 330 // Closes graphs in the zone
331 331 processGraphs(*ui->dragDropContainer->layout(),
332 332 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
333 333
334 334 // Delete synchronization group from variable controller
335 335 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
336 336 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
337 337
338 338 QWidget::closeEvent(event);
339 339 }
340 340
341 341 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
342 342 {
343 343 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
344 344 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
345 345 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
346 346 }
347 347
348 348 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
349 349 {
350 350 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
351 351 Q_ARG(std::shared_ptr<Variable>, variable),
352 352 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
353 353 }
354 354
355 355 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
356 356 {
357 357 auto &helper = sqpApp->dragDropHelper();
358 358 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
359 359 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
360 360 auto parentDragDropContainer
361 361 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
362 362 Q_ASSERT(parentDragDropContainer);
363 363
364 364 const auto &variables = graphWidget->variables();
365 365
366 366 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
367 367 // The drop didn't occur in the same zone
368 368
369 369 // Abort the requests for the variables (if any)
370 370 // Commented, because it's not sure if it's needed or not
371 371 // for (const auto& var : variables)
372 372 //{
373 373 // sqpApp->variableController().onAbortProgressRequested(var);
374 374 //}
375 375
376 376 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
377 377 auto nbGraph = parentDragDropContainer->countDragWidget();
378 378 if (nbGraph == 1) {
379 379 // This is the only graph in the previous zone, close the zone
380 380 previousParentZoneWidget->close();
381 381 }
382 382 else {
383 383 // Close the graph
384 384 graphWidget->close();
385 385 }
386 386
387 387 // Creates the new graph in the zone
388 388 createGraph(variables, index);
389 389 }
390 390 else {
391 391 // The drop occurred in the same zone or the graph is empty
392 392 // Simple move of the graph, no variable operation associated
393 393 parentDragDropContainer->layout()->removeWidget(graphWidget);
394 394
395 395 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
396 396 // The graph is empty and dropped in a different zone.
397 397 // Take the range of the first graph in the zone (if existing).
398 398 auto layout = ui->dragDropContainer->layout();
399 399 if (layout->count() > 0) {
400 400 if (auto visualizationGraphWidget
401 401 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
402 402 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
403 403 }
404 404 }
405 405 }
406 406
407 407 ui->dragDropContainer->insertDragWidget(index, graphWidget);
408 408 }
409 409 }
410 410 }
General Comments 0
You need to be logged in to leave comments. Login now