##// END OF EJS Templates
Manage drag&drop of empty graphs
trabillard -
r841:a582bf0b199a
parent child
Show More
@@ -1,72 +1,79
1 1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QWidget>
10 10 #include <QMimeData>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
13 13
14 14 class Variable;
15 15 class VisualizationZoneWidget;
16 16
17 17 namespace Ui {
18 18 class VisualizationTabWidget;
19 19 } // namespace Ui
20 20
21 21 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
22 22 Q_OBJECT
23 23
24 24 public:
25 25 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
26 26 virtual ~VisualizationTabWidget();
27 27
28 28 /// Add a zone widget
29 29 void addZone(VisualizationZoneWidget *zoneWidget);
30 30
31 31 void insertZone(int index, VisualizationZoneWidget *zoneWidget);
32 32
33 33 /**
34 34 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
35 35 * zone. The zone is added at the end.
36 36 * @param variable the variable for which to create the zone
37 37 * @return the pointer to the created zone
38 38 */
39 39 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
40 40
41 41 /**
42 42 * Creates a zone using a list of variables. The variables will be displayed in a new graph of the new
43 43 * zone. The zone is inserted at the specified index.
44 44 * @param variables the variables for which to create the zone
45 45 * @param index The index where the zone should be inserted in the layout
46 46 * @return the pointer to the created zone
47 47 */
48 48 VisualizationZoneWidget *createZone(const QList<std::shared_ptr<Variable>>& variables, int index);
49 49
50 /**
51 * Creates a zone which is empty (no variables). The zone is inserted at the specified index.
52 * @param index The index where the zone should be inserted in the layout
53 * @return the pointer to the created zone
54 */
55 VisualizationZoneWidget *createEmptyZone(int index);
56
50 57 // IVisualizationWidget interface
51 58 void accept(IVisualizationWidgetVisitor *visitor) override;
52 59 bool canDrop(const Variable &variable) const override;
53 60 bool contains(const Variable &variable) const override;
54 61 QString name() const override;
55 62
56 63 protected:
57 64 void closeEvent(QCloseEvent *event) override;
58 65
59 66 private:
60 67 /// @return the layout of tab in which zones are added
61 68 QLayout &tabLayout() const noexcept;
62 69
63 70 Ui::VisualizationTabWidget *ui;
64 71
65 72 class VisualizationTabWidgetPrivate;
66 73 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
67 74
68 75 private slots:
69 76 void dropMimeData(int index, const QMimeData *mimeData);
70 77 };
71 78
72 79 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -1,183 +1,212
1 1 #include "Visualization/VisualizationTabWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationTabWidget.h"
4 4
5 5 #include "Visualization/VisualizationZoneWidget.h"
6 6 #include "Visualization/VisualizationGraphWidget.h"
7 7
8 #include "Variable/VariableController.h"
9
8 10 #include "SqpApplication.h"
9 11 #include "DragDropHelper.h"
10 12
11 13 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
12 14
13 15 namespace {
14 16
15 17 /// Generates a default name for a new zone, according to the number of zones already displayed in
16 18 /// the tab
17 19 QString defaultZoneName(const QLayout &layout)
18 20 {
19 21 auto count = 0;
20 22 for (auto i = 0; i < layout.count(); ++i) {
21 23 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
22 24 count++;
23 25 }
24 26 }
25 27
26 28 return QObject::tr("Zone %1").arg(count + 1);
27 29 }
28 30
29 31 /**
30 32 * Applies a function to all zones of the tab represented by its layout
31 33 * @param layout the layout that contains zones
32 34 * @param fun the function to apply to each zone
33 35 */
34 36 template <typename Fun>
35 37 void processZones(QLayout &layout, Fun fun)
36 38 {
37 39 for (auto i = 0; i < layout.count(); ++i) {
38 40 if (auto item = layout.itemAt(i)) {
39 41 if (auto visualizationZoneWidget
40 42 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
41 43 fun(*visualizationZoneWidget);
42 44 }
43 45 }
44 46 }
45 47 }
46 48
47 49 } // namespace
48 50
49 51 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
50 52 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
51 53
52 54 QString m_Name;
53 55 };
54 56
55 57 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
56 58 : QWidget{parent},
57 59 ui{new Ui::VisualizationTabWidget},
58 60 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
59 61 {
60 62 ui->setupUi(this);
61 63
62 64 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH, DragDropHelper::MIME_TYPE_ZONE});
63 65 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this, &VisualizationTabWidget::dropMimeData);
64 66 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
65 67
66 68 // Widget is deleted when closed
67 69 setAttribute(Qt::WA_DeleteOnClose);
68 70 }
69 71
70 72 VisualizationTabWidget::~VisualizationTabWidget()
71 73 {
72 74 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
73 75 delete ui;
74 76 }
75 77
76 78 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
77 79 {
78 80 ui->dragDropContainer->addDragWidget(zoneWidget);
79 81 }
80 82
81 83 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
82 84 {
83 85 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
84 86 }
85 87
86 88 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
87 89 {
88 90 return createZone({variable}, -1);
89 91 }
90 92
91 93 VisualizationZoneWidget *VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
92 94 {
93 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
94 this->insertZone(index, zoneWidget);
95 auto zoneWidget = createEmptyZone(index);
95 96
96 97 // Creates a new graph into the zone
97 98 zoneWidget->createGraph(variables, index);
98 99
99 100 return zoneWidget;
100 101 }
101 102
103 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
104 {
105 auto zoneWidget = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
106 this->insertZone(index, zoneWidget);
107
108 return zoneWidget;
109 }
110
102 111 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
103 112 {
104 113 if (visitor) {
105 114 visitor->visitEnter(this);
106 115
107 116 // Apply visitor to zone children: widgets different from zones are not visited (no action)
108 117 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
109 118 zoneWidget.accept(visitor);
110 119 });
111 120
112 121 visitor->visitLeave(this);
113 122 }
114 123 else {
115 124 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
116 125 }
117 126 }
118 127
119 128 bool VisualizationTabWidget::canDrop(const Variable &variable) const
120 129 {
121 130 // A tab can always accomodate a variable
122 131 Q_UNUSED(variable);
123 132 return true;
124 133 }
125 134
126 135 bool VisualizationTabWidget::contains(const Variable &variable) const
127 136 {
128 137 Q_UNUSED(variable);
129 138 return false;
130 139 }
131 140
132 141 QString VisualizationTabWidget::name() const
133 142 {
134 143 return impl->m_Name;
135 144 }
136 145
137 146 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
138 147 {
139 148 // Closes zones in the tab
140 149 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
141 150
142 151 QWidget::closeEvent(event);
143 152 }
144 153
145 154 QLayout &VisualizationTabWidget::tabLayout() const noexcept
146 155 {
147 156 return *ui->dragDropContainer->layout();
148 157 }
149 158
150 159 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
151 160 {
152 161 auto& helper = sqpApp->dragDropHelper();
153 162 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH))
154 163 {
155 164 auto graphWidget = static_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
156 165 auto parentDragDropContainer = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
157 166 Q_ASSERT(parentDragDropContainer);
158 167
159 168 auto nbGraph = parentDragDropContainer->countDragWidget();
160 if (nbGraph == 1)
169
170 const auto& variables = graphWidget->variables();
171
172 if (!variables.isEmpty())
161 173 {
162 //This is the only graph in the previous zone, close the zone
163 graphWidget->parentZoneWidget()->close();
174 if (nbGraph == 1)
175 {
176 //This is the only graph in the previous zone, close the zone
177 graphWidget->parentZoneWidget()->close();
178 }
179 else
180 {
181 //Close the graph
182 graphWidget->close();
183 }
184
185 createZone(variables, index);
164 186 }
165 187 else
166 188 {
167 //Close the graph
168 graphWidget->close();
169 }
189 //The graph is empty, create an empty zone and move the graph inside
170 190
171 const auto& variables = graphWidget->variables();
172 createZone(variables, index);
191 auto parentZoneWidget = graphWidget->parentZoneWidget();
192
193 parentDragDropContainer->layout()->removeWidget(graphWidget);
194
195 auto zoneWidget = createEmptyZone(index);
196 zoneWidget->addGraph(graphWidget);
197
198 //Close the old zone if it was the only graph inside
199 if (nbGraph == 1)
200 parentZoneWidget->close();
201 }
173 202 }
174 203 else if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_ZONE))
175 204 {
176 205 //Simple move of the zone, no variable operation associated
177 206 auto zoneWidget = static_cast<VisualizationZoneWidget*>(helper.getCurrentDragWidget());
178 207 auto parentDragDropContainer = zoneWidget->parentWidget();
179 208 parentDragDropContainer->layout()->removeWidget(zoneWidget);
180 209
181 210 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
182 211 }
183 212 }
@@ -1,394 +1,406
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 <QUuid>
13 13 #include <SqpApplication.h>
14 14 #include <DragDropHelper.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, &VisualizationZoneWidget::dropMimeData);
82 82
83 83 // 'Close' options : widget is deleted when closed
84 84 setAttribute(Qt::WA_DeleteOnClose);
85 85 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
86 86 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
87 87
88 88 // Synchronisation id
89 89 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
90 90 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
91 91 }
92 92
93 93 VisualizationZoneWidget::~VisualizationZoneWidget()
94 94 {
95 95 delete ui;
96 96 }
97 97
98 98 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
99 99 {
100 100 // Synchronize new graph with others in the zone
101 101 impl->m_Synchronizer->addGraph(*graphWidget);
102 102
103 103 ui->dragDropContainer->addDragWidget(graphWidget);
104 104 }
105 105
106 106 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
107 107 {
108 108 // Synchronize new graph with others in the zone
109 109 impl->m_Synchronizer->addGraph(*graphWidget);
110 110
111 111 ui->dragDropContainer->insertDragWidget(index, graphWidget);
112 112 }
113 113
114 114 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
115 115 {
116 116 return createGraph(variable, -1);
117 117 }
118 118
119 119 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable, int index)
120 120 {
121 121 auto graphWidget = new VisualizationGraphWidget{
122 122 defaultGraphName(*ui->dragDropContainer->layout()), this};
123 123
124 124
125 125 // Set graph properties
126 126 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
127 127 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
128 128
129 129
130 130 // Lambda to synchronize zone widget
131 131 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
132 132 const SqpRange &oldGraphRange) {
133 133
134 134 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
135 135 auto frameLayout = ui->dragDropContainer->layout();
136 136 for (auto i = 0; i < frameLayout->count(); ++i) {
137 137 auto graphChild
138 138 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
139 139 if (graphChild && (graphChild != graphWidget)) {
140 140
141 141 auto graphChildRange = graphChild->graphRange();
142 142 switch (zoomType) {
143 143 case AcquisitionZoomType::ZoomIn: {
144 144 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
145 145 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
146 146 graphChildRange.m_TStart += deltaLeft;
147 147 graphChildRange.m_TEnd -= deltaRight;
148 148 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
149 149 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
150 150 << deltaLeft;
151 151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
152 152 << deltaRight;
153 153 qCDebug(LOG_VisualizationZoneWidget())
154 154 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
155 155
156 156 break;
157 157 }
158 158
159 159 case AcquisitionZoomType::ZoomOut: {
160 160 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
161 161 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
162 162 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
163 163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
164 164 << deltaLeft;
165 165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
166 166 << deltaRight;
167 167 qCDebug(LOG_VisualizationZoneWidget())
168 168 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
169 169 graphChildRange.m_TStart -= deltaLeft;
170 170 graphChildRange.m_TEnd += deltaRight;
171 171 break;
172 172 }
173 173 case AcquisitionZoomType::PanRight: {
174 174 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
175 175 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
176 176 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
177 177 graphChildRange.m_TStart += deltaLeft;
178 178 graphChildRange.m_TEnd += deltaRight;
179 179 qCDebug(LOG_VisualizationZoneWidget())
180 180 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
181 181 break;
182 182 }
183 183 case AcquisitionZoomType::PanLeft: {
184 184 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
185 185 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
186 186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
187 187 graphChildRange.m_TStart -= deltaLeft;
188 188 graphChildRange.m_TEnd -= deltaRight;
189 189 break;
190 190 }
191 191 case AcquisitionZoomType::Unknown: {
192 192 qCDebug(LOG_VisualizationZoneWidget())
193 193 << tr("Impossible to synchronize: zoom type unknown");
194 194 break;
195 195 }
196 196 default:
197 197 qCCritical(LOG_VisualizationZoneWidget())
198 198 << tr("Impossible to synchronize: zoom type not take into account");
199 199 // No action
200 200 break;
201 201 }
202 202 graphChild->enableAcquisition(false);
203 203 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
204 204 << graphChild->graphRange();
205 205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
206 206 << graphChildRange;
207 207 qCDebug(LOG_VisualizationZoneWidget())
208 208 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
209 209 graphChild->setGraphRange(graphChildRange);
210 210 graphChild->enableAcquisition(true);
211 211 }
212 212 }
213 213 };
214 214
215 215 // connection for synchronization
216 216 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
217 217 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
218 218 &VisualizationZoneWidget::onVariableAdded);
219 219 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
220 220 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
221 221
222 222 auto range = SqpRange{};
223 223
224 224 // Apply visitor to graph children
225 225 auto layout = ui->dragDropContainer->layout();
226 226 if (layout->count() > 0) {
227 227 // Case of a new graph in a existant zone
228 228 if (auto visualizationGraphWidget
229 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
229 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
230 230 range = visualizationGraphWidget->graphRange();
231 231 }
232 232 }
233 233 else {
234 234 // Case of a new graph as the first of the zone
235 235 range = variable->range();
236 236 }
237 237
238 238 this->insertGraph(index, graphWidget);
239 239
240 240 graphWidget->addVariable(variable, range);
241 241
242 242 // get y using variable range
243 243 if (auto dataSeries = variable->dataSeries()) {
244 244 dataSeries->lockRead();
245 245 auto valuesBounds
246 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
246 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
247 247 auto end = dataSeries->cend();
248 248 if (valuesBounds.first != end && valuesBounds.second != end) {
249 249 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
250 250
251 251 auto minValue = rangeValue(valuesBounds.first->minValue());
252 252 auto maxValue = rangeValue(valuesBounds.second->maxValue());
253 253
254 254 graphWidget->setYRange(SqpRange{minValue, maxValue});
255 255 }
256 256 dataSeries->unlock();
257 257 }
258 258
259 259 return graphWidget;
260 260 }
261 261
262 262 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
263 263 {
264 264 if (variables.isEmpty())
265 265 return nullptr;
266 266
267 267 auto graphWidget = createGraph(variables.first(), index);
268 268 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt)
269 269 {
270 270 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
271 271 }
272 272
273 273 return graphWidget;
274 274 }
275 275
276 276 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
277 277 {
278 278 if (visitor) {
279 279 visitor->visitEnter(this);
280 280
281 281 // Apply visitor to graph children: widgets different from graphs are not visited (no
282 282 // action)
283 283 processGraphs(
284 284 *ui->dragDropContainer->layout(),
285 285 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
286 286
287 287 visitor->visitLeave(this);
288 288 }
289 289 else {
290 290 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
291 291 }
292 292 }
293 293
294 294 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
295 295 {
296 296 // A tab can always accomodate a variable
297 297 Q_UNUSED(variable);
298 298 return true;
299 299 }
300 300
301 301 bool VisualizationZoneWidget::contains(const Variable &variable) const
302 302 {
303 303 Q_UNUSED(variable);
304 304 return false;
305 305 }
306 306
307 307 QString VisualizationZoneWidget::name() const
308 308 {
309 309 return ui->zoneNameLabel->text();
310 310 }
311 311
312 312 QMimeData *VisualizationZoneWidget::mimeData() const
313 313 {
314 314 auto *mimeData = new QMimeData;
315 315 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
316 316
317 317 return mimeData;
318 318 }
319 319
320 320 bool VisualizationZoneWidget::isDragAllowed() const
321 321 {
322 322 return true;
323 323 }
324 324
325 325 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
326 326 {
327 327 // Closes graphs in the zone
328 328 processGraphs(*ui->dragDropContainer->layout(),
329 329 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
330 330
331 331 // Delete synchronization group from variable controller
332 332 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
333 333 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
334 334
335 335 QWidget::closeEvent(event);
336 336 }
337 337
338 338 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
339 339 {
340 340 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
341 341 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
342 342 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
343 343 }
344 344
345 345 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
346 346 {
347 347 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
348 348 Q_ARG(std::shared_ptr<Variable>, variable),
349 349 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
350 350 }
351 351
352 352 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
353 353 {
354 354 auto& helper = sqpApp->dragDropHelper();
355 355 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH))
356 356 {
357 357 auto graphWidget = static_cast<VisualizationGraphWidget*>(helper.getCurrentDragWidget());
358 358 auto parentDragDropContainer = qobject_cast<VisualizationDragDropContainer*>(graphWidget->parentWidget());
359 359 Q_ASSERT(parentDragDropContainer);
360 360
361 361 const auto& variables = graphWidget->variables();
362 362
363 if (!variables.empty())
363 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty())
364 364 {
365 if (parentDragDropContainer != ui->dragDropContainer)
366 {
367 //The drop didn't occur in the same zone
365 //The drop didn't occur in the same zone
368 366
369 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
370 auto nbGraph = parentDragDropContainer->countDragWidget();
371 if (nbGraph == 1)
372 {
373 //This is the only graph in the previous zone, close the zone
374 previousParentZoneWidget->close();
375 }
376 else
377 {
378 //Close the graph
379 graphWidget->close();
380 }
381
382 //Creates the new graph in the zone
383 createGraph(variables, index);
367 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
368 auto nbGraph = parentDragDropContainer->countDragWidget();
369 if (nbGraph == 1)
370 {
371 //This is the only graph in the previous zone, close the zone
372 previousParentZoneWidget->close();
384 373 }
385 374 else
386 375 {
387 //The drop occurred in the same zone
388 //Simple move of the graph, no variable operation associated
389 parentDragDropContainer->layout()->removeWidget(graphWidget);
390 ui->dragDropContainer->insertDragWidget(index, graphWidget);
376 //Close the graph
377 graphWidget->close();
391 378 }
379
380 //Creates the new graph in the zone
381 createGraph(variables, index);
382 }
383 else
384 {
385 //The drop occurred in the same zone or the graph is empty
386 //Simple move of the graph, no variable operation associated
387 parentDragDropContainer->layout()->removeWidget(graphWidget);
388
389 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer)
390 {
391 // The graph is empty and dropped in a different zone.
392 // Take the range of the first graph in the zone (if existing).
393 auto layout = ui->dragDropContainer->layout();
394 if (layout->count() > 0)
395 {
396 if (auto visualizationGraphWidget = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget()))
397 {
398 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
399 }
400 }
401 }
402
403 ui->dragDropContainer->insertDragWidget(index, graphWidget);
392 404 }
393 405 }
394 406 }
General Comments 0
You need to be logged in to leave comments. Login now