##// END OF EJS Templates
Removes synchronisation group from Variable controller when a zone is being closed
Alexandre Leroux -
r739:0435199fe310
parent child
Show More
@@ -1,298 +1,302
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 <cmath>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
17 17
18 18 namespace {
19 19
20 20 /// Minimum height for graph added in zones (in pixels)
21 21 const auto GRAPH_MINIMUM_HEIGHT = 300;
22 22
23 23 /// Generates a default name for a new graph, according to the number of graphs already displayed in
24 24 /// the zone
25 25 QString defaultGraphName(const QLayout &layout)
26 26 {
27 27 auto count = 0;
28 28 for (auto i = 0; i < layout.count(); ++i) {
29 29 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
30 30 count++;
31 31 }
32 32 }
33 33
34 34 return QObject::tr("Graph %1").arg(count + 1);
35 35 }
36 36
37 37 /**
38 38 * Applies a function to all graphs of the zone represented by its layout
39 39 * @param layout the layout that contains graphs
40 40 * @param fun the function to apply to each graph
41 41 */
42 42 template <typename Fun>
43 43 void processGraphs(QLayout &layout, Fun fun)
44 44 {
45 45 for (auto i = 0; i < layout.count(); ++i) {
46 46 if (auto item = layout.itemAt(i)) {
47 47 if (auto visualizationGraphWidget
48 48 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
49 49 fun(*visualizationGraphWidget);
50 50 }
51 51 }
52 52 }
53 53 }
54 54
55 55 } // namespace
56 56
57 57 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
58 58
59 59 explicit VisualizationZoneWidgetPrivate()
60 60 : m_SynchronisationGroupId{QUuid::createUuid()},
61 61 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
62 62 {
63 63 }
64 64 QUuid m_SynchronisationGroupId;
65 65 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
66 66 };
67 67
68 68 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
69 69 : QWidget{parent},
70 70 ui{new Ui::VisualizationZoneWidget},
71 71 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
72 72 {
73 73 ui->setupUi(this);
74 74
75 75 ui->zoneNameLabel->setText(name);
76 76
77 77 // 'Close' options : widget is deleted when closed
78 78 setAttribute(Qt::WA_DeleteOnClose);
79 79 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
80 80 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
81 81
82 82 // Synchronisation id
83 83 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
84 84 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
85 85 }
86 86
87 87 VisualizationZoneWidget::~VisualizationZoneWidget()
88 88 {
89 89 delete ui;
90 90 }
91 91
92 92 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
93 93 {
94 94 // Synchronize new graph with others in the zone
95 95 impl->m_Synchronizer->addGraph(*graphWidget);
96 96
97 97 ui->visualizationZoneFrame->layout()->addWidget(graphWidget);
98 98 }
99 99
100 100 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
101 101 {
102 102 auto graphWidget = new VisualizationGraphWidget{
103 103 defaultGraphName(*ui->visualizationZoneFrame->layout()), this};
104 104
105 105
106 106 // Set graph properties
107 107 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
108 108 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
109 109
110 110
111 111 // Lambda to synchronize zone widget
112 112 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
113 113 const SqpRange &oldGraphRange) {
114 114
115 115 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
116 116 auto frameLayout = ui->visualizationZoneFrame->layout();
117 117 for (auto i = 0; i < frameLayout->count(); ++i) {
118 118 auto graphChild
119 119 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
120 120 if (graphChild && (graphChild != graphWidget)) {
121 121
122 122 auto graphChildRange = graphChild->graphRange();
123 123 switch (zoomType) {
124 124 case AcquisitionZoomType::ZoomIn: {
125 125 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
126 126 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
127 127 graphChildRange.m_TStart += deltaLeft;
128 128 graphChildRange.m_TEnd -= deltaRight;
129 129 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
130 130 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
131 131 << deltaLeft;
132 132 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
133 133 << deltaRight;
134 134 qCDebug(LOG_VisualizationZoneWidget())
135 135 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
136 136
137 137 break;
138 138 }
139 139
140 140 case AcquisitionZoomType::ZoomOut: {
141 141 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
142 142 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
143 143 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
144 144 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
145 145 << deltaLeft;
146 146 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
147 147 << deltaRight;
148 148 qCDebug(LOG_VisualizationZoneWidget())
149 149 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
150 150 graphChildRange.m_TStart -= deltaLeft;
151 151 graphChildRange.m_TEnd += deltaRight;
152 152 break;
153 153 }
154 154 case AcquisitionZoomType::PanRight: {
155 155 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
156 156 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
157 157 graphChildRange.m_TStart += deltaRight;
158 158 graphChildRange.m_TEnd += deltaRight;
159 159 qCDebug(LOG_VisualizationZoneWidget())
160 160 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
161 161 break;
162 162 }
163 163 case AcquisitionZoomType::PanLeft: {
164 164 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
165 165 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
166 166 graphChildRange.m_TStart -= deltaLeft;
167 167 graphChildRange.m_TEnd -= deltaLeft;
168 168 break;
169 169 }
170 170 case AcquisitionZoomType::Unknown: {
171 171 qCDebug(LOG_VisualizationZoneWidget())
172 172 << tr("Impossible to synchronize: zoom type unknown");
173 173 break;
174 174 }
175 175 default:
176 176 qCCritical(LOG_VisualizationZoneWidget())
177 177 << tr("Impossible to synchronize: zoom type not take into account");
178 178 // No action
179 179 break;
180 180 }
181 181 graphChild->enableAcquisition(false);
182 182 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
183 183 << graphChild->graphRange();
184 184 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
185 185 << graphChildRange;
186 186 qCDebug(LOG_VisualizationZoneWidget())
187 187 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
188 188 graphChild->setGraphRange(graphChildRange);
189 189 graphChild->enableAcquisition(true);
190 190 }
191 191 }
192 192 };
193 193
194 194 // connection for synchronization
195 195 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
196 196 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
197 197 &VisualizationZoneWidget::onVariableAdded);
198 198 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
199 199 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
200 200
201 201 auto range = SqpRange{};
202 202
203 203 // Apply visitor to graph children
204 204 auto layout = ui->visualizationZoneFrame->layout();
205 205 if (layout->count() > 0) {
206 206 // Case of a new graph in a existant zone
207 207 if (auto visualizationGraphWidget
208 208 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
209 209 range = visualizationGraphWidget->graphRange();
210 210 }
211 211 }
212 212 else {
213 213 // Case of a new graph as the first of the zone
214 214 range = variable->range();
215 215 }
216 216
217 217 this->addGraph(graphWidget);
218 218
219 219 graphWidget->addVariable(variable, range);
220 220
221 221 // get y using variable range
222 222 if (auto dataSeries = variable->dataSeries()) {
223 223 dataSeries->lockRead();
224 224 auto valuesBounds
225 225 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
226 226 auto end = dataSeries->cend();
227 227 if (valuesBounds.first != end && valuesBounds.second != end) {
228 228 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
229 229
230 230 auto minValue = rangeValue(valuesBounds.first->minValue());
231 231 auto maxValue = rangeValue(valuesBounds.second->maxValue());
232 232
233 233 graphWidget->setYRange(SqpRange{minValue, maxValue});
234 234 }
235 235 dataSeries->unlock();
236 236 }
237 237
238 238 return graphWidget;
239 239 }
240 240
241 241 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
242 242 {
243 243 if (visitor) {
244 244 visitor->visitEnter(this);
245 245
246 246 // Apply visitor to graph children: widgets different from graphs are not visited (no
247 247 // action)
248 248 processGraphs(
249 249 *ui->visualizationZoneFrame->layout(),
250 250 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
251 251
252 252 visitor->visitLeave(this);
253 253 }
254 254 else {
255 255 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
256 256 }
257 257 }
258 258
259 259 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
260 260 {
261 261 // A tab can always accomodate a variable
262 262 Q_UNUSED(variable);
263 263 return true;
264 264 }
265 265
266 266 bool VisualizationZoneWidget::contains(const Variable &variable) const
267 267 {
268 268 Q_UNUSED(variable);
269 269 return false;
270 270 }
271 271
272 272 QString VisualizationZoneWidget::name() const
273 273 {
274 274 return ui->zoneNameLabel->text();
275 275 }
276 276
277 277 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
278 278 {
279 279 // Closes graphs in the zone
280 280 processGraphs(*ui->visualizationZoneFrame->layout(),
281 281 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
282 282
283 // Delete synchronization group from variable controller
284 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
285 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
286
283 287 QWidget::closeEvent(event);
284 288 }
285 289
286 290 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
287 291 {
288 292 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
289 293 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
290 294 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
291 295 }
292 296
293 297 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
294 298 {
295 299 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
296 300 Q_ARG(std::shared_ptr<Variable>, variable),
297 301 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
298 302 }
General Comments 0
You need to be logged in to leave comments. Login now