##// END OF EJS Templates
Product field now display products event list instead of only its size
perrinel -
r1364:6ea80a9a6c65
parent child
Show More
@@ -1,472 +1,478
1 #include "Catalogue/CatalogueEventsModel.h"
1 #include "Catalogue/CatalogueEventsModel.h"
2
2
3 #include <Catalogue/CatalogueController.h>
3 #include <Catalogue/CatalogueController.h>
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6 #include <DBEvent.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
8 #include <DBTag.h>
9 #include <Data/SqpRange.h>
9 #include <Data/SqpRange.h>
10 #include <SqpApplication.h>
10 #include <SqpApplication.h>
11 #include <Time/TimeController.h>
11 #include <Time/TimeController.h>
12
12
13 #include <list>
13 #include <list>
14 #include <unordered_map>
14 #include <unordered_map>
15
15
16 #include <QHash>
16 #include <QHash>
17 #include <QMimeData>
17 #include <QMimeData>
18
18
19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
20
20
21 const auto EVENT_ITEM_TYPE = 1;
21 const auto EVENT_ITEM_TYPE = 1;
22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
22 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
23
23
24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
24 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
25 QVector<std::shared_ptr<DBEvent> > m_Events;
25 QVector<std::shared_ptr<DBEvent> > m_Events;
26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
26 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
27 QVector<std::shared_ptr<DBCatalogue> > m_SourceCatalogue;
27 QVector<std::shared_ptr<DBCatalogue> > m_SourceCatalogue;
28
28
29 QStringList columnNames()
29 QStringList columnNames()
30 {
30 {
31 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
31 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
32 tr("Tags"), tr("Product"), tr("")};
32 tr("Tags"), tr("Product"), tr("")};
33 }
33 }
34
34
35 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
35 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
36 {
36 {
37 if (col == (int)CatalogueEventsModel::Column::Validation) {
37 if (col == (int)CatalogueEventsModel::Column::Validation) {
38 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
38 auto hasChanges = sqpApp->catalogueController().eventHasChanges(event);
39 return hasChanges ? true : QVariant();
39 return hasChanges ? true : QVariant();
40 }
40 }
41
41
42 return eventData(col, event);
42 return eventData(col, event);
43 }
43 }
44
44
45 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
45 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
46 {
46 {
47 switch (static_cast<Column>(col)) {
47 switch (static_cast<Column>(col)) {
48 case CatalogueEventsModel::Column::Name:
48 case CatalogueEventsModel::Column::Name:
49 return event->getName();
49 return event->getName();
50 case CatalogueEventsModel::Column::TStart:
50 case CatalogueEventsModel::Column::TStart:
51 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
51 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
52 : QVariant{};
52 : QVariant{};
53 case CatalogueEventsModel::Column::TEnd:
53 case CatalogueEventsModel::Column::TEnd:
54 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
54 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
55 : QVariant{};
55 : QVariant{};
56 case CatalogueEventsModel::Column::Product:
56 case CatalogueEventsModel::Column::Product: {
57 return QString::number(nbEventProducts(event)) + " product(s)";
57 auto eventProducts = event->getEventProducts();
58 QStringList eventProductList;
59 for (auto evtProduct : eventProducts) {
60 eventProductList << evtProduct.getProductId();
61 }
62 return eventProductList.join(";");
63 }
58 case CatalogueEventsModel::Column::Tags: {
64 case CatalogueEventsModel::Column::Tags: {
59 QString tagList;
65 QString tagList;
60 auto tags = event->getTags();
66 auto tags = event->getTags();
61 for (auto tag : tags) {
67 for (auto tag : tags) {
62 tagList += tag.getName();
68 tagList += tag.getName();
63 tagList += ' ';
69 tagList += ' ';
64 }
70 }
65
71
66 return tagList;
72 return tagList;
67 }
73 }
68 case CatalogueEventsModel::Column::Validation:
74 case CatalogueEventsModel::Column::Validation:
69 return QVariant();
75 return QVariant();
70 default:
76 default:
71 break;
77 break;
72 }
78 }
73
79
74 Q_ASSERT(false);
80 Q_ASSERT(false);
75 return QStringLiteral("Unknown Data");
81 return QStringLiteral("Unknown Data");
76 }
82 }
77
83
78 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
84 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
79 {
85 {
80 for (auto product : event->getEventProducts()) {
86 for (auto product : event->getEventProducts()) {
81 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
87 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
82 }
88 }
83 }
89 }
84
90
85 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
91 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
86 {
92 {
87 auto eventProductsIt = m_EventProducts.find(event.get());
93 auto eventProductsIt = m_EventProducts.find(event.get());
88 if (eventProductsIt != m_EventProducts.cend()) {
94 if (eventProductsIt != m_EventProducts.cend()) {
89 return m_EventProducts.at(event.get()).count();
95 return m_EventProducts.at(event.get()).count();
90 }
96 }
91 else {
97 else {
92 return 0;
98 return 0;
93 }
99 }
94 }
100 }
95
101
96 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
102 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
97 {
103 {
98 switch (static_cast<Column>(col)) {
104 switch (static_cast<Column>(col)) {
99 case CatalogueEventsModel::Column::Name:
105 case CatalogueEventsModel::Column::Name:
100 return eventProduct->getProductId();
106 return eventProduct->getProductId();
101 case CatalogueEventsModel::Column::TStart:
107 case CatalogueEventsModel::Column::TStart:
102 return DateUtils::dateTime(eventProduct->getTStart());
108 return DateUtils::dateTime(eventProduct->getTStart());
103 case CatalogueEventsModel::Column::TEnd:
109 case CatalogueEventsModel::Column::TEnd:
104 return DateUtils::dateTime(eventProduct->getTEnd());
110 return DateUtils::dateTime(eventProduct->getTEnd());
105 case CatalogueEventsModel::Column::Product:
111 case CatalogueEventsModel::Column::Product:
106 return eventProduct->getProductId();
112 return eventProduct->getProductId();
107 case CatalogueEventsModel::Column::Tags:
113 case CatalogueEventsModel::Column::Tags:
108 return QString();
114 return QString();
109 case CatalogueEventsModel::Column::Validation:
115 case CatalogueEventsModel::Column::Validation:
110 return QVariant();
116 return QVariant();
111 default:
117 default:
112 break;
118 break;
113 }
119 }
114
120
115 Q_ASSERT(false);
121 Q_ASSERT(false);
116 return QStringLiteral("Unknown Data");
122 return QStringLiteral("Unknown Data");
117 }
123 }
118
124
119 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
125 void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const
120 {
126 {
121 auto childCount = model->rowCount(index);
127 auto childCount = model->rowCount(index);
122 auto colCount = model->columnCount();
128 auto colCount = model->columnCount();
123 emit model->dataChanged(model->index(0, 0, index),
129 emit model->dataChanged(model->index(0, 0, index),
124 model->index(childCount, colCount, index));
130 model->index(childCount, colCount, index));
125 }
131 }
126 };
132 };
127
133
128 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
134 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
129 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
135 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
130 {
136 {
131 }
137 }
132
138
133 void CatalogueEventsModel::setSourceCatalogues(
139 void CatalogueEventsModel::setSourceCatalogues(
134 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
140 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
135 {
141 {
136 impl->m_SourceCatalogue = catalogues;
142 impl->m_SourceCatalogue = catalogues;
137 }
143 }
138
144
139 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
145 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
140 {
146 {
141 beginResetModel();
147 beginResetModel();
142
148
143 impl->m_Events = events;
149 impl->m_Events = events;
144 impl->m_EventProducts.clear();
150 impl->m_EventProducts.clear();
145 for (auto event : events) {
151 for (auto event : events) {
146 impl->parseEventProduct(event);
152 impl->parseEventProduct(event);
147 }
153 }
148
154
149 endResetModel();
155 endResetModel();
150 }
156 }
151
157
152 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
158 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
153 {
159 {
154 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
160 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
155 return impl->m_Events.value(index.row());
161 return impl->m_Events.value(index.row());
156 }
162 }
157 else {
163 else {
158 return nullptr;
164 return nullptr;
159 }
165 }
160 }
166 }
161
167
162 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
168 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
163 {
169 {
164 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
170 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
165 return getEvent(index.parent());
171 return getEvent(index.parent());
166 }
172 }
167 else {
173 else {
168 return nullptr;
174 return nullptr;
169 }
175 }
170 }
176 }
171
177
172 std::shared_ptr<DBEventProduct>
178 std::shared_ptr<DBEventProduct>
173 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
179 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
174 {
180 {
175 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
181 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
176 auto event = static_cast<DBEvent *>(index.internalPointer());
182 auto event = static_cast<DBEvent *>(index.internalPointer());
177 return impl->m_EventProducts.at(event).value(index.row());
183 return impl->m_EventProducts.at(event).value(index.row());
178 }
184 }
179 else {
185 else {
180 return nullptr;
186 return nullptr;
181 }
187 }
182 }
188 }
183
189
184 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
190 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
185 {
191 {
186 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
192 beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count());
187 impl->m_Events.append(event);
193 impl->m_Events.append(event);
188 impl->parseEventProduct(event);
194 impl->parseEventProduct(event);
189 endInsertRows();
195 endInsertRows();
190
196
191 // Also refreshes its children event products
197 // Also refreshes its children event products
192 auto eventIndex = index(impl->m_Events.count(), 0);
198 auto eventIndex = index(impl->m_Events.count(), 0);
193 impl->refreshChildrenOfIndex(this, eventIndex);
199 impl->refreshChildrenOfIndex(this, eventIndex);
194 }
200 }
195
201
196 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
202 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
197 {
203 {
198 auto index = impl->m_Events.indexOf(event);
204 auto index = impl->m_Events.indexOf(event);
199 if (index >= 0) {
205 if (index >= 0) {
200 beginRemoveRows(QModelIndex(), index, index);
206 beginRemoveRows(QModelIndex(), index, index);
201 impl->m_Events.removeAt(index);
207 impl->m_Events.removeAt(index);
202 impl->m_EventProducts.erase(event.get());
208 impl->m_EventProducts.erase(event.get());
203 endRemoveRows();
209 endRemoveRows();
204 }
210 }
205 }
211 }
206
212
207 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
213 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
208 {
214 {
209 return impl->m_Events;
215 return impl->m_Events;
210 }
216 }
211
217
212 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
218 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event,
213 bool refreshEventProducts)
219 bool refreshEventProducts)
214 {
220 {
215 auto eventIndex = indexOf(event);
221 auto eventIndex = indexOf(event);
216 if (eventIndex.isValid()) {
222 if (eventIndex.isValid()) {
217
223
218 if (refreshEventProducts) {
224 if (refreshEventProducts) {
219 // Reparse the associated event products
225 // Reparse the associated event products
220
226
221 auto nbEventProducts = impl->nbEventProducts(event);
227 auto nbEventProducts = impl->nbEventProducts(event);
222 auto newNbOfEventProducts = event->getEventProducts().size();
228 auto newNbOfEventProducts = event->getEventProducts().size();
223 if (newNbOfEventProducts < nbEventProducts) {
229 if (newNbOfEventProducts < nbEventProducts) {
224 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
230 beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1);
225 impl->m_EventProducts.erase(event.get());
231 impl->m_EventProducts.erase(event.get());
226 impl->parseEventProduct(event);
232 impl->parseEventProduct(event);
227 endRemoveRows();
233 endRemoveRows();
228 }
234 }
229 else if (newNbOfEventProducts > nbEventProducts) {
235 else if (newNbOfEventProducts > nbEventProducts) {
230 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
236 beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1);
231 impl->m_EventProducts.erase(event.get());
237 impl->m_EventProducts.erase(event.get());
232 impl->parseEventProduct(event);
238 impl->parseEventProduct(event);
233 endInsertRows();
239 endInsertRows();
234 }
240 }
235 else { // newNbOfEventProducts == nbEventProducts
241 else { // newNbOfEventProducts == nbEventProducts
236 impl->m_EventProducts.erase(event.get());
242 impl->m_EventProducts.erase(event.get());
237 impl->parseEventProduct(event);
243 impl->parseEventProduct(event);
238 }
244 }
239 }
245 }
240
246
241 // Refreshes the event line
247 // Refreshes the event line
242 auto colCount = columnCount();
248 auto colCount = columnCount();
243 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
249 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
244
250
245 // Also refreshes its children event products
251 // Also refreshes its children event products
246 impl->refreshChildrenOfIndex(this, eventIndex);
252 impl->refreshChildrenOfIndex(this, eventIndex);
247 }
253 }
248 else {
254 else {
249 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
255 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
250 }
256 }
251 }
257 }
252
258
253 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
259 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
254 {
260 {
255 auto row = impl->m_Events.indexOf(event);
261 auto row = impl->m_Events.indexOf(event);
256 if (row >= 0) {
262 if (row >= 0) {
257 return index(row, 0);
263 return index(row, 0);
258 }
264 }
259
265
260 return QModelIndex();
266 return QModelIndex();
261 }
267 }
262
268
263 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
269 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
264 {
270 {
265 if (!hasIndex(row, column, parent)) {
271 if (!hasIndex(row, column, parent)) {
266 return QModelIndex();
272 return QModelIndex();
267 }
273 }
268
274
269 switch (itemTypeOf(parent)) {
275 switch (itemTypeOf(parent)) {
270 case CatalogueEventsModel::ItemType::Root:
276 case CatalogueEventsModel::ItemType::Root:
271 return createIndex(row, column);
277 return createIndex(row, column);
272 case CatalogueEventsModel::ItemType::Event: {
278 case CatalogueEventsModel::ItemType::Event: {
273 auto event = getEvent(parent);
279 auto event = getEvent(parent);
274 return createIndex(row, column, event.get());
280 return createIndex(row, column, event.get());
275 }
281 }
276 case CatalogueEventsModel::ItemType::EventProduct:
282 case CatalogueEventsModel::ItemType::EventProduct:
277 break;
283 break;
278 default:
284 default:
279 break;
285 break;
280 }
286 }
281
287
282 return QModelIndex();
288 return QModelIndex();
283 }
289 }
284
290
285 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
291 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
286 {
292 {
287 switch (itemTypeOf(index)) {
293 switch (itemTypeOf(index)) {
288 case CatalogueEventsModel::ItemType::EventProduct: {
294 case CatalogueEventsModel::ItemType::EventProduct: {
289 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
295 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
290 auto it
296 auto it
291 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
297 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
292 [parentEvent](auto event) { return event.get() == parentEvent; });
298 [parentEvent](auto event) { return event.get() == parentEvent; });
293
299
294 if (it != impl->m_Events.cend()) {
300 if (it != impl->m_Events.cend()) {
295 return createIndex(it - impl->m_Events.cbegin(), 0);
301 return createIndex(it - impl->m_Events.cbegin(), 0);
296 }
302 }
297 else {
303 else {
298 return QModelIndex();
304 return QModelIndex();
299 }
305 }
300 }
306 }
301 case CatalogueEventsModel::ItemType::Root:
307 case CatalogueEventsModel::ItemType::Root:
302 break;
308 break;
303 case CatalogueEventsModel::ItemType::Event:
309 case CatalogueEventsModel::ItemType::Event:
304 break;
310 break;
305 default:
311 default:
306 break;
312 break;
307 }
313 }
308
314
309 return QModelIndex();
315 return QModelIndex();
310 }
316 }
311
317
312 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
318 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
313 {
319 {
314 if (parent.column() > 0) {
320 if (parent.column() > 0) {
315 return 0;
321 return 0;
316 }
322 }
317
323
318 switch (itemTypeOf(parent)) {
324 switch (itemTypeOf(parent)) {
319 case CatalogueEventsModel::ItemType::Root:
325 case CatalogueEventsModel::ItemType::Root:
320 return impl->m_Events.count();
326 return impl->m_Events.count();
321 case CatalogueEventsModel::ItemType::Event: {
327 case CatalogueEventsModel::ItemType::Event: {
322 auto event = getEvent(parent);
328 auto event = getEvent(parent);
323 return impl->m_EventProducts[event.get()].count();
329 return impl->m_EventProducts[event.get()].count();
324 }
330 }
325 case CatalogueEventsModel::ItemType::EventProduct:
331 case CatalogueEventsModel::ItemType::EventProduct:
326 break;
332 break;
327 default:
333 default:
328 break;
334 break;
329 }
335 }
330
336
331 return 0;
337 return 0;
332 }
338 }
333
339
334 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
340 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
335 {
341 {
336 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
342 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
337 }
343 }
338
344
339 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
345 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
340 {
346 {
341 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
347 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
342 }
348 }
343
349
344 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
350 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
345 {
351 {
346 if (index.isValid()) {
352 if (index.isValid()) {
347
353
348 auto type = itemTypeOf(index);
354 auto type = itemTypeOf(index);
349 if (type == CatalogueEventsModel::ItemType::Event) {
355 if (type == CatalogueEventsModel::ItemType::Event) {
350 auto event = getEvent(index);
356 auto event = getEvent(index);
351 switch (role) {
357 switch (role) {
352 case Qt::DisplayRole:
358 case Qt::DisplayRole:
353 return impl->eventData(index.column(), event);
359 return impl->eventData(index.column(), event);
354 break;
360 break;
355 }
361 }
356 }
362 }
357 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
363 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
358 auto product = getEventProduct(index);
364 auto product = getEventProduct(index);
359 switch (role) {
365 switch (role) {
360 case Qt::DisplayRole:
366 case Qt::DisplayRole:
361 return impl->eventProductData(index.column(), product);
367 return impl->eventProductData(index.column(), product);
362 break;
368 break;
363 }
369 }
364 }
370 }
365 }
371 }
366
372
367 return QVariant{};
373 return QVariant{};
368 }
374 }
369
375
370 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
376 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
371 {
377 {
372 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
378 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
373 return impl->columnNames().value(section);
379 return impl->columnNames().value(section);
374 }
380 }
375
381
376 return QVariant();
382 return QVariant();
377 }
383 }
378
384
379 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
385 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
380 {
386 {
381 beginResetModel();
387 beginResetModel();
382 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
388 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
383 [this, column, order](auto e1, auto e2) {
389 [this, column, order](auto e1, auto e2) {
384 auto data1 = impl->sortData(column, e1);
390 auto data1 = impl->sortData(column, e1);
385 auto data2 = impl->sortData(column, e2);
391 auto data2 = impl->sortData(column, e2);
386
392
387 auto result = data1.toString() < data2.toString();
393 auto result = data1.toString() < data2.toString();
388
394
389 return order == Qt::AscendingOrder ? result : !result;
395 return order == Qt::AscendingOrder ? result : !result;
390 });
396 });
391
397
392 endResetModel();
398 endResetModel();
393 emit modelSorted();
399 emit modelSorted();
394 }
400 }
395
401
396 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
402 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
397 {
403 {
398 return Qt::CopyAction | Qt::MoveAction;
404 return Qt::CopyAction | Qt::MoveAction;
399 }
405 }
400
406
401 QStringList CatalogueEventsModel::mimeTypes() const
407 QStringList CatalogueEventsModel::mimeTypes() const
402 {
408 {
403 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
409 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_SOURCE_CATALOGUE_LIST, MIME_TYPE_TIME_RANGE};
404 }
410 }
405
411
406 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
412 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
407 {
413 {
408 auto mimeData = new QMimeData;
414 auto mimeData = new QMimeData;
409
415
410 bool isFirst = true;
416 bool isFirst = true;
411
417
412 QVector<std::shared_ptr<DBEvent> > eventList;
418 QVector<std::shared_ptr<DBEvent> > eventList;
413 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
419 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
414
420
415 SqpRange firstTimeRange;
421 SqpRange firstTimeRange;
416 for (const auto &index : indexes) {
422 for (const auto &index : indexes) {
417 if (index.column() == 0) { // only the first column
423 if (index.column() == 0) { // only the first column
418
424
419 auto type = itemTypeOf(index);
425 auto type = itemTypeOf(index);
420 if (type == ItemType::Event) {
426 if (type == ItemType::Event) {
421 auto event = getEvent(index);
427 auto event = getEvent(index);
422 eventList << event;
428 eventList << event;
423
429
424 if (isFirst) {
430 if (isFirst) {
425 isFirst = false;
431 isFirst = false;
426 firstTimeRange.m_TStart = event->getTStart();
432 firstTimeRange.m_TStart = event->getTStart();
427 firstTimeRange.m_TEnd = event->getTEnd();
433 firstTimeRange.m_TEnd = event->getTEnd();
428 }
434 }
429 }
435 }
430 else if (type == ItemType::EventProduct) {
436 else if (type == ItemType::EventProduct) {
431 auto product = getEventProduct(index);
437 auto product = getEventProduct(index);
432 eventProductList << product;
438 eventProductList << product;
433
439
434 if (isFirst) {
440 if (isFirst) {
435 isFirst = false;
441 isFirst = false;
436 firstTimeRange.m_TStart = product->getTStart();
442 firstTimeRange.m_TStart = product->getTStart();
437 firstTimeRange.m_TEnd = product->getTEnd();
443 firstTimeRange.m_TEnd = product->getTEnd();
438 }
444 }
439 }
445 }
440 }
446 }
441 }
447 }
442
448
443 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
449 if (!eventList.isEmpty() && eventProductList.isEmpty()) {
444 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
450 auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList);
445 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
451 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
446
452
447 auto sourceCataloguesEncodedData
453 auto sourceCataloguesEncodedData
448 = sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
454 = sqpApp->catalogueController().mimeDataForCatalogues(impl->m_SourceCatalogue);
449 mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
455 mimeData->setData(MIME_TYPE_SOURCE_CATALOGUE_LIST, sourceCataloguesEncodedData);
450 }
456 }
451
457
452 if (eventList.count() + eventProductList.count() == 1) {
458 if (eventList.count() + eventProductList.count() == 1) {
453 // No time range MIME data if multiple events are dragged
459 // No time range MIME data if multiple events are dragged
454 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
460 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
455 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
461 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
456 }
462 }
457
463
458 return mimeData;
464 return mimeData;
459 }
465 }
460
466
461 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
467 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
462 {
468 {
463 if (!index.isValid()) {
469 if (!index.isValid()) {
464 return ItemType::Root;
470 return ItemType::Root;
465 }
471 }
466 else if (index.internalPointer() == nullptr) {
472 else if (index.internalPointer() == nullptr) {
467 return ItemType::Event;
473 return ItemType::Event;
468 }
474 }
469 else {
475 else {
470 return ItemType::EventProduct;
476 return ItemType::EventProduct;
471 }
477 }
472 }
478 }
@@ -1,227 +1,233
1 #include "Catalogue/CatalogueInspectorWidget.h"
1 #include "Catalogue/CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
2 #include "ui_CatalogueInspectorWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <DBCatalogue.h>
5 #include <DBCatalogue.h>
6 #include <DBEvent.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
8 #include <DBTag.h>
9
9
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
14
14
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
16 Ui::CatalogueInspectorWidget *ui);
16 Ui::CatalogueInspectorWidget *ui);
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
18 Ui::CatalogueInspectorWidget *ui);
18 Ui::CatalogueInspectorWidget *ui);
19 };
19 };
20
20
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
22 : QWidget(parent),
22 : QWidget(parent),
23 ui(new Ui::CatalogueInspectorWidget),
23 ui(new Ui::CatalogueInspectorWidget),
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
25 {
25 {
26 ui->setupUi(this);
26 ui->setupUi(this);
27 showPage(Page::Empty);
27 showPage(Page::Empty);
28
28
29 impl->connectCatalogueUpdateSignals(this, ui);
29 impl->connectCatalogueUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
31 }
31 }
32
32
33 CatalogueInspectorWidget::~CatalogueInspectorWidget()
33 CatalogueInspectorWidget::~CatalogueInspectorWidget()
34 {
34 {
35 delete ui;
35 delete ui;
36 }
36 }
37
37
38 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
38 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
39 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
39 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
40 {
40 {
41 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
41 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
42 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
42 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
43 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
43 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
44 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
44 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
45 }
45 }
46 });
46 });
47
47
48 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
48 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
49 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
49 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
50 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
50 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
51 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
51 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
52 }
52 }
53 });
53 });
54 }
54 }
55
55
56 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
56 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
57 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
57 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
58 {
58 {
59 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
59 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
60 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
60 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
61 m_DisplayedEvent->setName(ui->leEventName->text());
61 m_DisplayedEvent->setName(ui->leEventName->text());
62 emit inspector->eventUpdated(m_DisplayedEvent);
62 emit inspector->eventUpdated(m_DisplayedEvent);
63 }
63 }
64 });
64 });
65
65
66 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
66 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
67 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
67 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"), QString::SkipEmptyParts);
68 std::list<QString> tagNames;
68 std::list<QString> tagNames;
69 for (auto tag : tags) {
69 for (auto tag : tags) {
70 tagNames.push_back(tag);
70 tagNames.push_back(tag);
71 }
71 }
72
72
73 if (m_DisplayedEvent->getTagsNames() != tagNames) {
73 if (m_DisplayedEvent->getTagsNames() != tagNames) {
74 m_DisplayedEvent->setTagsNames(tagNames);
74 m_DisplayedEvent->setTagsNames(tagNames);
75 emit inspector->eventUpdated(m_DisplayedEvent);
75 emit inspector->eventUpdated(m_DisplayedEvent);
76 }
76 }
77 });
77 });
78
78
79 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
79 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
80 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
80 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
81 auto oldProductId = m_DisplayedEventProduct->getProductId();
81 auto oldProductId = m_DisplayedEventProduct->getProductId();
82 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
82 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
83
83
84 auto eventProducts = m_DisplayedEvent->getEventProducts();
84 auto eventProducts = m_DisplayedEvent->getEventProducts();
85 for (auto &eventProduct : eventProducts) {
85 for (auto &eventProduct : eventProducts) {
86 if (eventProduct.getProductId() == oldProductId) {
86 if (eventProduct.getProductId() == oldProductId) {
87 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
87 eventProduct.setProductId(m_DisplayedEventProduct->getProductId());
88 }
88 }
89 }
89 }
90 m_DisplayedEvent->setEventProducts(eventProducts);
90 m_DisplayedEvent->setEventProducts(eventProducts);
91
91
92 emit inspector->eventUpdated(m_DisplayedEvent);
92 emit inspector->eventUpdated(m_DisplayedEvent);
93 }
93 }
94 });
94 });
95
95
96 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
96 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
97 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
97 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
98 if (time != m_DisplayedEventProduct->getTStart()) {
98 if (time != m_DisplayedEventProduct->getTStart()) {
99 m_DisplayedEventProduct->setTStart(time);
99 m_DisplayedEventProduct->setTStart(time);
100
100
101 auto eventProducts = m_DisplayedEvent->getEventProducts();
101 auto eventProducts = m_DisplayedEvent->getEventProducts();
102 for (auto &eventProduct : eventProducts) {
102 for (auto &eventProduct : eventProducts) {
103 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
103 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
104 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
104 eventProduct.setTStart(m_DisplayedEventProduct->getTStart());
105 }
105 }
106 }
106 }
107 m_DisplayedEvent->setEventProducts(eventProducts);
107 m_DisplayedEvent->setEventProducts(eventProducts);
108
108
109 emit inspector->eventUpdated(m_DisplayedEvent);
109 emit inspector->eventUpdated(m_DisplayedEvent);
110 }
110 }
111 });
111 });
112
112
113 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
113 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
114 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
114 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
115 if (time != m_DisplayedEventProduct->getTEnd()) {
115 if (time != m_DisplayedEventProduct->getTEnd()) {
116 m_DisplayedEventProduct->setTEnd(time);
116 m_DisplayedEventProduct->setTEnd(time);
117
117
118 auto eventProducts = m_DisplayedEvent->getEventProducts();
118 auto eventProducts = m_DisplayedEvent->getEventProducts();
119 for (auto &eventProduct : eventProducts) {
119 for (auto &eventProduct : eventProducts) {
120 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
120 if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) {
121 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
121 eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd());
122 }
122 }
123 }
123 }
124 m_DisplayedEvent->setEventProducts(eventProducts);
124 m_DisplayedEvent->setEventProducts(eventProducts);
125
125
126 emit inspector->eventUpdated(m_DisplayedEvent);
126 emit inspector->eventUpdated(m_DisplayedEvent);
127 }
127 }
128 });
128 });
129 }
129 }
130
130
131 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
131 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
132 {
132 {
133 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
133 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
134 }
134 }
135
135
136 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
136 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
137 {
137 {
138 return static_cast<Page>(ui->stackedWidget->currentIndex());
138 return static_cast<Page>(ui->stackedWidget->currentIndex());
139 }
139 }
140
140
141 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
141 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
142 {
142 {
143 impl->m_DisplayedEvent = event;
143 impl->m_DisplayedEvent = event;
144
144
145 blockSignals(true);
145 blockSignals(true);
146
146
147 showPage(Page::EventProperties);
147 showPage(Page::EventProperties);
148 ui->leEventName->setEnabled(true);
148 ui->leEventName->setEnabled(true);
149 ui->leEventName->setText(event->getName());
149 ui->leEventName->setText(event->getName());
150 ui->leEventProduct->setEnabled(false);
150 ui->leEventProduct->setEnabled(false);
151 ui->leEventProduct->setText(
151
152 QString::number(event->getEventProducts().size()).append(" product(s)"));
152 auto eventProducts = event->getEventProducts();
153 QStringList eventProductList;
154 for (auto evtProduct : eventProducts) {
155 eventProductList << evtProduct.getProductId();
156 }
157
158 ui->leEventProduct->setText(eventProductList.join(";"));
153
159
154 QString tagList;
160 QString tagList;
155 auto tags = event->getTagsNames();
161 auto tags = event->getTagsNames();
156 for (auto tag : tags) {
162 for (auto tag : tags) {
157 tagList += tag;
163 tagList += tag;
158 tagList += ' ';
164 tagList += ' ';
159 }
165 }
160
166
161 ui->leEventTags->setEnabled(true);
167 ui->leEventTags->setEnabled(true);
162 ui->leEventTags->setText(tagList);
168 ui->leEventTags->setText(tagList);
163
169
164 ui->dateTimeEventTStart->setEnabled(false);
170 ui->dateTimeEventTStart->setEnabled(false);
165 ui->dateTimeEventTEnd->setEnabled(false);
171 ui->dateTimeEventTEnd->setEnabled(false);
166
172
167 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
173 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
168 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
174 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
169
175
170 blockSignals(false);
176 blockSignals(false);
171 }
177 }
172
178
173 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
179 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
174 const std::shared_ptr<DBEventProduct> &eventProduct)
180 const std::shared_ptr<DBEventProduct> &eventProduct)
175 {
181 {
176
182
177 impl->m_DisplayedEvent = event;
183 impl->m_DisplayedEvent = event;
178 impl->m_DisplayedEventProduct = eventProduct;
184 impl->m_DisplayedEventProduct = eventProduct;
179
185
180 blockSignals(true);
186 blockSignals(true);
181
187
182 showPage(Page::EventProperties);
188 showPage(Page::EventProperties);
183 ui->leEventName->setEnabled(false);
189 ui->leEventName->setEnabled(false);
184 ui->leEventName->setText(event->getName());
190 ui->leEventName->setText(event->getName());
185 ui->leEventProduct->setEnabled(false);
191 ui->leEventProduct->setEnabled(false);
186 ui->leEventProduct->setText(eventProduct->getProductId());
192 ui->leEventProduct->setText(eventProduct->getProductId());
187
193
188 ui->leEventTags->setEnabled(false);
194 ui->leEventTags->setEnabled(false);
189 ui->leEventTags->clear();
195 ui->leEventTags->clear();
190
196
191 ui->dateTimeEventTStart->setEnabled(true);
197 ui->dateTimeEventTStart->setEnabled(true);
192 ui->dateTimeEventTEnd->setEnabled(true);
198 ui->dateTimeEventTEnd->setEnabled(true);
193
199
194 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
200 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
195 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
201 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
196
202
197 blockSignals(false);
203 blockSignals(false);
198 }
204 }
199
205
200 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
206 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
201 {
207 {
202 impl->m_DisplayedCatalogue = catalogue;
208 impl->m_DisplayedCatalogue = catalogue;
203
209
204 blockSignals(true);
210 blockSignals(true);
205
211
206 showPage(Page::CatalogueProperties);
212 showPage(Page::CatalogueProperties);
207 ui->leCatalogueName->setText(catalogue->getName());
213 ui->leCatalogueName->setText(catalogue->getName());
208 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
214 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
209
215
210 blockSignals(false);
216 blockSignals(false);
211 }
217 }
212
218
213 void CatalogueInspectorWidget::refresh()
219 void CatalogueInspectorWidget::refresh()
214 {
220 {
215 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
221 switch (static_cast<Page>(ui->stackedWidget->currentIndex())) {
216 case Page::CatalogueProperties:
222 case Page::CatalogueProperties:
217 setCatalogue(impl->m_DisplayedCatalogue);
223 setCatalogue(impl->m_DisplayedCatalogue);
218 break;
224 break;
219 case Page::EventProperties: {
225 case Page::EventProperties: {
220 auto isEventShowed = ui->leEventName->isEnabled();
226 auto isEventShowed = ui->leEventName->isEnabled();
221 setEvent(impl->m_DisplayedEvent);
227 setEvent(impl->m_DisplayedEvent);
222 if (!isEventShowed && impl->m_DisplayedEvent) {
228 if (!isEventShowed && impl->m_DisplayedEvent) {
223 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
229 setEventProduct(impl->m_DisplayedEvent, impl->m_DisplayedEventProduct);
224 }
230 }
225 }
231 }
226 }
232 }
227 }
233 }
@@ -1,658 +1,658
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 "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <DataSource/DataSourceController.h>
13 #include <DataSource/DataSourceController.h>
14 #include <Time/TimeController.h>
14 #include <Time/TimeController.h>
15 #include <Variable/Variable.h>
15 #include <Variable/Variable.h>
16 #include <Variable/VariableController.h>
16 #include <Variable/VariableController.h>
17
17
18 #include <Visualization/operations/FindVariableOperation.h>
18 #include <Visualization/operations/FindVariableOperation.h>
19
19
20 #include <DragAndDrop/DragDropGuiController.h>
20 #include <DragAndDrop/DragDropGuiController.h>
21 #include <QUuid>
21 #include <QUuid>
22 #include <SqpApplication.h>
22 #include <SqpApplication.h>
23 #include <cmath>
23 #include <cmath>
24
24
25 #include <QLayout>
25 #include <QLayout>
26
26
27 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
28
28
29 namespace {
29 namespace {
30
30
31 /**
31 /**
32 * Applies a function to all graphs of the zone represented by its layout
32 * Applies a function to all graphs of the zone represented by its layout
33 * @param layout the layout that contains graphs
33 * @param layout the layout that contains graphs
34 * @param fun the function to apply to each graph
34 * @param fun the function to apply to each graph
35 */
35 */
36 template <typename Fun>
36 template <typename Fun>
37 void processGraphs(QLayout &layout, Fun fun)
37 void processGraphs(QLayout &layout, Fun fun)
38 {
38 {
39 for (auto i = 0; i < layout.count(); ++i) {
39 for (auto i = 0; i < layout.count(); ++i) {
40 if (auto item = layout.itemAt(i)) {
40 if (auto item = layout.itemAt(i)) {
41 if (auto visualizationGraphWidget
41 if (auto visualizationGraphWidget
42 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
42 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
43 fun(*visualizationGraphWidget);
43 fun(*visualizationGraphWidget);
44 }
44 }
45 }
45 }
46 }
46 }
47 }
47 }
48
48
49 /// Generates a default name for a new graph, according to the number of graphs already displayed in
49 /// Generates a default name for a new graph, according to the number of graphs already displayed in
50 /// the zone
50 /// the zone
51 QString defaultGraphName(QLayout &layout)
51 QString defaultGraphName(QLayout &layout)
52 {
52 {
53 QSet<QString> existingNames;
53 QSet<QString> existingNames;
54 processGraphs(
54 processGraphs(
55 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
55 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
56
56
57 int zoneNum = 1;
57 int zoneNum = 1;
58 QString name;
58 QString name;
59 do {
59 do {
60 name = QObject::tr("Graph ").append(QString::number(zoneNum));
60 name = QObject::tr("Graph ").append(QString::number(zoneNum));
61 ++zoneNum;
61 ++zoneNum;
62 } while (existingNames.contains(name));
62 } while (existingNames.contains(name));
63
63
64 return name;
64 return name;
65 }
65 }
66
66
67 } // namespace
67 } // namespace
68
68
69 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
69 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
70
70
71 explicit VisualizationZoneWidgetPrivate()
71 explicit VisualizationZoneWidgetPrivate()
72 : m_SynchronisationGroupId{QUuid::createUuid()},
72 : m_SynchronisationGroupId{QUuid::createUuid()},
73 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
73 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
74 {
74 {
75 }
75 }
76 QUuid m_SynchronisationGroupId;
76 QUuid m_SynchronisationGroupId;
77 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
77 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
78
78
79 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
79 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
80 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
80 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
81 VisualizationZoneWidget *zoneWidget);
81 VisualizationZoneWidget *zoneWidget);
82 void dropProducts(const QVariantList &productsData, int index,
82 void dropProducts(const QVariantList &productsData, int index,
83 VisualizationZoneWidget *zoneWidget);
83 VisualizationZoneWidget *zoneWidget);
84 };
84 };
85
85
86 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
86 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
87 : VisualizationDragWidget{parent},
87 : VisualizationDragWidget{parent},
88 ui{new Ui::VisualizationZoneWidget},
88 ui{new Ui::VisualizationZoneWidget},
89 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
89 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
90 {
90 {
91 ui->setupUi(this);
91 ui->setupUi(this);
92
92
93 ui->zoneNameLabel->setText(name);
93 ui->zoneNameLabel->setText(name);
94
94
95 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
95 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
96 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
96 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
97 VisualizationDragDropContainer::DropBehavior::Inserted);
97 VisualizationDragDropContainer::DropBehavior::Inserted);
98 ui->dragDropContainer->setMimeType(
98 ui->dragDropContainer->setMimeType(
99 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
99 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
100 ui->dragDropContainer->setMimeType(
100 ui->dragDropContainer->setMimeType(
101 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
101 MIME_TYPE_PRODUCT_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
102 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
102 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
103 VisualizationDragDropContainer::DropBehavior::Merged);
103 VisualizationDragDropContainer::DropBehavior::Merged);
104 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
104 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
105 VisualizationDragDropContainer::DropBehavior::Forbidden);
105 VisualizationDragDropContainer::DropBehavior::Forbidden);
106 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
106 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
107 VisualizationDragDropContainer::DropBehavior::Forbidden);
108 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
108 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
109 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
109 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
110 ui->dragDropContainer);
110 ui->dragDropContainer);
111 });
111 });
112
112
113 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
113 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
114 if (!mimeData) {
114 if (!mimeData) {
115 return false;
115 return false;
116 }
116 }
117
117
118 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
118 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
119 auto variables = sqpApp->variableController().variablesForMimeData(
119 auto variables = sqpApp->variableController().variablesForMimeData(
120 mimeData->data(MIME_TYPE_VARIABLE_LIST));
120 mimeData->data(MIME_TYPE_VARIABLE_LIST));
121
121
122 if (variables.count() != 1) {
122 if (variables.count() != 1) {
123 return false;
123 return false;
124 }
124 }
125 auto variable = variables.first();
125 auto variable = variables.first();
126
126
127 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
127 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
128 return graphWidget->canDrop(*variable);
128 return graphWidget->canDrop(*variable);
129 }
129 }
130 }
130 }
131
131
132 return true;
132 return true;
133 };
133 };
134 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
134 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
135
135
136 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
136 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
137 &VisualizationZoneWidget::dropMimeData);
137 &VisualizationZoneWidget::dropMimeData);
138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
138 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
139 &VisualizationZoneWidget::dropMimeDataOnGraph);
139 &VisualizationZoneWidget::dropMimeDataOnGraph);
140
140
141 // 'Close' options : widget is deleted when closed
141 // 'Close' options : widget is deleted when closed
142 setAttribute(Qt::WA_DeleteOnClose);
142 setAttribute(Qt::WA_DeleteOnClose);
143 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
143 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
144 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
144 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
145
145
146 // Synchronisation id
146 // Synchronisation id
147 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
147 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
148 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
148 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
149 }
149 }
150
150
151 VisualizationZoneWidget::~VisualizationZoneWidget()
151 VisualizationZoneWidget::~VisualizationZoneWidget()
152 {
152 {
153 delete ui;
153 delete ui;
154 }
154 }
155
155
156 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
156 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
157 {
157 {
158 if (auto graph = firstGraph()) {
158 if (auto graph = firstGraph()) {
159 graph->setGraphRange(range);
159 graph->setGraphRange(range);
160 }
160 }
161 else {
161 else {
162 qCWarning(LOG_VisualizationZoneWidget())
162 qCWarning(LOG_VisualizationZoneWidget())
163 << tr("setZoneRange:Cannot set the range of an empty zone.");
163 << tr("setZoneRange:Cannot set the range of an empty zone.");
164 }
164 }
165 }
165 }
166
166
167 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
167 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
168 {
168 {
169 // Synchronize new graph with others in the zone
169 // Synchronize new graph with others in the zone
170 impl->m_Synchronizer->addGraph(*graphWidget);
170 impl->m_Synchronizer->addGraph(*graphWidget);
171
171
172 ui->dragDropContainer->addDragWidget(graphWidget);
172 ui->dragDropContainer->addDragWidget(graphWidget);
173 }
173 }
174
174
175 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
175 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
176 {
176 {
177 // Synchronize new graph with others in the zone
177 // Synchronize new graph with others in the zone
178 impl->m_Synchronizer->addGraph(*graphWidget);
178 impl->m_Synchronizer->addGraph(*graphWidget);
179
179
180 ui->dragDropContainer->insertDragWidget(index, graphWidget);
180 ui->dragDropContainer->insertDragWidget(index, graphWidget);
181 }
181 }
182
182
183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
184 {
184 {
185 return createGraph(variable, -1);
185 return createGraph(variable, -1);
186 }
186 }
187
187
188 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
188 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
189 int index)
189 int index)
190 {
190 {
191 auto graphWidget
191 auto graphWidget
192 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
192 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
193
193
194
194
195 // Set graph properties
195 // Set graph properties
196 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
196 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
197 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
197 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
198
198
199
199
200 // Lambda to synchronize zone widget
200 // Lambda to synchronize zone widget
201 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
201 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
202 const SqpRange &oldGraphRange) {
202 const SqpRange &oldGraphRange) {
203
203
204 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
204 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
205 auto frameLayout = ui->dragDropContainer->layout();
205 auto frameLayout = ui->dragDropContainer->layout();
206 for (auto i = 0; i < frameLayout->count(); ++i) {
206 for (auto i = 0; i < frameLayout->count(); ++i) {
207 auto graphChild
207 auto graphChild
208 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
208 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
209 if (graphChild && (graphChild != graphWidget)) {
209 if (graphChild && (graphChild != graphWidget)) {
210
210
211 auto graphChildRange = graphChild->graphRange();
211 auto graphChildRange = graphChild->graphRange();
212 switch (zoomType) {
212 switch (zoomType) {
213 case AcquisitionZoomType::ZoomIn: {
213 case AcquisitionZoomType::ZoomIn: {
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
215 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
215 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
216 graphChildRange.m_TStart += deltaLeft;
216 graphChildRange.m_TStart += deltaLeft;
217 graphChildRange.m_TEnd -= deltaRight;
217 graphChildRange.m_TEnd -= deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
220 << deltaLeft;
220 << deltaLeft;
221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
222 << deltaRight;
222 << deltaRight;
223 qCDebug(LOG_VisualizationZoneWidget())
223 qCDebug(LOG_VisualizationZoneWidget())
224 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
224 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
225
225
226 break;
226 break;
227 }
227 }
228
228
229 case AcquisitionZoomType::ZoomOut: {
229 case AcquisitionZoomType::ZoomOut: {
230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
231 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
231 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
232 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
233 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
233 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
234 << deltaLeft;
234 << deltaLeft;
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
236 << deltaRight;
236 << deltaRight;
237 qCDebug(LOG_VisualizationZoneWidget())
237 qCDebug(LOG_VisualizationZoneWidget())
238 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
238 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
239 graphChildRange.m_TStart -= deltaLeft;
239 graphChildRange.m_TStart -= deltaLeft;
240 graphChildRange.m_TEnd += deltaRight;
240 graphChildRange.m_TEnd += deltaRight;
241 break;
241 break;
242 }
242 }
243 case AcquisitionZoomType::PanRight: {
243 case AcquisitionZoomType::PanRight: {
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
245 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
245 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
246 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
246 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
247 graphChildRange.m_TStart += deltaLeft;
247 graphChildRange.m_TStart += deltaLeft;
248 graphChildRange.m_TEnd += deltaRight;
248 graphChildRange.m_TEnd += deltaRight;
249 qCDebug(LOG_VisualizationZoneWidget())
249 qCDebug(LOG_VisualizationZoneWidget())
250 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
250 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
251 break;
251 break;
252 }
252 }
253 case AcquisitionZoomType::PanLeft: {
253 case AcquisitionZoomType::PanLeft: {
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
255 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
255 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
256 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
256 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
257 graphChildRange.m_TStart -= deltaLeft;
257 graphChildRange.m_TStart -= deltaLeft;
258 graphChildRange.m_TEnd -= deltaRight;
258 graphChildRange.m_TEnd -= deltaRight;
259 break;
259 break;
260 }
260 }
261 case AcquisitionZoomType::Unknown: {
261 case AcquisitionZoomType::Unknown: {
262 qCDebug(LOG_VisualizationZoneWidget())
262 qCDebug(LOG_VisualizationZoneWidget())
263 << tr("Impossible to synchronize: zoom type unknown");
263 << tr("Impossible to synchronize: zoom type unknown");
264 break;
264 break;
265 }
265 }
266 default:
266 default:
267 qCCritical(LOG_VisualizationZoneWidget())
267 qCCritical(LOG_VisualizationZoneWidget())
268 << tr("Impossible to synchronize: zoom type not take into account");
268 << tr("Impossible to synchronize: zoom type not take into account");
269 // No action
269 // No action
270 break;
270 break;
271 }
271 }
272 graphChild->setFlags(GraphFlag::DisableAll);
272 graphChild->setFlags(GraphFlag::DisableAll);
273 qCDebug(LOG_VisualizationZoneWidget())
273 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
274 << tr("TORM: Range before: ") << graphChild->graphRange();
274 << graphChild->graphRange();
275 qCDebug(LOG_VisualizationZoneWidget())
275 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
276 << tr("TORM: Range after : ") << graphChildRange;
276 << graphChildRange;
277 qCDebug(LOG_VisualizationZoneWidget())
277 qCDebug(LOG_VisualizationZoneWidget())
278 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
278 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
279 graphChild->setGraphRange(graphChildRange);
279 graphChild->setGraphRange(graphChildRange);
280 graphChild->setFlags(GraphFlag::EnableAll);
280 graphChild->setFlags(GraphFlag::EnableAll);
281 }
281 }
282 }
282 }
283 };
283 };
284
284
285 // connection for synchronization
285 // connection for synchronization
286 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
286 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
287 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
287 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
288 &VisualizationZoneWidget::onVariableAdded);
288 &VisualizationZoneWidget::onVariableAdded);
289 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
289 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
290 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
290 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
291
291
292 auto range = SqpRange{};
292 auto range = SqpRange{};
293 if (auto firstGraph = this->firstGraph()) {
293 if (auto firstGraph = this->firstGraph()) {
294 // Case of a new graph in a existant zone
294 // Case of a new graph in a existant zone
295 range = firstGraph->graphRange();
295 range = firstGraph->graphRange();
296 }
296 }
297 else {
297 else {
298 // Case of a new graph as the first of the zone
298 // Case of a new graph as the first of the zone
299 range = variable->range();
299 range = variable->range();
300 }
300 }
301
301
302 this->insertGraph(index, graphWidget);
302 this->insertGraph(index, graphWidget);
303
303
304 graphWidget->addVariable(variable, range);
304 graphWidget->addVariable(variable, range);
305 graphWidget->setYRange(variable);
305 graphWidget->setYRange(variable);
306
306
307 return graphWidget;
307 return graphWidget;
308 }
308 }
309
309
310 VisualizationGraphWidget *
310 VisualizationGraphWidget *
311 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
311 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
312 {
312 {
313 if (variables.isEmpty()) {
313 if (variables.isEmpty()) {
314 return nullptr;
314 return nullptr;
315 }
315 }
316
316
317 auto graphWidget = createGraph(variables.first(), index);
317 auto graphWidget = createGraph(variables.first(), index);
318 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
318 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
319 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
319 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
320 }
320 }
321
321
322 return graphWidget;
322 return graphWidget;
323 }
323 }
324
324
325 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
325 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
326 {
326 {
327 VisualizationGraphWidget *firstGraph = nullptr;
327 VisualizationGraphWidget *firstGraph = nullptr;
328 auto layout = ui->dragDropContainer->layout();
328 auto layout = ui->dragDropContainer->layout();
329 if (layout->count() > 0) {
329 if (layout->count() > 0) {
330 if (auto visualizationGraphWidget
330 if (auto visualizationGraphWidget
331 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
331 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
332 firstGraph = visualizationGraphWidget;
332 firstGraph = visualizationGraphWidget;
333 }
333 }
334 }
334 }
335
335
336 return firstGraph;
336 return firstGraph;
337 }
337 }
338
338
339 void VisualizationZoneWidget::closeAllGraphs()
339 void VisualizationZoneWidget::closeAllGraphs()
340 {
340 {
341 processGraphs(*ui->dragDropContainer->layout(),
341 processGraphs(*ui->dragDropContainer->layout(),
342 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
342 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
343 }
343 }
344
344
345 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
345 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
346 {
346 {
347 if (visitor) {
347 if (visitor) {
348 visitor->visitEnter(this);
348 visitor->visitEnter(this);
349
349
350 // Apply visitor to graph children: widgets different from graphs are not visited (no
350 // Apply visitor to graph children: widgets different from graphs are not visited (no
351 // action)
351 // action)
352 processGraphs(
352 processGraphs(
353 *ui->dragDropContainer->layout(),
353 *ui->dragDropContainer->layout(),
354 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
354 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
355
355
356 visitor->visitLeave(this);
356 visitor->visitLeave(this);
357 }
357 }
358 else {
358 else {
359 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
359 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
360 }
360 }
361 }
361 }
362
362
363 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
363 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
364 {
364 {
365 // A tab can always accomodate a variable
365 // A tab can always accomodate a variable
366 Q_UNUSED(variable);
366 Q_UNUSED(variable);
367 return true;
367 return true;
368 }
368 }
369
369
370 bool VisualizationZoneWidget::contains(const Variable &variable) const
370 bool VisualizationZoneWidget::contains(const Variable &variable) const
371 {
371 {
372 Q_UNUSED(variable);
372 Q_UNUSED(variable);
373 return false;
373 return false;
374 }
374 }
375
375
376 QString VisualizationZoneWidget::name() const
376 QString VisualizationZoneWidget::name() const
377 {
377 {
378 return ui->zoneNameLabel->text();
378 return ui->zoneNameLabel->text();
379 }
379 }
380
380
381 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
381 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
382 {
382 {
383 Q_UNUSED(position);
383 Q_UNUSED(position);
384
384
385 auto mimeData = new QMimeData;
385 auto mimeData = new QMimeData;
386 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
386 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
387
387
388 if (auto firstGraph = this->firstGraph()) {
388 if (auto firstGraph = this->firstGraph()) {
389 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
389 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
390 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
390 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
391 }
391 }
392
392
393 return mimeData;
393 return mimeData;
394 }
394 }
395
395
396 bool VisualizationZoneWidget::isDragAllowed() const
396 bool VisualizationZoneWidget::isDragAllowed() const
397 {
397 {
398 return true;
398 return true;
399 }
399 }
400
400
401 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
401 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
402 const QPointF &plotPosition,
402 const QPointF &plotPosition,
403 VisualizationGraphWidget *graphWidget)
403 VisualizationGraphWidget *graphWidget)
404 {
404 {
405 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
405 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
406 VisualizationGraphWidget &processedGraph) {
406 VisualizationGraphWidget &processedGraph) {
407
407
408 switch (sqpApp->plotsCursorMode()) {
408 switch (sqpApp->plotsCursorMode()) {
409 case SqpApplication::PlotsCursorMode::Vertical:
409 case SqpApplication::PlotsCursorMode::Vertical:
410 processedGraph.removeHorizontalCursor();
410 processedGraph.removeHorizontalCursor();
411 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
411 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
412 break;
412 break;
413 case SqpApplication::PlotsCursorMode::Temporal:
413 case SqpApplication::PlotsCursorMode::Temporal:
414 processedGraph.addVerticalCursor(plotPosition.x());
414 processedGraph.addVerticalCursor(plotPosition.x());
415 processedGraph.removeHorizontalCursor();
415 processedGraph.removeHorizontalCursor();
416 break;
416 break;
417 case SqpApplication::PlotsCursorMode::Horizontal:
417 case SqpApplication::PlotsCursorMode::Horizontal:
418 processedGraph.removeVerticalCursor();
418 processedGraph.removeVerticalCursor();
419 if (&processedGraph == graphWidget) {
419 if (&processedGraph == graphWidget) {
420 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
420 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
421 }
421 }
422 else {
422 else {
423 processedGraph.removeHorizontalCursor();
423 processedGraph.removeHorizontalCursor();
424 }
424 }
425 break;
425 break;
426 case SqpApplication::PlotsCursorMode::Cross:
426 case SqpApplication::PlotsCursorMode::Cross:
427 if (&processedGraph == graphWidget) {
427 if (&processedGraph == graphWidget) {
428 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
428 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
429 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
429 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
430 }
430 }
431 else {
431 else {
432 processedGraph.removeHorizontalCursor();
432 processedGraph.removeHorizontalCursor();
433 processedGraph.removeVerticalCursor();
433 processedGraph.removeVerticalCursor();
434 }
434 }
435 break;
435 break;
436 case SqpApplication::PlotsCursorMode::NoCursor:
436 case SqpApplication::PlotsCursorMode::NoCursor:
437 processedGraph.removeHorizontalCursor();
437 processedGraph.removeHorizontalCursor();
438 processedGraph.removeVerticalCursor();
438 processedGraph.removeVerticalCursor();
439 break;
439 break;
440 }
440 }
441
441
442
442
443 });
443 });
444 }
444 }
445
445
446 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
446 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
447 {
447 {
448 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
448 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
449 processedGraph.removeHorizontalCursor();
449 processedGraph.removeHorizontalCursor();
450 processedGraph.removeVerticalCursor();
450 processedGraph.removeVerticalCursor();
451 });
451 });
452 }
452 }
453
453
454 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
454 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
455 {
455 {
456 // Closes graphs in the zone
456 // Closes graphs in the zone
457 processGraphs(*ui->dragDropContainer->layout(),
457 processGraphs(*ui->dragDropContainer->layout(),
458 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
458 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
459
459
460 // Delete synchronization group from variable controller
460 // Delete synchronization group from variable controller
461 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
461 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
462 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
462 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
463
463
464 QWidget::closeEvent(event);
464 QWidget::closeEvent(event);
465 }
465 }
466
466
467 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
467 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
468 {
468 {
469 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
469 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
470 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
470 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
471 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
471 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
472 }
472 }
473
473
474 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
474 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
475 {
475 {
476 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
476 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
477 Q_ARG(std::shared_ptr<Variable>, variable),
477 Q_ARG(std::shared_ptr<Variable>, variable),
478 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
478 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
479 }
479 }
480
480
481 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
481 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
482 {
482 {
483 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
483 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
484 impl->dropGraph(index, this);
484 impl->dropGraph(index, this);
485 }
485 }
486 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
486 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
487 auto variables = sqpApp->variableController().variablesForMimeData(
487 auto variables = sqpApp->variableController().variablesForMimeData(
488 mimeData->data(MIME_TYPE_VARIABLE_LIST));
488 mimeData->data(MIME_TYPE_VARIABLE_LIST));
489 impl->dropVariables(variables, index, this);
489 impl->dropVariables(variables, index, this);
490 }
490 }
491 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
491 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
492 auto products = sqpApp->dataSourceController().productsDataForMimeData(
492 auto products = sqpApp->dataSourceController().productsDataForMimeData(
493 mimeData->data(MIME_TYPE_PRODUCT_LIST));
493 mimeData->data(MIME_TYPE_PRODUCT_LIST));
494 impl->dropProducts(products, index, this);
494 impl->dropProducts(products, index, this);
495 }
495 }
496 else {
496 else {
497 qCWarning(LOG_VisualizationZoneWidget())
497 qCWarning(LOG_VisualizationZoneWidget())
498 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
498 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
499 }
499 }
500 }
500 }
501
501
502 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
502 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
503 const QMimeData *mimeData)
503 const QMimeData *mimeData)
504 {
504 {
505 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
505 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
506 if (!graphWidget) {
506 if (!graphWidget) {
507 qCWarning(LOG_VisualizationZoneWidget())
507 qCWarning(LOG_VisualizationZoneWidget())
508 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
508 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
509 "drop aborted");
509 "drop aborted");
510 Q_ASSERT(false);
510 Q_ASSERT(false);
511 return;
511 return;
512 }
512 }
513
513
514 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
514 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
515 auto variables = sqpApp->variableController().variablesForMimeData(
515 auto variables = sqpApp->variableController().variablesForMimeData(
516 mimeData->data(MIME_TYPE_VARIABLE_LIST));
516 mimeData->data(MIME_TYPE_VARIABLE_LIST));
517 for (const auto &var : variables) {
517 for (const auto &var : variables) {
518 graphWidget->addVariable(var, graphWidget->graphRange());
518 graphWidget->addVariable(var, graphWidget->graphRange());
519 }
519 }
520 }
520 }
521 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
521 else if (mimeData->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
522 auto products = sqpApp->dataSourceController().productsDataForMimeData(
522 auto products = sqpApp->dataSourceController().productsDataForMimeData(
523 mimeData->data(MIME_TYPE_PRODUCT_LIST));
523 mimeData->data(MIME_TYPE_PRODUCT_LIST));
524
524
525 auto context = new QObject{this};
525 auto context = new QObject{this};
526 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
526 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
527 [this, graphWidget, context](auto variable) {
527 [this, graphWidget, context](auto variable) {
528 graphWidget->addVariable(variable, graphWidget->graphRange());
528 graphWidget->addVariable(variable, graphWidget->graphRange());
529 delete context; // removes the connection
529 delete context; // removes the connection
530 },
530 },
531 Qt::QueuedConnection);
531 Qt::QueuedConnection);
532
532
533 auto productData = products.first().toHash();
533 auto productData = products.first().toHash();
534 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
534 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
535 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
535 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
536 }
536 }
537 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
537 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
538 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
538 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
539 graphWidget->setGraphRange(range);
539 graphWidget->setGraphRange(range);
540 }
540 }
541 else {
541 else {
542 qCWarning(LOG_VisualizationZoneWidget())
542 qCWarning(LOG_VisualizationZoneWidget())
543 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
543 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
544 }
544 }
545 }
545 }
546
546
547 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
547 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
548 int index, VisualizationZoneWidget *zoneWidget)
548 int index, VisualizationZoneWidget *zoneWidget)
549 {
549 {
550 auto &helper = sqpApp->dragDropGuiController();
550 auto &helper = sqpApp->dragDropGuiController();
551
551
552 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
552 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
553 if (!graphWidget) {
553 if (!graphWidget) {
554 qCWarning(LOG_VisualizationZoneWidget())
554 qCWarning(LOG_VisualizationZoneWidget())
555 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
555 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
556 "found or invalid.");
556 "found or invalid.");
557 Q_ASSERT(false);
557 Q_ASSERT(false);
558 return;
558 return;
559 }
559 }
560
560
561 auto parentDragDropContainer
561 auto parentDragDropContainer
562 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
562 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
563 if (!parentDragDropContainer) {
563 if (!parentDragDropContainer) {
564 qCWarning(LOG_VisualizationZoneWidget())
564 qCWarning(LOG_VisualizationZoneWidget())
565 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
565 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
566 "the dropped graph is not found.");
566 "the dropped graph is not found.");
567 Q_ASSERT(false);
567 Q_ASSERT(false);
568 return;
568 return;
569 }
569 }
570
570
571 const auto &variables = graphWidget->variables();
571 const auto &variables = graphWidget->variables();
572
572
573 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
573 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
574 // The drop didn't occur in the same zone
574 // The drop didn't occur in the same zone
575
575
576 // Abort the requests for the variables (if any)
576 // Abort the requests for the variables (if any)
577 // Commented, because it's not sure if it's needed or not
577 // Commented, because it's not sure if it's needed or not
578 // for (const auto& var : variables)
578 // for (const auto& var : variables)
579 //{
579 //{
580 // sqpApp->variableController().onAbortProgressRequested(var);
580 // sqpApp->variableController().onAbortProgressRequested(var);
581 //}
581 //}
582
582
583 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
583 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
584 auto nbGraph = parentDragDropContainer->countDragWidget();
584 auto nbGraph = parentDragDropContainer->countDragWidget();
585 if (nbGraph == 1) {
585 if (nbGraph == 1) {
586 // This is the only graph in the previous zone, close the zone
586 // This is the only graph in the previous zone, close the zone
587 helper.delayedCloseWidget(previousParentZoneWidget);
587 helper.delayedCloseWidget(previousParentZoneWidget);
588 }
588 }
589 else {
589 else {
590 // Close the graph
590 // Close the graph
591 helper.delayedCloseWidget(graphWidget);
591 helper.delayedCloseWidget(graphWidget);
592 }
592 }
593
593
594 // Creates the new graph in the zone
594 // Creates the new graph in the zone
595 auto newGraphWidget = zoneWidget->createGraph(variables, index);
595 auto newGraphWidget = zoneWidget->createGraph(variables, index);
596 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
596 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
597 }
597 }
598 else {
598 else {
599 // The drop occurred in the same zone or the graph is empty
599 // The drop occurred in the same zone or the graph is empty
600 // Simple move of the graph, no variable operation associated
600 // Simple move of the graph, no variable operation associated
601 parentDragDropContainer->layout()->removeWidget(graphWidget);
601 parentDragDropContainer->layout()->removeWidget(graphWidget);
602
602
603 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
603 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
604 // The graph is empty and dropped in a different zone.
604 // The graph is empty and dropped in a different zone.
605 // Take the range of the first graph in the zone (if existing).
605 // Take the range of the first graph in the zone (if existing).
606 auto layout = zoneWidget->ui->dragDropContainer->layout();
606 auto layout = zoneWidget->ui->dragDropContainer->layout();
607 if (layout->count() > 0) {
607 if (layout->count() > 0) {
608 if (auto visualizationGraphWidget
608 if (auto visualizationGraphWidget
609 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
609 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
610 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
610 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
611 }
611 }
612 }
612 }
613 }
613 }
614
614
615 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
615 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
616 }
616 }
617 }
617 }
618
618
619 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
619 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
620 const QList<std::shared_ptr<Variable> > &variables, int index,
620 const QList<std::shared_ptr<Variable> > &variables, int index,
621 VisualizationZoneWidget *zoneWidget)
621 VisualizationZoneWidget *zoneWidget)
622 {
622 {
623 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
623 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
624 // compatible variable here
624 // compatible variable here
625 if (variables.count() > 1) {
625 if (variables.count() > 1) {
626 qCWarning(LOG_VisualizationZoneWidget())
626 qCWarning(LOG_VisualizationZoneWidget())
627 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
627 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
628 "aborted.");
628 "aborted.");
629 return;
629 return;
630 }
630 }
631
631
632 zoneWidget->createGraph(variables, index);
632 zoneWidget->createGraph(variables, index);
633 }
633 }
634
634
635 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
635 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropProducts(
636 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
636 const QVariantList &productsData, int index, VisualizationZoneWidget *zoneWidget)
637 {
637 {
638 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
638 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
639 // compatible variable here
639 // compatible variable here
640 if (productsData.count() != 1) {
640 if (productsData.count() != 1) {
641 qCWarning(LOG_VisualizationZoneWidget())
641 qCWarning(LOG_VisualizationZoneWidget())
642 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
642 << tr("VisualizationTabWidget::dropProducts, dropping multiple products, operation "
643 "aborted.");
643 "aborted.");
644 return;
644 return;
645 }
645 }
646
646
647 auto context = new QObject{zoneWidget};
647 auto context = new QObject{zoneWidget};
648 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
648 connect(&sqpApp->variableController(), &VariableController::variableAdded, context,
649 [this, index, zoneWidget, context](auto variable) {
649 [this, index, zoneWidget, context](auto variable) {
650 zoneWidget->createGraph(variable, index);
650 zoneWidget->createGraph(variable, index);
651 delete context; // removes the connection
651 delete context; // removes the connection
652 },
652 },
653 Qt::QueuedConnection);
653 Qt::QueuedConnection);
654
654
655 auto productData = productsData.first().toHash();
655 auto productData = productsData.first().toHash();
656 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
656 QMetaObject::invokeMethod(&sqpApp->dataSourceController(), "requestVariable",
657 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
657 Qt::QueuedConnection, Q_ARG(QVariantHash, productData));
658 }
658 }
General Comments 0
You need to be logged in to leave comments. Login now