##// END OF EJS Templates
Merge pull request 390 from SciQLop-fork develop...
perrinel -
r1157:3d2098c90692 merge
parent child
Show More
@@ -0,0 +1,46
1 #ifndef SCIQLOP_CATALOGUEEVENTSMODEL_H
2 #define SCIQLOP_CATALOGUEEVENTSMODEL_H
3
4 #include <Common/spimpl.h>
5 #include <QAbstractItemModel>
6
7 class DBEvent;
8 class DBEventProduct;
9
10 class CatalogueEventsModel : public QAbstractItemModel {
11 public:
12 CatalogueEventsModel(QObject *parent = nullptr);
13
14 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events);
15 void addEvent(const std::shared_ptr<DBEvent> &event);
16 void removeEvent(const std::shared_ptr<DBEvent> &event);
17
18 enum class ItemType { Root, Event, EventProduct };
19 ItemType itemTypeOf(const QModelIndex &index) const;
20 std::shared_ptr<DBEvent> getEvent(const QModelIndex &index) const;
21 std::shared_ptr<DBEvent> getParentEvent(const QModelIndex &index) const;
22 std::shared_ptr<DBEventProduct> getEventProduct(const QModelIndex &index) const;
23
24 void refreshEvent(const std::shared_ptr<DBEvent> &event);
25
26 // Model
27 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
28 QModelIndex parent(const QModelIndex &index) const;
29 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
30 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
31 Qt::ItemFlags flags(const QModelIndex &index) const override;
32 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
33 QVariant headerData(int section, Qt::Orientation orientation,
34 int role = Qt::DisplayRole) const override;
35 void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
36
37 Qt::DropActions supportedDragActions() const override;
38 QStringList mimeTypes() const override;
39 QMimeData *mimeData(const QModelIndexList &indexes) const override;
40
41 private:
42 class CatalogueEventsModelPrivate;
43 spimpl::unique_impl_ptr<CatalogueEventsModelPrivate> impl;
44 };
45
46 #endif // SCIQLOP_CATALOGUEEVENTSMODEL_H
@@ -0,0 +1,33
1 #ifndef SCIQLOP_CATALOGUETREEWIDGETITEM_H
2 #define SCIQLOP_CATALOGUETREEWIDGETITEM_H
3
4 #include <Common/spimpl.h>
5 #include <QTreeWidgetItem>
6
7 class DBCatalogue;
8
9
10 class CatalogueTreeWidgetItem : public QTreeWidgetItem {
11 public:
12 CatalogueTreeWidgetItem(std::shared_ptr<DBCatalogue> catalogue,
13 int type = QTreeWidgetItem::Type);
14
15 QVariant data(int column, int role) const override;
16 void setData(int column, int role, const QVariant &value) override;
17
18 /// Returns the catalogue represented by the item
19 std::shared_ptr<DBCatalogue> catalogue() const;
20
21 /// Displays or hides the save and cancel buttons indicating that the catalogue has unsaved
22 /// changes
23 void setHasChanges(bool value);
24
25 /// Refreshes the data displayed by the item from the catalogue
26 void refresh();
27
28 private:
29 class CatalogueTreeWidgetItemPrivate;
30 spimpl::unique_impl_ptr<CatalogueTreeWidgetItemPrivate> impl;
31 };
32
33 #endif // SCIQLOP_CATALOGUETREEWIDGETITEM_H
1 NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,381
1 #include "Catalogue/CatalogueEventsModel.h"
2
3 #include <Common/DateUtils.h>
4 #include <Common/MimeTypesDef.h>
5 #include <DBEvent.h>
6 #include <DBEventProduct.h>
7 #include <DBTag.h>
8 #include <Data/SqpRange.h>
9 #include <SqpApplication.h>
10 #include <Time/TimeController.h>
11
12 #include <list>
13 #include <unordered_map>
14
15 #include <QHash>
16 #include <QMimeData>
17
18 const auto EVENT_ITEM_TYPE = 1;
19 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
20
21 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
22 QVector<std::shared_ptr<DBEvent> > m_Events;
23 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
24
25 enum class Column { Name, TStart, TEnd, Tags, Product, NbColumn };
26 QStringList columnNames()
27 {
28 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"), tr("Tags"), tr("Product")};
29 }
30
31 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
32 {
33 switch (static_cast<Column>(col)) {
34 case Column::Name:
35 return event->getName();
36 case Column::TStart:
37 return DateUtils::dateTime(event->getTStart());
38 case Column::TEnd:
39 return DateUtils::dateTime(event->getTEnd());
40 case Column::Product: {
41 auto eventProductsIt = m_EventProducts.find(event.get());
42 if (eventProductsIt != m_EventProducts.cend()) {
43 return QString::number(m_EventProducts.at(event.get()).count()) + " product(s)";
44 }
45 else {
46 return "0 product";
47 }
48 }
49 case Column::Tags: {
50 QString tagList;
51 auto tags = event->getTags();
52 for (auto tag : tags) {
53 tagList += tag.getName();
54 tagList += ' ';
55 }
56
57 return tagList;
58 }
59 default:
60 break;
61 }
62
63 Q_ASSERT(false);
64 return QStringLiteral("Unknown Data");
65 }
66
67 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
68 {
69 for (auto product : event->getEventProducts()) {
70 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
71 }
72 }
73
74 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
75 {
76 switch (static_cast<Column>(col)) {
77 case Column::Name:
78 return eventProduct->getProductId();
79 case Column::TStart:
80 return DateUtils::dateTime(eventProduct->getTStart());
81 case Column::TEnd:
82 return DateUtils::dateTime(eventProduct->getTEnd());
83 case Column::Product:
84 return eventProduct->getProductId();
85 case Column::Tags: {
86 return QString();
87 }
88 default:
89 break;
90 }
91
92 Q_ASSERT(false);
93 return QStringLiteral("Unknown Data");
94 }
95 };
96
97 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
98 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
99 {
100 }
101
102 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
103 {
104 beginResetModel();
105
106 impl->m_Events = events;
107 impl->m_EventProducts.clear();
108 for (auto event : events) {
109 impl->parseEventProduct(event);
110 }
111
112 endResetModel();
113 }
114
115 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
116 {
117 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
118 return impl->m_Events.value(index.row());
119 }
120 else {
121 return nullptr;
122 }
123 }
124
125 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
126 {
127 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
128 return getEvent(index.parent());
129 }
130 else {
131 return nullptr;
132 }
133 }
134
135 std::shared_ptr<DBEventProduct>
136 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
137 {
138 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
139 auto event = static_cast<DBEvent *>(index.internalPointer());
140 return impl->m_EventProducts.at(event).value(index.row());
141 }
142 else {
143 return nullptr;
144 }
145 }
146
147 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
148 {
149 beginInsertRows(QModelIndex(), impl->m_Events.count() - 1, impl->m_Events.count() - 1);
150 impl->m_Events.append(event);
151 impl->parseEventProduct(event);
152 endInsertRows();
153 }
154
155 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
156 {
157 auto index = impl->m_Events.indexOf(event);
158 if (index >= 0) {
159 beginRemoveRows(QModelIndex(), index, index);
160 impl->m_Events.removeAt(index);
161 impl->m_EventProducts.erase(event.get());
162 endRemoveRows();
163 }
164 }
165
166 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
167 {
168 auto i = impl->m_Events.indexOf(event);
169 if (i >= 0) {
170 auto eventIndex = index(i, 0);
171 auto colCount = columnCount();
172 emit dataChanged(eventIndex, index(i, colCount));
173
174 auto childCount = rowCount(eventIndex);
175 emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex));
176 }
177 }
178
179 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
180 {
181 if (!hasIndex(row, column, parent)) {
182 return QModelIndex();
183 }
184
185 switch (itemTypeOf(parent)) {
186 case CatalogueEventsModel::ItemType::Root:
187 return createIndex(row, column);
188 case CatalogueEventsModel::ItemType::Event: {
189 auto event = getEvent(parent);
190 return createIndex(row, column, event.get());
191 }
192 case CatalogueEventsModel::ItemType::EventProduct:
193 break;
194 default:
195 break;
196 }
197
198 return QModelIndex();
199 }
200
201 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
202 {
203 switch (itemTypeOf(index)) {
204 case CatalogueEventsModel::ItemType::EventProduct: {
205 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
206 auto it
207 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
208 [parentEvent](auto event) { return event.get() == parentEvent; });
209
210 if (it != impl->m_Events.cend()) {
211 return createIndex(it - impl->m_Events.cbegin(), 0);
212 }
213 else {
214 return QModelIndex();
215 }
216 }
217 case CatalogueEventsModel::ItemType::Root:
218 break;
219 case CatalogueEventsModel::ItemType::Event:
220 break;
221 default:
222 break;
223 }
224
225 return QModelIndex();
226 }
227
228 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
229 {
230 if (parent.column() > 0) {
231 return 0;
232 }
233
234 switch (itemTypeOf(parent)) {
235 case CatalogueEventsModel::ItemType::Root:
236 return impl->m_Events.count();
237 case CatalogueEventsModel::ItemType::Event: {
238 auto event = getEvent(parent);
239 return impl->m_EventProducts[event.get()].count();
240 }
241 case CatalogueEventsModel::ItemType::EventProduct:
242 break;
243 default:
244 break;
245 }
246
247 return 0;
248 }
249
250 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
251 {
252 return static_cast<int>(CatalogueEventsModelPrivate::Column::NbColumn);
253 }
254
255 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
256 {
257 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
258 }
259
260 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
261 {
262 if (index.isValid()) {
263
264 auto type = itemTypeOf(index);
265 if (type == CatalogueEventsModel::ItemType::Event) {
266 auto event = getEvent(index);
267 switch (role) {
268 case Qt::DisplayRole:
269 return impl->eventData(index.column(), event);
270 break;
271 }
272 }
273 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
274 auto product = getEventProduct(index);
275 switch (role) {
276 case Qt::DisplayRole:
277 return impl->eventProductData(index.column(), product);
278 break;
279 }
280 }
281 }
282
283 return QVariant{};
284 }
285
286 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
287 {
288 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
289 return impl->columnNames().value(section);
290 }
291
292 return QVariant();
293 }
294
295 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
296 {
297 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
298 [this, column, order](auto e1, auto e2) {
299 auto data1 = impl->eventData(column, e1);
300 auto data2 = impl->eventData(column, e2);
301
302 auto result = data1.toString() < data2.toString();
303
304 return order == Qt::AscendingOrder ? result : !result;
305 });
306
307 emit dataChanged(QModelIndex(), QModelIndex());
308 }
309
310 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
311 {
312 return Qt::CopyAction | Qt::MoveAction;
313 }
314
315 QStringList CatalogueEventsModel::mimeTypes() const
316 {
317 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
318 }
319
320 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
321 {
322 auto mimeData = new QMimeData;
323
324 bool isFirst = true;
325
326 QVector<std::shared_ptr<DBEvent> > eventList;
327 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
328
329 SqpRange firstTimeRange;
330 for (const auto &index : indexes) {
331 if (index.column() == 0) { // only the first column
332
333 auto type = itemTypeOf(index);
334 if (type == ItemType::Event) {
335 auto event = getEvent(index);
336 eventList << event;
337
338 if (isFirst) {
339 isFirst = false;
340 firstTimeRange.m_TStart = event->getTStart();
341 firstTimeRange.m_TEnd = event->getTEnd();
342 }
343 }
344 else if (type == ItemType::EventProduct) {
345 auto product = getEventProduct(index);
346 eventProductList << product;
347
348 if (isFirst) {
349 isFirst = false;
350 firstTimeRange.m_TStart = product->getTStart();
351 firstTimeRange.m_TEnd = product->getTEnd();
352 }
353 }
354 }
355 }
356
357 auto eventsEncodedData
358 = QByteArray{}; // sqpApp->catalogueController().->mimeDataForEvents(eventList); //TODO
359 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
360
361 if (eventList.count() + eventProductList.count() == 1) {
362 // No time range MIME data if multiple events are dragged
363 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
364 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
365 }
366
367 return mimeData;
368 }
369
370 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
371 {
372 if (!index.isValid()) {
373 return ItemType::Root;
374 }
375 else if (index.internalPointer() == nullptr) {
376 return ItemType::Event;
377 }
378 else {
379 return ItemType::EventProduct;
380 }
381 }
@@ -0,0 +1,103
1 #include "Catalogue/CatalogueTreeWidgetItem.h"
2
3 #include <memory>
4
5 #include <DBCatalogue.h>
6 #include <QBoxLayout>
7 #include <QToolButton>
8
9 const auto VALIDATION_BUTTON_ICON_SIZE = 12;
10
11 /// Column in the tree widget where the apply and cancel buttons must appear
12 const auto APPLY_CANCEL_BUTTONS_COLUMN = 1;
13
14 struct CatalogueTreeWidgetItem::CatalogueTreeWidgetItemPrivate {
15
16 std::shared_ptr<DBCatalogue> m_Catalogue;
17
18 CatalogueTreeWidgetItemPrivate(std::shared_ptr<DBCatalogue> catalogue) : m_Catalogue(catalogue)
19 {
20 }
21 };
22
23
24 CatalogueTreeWidgetItem::CatalogueTreeWidgetItem(std::shared_ptr<DBCatalogue> catalogue, int type)
25 : QTreeWidgetItem(type),
26 impl{spimpl::make_unique_impl<CatalogueTreeWidgetItemPrivate>(catalogue)}
27 {
28 setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
29 }
30
31 QVariant CatalogueTreeWidgetItem::data(int column, int role) const
32 {
33 if (column == 0) {
34 switch (role) {
35 case Qt::EditRole: // fallthrough
36 case Qt::DisplayRole:
37 return impl->m_Catalogue->getName();
38 default:
39 break;
40 }
41 }
42
43 return QTreeWidgetItem::data(column, role);
44 }
45
46 void CatalogueTreeWidgetItem::setData(int column, int role, const QVariant &value)
47 {
48 if (role == Qt::EditRole && column == 0) {
49 auto newName = value.toString();
50 if (newName != impl->m_Catalogue->getName()) {
51 setText(0, newName);
52 impl->m_Catalogue->setName(newName);
53 setHasChanges(true);
54 }
55 }
56 else {
57 QTreeWidgetItem::setData(column, role, value);
58 }
59 }
60
61 std::shared_ptr<DBCatalogue> CatalogueTreeWidgetItem::catalogue() const
62 {
63 return impl->m_Catalogue;
64 }
65
66 void CatalogueTreeWidgetItem::setHasChanges(bool value)
67 {
68 if (value) {
69 if (treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) == nullptr) {
70 auto widet = new QWidget{treeWidget()};
71
72 auto layout = new QHBoxLayout{widet};
73 layout->setContentsMargins(0, 0, 0, 0);
74 layout->setSpacing(0);
75
76 auto btnValid = new QToolButton{widet};
77 btnValid->setIcon(QIcon{":/icones/save"});
78 btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
79 btnValid->setAutoRaise(true);
80 QObject::connect(btnValid, &QToolButton::clicked, [this]() { setHasChanges(false); });
81 layout->addWidget(btnValid);
82
83 auto btnDiscard = new QToolButton{widet};
84 btnDiscard->setIcon(QIcon{":/icones/discard"});
85 btnDiscard->setIconSize(
86 QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
87 btnDiscard->setAutoRaise(true);
88 QObject::connect(btnDiscard, &QToolButton::clicked, [this]() { setHasChanges(false); });
89 layout->addWidget(btnDiscard);
90
91 treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, {widet});
92 }
93 }
94 else {
95 // Note: the widget is destroyed
96 treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, nullptr);
97 }
98 }
99
100 void CatalogueTreeWidgetItem::refresh()
101 {
102 emitDataChanged();
103 }
@@ -1,6 +1,8
1 1 build/
2 2 CMakeLists.txt.user
3 3 /.project
4 4 core/src/Version.cpp
5 5 core/include/Version.h
6 6 3rdparty/
7 subprojects/CatalogueAPI/
8 subprojects/QxOrm/
@@ -1,80 +1,89
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the QLop Software
3 3 -- Copyright (C) 2015, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include <QProcessEnvironment>
24 24 #include <QThread>
25 25 #include <SqpApplication.h>
26 26 #include <qglobal.h>
27 27
28 #include <QtPlugin>
28 29 #include <Plugin/PluginManager.h>
29 30 #include <QDir>
30 31
31 32 #include <QLoggingCategory>
32 33
33 34 Q_LOGGING_CATEGORY(LOG_Main, "Main")
34 35
35 36 namespace {
36 37
37 38 const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins");
38 39
39 40
40 41 } // namespace
41 42
42 43 int main(int argc, char *argv[])
43 44 {
45 #ifdef QT_STATICPLUGIN
46 Q_IMPORT_PLUGIN(MockPlugin)
47 Q_IMPORT_PLUGIN(AmdaPlugin)
48 Q_INIT_RESOURCE(amdaresources);
49 #endif
50 Q_INIT_RESOURCE(sqpguiresources);
51
44 52 SqpApplication a{argc, argv};
45 53 SqpApplication::setOrganizationName("LPP");
46 54 SqpApplication::setOrganizationDomain("lpp.fr");
47 55 SqpApplication::setApplicationName("SciQLop");
48 56 MainWindow w;
49 57 w.show();
50 58
51 59 // Loads plugins
52 60 auto pluginDir = QDir{a.applicationDirPath()};
53 61 auto pluginLookupPath = {
54 62 a.applicationDirPath(),
55 63 a.applicationDirPath() + "/" + PLUGIN_DIRECTORY_NAME,
56 64 a.applicationDirPath() + "/../lib64/SciQlop",
57 65 a.applicationDirPath() + "/../lib64/sciqlop",
58 66 a.applicationDirPath() + "/../lib/SciQlop",
59 67 a.applicationDirPath() + "/../lib/sciqlop",
60 68 a.applicationDirPath() + "/../plugins",
61 69 };
62 70
63 71 #if _WIN32 || _WIN64
64 72 pluginDir.mkdir(PLUGIN_DIRECTORY_NAME);
65 73 pluginDir.cd(PLUGIN_DIRECTORY_NAME);
66 74 #endif
67 75
68 76 PluginManager pluginManager{};
69 77
70 78 for (auto &&path : pluginLookupPath) {
71 79 QDir directory{path};
72 80 if (directory.exists()) {
73 81 qCDebug(LOG_Main())
74 82 << QObject::tr("Plugin directory: %1").arg(directory.absolutePath());
75 83 pluginManager.loadPlugins(directory);
76 84 }
77 85 }
86 pluginManager.loadStaticPlugins();
78 87
79 88 return a.exec();
80 89 }
@@ -1,364 +1,366
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the SciQLop Software
3 3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include "ui_MainWindow.h"
24 24
25 25 #include <Catalogue/CatalogueExplorer.h>
26 26 #include <DataSource/DataSourceController.h>
27 27 #include <DataSource/DataSourceWidget.h>
28 28 #include <Settings/SqpSettingsDialog.h>
29 29 #include <Settings/SqpSettingsGeneralWidget.h>
30 30 #include <SidePane/SqpSidePane.h>
31 31 #include <SqpApplication.h>
32 32 #include <Time/TimeController.h>
33 33 #include <TimeWidget/TimeWidget.h>
34 34 #include <Variable/Variable.h>
35 35 #include <Variable/VariableController.h>
36 36 #include <Visualization/VisualizationController.h>
37 37
38 38 #include <QAction>
39 39 #include <QDate>
40 40 #include <QDir>
41 41 #include <QFileDialog>
42 42 #include <QToolBar>
43 43 #include <QToolButton>
44 44 #include <memory.h>
45 45
46 46 #include "iostream"
47 47
48 48 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
49 49
50 50 namespace {
51 51 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
52 52 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
53 53 const auto VIEWPLITTERINDEX = 2;
54 54 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
55 55 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
56 56 }
57 57
58 58 class MainWindow::MainWindowPrivate {
59 59 public:
60 60 explicit MainWindowPrivate(MainWindow *mainWindow)
61 61 : m_LastOpenLeftInspectorSize{},
62 62 m_LastOpenRightInspectorSize{},
63 63 m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}},
64 64 m_SettingsDialog{new SqpSettingsDialog{mainWindow}},
65 65 m_CatalogExplorer{new CatalogueExplorer{mainWindow}}
66 66 {
67 67 }
68 68
69 69 QSize m_LastOpenLeftInspectorSize;
70 70 QSize m_LastOpenRightInspectorSize;
71 71 /// General settings widget. MainWindow has the ownership
72 72 SqpSettingsGeneralWidget *m_GeneralSettingsWidget;
73 73 /// Settings dialog. MainWindow has the ownership
74 74 SqpSettingsDialog *m_SettingsDialog;
75 75 /// Catalogue dialog. MainWindow has the ownership
76 76 CatalogueExplorer *m_CatalogExplorer;
77 77 };
78 78
79 79 MainWindow::MainWindow(QWidget *parent)
80 80 : QMainWindow{parent},
81 81 m_Ui{new Ui::MainWindow},
82 82 impl{spimpl::make_unique_impl<MainWindowPrivate>(this)}
83 83 {
84 84 m_Ui->setupUi(this);
85 85
86 86 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
87 87 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
88 88
89 impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view);
90
89 91
90 92 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
91 93 auto openLeftInspectorAction = new QAction{QIcon{
92 94 ":/icones/previous.png",
93 95 },
94 96 tr("Show/hide the left inspector"), this};
95 97
96 98
97 99 auto spacerLeftTop = new QWidget{};
98 100 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
99 101
100 102 auto spacerLeftBottom = new QWidget{};
101 103 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
102 104
103 105 leftSidePane->addWidget(spacerLeftTop);
104 106 leftSidePane->addAction(openLeftInspectorAction);
105 107 leftSidePane->addWidget(spacerLeftBottom);
106 108
107 109
108 110 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
109 111 auto openRightInspectorAction = new QAction{QIcon{
110 112 ":/icones/next.png",
111 113 },
112 114 tr("Show/hide the right inspector"), this};
113 115
114 116 auto spacerRightTop = new QWidget{};
115 117 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
116 118
117 119 auto spacerRightBottom = new QWidget{};
118 120 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
119 121
120 122 rightSidePane->addWidget(spacerRightTop);
121 123 rightSidePane->addAction(openRightInspectorAction);
122 124 rightSidePane->addWidget(spacerRightBottom);
123 125
124 126 openLeftInspectorAction->setCheckable(true);
125 127 openRightInspectorAction->setCheckable(true);
126 128
127 129 auto openInspector = [this](bool checked, bool right, auto action) {
128 130
129 131 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
130 132
131 133 auto &lastInspectorSize
132 134 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
133 135
134 136 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
135 137 : m_Ui->leftMainInspectorWidget->size();
136 138
137 139 // Update of the last opened geometry
138 140 if (checked) {
139 141 lastInspectorSize = nextInspectorSize;
140 142 }
141 143
142 144 auto startSize = lastInspectorSize;
143 145 auto endSize = startSize;
144 146 endSize.setWidth(0);
145 147
146 148 auto splitterInspectorIndex
147 149 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
148 150
149 151 auto currentSizes = m_Ui->splitter->sizes();
150 152 if (checked) {
151 153 // adjust sizes individually here, e.g.
152 154 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
153 155 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
154 156 m_Ui->splitter->setSizes(currentSizes);
155 157 }
156 158 else {
157 159 // adjust sizes individually here, e.g.
158 160 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
159 161 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
160 162 m_Ui->splitter->setSizes(currentSizes);
161 163 }
162 164
163 165 };
164 166
165 167
166 168 connect(openLeftInspectorAction, &QAction::triggered,
167 169 [openInspector, openLeftInspectorAction](bool checked) {
168 170 openInspector(checked, false, openLeftInspectorAction);
169 171 });
170 172 connect(openRightInspectorAction, &QAction::triggered,
171 173 [openInspector, openRightInspectorAction](bool checked) {
172 174 openInspector(checked, true, openRightInspectorAction);
173 175 });
174 176
175 177 // //////////////// //
176 178 // Menu and Toolbar //
177 179 // //////////////// //
178 180 this->menuBar()->addAction(tr("File"));
179 181 auto toolsMenu = this->menuBar()->addMenu(tr("Tools"));
180 182 toolsMenu->addAction(tr("Settings..."), [this]() {
181 183 // Loads settings
182 184 impl->m_SettingsDialog->loadSettings();
183 185
184 186 // Open settings dialog and save settings if the dialog is accepted
185 187 if (impl->m_SettingsDialog->exec() == QDialog::Accepted) {
186 188 impl->m_SettingsDialog->saveSettings();
187 189 }
188 190
189 191 });
190 192
191 193 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
192 194
193 195 auto timeWidget = new TimeWidget{};
194 196 mainToolBar->addWidget(timeWidget);
195 197
196 198 // Interaction modes
197 199 auto actionPointerMode = new QAction{QIcon(":/icones/pointer.png"), "Move", this};
198 200 actionPointerMode->setCheckable(true);
199 201 actionPointerMode->setChecked(sqpApp->plotsInteractionMode()
200 202 == SqpApplication::PlotsInteractionMode::None);
201 203 connect(actionPointerMode, &QAction::triggered,
202 204 []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); });
203 205
204 206 auto actionZoomMode = new QAction{QIcon(":/icones/zoom.png"), "Zoom", this};
205 207 actionZoomMode->setCheckable(true);
206 208 actionZoomMode->setChecked(sqpApp->plotsInteractionMode()
207 209 == SqpApplication::PlotsInteractionMode::ZoomBox);
208 210 connect(actionZoomMode, &QAction::triggered, []() {
209 211 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox);
210 212 });
211 213
212 214 auto actionOrganisationMode = new QAction{QIcon(":/icones/drag.png"), "Organize", this};
213 215 actionOrganisationMode->setCheckable(true);
214 216 actionOrganisationMode->setChecked(sqpApp->plotsInteractionMode()
215 217 == SqpApplication::PlotsInteractionMode::DragAndDrop);
216 218 connect(actionOrganisationMode, &QAction::triggered, []() {
217 219 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop);
218 220 });
219 221
220 222 auto actionZonesMode = new QAction{QIcon(":/icones/rectangle.png"), "Zones", this};
221 223 actionZonesMode->setCheckable(true);
222 224 actionZonesMode->setChecked(sqpApp->plotsInteractionMode()
223 225 == SqpApplication::PlotsInteractionMode::SelectionZones);
224 226 connect(actionZonesMode, &QAction::triggered, []() {
225 227 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones);
226 228 });
227 229
228 230 auto modeActionGroup = new QActionGroup{this};
229 231 modeActionGroup->addAction(actionZoomMode);
230 232 modeActionGroup->addAction(actionZonesMode);
231 233 modeActionGroup->addAction(actionOrganisationMode);
232 234 modeActionGroup->addAction(actionPointerMode);
233 235 modeActionGroup->setExclusive(true);
234 236
235 237 mainToolBar->addSeparator();
236 238 mainToolBar->addAction(actionPointerMode);
237 239 mainToolBar->addAction(actionZoomMode);
238 240 mainToolBar->addAction(actionOrganisationMode);
239 241 mainToolBar->addAction(actionZonesMode);
240 242 mainToolBar->addSeparator();
241 243
242 244 // Cursors
243 245 auto btnCursor = new QToolButton{this};
244 246 btnCursor->setIcon(QIcon(":/icones/cursor.png"));
245 247 btnCursor->setText("Cursor");
246 248 btnCursor->setToolTip("Cursor");
247 249 btnCursor->setPopupMode(QToolButton::InstantPopup);
248 250 auto cursorMenu = new QMenu("CursorMenu", this);
249 251 btnCursor->setMenu(cursorMenu);
250 252
251 253 auto noCursorAction = cursorMenu->addAction("No Cursor");
252 254 noCursorAction->setCheckable(true);
253 255 noCursorAction->setChecked(sqpApp->plotsCursorMode()
254 256 == SqpApplication::PlotsCursorMode::NoCursor);
255 257 connect(noCursorAction, &QAction::triggered,
256 258 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); });
257 259
258 260 cursorMenu->addSeparator();
259 261 auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor");
260 262 verticalCursorAction->setCheckable(true);
261 263 verticalCursorAction->setChecked(sqpApp->plotsCursorMode()
262 264 == SqpApplication::PlotsCursorMode::Vertical);
263 265 connect(verticalCursorAction, &QAction::triggered,
264 266 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); });
265 267
266 268 auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor");
267 269 temporalCursorAction->setCheckable(true);
268 270 temporalCursorAction->setChecked(sqpApp->plotsCursorMode()
269 271 == SqpApplication::PlotsCursorMode::Temporal);
270 272 connect(temporalCursorAction, &QAction::triggered,
271 273 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); });
272 274
273 275 auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor");
274 276 horizontalCursorAction->setCheckable(true);
275 277 horizontalCursorAction->setChecked(sqpApp->plotsCursorMode()
276 278 == SqpApplication::PlotsCursorMode::Horizontal);
277 279 connect(horizontalCursorAction, &QAction::triggered,
278 280 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); });
279 281
280 282 auto crossCursorAction = cursorMenu->addAction("Cross Cursor");
281 283 crossCursorAction->setCheckable(true);
282 284 crossCursorAction->setChecked(sqpApp->plotsCursorMode()
283 285 == SqpApplication::PlotsCursorMode::Cross);
284 286 connect(crossCursorAction, &QAction::triggered,
285 287 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); });
286 288
287 289 mainToolBar->addWidget(btnCursor);
288 290
289 291 auto cursorModeActionGroup = new QActionGroup{this};
290 292 cursorModeActionGroup->setExclusive(true);
291 293 cursorModeActionGroup->addAction(noCursorAction);
292 294 cursorModeActionGroup->addAction(verticalCursorAction);
293 295 cursorModeActionGroup->addAction(temporalCursorAction);
294 296 cursorModeActionGroup->addAction(horizontalCursorAction);
295 297 cursorModeActionGroup->addAction(crossCursorAction);
296 298
297 299 // Catalog
298 300 mainToolBar->addSeparator();
299 301 mainToolBar->addAction(QIcon(":/icones/catalogue.png"), "Catalogues",
300 302 [this]() { impl->m_CatalogExplorer->show(); });
301 303
302 304 // //////// //
303 305 // Settings //
304 306 // //////// //
305 307
306 308 // Registers "general settings" widget to the settings dialog
307 309 impl->m_SettingsDialog->registerWidget(QStringLiteral("General"),
308 310 impl->m_GeneralSettingsWidget);
309 311
310 312 // /////////// //
311 313 // Connections //
312 314 // /////////// //
313 315
314 316 // Controllers / controllers connections
315 317 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpRange)), &sqpApp->variableController(),
316 318 SLOT(onDateTimeOnSelection(SqpRange)));
317 319
318 320 // Widgets / controllers connections
319 321
320 322 // DataSource
321 323 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
322 324 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
323 325
324 326 // Time
325 327 connect(timeWidget, SIGNAL(timeUpdated(SqpRange)), &sqpApp->timeController(),
326 328 SLOT(onTimeToUpdate(SqpRange)));
327 329
328 330 // Visualization
329 331 connect(&sqpApp->visualizationController(),
330 332 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
331 333 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
332 334
333 335 connect(&sqpApp->visualizationController(),
334 336 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), m_Ui->view,
335 337 SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
336 338
337 339 // Widgets / widgets connections
338 340
339 341 // For the following connections, we use DirectConnection to allow each widget that can
340 342 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
341 343 // The order of connections is also important, since it determines the order in which each
342 344 // widget will attach its menu
343 345 connect(
344 346 m_Ui->variableInspectorWidget,
345 347 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
346 348 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
347 349 Qt::DirectConnection);
348 350 }
349 351
350 352 MainWindow::~MainWindow()
351 353 {
352 354 }
353 355
354 356 void MainWindow::changeEvent(QEvent *e)
355 357 {
356 358 QMainWindow::changeEvent(e);
357 359 switch (e->type()) {
358 360 case QEvent::LanguageChange:
359 361 m_Ui->retranslateUi(this);
360 362 break;
361 363 default:
362 364 break;
363 365 }
364 366 }
@@ -1,51 +1,69
1 1 #ifndef SCIQLOP_CATALOGUECONTROLLER_H
2 2 #define SCIQLOP_CATALOGUECONTROLLER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Data/SqpRange.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QObject>
10 10 #include <QUuid>
11 11
12 12 #include <Common/spimpl.h>
13 13
14 #include <memory>
15
16 class DBCatalogue;
17 class DBEvent;
18
14 19 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
15 20
16 21 class DataSourceItem;
17 22 class Variable;
18 23
19 24 /**
20 * @brief The CatalogueController class aims to make the link between SciQlop and its plugins.
21 * This is the intermediate class that SciQlop has to use in the way to connect a data source.
22 * Please first use register method to initialize a plugin specified by its metadata name (JSON
23 * plugin source) then others specifics method will be able to access it. You can load a data source
24 * driver plugin then create a data source.
25 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
26 * library.
25 27 */
26 28 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
27 29 Q_OBJECT
28 30 public:
29 31 explicit CatalogueController(QObject *parent = 0);
30 32 virtual ~CatalogueController();
31 33
32 signals:
33 /// Signal emitted when a variable is about to be deleted from SciQlop
34 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
34 // DB
35 // QStringList getRepositories() const;
36 void addDB(const QString &dbPath);
37 void saveDB(const QString &destinationPath, const QString &repository);
38
39 // Event
40 // bool createEvent(const QString &name);
41 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
42 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
43 std::list<std::shared_ptr<DBEvent> >
44 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
45 // void updateEvent(std::shared_ptr<DBEvent> event);
46 // void trashEvent(std::shared_ptr<DBEvent> event);
47 // void removeEvent(std::shared_ptr<DBEvent> event);
48 // void restore(QUuid eventId);
49 // void saveEvent(std::shared_ptr<DBEvent> event);
35 50
36 /// Signal emitted when a data acquisition is requested on a range for a variable
37 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
51 // Catalogue
52 // bool createCatalogue(const QString &name, QVector<QUuid> eventList);
53 std::list<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const;
54 // void removeEvent(QUuid catalogueId, const QString &repository);
55 // void saveCatalogue(std::shared_ptr<DBEvent> event);
38 56
39 57 public slots:
40 58 /// Manage init/end of the controller
41 59 void initialize();
42 60 void finalize();
43 61
44 62 private:
45 63 void waitForFinish();
46 64
47 65 class CatalogueControllerPrivate;
48 66 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
49 67 };
50 68
51 69 #endif // SCIQLOP_CATALOGUECONTROLLER_H
@@ -1,20 +1,21
1 1 #ifndef SCIQLOP_MIMETYPESDEF_H
2 2 #define SCIQLOP_MIMETYPESDEF_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <QString>
7 7
8 8 // ////////////////// //
9 9 // SciQlop Mime Types //
10 10 // ////////////////// //
11 11
12 12 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_GRAPH;
13 13 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE;
14 14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
15 15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_PRODUCT_LIST;
16 16 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
17 17 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_SELECTION_ZONE;
18 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_EVENT_LIST;
18 19
19 20
20 21 #endif // SCIQLOP_MIMETYPESDEF_H
@@ -1,36 +1,41
1 1 #ifndef SCIQLOP_PLUGINMANAGER_H
2 2 #define SCIQLOP_PLUGINMANAGER_H
3 3
4 4 #include "CoreGlobal.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9
10 10 class QDir;
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_PluginManager)
13 13
14 14 /**
15 15 * @brief The PluginManager class aims to handle the plugins loaded dynamically into SciQLop.
16 16 */
17 17 class SCIQLOP_CORE_EXPORT PluginManager {
18 18 public:
19 19 explicit PluginManager();
20 20
21 21 /**
22 22 * Loads plugins into SciQlop. The loaded plugins are those located in the directory passed in
23 23 * parameter
24 24 * @param pluginDir the directory containing the plugins
25 25 */
26 26 void loadPlugins(const QDir &pluginDir);
27 27
28 /**
29 * Loads static plugins into SciQlop. SciQLOP supports statically linked plugins.
30 */
31 void loadStaticPlugins();
32
28 33 /// @returns the number of plugins loaded
29 34 int nbPluginsLoaded() const noexcept;
30 35
31 36 private:
32 class PluginManagerPrivate;
37 struct PluginManagerPrivate;
33 38 spimpl::unique_impl_ptr<PluginManagerPrivate> impl;
34 39 };
35 40
36 41 #endif // SCIQLOP_PLUGINMANAGER_H
@@ -1,52 +1,161
1 1 #include <Catalogue/CatalogueController.h>
2 2
3 3 #include <Variable/Variable.h>
4 4
5 5 #include <CatalogueDao.h>
6 6
7 #include <ComparaisonPredicate.h>
8 #include <CompoundPredicate.h>
9 #include <DBCatalogue.h>
10 #include <DBEvent.h>
11 #include <DBTag.h>
12 #include <IRequestPredicate.h>
13
7 14 #include <QMutex>
8 15 #include <QThread>
9 16
10 17 #include <QDir>
11 18 #include <QStandardPaths>
12 19
13 20 Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController")
14 21
22 namespace {
23
24 static QString REPOSITORY_WORK_SUFFIX = QString{"Work"};
25
26 }
27
15 28 class CatalogueController::CatalogueControllerPrivate {
16 29 public:
17 30 QMutex m_WorkingMutex;
18 31 CatalogueDao m_CatalogueDao;
32
33 std::list<QString> m_RepositoryList;
19 34 };
20 35
21 36 CatalogueController::CatalogueController(QObject *parent)
22 37 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>()}
23 38 {
24 39 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
25 40 << QThread::currentThread();
26 41 }
27 42
28 43 CatalogueController::~CatalogueController()
29 44 {
30 45 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
31 46 << QThread::currentThread();
32 47 this->waitForFinish();
33 48 }
34 49
50 void CatalogueController::addDB(const QString &dbPath)
51 {
52 QDir dbDir(dbPath);
53 if (dbDir.exists()) {
54 auto dirName = dbDir.dirName();
55
56 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
57 != impl->m_RepositoryList.cend()) {
58 qCCritical(LOG_CatalogueController())
59 << tr("Impossible to addDB that is already loaded");
60 }
61
62 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
63 qCCritical(LOG_CatalogueController())
64 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
65 }
66 else {
67 impl->m_RepositoryList.push_back(dirName);
68 }
69 }
70 else {
71 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
72 << dbPath;
73 }
74 }
75
76 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
77 {
78 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
79 qCCritical(LOG_CatalogueController())
80 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
81 }
82 }
83
84 std::list<std::shared_ptr<DBEvent> >
85 CatalogueController::retrieveEvents(const QString &repository) const
86 {
87 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
88 auto events = impl->m_CatalogueDao.getEvents(repository);
89 for (auto event : events) {
90 eventsShared.push_back(std::make_shared<DBEvent>(event));
91 }
92 return eventsShared;
93 }
94
95 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
96 {
97 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
98 for (auto repository : impl->m_RepositoryList) {
99 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
100 }
101
102 return eventsShared;
103 }
104
105 std::list<std::shared_ptr<DBEvent> >
106 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
107 {
108 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
109 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
110 for (auto event : events) {
111 eventsShared.push_back(std::make_shared<DBEvent>(event));
112 }
113 return eventsShared;
114 }
115
116 std::list<std::shared_ptr<DBCatalogue> >
117 CatalogueController::getCatalogues(const QString &repository) const
118 {
119 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
120 auto catalogues = impl->m_CatalogueDao.getCatalogues(repository);
121 for (auto catalogue : catalogues) {
122 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
123 }
124 return cataloguesShared;
125 }
126
35 127 void CatalogueController::initialize()
36 128 {
37 129 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
38 130 << QThread::currentThread();
39 131 impl->m_WorkingMutex.lock();
40 132 impl->m_CatalogueDao.initialize();
133 auto defaultRepositoryLocation
134 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
135
136 QDir defaultRepositoryLocationDir;
137 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
138 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
139 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
140 qCInfo(LOG_CatalogueController())
141 << tr("Persistant data loading from: ") << defaultRepository;
142 this->addDB(defaultRepository);
143 }
144 else {
145 qCWarning(LOG_CatalogueController())
146 << tr("Cannot load the persistent default repository from ")
147 << defaultRepositoryLocation;
148 }
149
41 150 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
42 151 }
43 152
44 153 void CatalogueController::finalize()
45 154 {
46 155 impl->m_WorkingMutex.unlock();
47 156 }
48 157
49 158 void CatalogueController::waitForFinish()
50 159 {
51 160 QMutexLocker locker{&impl->m_WorkingMutex};
52 161 }
@@ -1,8 +1,9
1 1 #include "Common/MimeTypesDef.h"
2 2
3 3 const QString MIME_TYPE_GRAPH = QStringLiteral("sciqlop/graph");
4 4 const QString MIME_TYPE_ZONE = QStringLiteral("sciqlop/zone");
5 5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("sciqlop/var-list");
6 6 const QString MIME_TYPE_PRODUCT_LIST = QStringLiteral("sciqlop/product-list");
7 7 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("sciqlop/time-range");
8 8 const QString MIME_TYPE_SELECTION_ZONE = QStringLiteral("sciqlop/selection-zone");
9 const QString MIME_TYPE_EVENT_LIST = QStringLiteral("sciqlop/event-list");
@@ -1,124 +1,138
1 1 #include <Plugin/PluginManager.h>
2 2
3 3 #include <Plugin/IPlugin.h>
4 4
5 5 #include <QDir>
6 6 #include <QLibrary>
7 7 #include <QPluginLoader>
8 8
9 9 Q_LOGGING_CATEGORY(LOG_PluginManager, "PluginManager")
10 10
11 11 namespace {
12 12
13 13 /// Key for retrieving metadata of the plugin
14 14 const auto PLUGIN_METADATA_KEY = QStringLiteral("MetaData");
15 15
16 16 /// Key for retrieving the name of the plugin in its metadata
17 17 const auto PLUGIN_NAME_KEY = QStringLiteral("name");
18 18
19 19 /// Helper to state the plugin loading operation
20 20 struct LoadPluginState {
21 21 explicit LoadPluginState(const QString &pluginPath)
22 22 : m_PluginPath{pluginPath}, m_Valid{true}, m_ErrorMessage{}
23 23 {
24 24 }
25 25
26 26 void log() const
27 27 {
28 28 if (m_Valid) {
29 29 qCDebug(LOG_PluginManager())
30 30 << QObject::tr("File '%1' has been loaded as a plugin").arg(m_PluginPath);
31 31 }
32 32 else {
33 33 qCWarning(LOG_PluginManager())
34 34 << QObject::tr("File '%1' can't be loaded as a plugin: %2")
35 35 .arg(m_PluginPath)
36 36 .arg(m_ErrorMessage);
37 37 }
38 38 }
39 39
40 40 void setError(const QString &errorMessage)
41 41 {
42 42 m_Valid = false;
43 43 m_ErrorMessage = errorMessage;
44 44 }
45 45
46 46 QString m_PluginPath;
47 47 bool m_Valid;
48 48 QString m_ErrorMessage;
49 49 };
50 50
51 51 } // namespace
52 52
53 53 struct PluginManager::PluginManagerPrivate {
54 54 /**
55 55 * Loads a single plugin into SciQlop. The method has no effect if the plugin is malformed (e.g.
56 56 * wrong library type, missing metadata, etc.)
57 57 * @param pluginPath the path to the plugin library.
58 58 */
59 59 void loadPlugin(const QString &pluginPath)
60 60 {
61 61 qCDebug(LOG_PluginManager())
62 62 << QObject::tr("Attempting to load file '%1' as a plugin").arg(pluginPath);
63 63
64 64 LoadPluginState loadState{pluginPath};
65 65
66 66 if (QLibrary::isLibrary(pluginPath)) {
67 67 QPluginLoader pluginLoader{pluginPath};
68 68
69 69 // Retrieving the plugin name to check if it can be loaded (i.e. no plugin with the same
70 70 // name has been registered yet)
71 71 auto metadata = pluginLoader.metaData().value(PLUGIN_METADATA_KEY).toObject();
72 72 auto pluginName = metadata.value(PLUGIN_NAME_KEY).toString();
73 73
74 74 if (pluginName.isEmpty()) {
75 75 loadState.setError(QObject::tr("empty file name"));
76 76 }
77 77 else if (m_RegisteredPlugins.contains(pluginName)) {
78 78 loadState.setError(QObject::tr("name '%1' already registered").arg(pluginName));
79 79 }
80 80 else {
81 81 if (auto pluginInstance = qobject_cast<IPlugin *>(pluginLoader.instance())) {
82 82 pluginInstance->initialize();
83 83 m_RegisteredPlugins.insert(pluginName, pluginPath);
84 84 }
85 85 else {
86 86 loadState.setError(QObject::tr("the file is not a Sciqlop plugin"));
87 87 }
88 88 }
89 89 }
90 90 else {
91 91 loadState.setError(QObject::tr("the file is not a library"));
92 92 }
93 93
94 94 // Log loading result
95 95 loadState.log();
96 96 }
97 97
98 void loadStaticPlugins()
99 {
100 for (QObject *plugin : QPluginLoader::staticInstances())
101 {
102 qobject_cast<IPlugin *>(plugin)->initialize();
103 m_RegisteredPlugins.insert(plugin->metaObject()->className(), "StaticPlugin");
104 }
105 }
106
98 107 /// Registered plugins (key: plugin name, value: plugin path)
99 108 QHash<QString, QString> m_RegisteredPlugins;
100 109 };
101 110
102 111 PluginManager::PluginManager() : impl{spimpl::make_unique_impl<PluginManagerPrivate>()}
103 112 {
104 113 }
105 114
106 115 void PluginManager::loadPlugins(const QDir &pluginDir)
107 116 {
108 117 // Load plugins
109 118 auto pluginInfoList
110 119 = pluginDir.entryInfoList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name);
111 120 for (auto entryInfo : qAsConst(pluginInfoList)) {
112 121 if (entryInfo.isDir()) {
113 122 this->loadPlugins(QDir{entryInfo.absoluteFilePath()});
114 123 }
115 124 else if (QLibrary::isLibrary(entryInfo.absoluteFilePath())) {
116 125 impl->loadPlugin(entryInfo.absoluteFilePath());
117 126 }
118 127 }
119 128 }
120 129
130 void PluginManager::loadStaticPlugins()
131 {
132 impl->loadStaticPlugins();
133 }
134
121 135 int PluginManager::nbPluginsLoaded() const noexcept
122 136 {
123 137 return impl->m_RegisteredPlugins.size();
124 138 }
@@ -1,1063 +1,1063
1 1 #include <Variable/Variable.h>
2 2 #include <Variable/VariableAcquisitionWorker.h>
3 3 #include <Variable/VariableCacheStrategy.h>
4 4 #include <Variable/VariableCacheStrategyFactory.h>
5 5 #include <Variable/VariableController.h>
6 6 #include <Variable/VariableModel.h>
7 7 #include <Variable/VariableSynchronizationGroup.h>
8 8
9 9 #include <Data/DataProviderParameters.h>
10 10 #include <Data/IDataProvider.h>
11 11 #include <Data/IDataSeries.h>
12 12 #include <Data/VariableRequest.h>
13 13 #include <Time/TimeController.h>
14 14
15 15 #include <QDataStream>
16 16 #include <QMutex>
17 17 #include <QThread>
18 18 #include <QUuid>
19 19 #include <QtCore/QItemSelectionModel>
20 20
21 21 #include <deque>
22 22 #include <set>
23 23 #include <unordered_map>
24 24
25 25 Q_LOGGING_CATEGORY(LOG_VariableController, "VariableController")
26 26
27 27 namespace {
28 28
29 29 SqpRange computeSynchroRangeRequested(const SqpRange &varRange, const SqpRange &graphRange,
30 30 const SqpRange &oldGraphRange)
31 31 {
32 32 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
33 33
34 34 auto varRangeRequested = varRange;
35 35 switch (zoomType) {
36 36 case AcquisitionZoomType::ZoomIn: {
37 37 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
38 38 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
39 39 varRangeRequested.m_TStart += deltaLeft;
40 40 varRangeRequested.m_TEnd -= deltaRight;
41 41 break;
42 42 }
43 43
44 44 case AcquisitionZoomType::ZoomOut: {
45 45 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
46 46 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
47 47 varRangeRequested.m_TStart -= deltaLeft;
48 48 varRangeRequested.m_TEnd += deltaRight;
49 49 break;
50 50 }
51 51 case AcquisitionZoomType::PanRight: {
52 52 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
53 53 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
54 54 varRangeRequested.m_TStart += deltaLeft;
55 55 varRangeRequested.m_TEnd += deltaRight;
56 56 break;
57 57 }
58 58 case AcquisitionZoomType::PanLeft: {
59 59 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
60 60 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
61 61 varRangeRequested.m_TStart -= deltaLeft;
62 62 varRangeRequested.m_TEnd -= deltaRight;
63 63 break;
64 64 }
65 65 case AcquisitionZoomType::Unknown: {
66 66 qCCritical(LOG_VariableController())
67 67 << VariableController::tr("Impossible to synchronize: zoom type unknown");
68 68 break;
69 69 }
70 70 default:
71 71 qCCritical(LOG_VariableController()) << VariableController::tr(
72 72 "Impossible to synchronize: zoom type not take into account");
73 73 // No action
74 74 break;
75 75 }
76 76
77 77 return varRangeRequested;
78 78 }
79 79 }
80 80
81 81 enum class VariableRequestHandlerState { OFF, RUNNING, PENDING };
82 82
83 83 struct VariableRequestHandler {
84 84
85 85 VariableRequestHandler()
86 86 {
87 87 m_CanUpdate = false;
88 88 m_State = VariableRequestHandlerState::OFF;
89 89 }
90 90
91 91 QUuid m_VarId;
92 92 VariableRequest m_RunningVarRequest;
93 93 VariableRequest m_PendingVarRequest;
94 94 VariableRequestHandlerState m_State;
95 95 bool m_CanUpdate;
96 96 };
97 97
98 98 struct VariableController::VariableControllerPrivate {
99 99 explicit VariableControllerPrivate(VariableController *parent)
100 100 : m_WorkingMutex{},
101 101 m_VariableModel{new VariableModel{parent}},
102 102 m_VariableSelectionModel{new QItemSelectionModel{m_VariableModel, parent}},
103 103 // m_VariableCacheStrategy{std::make_unique<VariableCacheStrategy>()},
104 104 m_VariableCacheStrategy{VariableCacheStrategyFactory::createCacheStrategy(
105 105 CacheStrategy::SingleThreshold)},
106 106 m_VariableAcquisitionWorker{std::make_unique<VariableAcquisitionWorker>()},
107 107 q{parent}
108 108 {
109 109
110 110 m_VariableAcquisitionWorker->moveToThread(&m_VariableAcquisitionWorkerThread);
111 111 m_VariableAcquisitionWorkerThread.setObjectName("VariableAcquisitionWorkerThread");
112 112 }
113 113
114 114
115 115 virtual ~VariableControllerPrivate()
116 116 {
117 117 qCDebug(LOG_VariableController()) << tr("VariableControllerPrivate destruction");
118 118 m_VariableAcquisitionWorkerThread.quit();
119 119 m_VariableAcquisitionWorkerThread.wait();
120 120 }
121 121
122 122
123 123 void processRequest(std::shared_ptr<Variable> var, const SqpRange &rangeRequested,
124 124 QUuid varRequestId);
125 125
126 126 std::shared_ptr<Variable> findVariable(QUuid vIdentifier);
127 127 std::shared_ptr<IDataSeries>
128 128 retrieveDataSeries(const QVector<AcquisitionDataPacket> acqDataPacketVector);
129 129
130 130 void registerProvider(std::shared_ptr<IDataProvider> provider);
131 131
132 132 void storeVariableRequest(QUuid varId, QUuid varRequestId, const VariableRequest &varRequest);
133 133 QUuid acceptVariableRequest(QUuid varId, std::shared_ptr<IDataSeries> dataSeries);
134 134 void updateVariables(QUuid varRequestId);
135 135 void updateVariableRequest(QUuid varRequestId);
136 136 void cancelVariableRequest(QUuid varRequestId);
137 137 void executeVarRequest(std::shared_ptr<Variable> var, VariableRequest &varRequest);
138 138
139 139 QMutex m_WorkingMutex;
140 140 /// Variable model. The VariableController has the ownership
141 141 VariableModel *m_VariableModel;
142 142 QItemSelectionModel *m_VariableSelectionModel;
143 143
144 144
145 145 TimeController *m_TimeController{nullptr};
146 146 std::unique_ptr<VariableCacheStrategy> m_VariableCacheStrategy;
147 147 std::unique_ptr<VariableAcquisitionWorker> m_VariableAcquisitionWorker;
148 148 QThread m_VariableAcquisitionWorkerThread;
149 149
150 150 std::unordered_map<std::shared_ptr<Variable>, std::shared_ptr<IDataProvider> >
151 151 m_VariableToProviderMap;
152 152 std::unordered_map<std::shared_ptr<Variable>, QUuid> m_VariableToIdentifierMap;
153 153 std::map<QUuid, std::shared_ptr<VariableSynchronizationGroup> >
154 154 m_GroupIdToVariableSynchronizationGroupMap;
155 155 std::map<QUuid, QUuid> m_VariableIdGroupIdMap;
156 156 std::set<std::shared_ptr<IDataProvider> > m_ProviderSet;
157 157
158 158 std::map<QUuid, std::list<QUuid> > m_VarGroupIdToVarIds;
159 159 std::map<QUuid, std::unique_ptr<VariableRequestHandler> > m_VarIdToVarRequestHandler;
160 160
161 161 VariableController *q;
162 162 };
163 163
164 164
165 165 VariableController::VariableController(QObject *parent)
166 166 : QObject{parent}, impl{spimpl::make_unique_impl<VariableControllerPrivate>(this)}
167 167 {
168 168 qCDebug(LOG_VariableController()) << tr("VariableController construction")
169 169 << QThread::currentThread();
170 170
171 171 connect(impl->m_VariableModel, &VariableModel::abortProgessRequested, this,
172 172 &VariableController::onAbortProgressRequested);
173 173
174 174 connect(impl->m_VariableAcquisitionWorker.get(),
175 175 &VariableAcquisitionWorker::variableCanceledRequested, this,
176 176 &VariableController::onAbortAcquisitionRequested);
177 177
178 178 connect(impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::dataProvided, this,
179 179 &VariableController::onDataProvided);
180 180 connect(impl->m_VariableAcquisitionWorker.get(),
181 181 &VariableAcquisitionWorker::variableRequestInProgress, this,
182 182 &VariableController::onVariableRetrieveDataInProgress);
183 183
184 184
185 185 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::started,
186 186 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::initialize);
187 187 connect(&impl->m_VariableAcquisitionWorkerThread, &QThread::finished,
188 188 impl->m_VariableAcquisitionWorker.get(), &VariableAcquisitionWorker::finalize);
189 189
190 190 connect(impl->m_VariableModel, &VariableModel::requestVariableRangeUpdate, this,
191 191 &VariableController::onUpdateDateTime);
192 192
193 193 impl->m_VariableAcquisitionWorkerThread.start();
194 194 }
195 195
196 196 VariableController::~VariableController()
197 197 {
198 198 qCDebug(LOG_VariableController()) << tr("VariableController destruction")
199 199 << QThread::currentThread();
200 200 this->waitForFinish();
201 201 }
202 202
203 203 VariableModel *VariableController::variableModel() noexcept
204 204 {
205 205 return impl->m_VariableModel;
206 206 }
207 207
208 208 QItemSelectionModel *VariableController::variableSelectionModel() noexcept
209 209 {
210 210 return impl->m_VariableSelectionModel;
211 211 }
212 212
213 213 void VariableController::setTimeController(TimeController *timeController) noexcept
214 214 {
215 215 impl->m_TimeController = timeController;
216 216 }
217 217
218 218 std::shared_ptr<Variable>
219 219 VariableController::cloneVariable(std::shared_ptr<Variable> variable) noexcept
220 220 {
221 221 if (impl->m_VariableModel->containsVariable(variable)) {
222 222 // Clones variable
223 223 auto duplicate = variable->clone();
224 224
225 225 // Adds clone to model
226 226 impl->m_VariableModel->addVariable(duplicate);
227 227
228 228 // Generates clone identifier
229 229 impl->m_VariableToIdentifierMap[duplicate] = QUuid::createUuid();
230 230
231 231 // Registers provider
232 232 auto variableProvider = impl->m_VariableToProviderMap.at(variable);
233 233 auto duplicateProvider = variableProvider != nullptr ? variableProvider->clone() : nullptr;
234 234
235 235 impl->m_VariableToProviderMap[duplicate] = duplicateProvider;
236 236 if (duplicateProvider) {
237 237 impl->registerProvider(duplicateProvider);
238 238 }
239 239
240 240 return duplicate;
241 241 }
242 242 else {
243 243 qCCritical(LOG_VariableController())
244 244 << tr("Can't create duplicate of variable %1: variable not registered in the model")
245 245 .arg(variable->name());
246 246 return nullptr;
247 247 }
248 248 }
249 249
250 250 void VariableController::deleteVariable(std::shared_ptr<Variable> variable) noexcept
251 251 {
252 252 if (!variable) {
253 253 qCCritical(LOG_VariableController()) << "Can't delete variable: variable is null";
254 254 return;
255 255 }
256 256
257 257 // Spreads in SciQlop that the variable will be deleted, so that potential receivers can
258 258 // make some treatments before the deletion
259 259 emit variableAboutToBeDeleted(variable);
260 260
261 261 // Deletes identifier
262 262 impl->m_VariableToIdentifierMap.erase(variable);
263 263
264 264 // Deletes provider
265 265 auto nbProvidersDeleted = impl->m_VariableToProviderMap.erase(variable);
266 266 qCDebug(LOG_VariableController())
267 267 << tr("Number of providers deleted for variable %1: %2")
268 268 .arg(variable->name(), QString::number(nbProvidersDeleted));
269 269
270 270
271 271 // Deletes from model
272 272 impl->m_VariableModel->deleteVariable(variable);
273 273 }
274 274
275 275 void VariableController::deleteVariables(
276 276 const QVector<std::shared_ptr<Variable> > &variables) noexcept
277 277 {
278 278 for (auto variable : qAsConst(variables)) {
279 279 deleteVariable(variable);
280 280 }
281 281 }
282 282
283 283 QByteArray
284 284 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
285 285 {
286 286 auto encodedData = QByteArray{};
287 287
288 288 QVariantList ids;
289 289 for (auto &var : variables) {
290 290 auto itVar = impl->m_VariableToIdentifierMap.find(var);
291 291 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
292 292 qCCritical(LOG_VariableController())
293 293 << tr("Impossible to find the data for an unknown variable.");
294 294 }
295 295
296 296 ids << itVar->second.toByteArray();
297 297 }
298 298
299 299 QDataStream stream{&encodedData, QIODevice::WriteOnly};
300 300 stream << ids;
301 301
302 302 return encodedData;
303 303 }
304 304
305 305 QList<std::shared_ptr<Variable> >
306 306 VariableController::variablesForMimeData(const QByteArray &mimeData) const
307 307 {
308 308 auto variables = QList<std::shared_ptr<Variable> >{};
309 309 QDataStream stream{mimeData};
310 310
311 311 QVariantList ids;
312 312 stream >> ids;
313 313
314 314 for (auto id : ids) {
315 315 auto uuid = QUuid{id.toByteArray()};
316 316 auto var = impl->findVariable(uuid);
317 317 variables << var;
318 318 }
319 319
320 320 return variables;
321 321 }
322 322
323 323 std::shared_ptr<Variable>
324 324 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
325 325 std::shared_ptr<IDataProvider> provider) noexcept
326 326 {
327 327 if (!impl->m_TimeController) {
328 328 qCCritical(LOG_VariableController())
329 329 << tr("Impossible to create variable: The time controller is null");
330 330 return nullptr;
331 331 }
332 332
333 333 auto range = impl->m_TimeController->dateTime();
334 334
335 335 if (auto newVariable = impl->m_VariableModel->createVariable(name, metadata)) {
336 336 auto varId = QUuid::createUuid();
337 337
338 338 // Create the handler
339 339 auto varRequestHandler = std::make_unique<VariableRequestHandler>();
340 340 varRequestHandler->m_VarId = varId;
341 341
342 342 impl->m_VarIdToVarRequestHandler.insert(
343 343 std::make_pair(varId, std::move(varRequestHandler)));
344 344
345 345 // store the provider
346 346 impl->registerProvider(provider);
347 347
348 348 // Associate the provider
349 349 impl->m_VariableToProviderMap[newVariable] = provider;
350 350 impl->m_VariableToIdentifierMap[newVariable] = varId;
351 351
352 352 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{newVariable}, range, false);
353 353
354 354 // auto varRequestId = QUuid::createUuid();
355 355 // qCInfo(LOG_VariableController()) << "createVariable: " << varId << varRequestId;
356 356 // impl->processRequest(newVariable, range, varRequestId);
357 357 // impl->updateVariableRequest(varRequestId);
358 358
359 359 return newVariable;
360 360 }
361 361
362 362 qCCritical(LOG_VariableController()) << tr("Impossible to create variable");
363 363 return nullptr;
364 364 }
365 365
366 366 void VariableController::onDateTimeOnSelection(const SqpRange &dateTime)
367 367 {
368 368 // NOTE: Even if acquisition request is aborting, the graphe range will be changed
369 369 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
370 370 << QThread::currentThread()->objectName();
371 371 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
372 372
373 373 // NOTE we only permit the time modification for one variable
374 374 // DEPRECATED
375 375 // auto variables = QVector<std::shared_ptr<Variable> >{};
376 376 // for (const auto &selectedRow : qAsConst(selectedRows)) {
377 377 // if (auto selectedVariable =
378 378 // impl->m_VariableModel->variable(selectedRow.row())) {
379 379 // variables << selectedVariable;
380 380
381 381 // // notify that rescale operation has to be done
382 382 // emit rangeChanged(selectedVariable, dateTime);
383 383 // }
384 384 // }
385 385 // if (!variables.isEmpty()) {
386 386 // this->onRequestDataLoading(variables, dateTime, synchro);
387 387 // }
388 388 if (selectedRows.size() == 1) {
389 389
390 390 if (auto selectedVariable
391 391 = impl->m_VariableModel->variable(qAsConst(selectedRows).first().row())) {
392 392
393 393 onUpdateDateTime(selectedVariable, dateTime);
394 394 }
395 395 }
396 396 else if (selectedRows.size() > 1) {
397 397 qCCritical(LOG_VariableController())
398 398 << tr("Impossible to set time for more than 1 variable in the same time");
399 399 }
400 400 else {
401 401 qCWarning(LOG_VariableController())
402 402 << tr("There is no variable selected to set the time one");
403 403 }
404 404 }
405 405
406 406 void VariableController::onUpdateDateTime(std::shared_ptr<Variable> variable,
407 407 const SqpRange &dateTime)
408 408 {
409 409 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
410 410 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
411 411 qCCritical(LOG_VariableController())
412 412 << tr("Impossible to onDateTimeOnSelection request for unknown variable");
413 413 return;
414 414 }
415 415
416 416 // notify that rescale operation has to be done
417 417 emit rangeChanged(variable, dateTime);
418 418
419 419 auto synchro
420 420 = impl->m_VariableIdGroupIdMap.find(itVar->second) != impl->m_VariableIdGroupIdMap.cend();
421 421
422 422 this->onRequestDataLoading(QVector<std::shared_ptr<Variable> >{variable}, dateTime, synchro);
423 423 }
424 424
425 425 void VariableController::onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
426 426 const SqpRange &cacheRangeRequested,
427 427 QVector<AcquisitionDataPacket> dataAcquired)
428 428 {
429 429 qCDebug(LOG_VariableController()) << tr("onDataProvided") << QThread::currentThread();
430 430 auto retrievedDataSeries = impl->retrieveDataSeries(dataAcquired);
431 431 auto varRequestId = impl->acceptVariableRequest(vIdentifier, retrievedDataSeries);
432 432 if (!varRequestId.isNull()) {
433 433 impl->updateVariables(varRequestId);
434 434 }
435 435 }
436 436
437 437 void VariableController::onVariableRetrieveDataInProgress(QUuid identifier, double progress)
438 438 {
439 439 qCDebug(LOG_VariableController())
440 440 << "TORM: variableController::onVariableRetrieveDataInProgress"
441 441 << QThread::currentThread()->objectName() << progress;
442 442 if (auto var = impl->findVariable(identifier)) {
443 443 impl->m_VariableModel->setDataProgress(var, progress);
444 444 }
445 445 else {
446 446 qCCritical(LOG_VariableController())
447 447 << tr("Impossible to notify progression of a null variable");
448 448 }
449 449 }
450 450
451 451 void VariableController::onAbortProgressRequested(std::shared_ptr<Variable> variable)
452 452 {
453 453 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortProgressRequested"
454 454 << QThread::currentThread()->objectName() << variable->name();
455 455
456 456 auto itVar = impl->m_VariableToIdentifierMap.find(variable);
457 457 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
458 458 qCCritical(LOG_VariableController())
459 459 << tr("Impossible to onAbortProgressRequested request for unknown variable");
460 460 return;
461 461 }
462 462
463 463 auto varId = itVar->second;
464 464
465 465 auto itVarHandler = impl->m_VarIdToVarRequestHandler.find(varId);
466 466 if (itVarHandler == impl->m_VarIdToVarRequestHandler.cend()) {
467 467 qCCritical(LOG_VariableController())
468 468 << tr("Impossible to onAbortProgressRequested for variable with unknown handler");
469 469 return;
470 470 }
471 471
472 472 auto varHandler = itVarHandler->second.get();
473 473
474 474 // case where a variable has a running request
475 475 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
476 476 impl->cancelVariableRequest(varHandler->m_RunningVarRequest.m_VariableGroupId);
477 477 }
478 478 }
479 479
480 480 void VariableController::onAbortAcquisitionRequested(QUuid vIdentifier)
481 481 {
482 482 qCDebug(LOG_VariableController()) << "TORM: variableController::onAbortAcquisitionRequested"
483 483 << QThread::currentThread()->objectName() << vIdentifier;
484 484
485 485 if (auto var = impl->findVariable(vIdentifier)) {
486 486 this->onAbortProgressRequested(var);
487 487 }
488 488 else {
489 489 qCCritical(LOG_VariableController())
490 490 << tr("Impossible to abort Acquisition Requestof a null variable");
491 491 }
492 492 }
493 493
494 494 void VariableController::onAddSynchronizationGroupId(QUuid synchronizationGroupId)
495 495 {
496 496 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronizationGroupId"
497 497 << QThread::currentThread()->objectName()
498 498 << synchronizationGroupId;
499 499 auto vSynchroGroup = std::make_shared<VariableSynchronizationGroup>();
500 500 impl->m_GroupIdToVariableSynchronizationGroupMap.insert(
501 501 std::make_pair(synchronizationGroupId, vSynchroGroup));
502 502 }
503 503
504 504 void VariableController::onRemoveSynchronizationGroupId(QUuid synchronizationGroupId)
505 505 {
506 506 impl->m_GroupIdToVariableSynchronizationGroupMap.erase(synchronizationGroupId);
507 507 }
508 508
509 509 void VariableController::onAddSynchronized(std::shared_ptr<Variable> variable,
510 510 QUuid synchronizationGroupId)
511 511
512 512 {
513 513 qCDebug(LOG_VariableController()) << "TORM: VariableController::onAddSynchronized"
514 514 << synchronizationGroupId;
515 515 auto varToVarIdIt = impl->m_VariableToIdentifierMap.find(variable);
516 516 if (varToVarIdIt != impl->m_VariableToIdentifierMap.cend()) {
517 517 auto groupIdToVSGIt
518 518 = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
519 519 if (groupIdToVSGIt != impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
520 520 impl->m_VariableIdGroupIdMap.insert(
521 521 std::make_pair(varToVarIdIt->second, synchronizationGroupId));
522 522 groupIdToVSGIt->second->addVariableId(varToVarIdIt->second);
523 523 }
524 524 else {
525 525 qCCritical(LOG_VariableController())
526 526 << tr("Impossible to synchronize a variable with an unknown sycnhronization group")
527 527 << variable->name();
528 528 }
529 529 }
530 530 else {
531 531 qCCritical(LOG_VariableController())
532 532 << tr("Impossible to synchronize a variable with no identifier") << variable->name();
533 533 }
534 534 }
535 535
536 536 void VariableController::desynchronize(std::shared_ptr<Variable> variable,
537 537 QUuid synchronizationGroupId)
538 538 {
539 539 // Gets variable id
540 540 auto variableIt = impl->m_VariableToIdentifierMap.find(variable);
541 541 if (variableIt == impl->m_VariableToIdentifierMap.cend()) {
542 542 qCCritical(LOG_VariableController())
543 543 << tr("Can't desynchronize variable %1: variable identifier not found")
544 544 .arg(variable->name());
545 545 return;
546 546 }
547 547
548 548 // Gets synchronization group
549 549 auto groupIt = impl->m_GroupIdToVariableSynchronizationGroupMap.find(synchronizationGroupId);
550 550 if (groupIt == impl->m_GroupIdToVariableSynchronizationGroupMap.cend()) {
551 551 qCCritical(LOG_VariableController())
552 552 << tr("Can't desynchronize variable %1: unknown synchronization group")
553 553 .arg(variable->name());
554 554 return;
555 555 }
556 556
557 557 auto variableId = variableIt->second;
558 558
559 559 // Removes variable from synchronization group
560 560 auto synchronizationGroup = groupIt->second;
561 561 synchronizationGroup->removeVariableId(variableId);
562 562
563 563 // Removes link between variable and synchronization group
564 564 impl->m_VariableIdGroupIdMap.erase(variableId);
565 565 }
566 566
567 567 void VariableController::onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables,
568 568 const SqpRange &range, bool synchronise)
569 569 {
570 570 // variables is assumed synchronized
571 571 // TODO: Asser variables synchronization
572 572 // we want to load data of the variable for the dateTime.
573 573 if (variables.isEmpty()) {
574 574 return;
575 575 }
576 576
577 577 auto varRequestId = QUuid::createUuid();
578 578 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
579 579 << QThread::currentThread()->objectName() << varRequestId
580 580 << range << synchronise;
581 581
582 582 if (!synchronise) {
583 583 auto varIds = std::list<QUuid>{};
584 584 for (const auto &var : variables) {
585 585 auto vId = impl->m_VariableToIdentifierMap.at(var);
586 586 varIds.push_back(vId);
587 587 }
588 588 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
589 589 for (const auto &var : variables) {
590 590 qCDebug(LOG_VariableController()) << "processRequest for" << var->name() << varRequestId
591 591 << varIds.size();
592 592 impl->processRequest(var, range, varRequestId);
593 593 }
594 594 }
595 595 else {
596 596 auto vId = impl->m_VariableToIdentifierMap.at(variables.first());
597 597 auto varIdToGroupIdIt = impl->m_VariableIdGroupIdMap.find(vId);
598 598 if (varIdToGroupIdIt != impl->m_VariableIdGroupIdMap.cend()) {
599 599 auto groupId = varIdToGroupIdIt->second;
600 600
601 601 auto vSynchronizationGroup
602 602 = impl->m_GroupIdToVariableSynchronizationGroupMap.at(groupId);
603 603 auto vSyncIds = vSynchronizationGroup->getIds();
604 604
605 605 auto varIds = std::list<QUuid>{};
606 606 for (auto vId : vSyncIds) {
607 607 varIds.push_back(vId);
608 608 }
609 609 impl->m_VarGroupIdToVarIds.insert(std::make_pair(varRequestId, varIds));
610 610
611 611 for (auto vId : vSyncIds) {
612 612 auto var = impl->findVariable(vId);
613 613
614 614 // Don't process already processed var
615 615 if (var != nullptr) {
616 616 qCDebug(LOG_VariableController()) << "processRequest synchro for" << var->name()
617 617 << varRequestId;
618 618 auto vSyncRangeRequested
619 619 = variables.contains(var)
620 620 ? range
621 621 : computeSynchroRangeRequested(var->range(), range,
622 622 variables.first()->range());
623 623 qCDebug(LOG_VariableController()) << "synchro RR" << vSyncRangeRequested;
624 624 impl->processRequest(var, vSyncRangeRequested, varRequestId);
625 625 }
626 626 else {
627 627 qCCritical(LOG_VariableController())
628 628
629 629 << tr("Impossible to synchronize a null variable");
630 630 }
631 631 }
632 632 }
633 633 }
634 634
635 635 impl->updateVariables(varRequestId);
636 636 }
637 637
638 638
639 639 void VariableController::initialize()
640 640 {
641 641 qCDebug(LOG_VariableController()) << tr("VariableController init") << QThread::currentThread();
642 642 impl->m_WorkingMutex.lock();
643 643 qCDebug(LOG_VariableController()) << tr("VariableController init END");
644 644 }
645 645
646 646 void VariableController::finalize()
647 647 {
648 648 impl->m_WorkingMutex.unlock();
649 649 }
650 650
651 651 void VariableController::waitForFinish()
652 652 {
653 653 QMutexLocker locker{&impl->m_WorkingMutex};
654 654 }
655 655
656 656 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const SqpRange &oldRange)
657 657 {
658 658 // t1.m_TStart <= t2.m_TStart && t2.m_TEnd <= t1.m_TEnd
659 659 auto zoomType = AcquisitionZoomType::Unknown;
660 660 if (range.m_TStart <= oldRange.m_TStart && oldRange.m_TEnd <= range.m_TEnd) {
661 661 qCDebug(LOG_VariableController()) << "zoomtype: ZoomOut";
662 662 zoomType = AcquisitionZoomType::ZoomOut;
663 663 }
664 664 else if (range.m_TStart > oldRange.m_TStart && range.m_TEnd > oldRange.m_TEnd) {
665 665 qCDebug(LOG_VariableController()) << "zoomtype: PanRight";
666 666 zoomType = AcquisitionZoomType::PanRight;
667 667 }
668 668 else if (range.m_TStart < oldRange.m_TStart && range.m_TEnd < oldRange.m_TEnd) {
669 669 qCDebug(LOG_VariableController()) << "zoomtype: PanLeft";
670 670 zoomType = AcquisitionZoomType::PanLeft;
671 671 }
672 else if (range.m_TStart > oldRange.m_TStart && oldRange.m_TEnd > range.m_TEnd) {
672 else if (range.m_TStart >= oldRange.m_TStart && oldRange.m_TEnd >= range.m_TEnd) {
673 673 qCDebug(LOG_VariableController()) << "zoomtype: ZoomIn";
674 674 zoomType = AcquisitionZoomType::ZoomIn;
675 675 }
676 676 else {
677 677 qCDebug(LOG_VariableController()) << "getZoomType: Unknown type detected";
678 678 }
679 679 return zoomType;
680 680 }
681 681
682 682 void VariableController::VariableControllerPrivate::processRequest(std::shared_ptr<Variable> var,
683 683 const SqpRange &rangeRequested,
684 684 QUuid varRequestId)
685 685 {
686 686 auto itVar = m_VariableToIdentifierMap.find(var);
687 687 if (itVar == m_VariableToIdentifierMap.cend()) {
688 688 qCCritical(LOG_VariableController())
689 689 << tr("Impossible to process request for unknown variable");
690 690 return;
691 691 }
692 692
693 693 auto varId = itVar->second;
694 694
695 695 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
696 696 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
697 697 qCCritical(LOG_VariableController())
698 698 << tr("Impossible to process request for variable with unknown handler");
699 699 return;
700 700 }
701 701
702 702 auto oldRange = var->range();
703 703
704 704 auto varHandler = itVarHandler->second.get();
705 705
706 706 if (varHandler->m_State != VariableRequestHandlerState::OFF) {
707 707 oldRange = varHandler->m_RunningVarRequest.m_RangeRequested;
708 708 }
709 709
710 710 auto varRequest = VariableRequest{};
711 711 varRequest.m_VariableGroupId = varRequestId;
712 712 auto varStrategyRangesRequested
713 713 = m_VariableCacheStrategy->computeRange(oldRange, rangeRequested);
714 714 varRequest.m_RangeRequested = varStrategyRangesRequested.first;
715 715 varRequest.m_CacheRangeRequested = varStrategyRangesRequested.second;
716 716
717 717 switch (varHandler->m_State) {
718 718 case VariableRequestHandlerState::OFF: {
719 719 qCDebug(LOG_VariableController()) << tr("Process Request OFF")
720 720 << varRequest.m_RangeRequested
721 721 << varRequest.m_CacheRangeRequested;
722 722 varHandler->m_RunningVarRequest = varRequest;
723 723 varHandler->m_State = VariableRequestHandlerState::RUNNING;
724 724 executeVarRequest(var, varRequest);
725 725 break;
726 726 }
727 727 case VariableRequestHandlerState::RUNNING: {
728 728 qCDebug(LOG_VariableController()) << tr("Process Request RUNNING")
729 729 << varRequest.m_RangeRequested
730 730 << varRequest.m_CacheRangeRequested;
731 731 varHandler->m_State = VariableRequestHandlerState::PENDING;
732 732 varHandler->m_PendingVarRequest = varRequest;
733 733 break;
734 734 }
735 735 case VariableRequestHandlerState::PENDING: {
736 736 qCDebug(LOG_VariableController()) << tr("Process Request PENDING")
737 737 << varRequest.m_RangeRequested
738 738 << varRequest.m_CacheRangeRequested;
739 739 auto variableGroupIdToCancel = varHandler->m_PendingVarRequest.m_VariableGroupId;
740 740 cancelVariableRequest(variableGroupIdToCancel);
741 741 // Cancel variable can make state downgrade
742 742 varHandler->m_State = VariableRequestHandlerState::PENDING;
743 743 varHandler->m_PendingVarRequest = varRequest;
744 744
745 745 break;
746 746 }
747 747 default:
748 748 qCCritical(LOG_VariableController())
749 749 << QObject::tr("Unknown VariableRequestHandlerState");
750 750 }
751 751 }
752 752
753 753 std::shared_ptr<Variable>
754 754 VariableController::VariableControllerPrivate::findVariable(QUuid vIdentifier)
755 755 {
756 756 std::shared_ptr<Variable> var;
757 757 auto findReply = [vIdentifier](const auto &entry) { return vIdentifier == entry.second; };
758 758
759 759 auto end = m_VariableToIdentifierMap.cend();
760 760 auto it = std::find_if(m_VariableToIdentifierMap.cbegin(), end, findReply);
761 761 if (it != end) {
762 762 var = it->first;
763 763 }
764 764 else {
765 765 qCCritical(LOG_VariableController())
766 766 << tr("Impossible to find the variable with the identifier: ") << vIdentifier;
767 767 }
768 768
769 769 return var;
770 770 }
771 771
772 772 std::shared_ptr<IDataSeries> VariableController::VariableControllerPrivate::retrieveDataSeries(
773 773 const QVector<AcquisitionDataPacket> acqDataPacketVector)
774 774 {
775 775 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size")
776 776 << acqDataPacketVector.size();
777 777 std::shared_ptr<IDataSeries> dataSeries;
778 778 if (!acqDataPacketVector.isEmpty()) {
779 779 dataSeries = acqDataPacketVector[0].m_DateSeries;
780 780 for (int i = 1; i < acqDataPacketVector.size(); ++i) {
781 781 dataSeries->merge(acqDataPacketVector[i].m_DateSeries.get());
782 782 }
783 783 }
784 784 qCDebug(LOG_VariableController()) << tr("TORM: retrieveDataSeries acqDataPacketVector size END")
785 785 << acqDataPacketVector.size();
786 786 return dataSeries;
787 787 }
788 788
789 789 void VariableController::VariableControllerPrivate::registerProvider(
790 790 std::shared_ptr<IDataProvider> provider)
791 791 {
792 792 if (m_ProviderSet.find(provider) == m_ProviderSet.end()) {
793 793 qCDebug(LOG_VariableController()) << tr("Registering of a new provider")
794 794 << provider->objectName();
795 795 m_ProviderSet.insert(provider);
796 796 connect(provider.get(), &IDataProvider::dataProvided, m_VariableAcquisitionWorker.get(),
797 797 &VariableAcquisitionWorker::onVariableDataAcquired);
798 798 connect(provider.get(), &IDataProvider::dataProvidedProgress,
799 799 m_VariableAcquisitionWorker.get(),
800 800 &VariableAcquisitionWorker::onVariableRetrieveDataInProgress);
801 801 connect(provider.get(), &IDataProvider::dataProvidedFailed,
802 802 m_VariableAcquisitionWorker.get(),
803 803 &VariableAcquisitionWorker::onVariableAcquisitionFailed);
804 804 }
805 805 else {
806 806 qCDebug(LOG_VariableController()) << tr("Cannot register provider, it already exists ");
807 807 }
808 808 }
809 809
810 810 QUuid VariableController::VariableControllerPrivate::acceptVariableRequest(
811 811 QUuid varId, std::shared_ptr<IDataSeries> dataSeries)
812 812 {
813 813 auto itVarHandler = m_VarIdToVarRequestHandler.find(varId);
814 814 if (itVarHandler == m_VarIdToVarRequestHandler.cend()) {
815 815 return QUuid();
816 816 }
817 817
818 818 auto varHandler = itVarHandler->second.get();
819 819 if (varHandler->m_State == VariableRequestHandlerState::OFF) {
820 820 qCCritical(LOG_VariableController())
821 821 << tr("acceptVariableRequest impossible on a variable with OFF state");
822 822 }
823 823
824 824 varHandler->m_RunningVarRequest.m_DataSeries = dataSeries;
825 825 varHandler->m_CanUpdate = true;
826 826
827 827 // Element traité, on a déjà toutes les données necessaires
828 828 auto varGroupId = varHandler->m_RunningVarRequest.m_VariableGroupId;
829 829 qCDebug(LOG_VariableController()) << "Variable::acceptVariableRequest" << varGroupId
830 830 << m_VarGroupIdToVarIds.size();
831 831
832 832 return varHandler->m_RunningVarRequest.m_VariableGroupId;
833 833 }
834 834
835 835 void VariableController::VariableControllerPrivate::updateVariables(QUuid varRequestId)
836 836 {
837 837 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
838 838 << QThread::currentThread()->objectName() << varRequestId;
839 839
840 840 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
841 841 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
842 842 qCWarning(LOG_VariableController())
843 843 << tr("Impossible to updateVariables of unknown variables") << varRequestId;
844 844 return;
845 845 }
846 846
847 847 auto &varIds = varGroupIdToVarIdsIt->second;
848 848 auto varIdsEnd = varIds.end();
849 849 bool processVariableUpdate = true;
850 850 qCDebug(LOG_VariableController()) << "VariableControllerPrivate::updateVariables"
851 851 << varRequestId << varIds.size();
852 852 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd) && processVariableUpdate;
853 853 ++varIdsIt) {
854 854 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
855 855 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
856 856 processVariableUpdate &= itVarHandler->second->m_CanUpdate;
857 857 }
858 858 }
859 859
860 860 if (processVariableUpdate) {
861 861 qCDebug(LOG_VariableController()) << "Final update OK for the var request" << varIds.size();
862 862 for (auto varIdsIt = varIds.begin(); varIdsIt != varIdsEnd; ++varIdsIt) {
863 863 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
864 864 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
865 865 if (auto var = findVariable(*varIdsIt)) {
866 866 auto &varRequest = itVarHandler->second->m_RunningVarRequest;
867 867 var->setRange(varRequest.m_RangeRequested);
868 868 var->setCacheRange(varRequest.m_CacheRangeRequested);
869 869 qCDebug(LOG_VariableController()) << tr("1: onDataProvided")
870 870 << varRequest.m_RangeRequested
871 871 << varRequest.m_CacheRangeRequested;
872 872 qCDebug(LOG_VariableController()) << tr("2: onDataProvided var points before")
873 873 << var->nbPoints()
874 874 << varRequest.m_DataSeries->nbPoints();
875 875 var->mergeDataSeries(varRequest.m_DataSeries);
876 876 qCDebug(LOG_VariableController()) << tr("3: onDataProvided var points after")
877 877 << var->nbPoints();
878 878
879 879 emit var->updated();
880 880 qCDebug(LOG_VariableController()) << tr("Update OK");
881 881 }
882 882 else {
883 883 qCCritical(LOG_VariableController())
884 884 << tr("Impossible to update data to a null variable");
885 885 }
886 886 }
887 887 }
888 888 updateVariableRequest(varRequestId);
889 889
890 890 // cleaning varRequestId
891 891 qCDebug(LOG_VariableController()) << tr("m_VarGroupIdToVarIds erase") << varRequestId;
892 892 m_VarGroupIdToVarIds.erase(varRequestId);
893 893 }
894 894 }
895 895
896 896
897 897 void VariableController::VariableControllerPrivate::updateVariableRequest(QUuid varRequestId)
898 898 {
899 899 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
900 900 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
901 901 qCCritical(LOG_VariableController()) << QObject::tr(
902 902 "Impossible to updateVariableRequest since varGroupdId isn't here anymore");
903 903
904 904 return;
905 905 }
906 906
907 907 auto &varIds = varGroupIdToVarIdsIt->second;
908 908 auto varIdsEnd = varIds.end();
909 909 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
910 910 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
911 911 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
912 912
913 913 auto varHandler = itVarHandler->second.get();
914 914 varHandler->m_CanUpdate = false;
915 915
916 916
917 917 switch (varHandler->m_State) {
918 918 case VariableRequestHandlerState::OFF: {
919 919 qCCritical(LOG_VariableController())
920 920 << QObject::tr("Impossible to update a variable with handler in OFF state");
921 921 } break;
922 922 case VariableRequestHandlerState::RUNNING: {
923 923 varHandler->m_State = VariableRequestHandlerState::OFF;
924 924 varHandler->m_RunningVarRequest = VariableRequest{};
925 925 break;
926 926 }
927 927 case VariableRequestHandlerState::PENDING: {
928 928 varHandler->m_State = VariableRequestHandlerState::RUNNING;
929 929 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
930 930 varHandler->m_PendingVarRequest = VariableRequest{};
931 931 auto var = findVariable(itVarHandler->first);
932 932 executeVarRequest(var, varHandler->m_RunningVarRequest);
933 933 break;
934 934 }
935 935 default:
936 936 qCCritical(LOG_VariableController())
937 937 << QObject::tr("Unknown VariableRequestHandlerState");
938 938 }
939 939 }
940 940 }
941 941 }
942 942
943 943
944 944 void VariableController::VariableControllerPrivate::cancelVariableRequest(QUuid varRequestId)
945 945 {
946 946 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest") << varRequestId;
947 947
948 948 auto varGroupIdToVarIdsIt = m_VarGroupIdToVarIds.find(varRequestId);
949 949 if (varGroupIdToVarIdsIt == m_VarGroupIdToVarIds.end()) {
950 950 qCCritical(LOG_VariableController())
951 951 << tr("Impossible to cancelVariableRequest for unknown varGroupdId") << varRequestId;
952 952 return;
953 953 }
954 954
955 955 auto &varIds = varGroupIdToVarIdsIt->second;
956 956 auto varIdsEnd = varIds.end();
957 957 for (auto varIdsIt = varIds.begin(); (varIdsIt != varIdsEnd); ++varIdsIt) {
958 958 auto itVarHandler = m_VarIdToVarRequestHandler.find(*varIdsIt);
959 959 if (itVarHandler != m_VarIdToVarRequestHandler.cend()) {
960 960
961 961 auto varHandler = itVarHandler->second.get();
962 962 varHandler->m_VarId = QUuid{};
963 963 switch (varHandler->m_State) {
964 964 case VariableRequestHandlerState::OFF: {
965 965 qCWarning(LOG_VariableController())
966 966 << QObject::tr("Impossible to cancel a variable with no running request");
967 967 break;
968 968 }
969 969 case VariableRequestHandlerState::RUNNING: {
970 970
971 971 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
972 972 auto var = findVariable(itVarHandler->first);
973 973 auto varProvider = m_VariableToProviderMap.at(var);
974 974 if (varProvider != nullptr) {
975 975 m_VariableAcquisitionWorker->abortProgressRequested(
976 976 itVarHandler->first);
977 977 }
978 978 m_VariableModel->setDataProgress(var, 0.0);
979 979 varHandler->m_CanUpdate = false;
980 980 varHandler->m_State = VariableRequestHandlerState::OFF;
981 981 varHandler->m_RunningVarRequest = VariableRequest{};
982 982 }
983 983 else {
984 984 // TODO: log Impossible to cancel the running variable request beacause its
985 985 // varRequestId isn't not the canceled one
986 986 }
987 987 break;
988 988 }
989 989 case VariableRequestHandlerState::PENDING: {
990 990 if (varHandler->m_RunningVarRequest.m_VariableGroupId == varRequestId) {
991 991 auto var = findVariable(itVarHandler->first);
992 992 auto varProvider = m_VariableToProviderMap.at(var);
993 993 if (varProvider != nullptr) {
994 994 m_VariableAcquisitionWorker->abortProgressRequested(
995 995 itVarHandler->first);
996 996 }
997 997 m_VariableModel->setDataProgress(var, 0.0);
998 998 varHandler->m_CanUpdate = false;
999 999 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1000 1000 varHandler->m_RunningVarRequest = varHandler->m_PendingVarRequest;
1001 1001 varHandler->m_PendingVarRequest = VariableRequest{};
1002 1002 executeVarRequest(var, varHandler->m_RunningVarRequest);
1003 1003 }
1004 1004 else if (varHandler->m_PendingVarRequest.m_VariableGroupId == varRequestId) {
1005 1005 varHandler->m_State = VariableRequestHandlerState::RUNNING;
1006 1006 varHandler->m_PendingVarRequest = VariableRequest{};
1007 1007 }
1008 1008 else {
1009 1009 // TODO: log Impossible to cancel the variable request beacause its
1010 1010 // varRequestId isn't not the canceled one
1011 1011 }
1012 1012 break;
1013 1013 }
1014 1014 default:
1015 1015 qCCritical(LOG_VariableController())
1016 1016 << QObject::tr("Unknown VariableRequestHandlerState");
1017 1017 }
1018 1018 }
1019 1019 }
1020 1020 qCDebug(LOG_VariableController()) << tr("cancelVariableRequest: erase") << varRequestId;
1021 1021 m_VarGroupIdToVarIds.erase(varRequestId);
1022 1022 }
1023 1023
1024 1024 void VariableController::VariableControllerPrivate::executeVarRequest(std::shared_ptr<Variable> var,
1025 1025 VariableRequest &varRequest)
1026 1026 {
1027 1027 qCDebug(LOG_VariableController()) << tr("TORM: executeVarRequest");
1028 1028
1029 1029 auto varId = m_VariableToIdentifierMap.at(var);
1030 1030
1031 1031 auto varCacheRange = var->cacheRange();
1032 1032 auto varCacheRangeRequested = varRequest.m_CacheRangeRequested;
1033 1033 auto notInCacheRangeList
1034 1034 = Variable::provideNotInCacheRangeList(varCacheRange, varCacheRangeRequested);
1035 1035 auto inCacheRangeList
1036 1036 = Variable::provideInCacheRangeList(varCacheRange, varCacheRangeRequested);
1037 1037
1038 1038 if (!notInCacheRangeList.empty()) {
1039 1039
1040 1040 auto varProvider = m_VariableToProviderMap.at(var);
1041 1041 if (varProvider != nullptr) {
1042 1042 qCDebug(LOG_VariableController()) << "executeVarRequest " << varRequest.m_RangeRequested
1043 1043 << varRequest.m_CacheRangeRequested;
1044 1044 m_VariableAcquisitionWorker->pushVariableRequest(
1045 1045 varRequest.m_VariableGroupId, varId, varRequest.m_RangeRequested,
1046 1046 varRequest.m_CacheRangeRequested,
1047 1047 DataProviderParameters{std::move(notInCacheRangeList), var->metadata()},
1048 1048 varProvider);
1049 1049 }
1050 1050 else {
1051 1051 qCCritical(LOG_VariableController())
1052 1052 << "Impossible to provide data with a null provider";
1053 1053 }
1054 1054
1055 1055 if (!inCacheRangeList.empty()) {
1056 1056 emit q->updateVarDisplaying(var, inCacheRangeList.first());
1057 1057 }
1058 1058 }
1059 1059 else {
1060 1060 acceptVariableRequest(varId,
1061 1061 var->dataSeries()->subDataSeries(varRequest.m_CacheRangeRequested));
1062 1062 }
1063 1063 }
@@ -1,73 +1,73
1 1 # - Clone and build CatalogueAPI Module
2 2 include(ExternalProject)
3 3
4 4 find_package(Git REQUIRED)
5 5
6 6 if(WIN32)
7 7 find_program(MesonExec meson PATHS C:/Appli/Meson)
8 8 if(NOT MesonExec)
9 9 Message("Error: Meson not found")
10 10 else()
11 11 message("Meson found: ${MesonExec}" )
12 12 endif()
13 13 find_program(NinjaExec ninja PATHS C:/Appli/Meson)
14 14 if(NOT NinjaExec)
15 15 Message("Error: Ninja not found")
16 16 else()
17 17 message("Ninja found: ${NinjaExec}" )
18 18 endif()
19 19 endif()
20 20 if(NOT MesonExec)
21 21 set (MesonExec meson)
22 22 endif()
23 23 if(NOT NinjaExec)
24 24 set (NinjaExec ninja)
25 25 endif()
26 26
27 27 SET(CATALOGUEAPI_SOURCES_PATH ${CMAKE_SOURCE_DIR}/3rdparty/CatalogueAPI)
28 28 SET(CATALOGUEAPI_BUILD_PATH ${CATALOGUEAPI_SOURCES_PATH}/build)
29 29 SET(CATALOGUEAPI_QXORM_LIB_PATH ${CATALOGUEAPI_BUILD_PATH}/subprojects/QxOrm)
30 30 SET(CatalogueAPI_build_type plain)
31 31
32 32 if(CMAKE_BUILD_TYPE STREQUAL "")
33 33 set(CMAKE_BUILD_TYPE Release)
34 34 endif()
35 35 string(TOLOWER ${CMAKE_BUILD_TYPE} CMAKE_BUILD_TYPE_TOLOWER)
36 36
37 37 ExternalProject_Add(
38 38 CatalogueAPI
39 39
40 40 GIT_REPOSITORY https://perrinel@hephaistos.lpp.polytechnique.fr/rhodecode/GIT_REPOSITORIES/LPP/Users/mperrinel/CatalogueAPI
41 41 GIT_TAG develop
42 42
43 UPDATE_COMMAND ${GIT_EXECUTABLE} pull
43 UPDATE_COMMAND ${GIT_EXECUTABLE} pull origin develop
44 44 PATCH_COMMAND ""
45 45
46 46 SOURCE_DIR "${CATALOGUEAPI_SOURCES_PATH}"
47 47 CONFIGURE_COMMAND ${MesonExec} --prefix=${CATALOGUEAPI_SOURCES_PATH} --buildtype=${CMAKE_BUILD_TYPE_TOLOWER} "${CATALOGUEAPI_SOURCES_PATH}" "${CATALOGUEAPI_BUILD_PATH}"
48 48
49 49 BUILD_COMMAND ${NinjaExec} -C "${CATALOGUEAPI_BUILD_PATH}"
50 50 INSTALL_COMMAND ${NinjaExec} -C "${CATALOGUEAPI_BUILD_PATH}" install
51 51 LOG_DOWNLOAD 1
52 52 LOG_UPDATE 1
53 53 )
54 54
55 55 set(CATALOG_LIB_PATH lib)
56 56 if(WIN32)
57 57 set(CATALOG_LIB_PATH bin)
58 58 endif()
59 59
60 60 ExternalProject_Add_Step(
61 61 CatalogueAPI CopyToBin
62 62 COMMAND ${CMAKE_COMMAND} -E copy_directory ${CATALOGUEAPI_SOURCES_PATH}/lib64 ${CATALOGUEAPI_SOURCES_PATH}/${CATALOG_LIB_PATH}
63 63 COMMAND ${CMAKE_COMMAND} -E copy_directory ${CATALOGUEAPI_QXORM_LIB_PATH} ${CATALOGUEAPI_SOURCES_PATH}/${CATALOG_LIB_PATH}
64 64 DEPENDEES install
65 65 )
66 66
67 67
68 68 set(CATALOGUEAPI_INCLUDE ${CATALOGUEAPI_SOURCES_PATH}/src)
69 69 set(CATALOGUEAPI_LIBRARIES ${CATALOGUEAPI_SOURCES_PATH}/${CATALOG_LIB_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}CatalogueAPI${CMAKE_SHARED_LIBRARY_SUFFIX})
70 70 list(APPEND CATALOGUEAPI_LIBRARIES ${CATALOGUEAPI_SOURCES_PATH}/${CATALOG_LIB_PATH}/${CMAKE_SHARED_LIBRARY_PREFIX}QxOrm${CMAKE_SHARED_LIBRARY_SUFFIX})
71 71
72 72 mark_as_advanced(CATALOGUEAPI_INCLUDE)
73 73 mark_as_advanced(CATALOGUEAPI_LIBRARIES)
@@ -1,169 +1,179
1 1
2 2 ## gui - CMakeLists.txt
3 3 STRING(TOLOWER ${CMAKE_PROJECT_NAME} LIBRARY_PREFFIX)
4 4 SET(SQPGUI_LIBRARY_NAME "${LIBRARY_PREFFIX}_gui${DEBUG_SUFFIX}")
5 5 SET(SOURCES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/src")
6 6 SET(INCLUDES_DIR "${CMAKE_CURRENT_SOURCE_DIR}/include")
7 7 SET(UI_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/ui")
8 8 SET(RES_FOLDER "${CMAKE_CURRENT_SOURCE_DIR}/resources")
9 9
10 10 # Include gui directory
11 11 include_directories("${INCLUDES_DIR}")
12 12 include_directories("${CMAKE_CURRENT_BINARY_DIR}")
13 13
14 14 # Set a variable to display a warning in the version files.
15 15 SET(SCIQLOP_CMAKE_GENERATION_WARNING "DON'T CHANGE THIS FILE. AUTOGENERATED BY CMAKE.")
16 16
17 17 #
18 18 # Find Qt modules
19 19 #
20 20 SCIQLOP_FIND_QT(Core Widgets PrintSupport)
21 21
22 22 #
23 23 # Find dependent libraries
24 24 # ========================
25 25 find_package(sciqlop-core)
26 26
27 27 SET(LIBRARIES ${SCIQLOP-CORE_LIBRARIES})
28 28
29 29 INCLUDE_DIRECTORIES(${SCIQLOP-CORE_INCLUDE_DIR})
30 30
31 31 # Add sqpcore to the list of libraries to use
32 32 list(APPEND LIBRARIES ${SQPCORE_LIBRARY_NAME})
33 33
34 34 # Add dependent shared libraries
35 35 list(APPEND SHARED_LIBRARIES ${SQPCORE_SHARED_LIBRARIES})
36 36
37 37
38 38 # Ui files
39 39 FILE (GLOB_RECURSE PROJECT_FORMS ${UI_FOLDER}/*.ui)
40 40
41 41 # Resources files
42 42 FILE (GLOB_RECURSE PROJECT_RESOURCES ${RES_FOLDER}/*.qrc)
43 43
44 44 #
45 45 # Compile the library library
46 46 #
47 47 FILE (GLOB_RECURSE MODULE_SOURCES
48 48 ${INCLUDES_DIR}/*.h
49 49 ${SOURCES_DIR}/*.c
50 50 ${SOURCES_DIR}/*.cpp
51 51 ${SOURCES_DIR}/*.h
52 52 ${PROJECT_FORMS})
53 53
54 54 QT5_ADD_RESOURCES(RCC_HDRS
55 55 ${PROJECT_RESOURCES}
56 56 )
57 57
58 58 QT5_WRAP_UI(UIS_HDRS
59 59 ${PROJECT_FORMS}
60 60 )
61 61
62 62
63 63 ADD_LIBRARY(${SQPGUI_LIBRARY_NAME} ${MODULE_SOURCES} ${UIS_HDRS} ${RCC_HDRS})
64 64 set_property(TARGET ${SQPGUI_LIBRARY_NAME} PROPERTY CXX_STANDARD 14)
65 65 set_property(TARGET ${SQPGUI_LIBRARY_NAME} PROPERTY CXX_STANDARD_REQUIRED ON)
66 66
67 67 TARGET_LINK_LIBRARIES(${SQPGUI_LIBRARY_NAME} ${LIBRARIES})
68 68 qt5_use_modules(${SQPGUI_LIBRARY_NAME} Core Widgets PrintSupport)
69 69
70 70
71 71 INSTALL(TARGETS ${SQPGUI_LIBRARY_NAME}
72 72 RUNTIME DESTINATION ${INSTALL_BINARY_DIR}
73 73 LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR}
74 74 ARCHIVE DESTINATION ${INSTALL_LIBRARY_DIR}
75 75 )
76 76 add_dependencies(${SQPGUI_LIBRARY_NAME} ${SQPCORE_LIBRARY_NAME})
77 77
78 # Find CATALOGUE_API
79 include_directories("${CATALOGUEAPI_INCLUDE}")
80 TARGET_LINK_LIBRARIES(${SQPGUI_LIBRARY_NAME} ${CATALOGUEAPI_LIBRARIES})
81 INSTALL(TARGETS ${SQPGUI_LIBRARY_NAME}
82 RUNTIME DESTINATION ${INSTALL_BINARY_DIR}
83 LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR}
84 ARCHIVE DESTINATION ${INSTALL_LIBRARY_DIR}
85 )
86
87 add_dependencies(${SQPGUI_LIBRARY_NAME} CatalogueAPI)
78 88
79 89 # From cmake documentation: http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html
80 90 # Entries in the COMPILE_DEFINITIONS are prefixed with -D or /D and added to the compile line in an unspecified order.
81 91 # The DEFINE_SYMBOL target property is also added as a compile definition as a special convenience case for SHARED and MODULE library targets
82 92 IF(BUILD_SHARED_LIBS)
83 93 SET_TARGET_PROPERTIES(${SQPGUI_LIBRARY_NAME} PROPERTIES COMPILE_DEFINITIONS "SCIQLOP_EXPORT")
84 94 ELSE()
85 95 TARGET_COMPILE_DEFINITIONS(${SQPGUI_LIBRARY_NAME} PUBLIC "SCIQLOP_STATIC_LIBRARIES")
86 96 ENDIF()
87 97
88 98 # Set the variable to parent scope so that the other projects can copy the
89 99 # dependent shared libraries
90 100 SCIQLOP_SET_TO_PARENT_SCOPE(SQPGUI_LIBRARY_NAME)
91 101
92 102 # Copy extern shared libraries to the lib folder
93 103 SCIQLOP_COPY_TO_TARGET(LIBRARY ${SQPGUI_LIBRARY_NAME})
94 104
95 105 # Add the files to the list of files to be analyzed
96 106 LIST(APPEND CHECKSTYLE_INPUT_FILES ${MODULE_SOURCES})
97 107 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_INPUT_FILES)
98 108 # Vera++ exclusion files
99 109 LIST(APPEND CHECKSTYLE_EXCLUSION_FILES ${CMAKE_CURRENT_SOURCE_DIR}/vera-exclusions/exclusions.txt)
100 110 SCIQLOP_SET_TO_PARENT_SCOPE(CHECKSTYLE_EXCLUSION_FILES)
101 111
102 112 #
103 113 # Compile the tests
104 114 #
105 115 IF(BUILD_TESTS)
106 116 INCLUDE_DIRECTORIES(${SOURCES_DIR})
107 117 FILE (GLOB_RECURSE TESTS_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/Test*.cpp)
108 118 FILE (GLOB_RECURSE TESTS_HEADERS ${CMAKE_CURRENT_SOURCE_DIR}/Test*.h)
109 119 SET( TEST_LIBRARIES ${SQPGUI_LIBRARY_NAME})
110 120
111 121 FOREACH( testFile ${TESTS_SOURCES} )
112 122 GET_FILENAME_COMPONENT( testDirectory ${testFile} DIRECTORY )
113 123 GET_FILENAME_COMPONENT( testName ${testFile} NAME_WE )
114 124
115 125 # Add to the list of sources files all the sources in the same
116 126 # directory that aren't another test
117 127 FILE (GLOB currentTestSources
118 128 ${testDirectory}/*.c
119 129 ${testDirectory}/*.cpp
120 130 ${testDirectory}/*.h)
121 131 LIST (REMOVE_ITEM currentTestSources ${TESTS_SOURCES})
122 132 # LIST (REMOVE_ITEM currentTestSources ${TESTS_HEADERS})
123 133
124 134 ADD_EXECUTABLE(${testName} ${testFile} ${currentTestSources})
125 135 set_property(TARGET ${testName} PROPERTY CXX_STANDARD 14)
126 136 set_property(TARGET ${testName} PROPERTY CXX_STANDARD_REQUIRED ON)
127 137 TARGET_LINK_LIBRARIES( ${testName} ${TEST_LIBRARIES} )
128 138 qt5_use_modules(${testName} Test)
129 139
130 140 ADD_TEST( NAME ${testName} COMMAND ${testName} )
131 141
132 142 SCIQLOP_COPY_TO_TARGET(RUNTIME ${testName} ${EXTERN_SHARED_LIBRARIES})
133 143 ENDFOREACH( testFile )
134 144
135 145 LIST(APPEND testFilesToFormat ${TESTS_SOURCES})
136 146 LIST(APPEND testFilesToFormat ${TESTS_HEADERS})
137 147 LIST(APPEND FORMATTING_INPUT_FILES ${testFilesToFormat})
138 148 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
139 149 ENDIF(BUILD_TESTS)
140 150
141 151 #
142 152 # Set the files that must be formatted by clang-format.
143 153 #
144 154 LIST (APPEND FORMATTING_INPUT_FILES ${MODULE_SOURCES})
145 155 SCIQLOP_SET_TO_PARENT_SCOPE(FORMATTING_INPUT_FILES)
146 156
147 157 #
148 158 # Set the directories that doxygen must browse to generate the
149 159 # documentation.
150 160 #
151 161 # Source directories:
152 162 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/docs")
153 163 LIST (APPEND DOXYGEN_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
154 164 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_INPUT_DIRS)
155 165 # Source directories to exclude from the documentation generation
156 166 #LIST (APPEND DOXYGEN_EXCLUDE_PATTERNS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir/*")
157 167 SCIQLOP_SET_TO_PARENT_SCOPE(DOXYGEN_EXCLUDE_PATTERNS)
158 168
159 169 #
160 170 # Set the directories with the sources to analyze and propagate the
161 171 # modification to the parent scope
162 172 #
163 173 # Source directories to analyze:
164 174 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/src")
165 175 LIST (APPEND ANALYSIS_INPUT_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/tests")
166 176 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_INPUT_DIRS)
167 177 # Source directories to exclude from the analysis
168 178 #LIST (APPEND ANALYSIS_EXCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/path/to/subdir")
169 179 SCIQLOP_SET_TO_PARENT_SCOPE(ANALYSIS_EXCLUDE_DIRS)
@@ -1,31 +1,47
1 1 #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H
2 2 #define SCIQLOP_CATALOGUEEVENTSWIDGET_H
3 3
4 4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 6 #include <QWidget>
6 7
8 class DBCatalogue;
9 class DBEvent;
10 class DBEventProduct;
11 class VisualizationWidget;
12
7 13 namespace Ui {
8 14 class CatalogueEventsWidget;
9 15 }
10 16
17 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsWidget)
18
11 19 class CatalogueEventsWidget : public QWidget {
12 20 Q_OBJECT
13 21
14 22 signals:
15 void eventSelected(const QString &event);
23 void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event);
24 void eventProductsSelected(
25 const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > >
26 &eventproducts);
27 void selectionCleared();
16 28
17 29 public:
18 30 explicit CatalogueEventsWidget(QWidget *parent = 0);
19 31 virtual ~CatalogueEventsWidget();
20 32
33 void setVisualizationWidget(VisualizationWidget *visualization);
34
35 void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
36
21 37 public slots:
22 void populateWithCatalogue(const QString &catalogue);
38 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
23 39
24 40 private:
25 41 Ui::CatalogueEventsWidget *ui;
26 42
27 43 class CatalogueEventsWidgetPrivate;
28 44 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
29 45 };
30 46
31 47 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
@@ -1,21 +1,29
1 1 #ifndef SCIQLOP_CATALOGUEEXPLORER_H
2 2 #define SCIQLOP_CATALOGUEEXPLORER_H
3 3
4 #include <Common/spimpl.h>
4 5 #include <QDialog>
5 6
6 7 namespace Ui {
7 8 class CatalogueExplorer;
8 9 }
9 10
11 class VisualizationWidget;
12
10 13 class CatalogueExplorer : public QDialog {
11 14 Q_OBJECT
12 15
13 16 public:
14 17 explicit CatalogueExplorer(QWidget *parent = 0);
15 18 virtual ~CatalogueExplorer();
16 19
20 void setVisualizationWidget(VisualizationWidget *visualization);
21
17 22 private:
18 23 Ui::CatalogueExplorer *ui;
24
25 class CatalogueExplorerPrivate;
26 spimpl::unique_impl_ptr<CatalogueExplorerPrivate> impl;
19 27 };
20 28
21 29 #endif // SCIQLOP_CATALOGUEEXPLORER_H
@@ -1,32 +1,49
1 1 #ifndef SCIQLOP_CATALOGUEINSPECTORWIDGET_H
2 2 #define SCIQLOP_CATALOGUEINSPECTORWIDGET_H
3 3
4 #include <Common/spimpl.h>
4 5 #include <QWidget>
6 #include <memory>
5 7
6 8 namespace Ui {
7 9 class CatalogueInspectorWidget;
8 10 }
9 11
12 class DBCatalogue;
13 class DBEvent;
14 class DBEventProduct;
15
10 16 class CatalogueInspectorWidget : public QWidget {
11 17 Q_OBJECT
12 18
19 signals:
20 void catalogueUpdated(const std::shared_ptr<DBCatalogue> &catalogue);
21 void eventUpdated(const std::shared_ptr<DBEvent> &event);
22 void eventProductUpdated(const std::shared_ptr<DBEvent> &event,
23 const std::shared_ptr<DBEventProduct> &eventProduct);
24
13 25 public:
14 26 explicit CatalogueInspectorWidget(QWidget *parent = 0);
15 27 virtual ~CatalogueInspectorWidget();
16 28
17 29 /// Enum matching the pages inside the stacked widget
18 30 enum class Page { Empty, CatalogueProperties, EventProperties };
19 31
20 32 Page currentPage() const;
21 33
22 void setEvent(const QString &event);
23 void setCatalogue(const QString &catalogue);
34 void setEvent(const std::shared_ptr<DBEvent> &event);
35 void setEventProduct(const std::shared_ptr<DBEvent> &event,
36 const std::shared_ptr<DBEventProduct> &eventProduct);
37 void setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue);
24 38
25 39 public slots:
26 40 void showPage(Page page);
27 41
28 42 private:
29 43 Ui::CatalogueInspectorWidget *ui;
44
45 class CatalogueInspectorWidgetPrivate;
46 spimpl::unique_impl_ptr<CatalogueInspectorWidgetPrivate> impl;
30 47 };
31 48
32 49 #endif // SCIQLOP_CATALOGUEINSPECTORWIDGET_H
@@ -1,31 +1,43
1 1 #ifndef SCIQLOP_CATALOGUESIDEBARWIDGET_H
2 2 #define SCIQLOP_CATALOGUESIDEBARWIDGET_H
3 3
4 4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 6 #include <QTreeWidgetItem>
6 7 #include <QWidget>
7 8
9 class DBCatalogue;
10
8 11 namespace Ui {
9 12 class CatalogueSideBarWidget;
10 13 }
11 14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget)
16
12 17 class CatalogueSideBarWidget : public QWidget {
13 18 Q_OBJECT
14 19
15 20 signals:
16 void catalogueSelected(const QString &catalogue);
21 void catalogueSelected(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
22 void databaseSelected(const QStringList &databases);
17 23 void allEventsSelected();
18 24 void trashSelected();
25 void selectionCleared();
19 26
20 27 public:
21 28 explicit CatalogueSideBarWidget(QWidget *parent = 0);
22 29 virtual ~CatalogueSideBarWidget();
23 30
31 void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges);
32
24 33 private:
25 34 Ui::CatalogueSideBarWidget *ui;
26 35
27 36 class CatalogueSideBarWidgetPrivate;
28 37 spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl;
38
39 private slots:
40 void onContextMenuRequested(const QPoint &pos);
29 41 };
30 42
31 43 #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H
@@ -1,69 +1,71
1 1 #ifndef SCIQLOP_SQPAPPLICATION_H
2 2 #define SCIQLOP_SQPAPPLICATION_H
3 3
4 4 #include "SqpApplication.h"
5 5
6 6 #include <QApplication>
7 7 #include <QLoggingCategory>
8 8
9 9 #include <Common/spimpl.h>
10 10
11 11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
12 12
13 13 #if defined(sqpApp)
14 14 #undef sqpApp
15 15 #endif
16 16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
17 17
18 18 class DataSourceController;
19 19 class NetworkController;
20 20 class TimeController;
21 21 class VariableController;
22 22 class VisualizationController;
23 23 class DragDropGuiController;
24 24 class ActionsGuiController;
25 class CatalogueController;
25 26
26 27 /**
27 28 * @brief The SqpApplication class aims to make the link between SciQlop
28 29 * and its plugins. This is the intermediate class that SciQlop has to use
29 30 * in the way to connect a data source. Please first use load method to initialize
30 31 * a plugin specified by its metadata name (JSON plugin source) then others specifics
31 32 * method will be able to access it.
32 33 * You can load a data source driver plugin then create a data source.
33 34 */
34 35
35 36 class SqpApplication : public QApplication {
36 37 Q_OBJECT
37 38 public:
38 39 explicit SqpApplication(int &argc, char **argv);
39 40 virtual ~SqpApplication();
40 41 void initialize();
41 42
42 43 /// Accessors for the differents sciqlop controllers
43 44 DataSourceController &dataSourceController() noexcept;
44 45 NetworkController &networkController() noexcept;
45 46 TimeController &timeController() noexcept;
46 47 VariableController &variableController() noexcept;
47 48 VisualizationController &visualizationController() noexcept;
49 CatalogueController &catalogueController() noexcept;
48 50
49 51 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
50 52 /// doesn't live in a thread and access gui
51 53 DragDropGuiController &dragDropGuiController() noexcept;
52 54 ActionsGuiController &actionsGuiController() noexcept;
53 55
54 56 enum class PlotsInteractionMode { None, ZoomBox, DragAndDrop, SelectionZones };
55 57
56 58 enum class PlotsCursorMode { NoCursor, Vertical, Temporal, Horizontal, Cross };
57 59
58 60 PlotsInteractionMode plotsInteractionMode() const;
59 61 void setPlotsInteractionMode(PlotsInteractionMode mode);
60 62
61 63 PlotsCursorMode plotsCursorMode() const;
62 64 void setPlotsCursorMode(PlotsCursorMode mode);
63 65
64 66 private:
65 67 class SqpApplicationPrivate;
66 68 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
67 69 };
68 70
69 71 #endif // SCIQLOP_SQPAPPLICATION_H
@@ -1,30 +1,30
1 1 #ifndef SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H
2 2 #define SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QDialog>
6 6
7 7 namespace Ui {
8 8 class VisualizationMultiZoneSelectionDialog;
9 9 }
10 10
11 11 class VisualizationSelectionZoneItem;
12 12
13 13 class VisualizationMultiZoneSelectionDialog : public QDialog {
14 14 Q_OBJECT
15 15
16 16 public:
17 17 explicit VisualizationMultiZoneSelectionDialog(QWidget *parent = 0);
18 ~VisualizationMultiZoneSelectionDialog();
18 virtual ~VisualizationMultiZoneSelectionDialog();
19 19
20 20 void setZones(const QVector<VisualizationSelectionZoneItem *> &zones);
21 21 QMap<VisualizationSelectionZoneItem *, bool> selectedZones() const;
22 22
23 23 private:
24 24 Ui::VisualizationMultiZoneSelectionDialog *ui;
25 25
26 26 class VisualizationMultiZoneSelectionDialogPrivate;
27 27 spimpl::unique_impl_ptr<VisualizationMultiZoneSelectionDialogPrivate> impl;
28 28 };
29 29
30 30 #endif // SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H
@@ -1,80 +1,88
1 1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QMimeData>
10 10 #include <QWidget>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
13 13
14 14 class Variable;
15 15 class VisualizationZoneWidget;
16 16
17 17 namespace Ui {
18 18 class VisualizationTabWidget;
19 19 } // namespace Ui
20 20
21 21 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
22 22 Q_OBJECT
23 23
24 24 public:
25 25 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
26 26 virtual ~VisualizationTabWidget();
27 27
28 /// Add a zone widget
28 /// Adds a zone widget
29 29 void addZone(VisualizationZoneWidget *zoneWidget);
30 30
31 /// Inserts a zone widget at the specified position
31 32 void insertZone(int index, VisualizationZoneWidget *zoneWidget);
32 33
34 /// Returns the list of zone widget names in the order they are displayed
35 QStringList availableZoneWidgets() const;
36
37 /// Returns the zone with the specified name.
38 /// If multiple zone with the same name exist, the first one is returned.
39 VisualizationZoneWidget *getZoneWithName(const QString &zoneName);
40
33 41 /**
34 42 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
35 43 * zone. The zone is added at the end.
36 44 * @param variable the variable for which to create the zone
37 45 * @return the pointer to the created zone
38 46 */
39 47 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
40 48
41 49 /**
42 50 * Creates a zone using a list of variables. The variables will be displayed in a new graph of
43 51 * the new zone. The zone is inserted at the specified index.
44 52 * @param variables the variables for which to create the zone
45 53 * @param index The index where the zone should be inserted in the layout
46 54 * @return the pointer to the created zone
47 55 */
48 56 VisualizationZoneWidget *createZone(const QList<std::shared_ptr<Variable> > &variables,
49 57 int index);
50 58
51 59 /**
52 60 * Creates a zone which is empty (no variables). The zone is inserted at the specified index.
53 61 * @param index The index where the zone should be inserted in the layout
54 62 * @return the pointer to the created zone
55 63 */
56 64 VisualizationZoneWidget *createEmptyZone(int index);
57 65
58 66 // IVisualizationWidget interface
59 67 void accept(IVisualizationWidgetVisitor *visitor) override;
60 68 bool canDrop(const Variable &variable) const override;
61 69 bool contains(const Variable &variable) const override;
62 70 QString name() const override;
63 71
64 72 protected:
65 73 void closeEvent(QCloseEvent *event) override;
66 74
67 75 private:
68 76 /// @return the layout of tab in which zones are added
69 77 QLayout &tabLayout() const noexcept;
70 78
71 79 Ui::VisualizationTabWidget *ui;
72 80
73 81 class VisualizationTabWidgetPrivate;
74 82 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
75 83
76 84 private slots:
77 85 void dropMimeData(int index, const QMimeData *mimeData);
78 86 };
79 87
80 88 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -1,63 +1,65
1 1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5 #include <Data/SqpRange.h>
6 6
7 7 #include <QLoggingCategory>
8 8 #include <QWidget>
9 9
10 10 #include <Common/spimpl.h>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
13 13
14 14 class QMenu;
15 15 class Variable;
16 16 class VisualizationTabWidget;
17 17 class VisualizationSelectionZoneManager;
18 18
19 19 namespace Ui {
20 20 class VisualizationWidget;
21 21 } // namespace Ui
22 22
23 23 class VisualizationWidget : public QWidget, public IVisualizationWidget {
24 24 Q_OBJECT
25 25
26 26 public:
27 27 explicit VisualizationWidget(QWidget *parent = 0);
28 28 virtual ~VisualizationWidget();
29 29
30 30 /// Returns the class which manage the selection of selection zone across the visualization
31 31 VisualizationSelectionZoneManager &selectionZoneManager() const;
32 32
33 VisualizationTabWidget *currentTabWidget() const;
34
33 35 // IVisualizationWidget interface
34 36 void accept(IVisualizationWidgetVisitor *visitor) override;
35 37 bool canDrop(const Variable &variable) const override;
36 38 bool contains(const Variable &variable) const override;
37 39 QString name() const override;
38 40
39 41 public slots:
40 42 /**
41 43 * Attaches to a menu the menu relative to the visualization of variables
42 44 * @param menu the parent menu of the generated menu
43 45 * @param variables the variables for which to generate the menu
44 46 */
45 47 void attachVariableMenu(QMenu *menu,
46 48 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
47 49
48 50 /// Slot called when a variable is about to be deleted from SciQlop
49 51 void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept;
50 52
51 53 void onRangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range) noexcept;
52 54
53 55 protected:
54 56 void closeEvent(QCloseEvent *event) override;
55 57
56 58 private:
57 59 Ui::VisualizationWidget *ui;
58 60
59 61 class VisualizationWidgetPrivate;
60 62 spimpl::unique_impl_ptr<VisualizationWidgetPrivate> impl;
61 63 };
62 64
63 65 #endif // VISUALIZATIONWIDGET_H
@@ -1,98 +1,103
1 1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3 3
4 #include "Data/SqpRange.h"
4 5 #include "Visualization/IVisualizationWidget.h"
5 6 #include "Visualization/VisualizationDragWidget.h"
6 7
7 8 #include <QLoggingCategory>
8 9 #include <QWidget>
9 10
10 11 #include <memory>
11 12
12 13 #include <Common/spimpl.h>
13 14
14 15 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
15 16
16 17 namespace Ui {
17 18 class VisualizationZoneWidget;
18 19 } // namespace Ui
19 20
20 21 class Variable;
21 22 class VisualizationGraphWidget;
22 23
23 24 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
24 25 Q_OBJECT
25 26
26 27 public:
27 28 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
28 29 virtual ~VisualizationZoneWidget();
29 30
31 /// Sets the range of the zone, only works if there is at least one graph in the zone
32 /// Note: calibrations between graphs are lost.
33 void setZoneRange(const SqpRange &range);
34
30 35 /// Adds a graph widget
31 36 void addGraph(VisualizationGraphWidget *graphWidget);
32 37
33 38 /// Inserts a graph widget
34 39 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
35 40
36 41 /**
37 42 * Creates a graph using a variable. The variable will be displayed in the new graph.
38 43 * The graph is added at the end.
39 44 * @param variable the variable for which to create the graph
40 45 * @return the pointer to the created graph
41 46 */
42 47 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
43 48
44 49 /**
45 50 * Creates a graph using a variable. The variable will be displayed in the new graph.
46 51 * The graph is inserted at the specified index.
47 52 * @param variable the variable for which to create the graph
48 53 * @param index The index where the graph should be inserted in the layout
49 54 * @return the pointer to the created graph
50 55 */
51 56 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
52 57
53 58 /**
54 59 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
55 60 * The graph is inserted at the specified index.
56 61 * @param variables List of variables to be added to the graph
57 62 * @param index The index where the graph should be inserted in the layout
58 63 * @return the pointer to the created graph
59 64 */
60 65 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
61 66 int index);
62 67
63 68 /// Returns the first graph in the zone or nullptr if there is no graph inside
64 69 VisualizationGraphWidget *firstGraph() const;
65 70
66 71 // IVisualizationWidget interface
67 72 void accept(IVisualizationWidgetVisitor *visitor) override;
68 73 bool canDrop(const Variable &variable) const override;
69 74 bool contains(const Variable &variable) const override;
70 75 QString name() const override;
71 76
72 77 // VisualisationDragWidget
73 78 QMimeData *mimeData(const QPoint &position) const override;
74 79 bool isDragAllowed() const override;
75 80
76 81 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
77 82 VisualizationGraphWidget *graphWidget);
78 83 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
79 84
80 85 protected:
81 86 void closeEvent(QCloseEvent *event) override;
82 87
83 88 private:
84 89 Ui::VisualizationZoneWidget *ui;
85 90
86 91 class VisualizationZoneWidgetPrivate;
87 92 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
88 93
89 94 private slots:
90 95 void onVariableAdded(std::shared_ptr<Variable> variable);
91 96 /// Slot called when a variable is about to be removed from a graph contained in the zone
92 97 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
93 98
94 99 void dropMimeData(int index, const QMimeData *mimeData);
95 100 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
96 101 };
97 102
98 103 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,122 +1,127
1 1
2 qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep'])
3 catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep'])
4
2 5 gui_moc_headers = [
3 6 'include/DataSource/DataSourceWidget.h',
4 7 'include/Settings/SqpSettingsDialog.h',
5 8 'include/Settings/SqpSettingsGeneralWidget.h',
6 9 'include/SidePane/SqpSidePane.h',
7 10 'include/SqpApplication.h',
8 11 'include/DragAndDrop/DragDropScroller.h',
9 12 'include/DragAndDrop/DragDropTabSwitcher.h',
10 13 'include/TimeWidget/TimeWidget.h',
11 14 'include/Variable/VariableInspectorWidget.h',
12 15 'include/Variable/RenameVariableDialog.h',
13 16 'include/Visualization/qcustomplot.h',
14 17 'include/Visualization/VisualizationGraphWidget.h',
15 18 'include/Visualization/VisualizationTabWidget.h',
16 19 'include/Visualization/VisualizationWidget.h',
17 20 'include/Visualization/VisualizationZoneWidget.h',
18 21 'include/Visualization/VisualizationDragDropContainer.h',
19 22 'include/Visualization/VisualizationDragWidget.h',
20 23 'include/Visualization/ColorScaleEditor.h',
21 24 'include/Actions/SelectionZoneAction.h',
22 25 'include/Visualization/VisualizationMultiZoneSelectionDialog.h',
23 26 'include/Catalogue/CatalogueExplorer.h',
24 27 'include/Catalogue/CatalogueEventsWidget.h',
25 28 'include/Catalogue/CatalogueSideBarWidget.h',
26 29 'include/Catalogue/CatalogueInspectorWidget.h'
27 30 ]
28 31
29 32 gui_ui_files = [
30 33 'ui/DataSource/DataSourceWidget.ui',
31 34 'ui/Settings/SqpSettingsDialog.ui',
32 35 'ui/Settings/SqpSettingsGeneralWidget.ui',
33 36 'ui/SidePane/SqpSidePane.ui',
34 37 'ui/TimeWidget/TimeWidget.ui',
35 38 'ui/Variable/VariableInspectorWidget.ui',
36 39 'ui/Variable/RenameVariableDialog.ui',
37 40 'ui/Variable/VariableMenuHeaderWidget.ui',
38 41 'ui/Visualization/VisualizationGraphWidget.ui',
39 42 'ui/Visualization/VisualizationTabWidget.ui',
40 43 'ui/Visualization/VisualizationWidget.ui',
41 44 'ui/Visualization/VisualizationZoneWidget.ui',
42 45 'ui/Visualization/ColorScaleEditor.ui',
43 46 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui',
44 47 'ui/Catalogue/CatalogueExplorer.ui',
45 48 'ui/Catalogue/CatalogueEventsWidget.ui',
46 49 'ui/Catalogue/CatalogueSideBarWidget.ui',
47 50 'ui/Catalogue/CatalogueInspectorWidget.ui'
48 51 ]
49 52
50 53 gui_qresources = ['resources/sqpguiresources.qrc']
51 54
52 55 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
53 56 ui_files : gui_ui_files,
54 57 qresources : gui_qresources)
55 58
56 59 gui_sources = [
57 60 'src/SqpApplication.cpp',
58 61 'src/DragAndDrop/DragDropGuiController.cpp',
59 62 'src/DragAndDrop/DragDropScroller.cpp',
60 63 'src/DragAndDrop/DragDropTabSwitcher.cpp',
61 64 'src/Common/ColorUtils.cpp',
62 65 'src/Common/VisualizationDef.cpp',
63 66 'src/DataSource/DataSourceTreeWidgetItem.cpp',
64 67 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
65 68 'src/DataSource/DataSourceWidget.cpp',
66 69 'src/DataSource/DataSourceTreeWidget.cpp',
67 70 'src/Settings/SqpSettingsDialog.cpp',
68 71 'src/Settings/SqpSettingsGeneralWidget.cpp',
69 72 'src/SidePane/SqpSidePane.cpp',
70 73 'src/TimeWidget/TimeWidget.cpp',
71 74 'src/Variable/VariableInspectorWidget.cpp',
72 75 'src/Variable/VariableInspectorTableView.cpp',
73 76 'src/Variable/VariableMenuHeaderWidget.cpp',
74 77 'src/Variable/RenameVariableDialog.cpp',
75 78 'src/Visualization/VisualizationGraphHelper.cpp',
76 79 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
77 80 'src/Visualization/VisualizationGraphWidget.cpp',
78 81 'src/Visualization/VisualizationTabWidget.cpp',
79 82 'src/Visualization/VisualizationWidget.cpp',
80 83 'src/Visualization/VisualizationZoneWidget.cpp',
81 84 'src/Visualization/qcustomplot.cpp',
82 85 'src/Visualization/QCustomPlotSynchronizer.cpp',
83 86 'src/Visualization/operations/FindVariableOperation.cpp',
84 87 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
85 88 'src/Visualization/operations/MenuBuilder.cpp',
86 89 'src/Visualization/operations/RemoveVariableOperation.cpp',
87 90 'src/Visualization/operations/RescaleAxeOperation.cpp',
88 91 'src/Visualization/VisualizationDragDropContainer.cpp',
89 92 'src/Visualization/VisualizationDragWidget.cpp',
90 93 'src/Visualization/AxisRenderingUtils.cpp',
91 94 'src/Visualization/PlottablesRenderingUtils.cpp',
92 95 'src/Visualization/MacScrollBarStyle.cpp',
93 96 'src/Visualization/VisualizationCursorItem.cpp',
94 97 'src/Visualization/ColorScaleEditor.cpp',
95 98 'src/Visualization/SqpColorScale.cpp',
96 99 'src/Visualization/QCPColorMapIterator.cpp',
97 100 'src/Visualization/VisualizationSelectionZoneItem.cpp',
98 101 'src/Visualization/VisualizationSelectionZoneManager.cpp',
99 102 'src/Actions/SelectionZoneAction.cpp',
100 103 'src/Actions/ActionsGuiController.cpp',
101 104 'src/Visualization/VisualizationActionManager.cpp',
102 105 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp',
103 106 'src/Catalogue/CatalogueExplorer.cpp',
104 107 'src/Catalogue/CatalogueEventsWidget.cpp',
105 108 'src/Catalogue/CatalogueSideBarWidget.cpp',
106 'src/Catalogue/CatalogueInspectorWidget.cpp'
109 'src/Catalogue/CatalogueInspectorWidget.cpp',
110 'src/Catalogue/CatalogueTreeWidgetItem.cpp',
111 'src/Catalogue/CatalogueEventsModel.cpp'
107 112 ]
108 113
109 114 gui_inc = include_directories(['include'])
110 115
111 116 sciqlop_gui_lib = library('sciqlopgui',
112 117 gui_sources,
113 118 gui_moc_files,
114 119 include_directories : [gui_inc],
115 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
120 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep],
116 121 install : true
117 122 )
118 123
119 124 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
120 125 include_directories : gui_inc,
121 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
126 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep])
122 127
@@ -1,29 +1,31
1 1 <RCC>
2 2 <qresource prefix="/">
3 3 <file>icones/dataSourceComponent.png</file>
4 4 <file>icones/dataSourceNode.png</file>
5 5 <file>icones/dataSourceProduct.png</file>
6 6 <file>icones/dataSourceRoot.png</file>
7 7 <file>icones/delete.png</file>
8 8 <file>icones/down.png</file>
9 9 <file>icones/openInspector.png</file>
10 10 <file>icones/next.png</file>
11 11 <file>icones/plot.png</file>
12 12 <file>icones/previous.png</file>
13 13 <file>icones/unplot.png</file>
14 14 <file>icones/up.png</file>
15 15 <file>icones/time.png</file>
16 16 <file>icones/zoom.png</file>
17 17 <file>icones/rectangle.png</file>
18 18 <file>icones/drag.png</file>
19 19 <file>icones/cursor.png</file>
20 20 <file>icones/pointer.png</file>
21 21 <file>icones/catalogue.png</file>
22 22 <file>icones/add.png</file>
23 23 <file>icones/remove.png</file>
24 24 <file>icones/chart.png</file>
25 25 <file>icones/allEvents.png</file>
26 26 <file>icones/trash.png</file>
27 27 <file>icones/database.png</file>
28 <file>icones/save.png</file>
29 <file>icones/discard.png</file>
28 30 </qresource>
29 31 </RCC>
@@ -1,100 +1,316
1 1 #include "Catalogue/CatalogueEventsWidget.h"
2 2 #include "ui_CatalogueEventsWidget.h"
3 3
4 #include <QtDebug>
4 #include <Catalogue/CatalogueController.h>
5 #include <Catalogue/CatalogueEventsModel.h>
6 #include <CatalogueDao.h>
7 #include <DBCatalogue.h>
8 #include <SqpApplication.h>
9 #include <Visualization/VisualizationTabWidget.h>
10 #include <Visualization/VisualizationWidget.h>
11 #include <Visualization/VisualizationZoneWidget.h>
12
13 #include <QDialog>
14 #include <QDialogButtonBox>
15 #include <QListWidget>
16
17 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
18
19 /// Format of the dates appearing in the label of a cursor
20 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss");
5 21
6 22 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
7 void addEventItem(const QStringList &data, QTableWidget *tableWidget);
8 23
9 enum class Column { Event, TStart, TEnd, Tags, Product, NbColumn };
10 QStringList columnNames() { return QStringList{"Event", "TStart", "TEnd", "Tags", "Product"}; }
11 };
24 CatalogueEventsModel *m_Model = nullptr;
25 QStringList m_ZonesForTimeMode;
26 QString m_ZoneForGraphMode;
12 27
28 VisualizationWidget *m_VisualizationWidget = nullptr;
29
30 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, QTreeView *treeView)
31 {
32 treeView->setSortingEnabled(false);
33 m_Model->setEvents(events);
34 treeView->setSortingEnabled(true);
35 }
36
37 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
38 {
39 treeView->setSortingEnabled(false);
40 m_Model->addEvent(event);
41 treeView->setSortingEnabled(true);
42 }
43
44 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
45 {
46 treeView->setSortingEnabled(false);
47 m_Model->removeEvent(event);
48 treeView->setSortingEnabled(true);
49 }
50
51 QStringList getAvailableVisualizationZoneList() const
52 {
53 if (m_VisualizationWidget) {
54 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
55 return tab->availableZoneWidgets();
56 }
57 }
58
59 return QStringList{};
60 }
61
62 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
63 bool allowMultiSelection, const QPoint &location)
64 {
65 auto availableZones = getAvailableVisualizationZoneList();
66 if (availableZones.isEmpty()) {
67 return QStringList{};
68 }
69
70 QDialog d(parent, Qt::Tool);
71 d.setWindowTitle("Choose a zone");
72 auto layout = new QVBoxLayout{&d};
73 layout->setContentsMargins(0, 0, 0, 0);
74 auto listWidget = new QListWidget{&d};
75 layout->addWidget(listWidget);
76
77 QSet<QListWidgetItem *> checkedItems;
78 for (auto zone : availableZones) {
79 auto item = new QListWidgetItem{zone};
80 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
81 if (selectedZones.contains(zone)) {
82 item->setCheckState(Qt::Checked);
83 checkedItems << item;
84 }
85 else {
86 item->setCheckState(Qt::Unchecked);
87 }
88
89 listWidget->addItem(item);
90 }
91
92 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
93 layout->addWidget(buttonBox);
94
95 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
96 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
97
98 QObject::connect(listWidget, &QListWidget::itemChanged,
99 [&checkedItems, allowMultiSelection, listWidget](auto item) {
100 if (item->checkState() == Qt::Checked) {
101 if (!allowMultiSelection) {
102 for (auto checkedItem : checkedItems) {
103 listWidget->blockSignals(true);
104 checkedItem->setCheckState(Qt::Unchecked);
105 listWidget->blockSignals(false);
106 }
107
108 checkedItems.clear();
109 }
110 checkedItems << item;
111 }
112 else {
113 checkedItems.remove(item);
114 }
115 });
116
117 QStringList result;
118
119 d.setMinimumWidth(120);
120 d.resize(d.minimumSizeHint());
121 d.move(location);
122 if (d.exec() == QDialog::Accepted) {
123 for (auto item : checkedItems) {
124 result += item->text();
125 }
126 }
127 else {
128 result = selectedZones;
129 }
130
131 return result;
132 }
133
134 void updateForTimeMode(QTreeView *treeView)
135 {
136 auto selectedRows = treeView->selectionModel()->selectedRows();
137
138 if (selectedRows.count() == 1) {
139 auto event = m_Model->getEvent(selectedRows.first());
140 if (event) {
141 if (m_VisualizationWidget) {
142 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
143
144 for (auto zoneName : m_ZonesForTimeMode) {
145 if (auto zone = tab->getZoneWithName(zoneName)) {
146 SqpRange eventRange;
147 eventRange.m_TStart = event->getTStart();
148 eventRange.m_TEnd = event->getTEnd();
149 zone->setZoneRange(eventRange);
150 }
151 }
152 }
153 else {
154 qCWarning(LOG_CatalogueEventsWidget())
155 << "updateTimeZone: no tab found in the visualization";
156 }
157 }
158 else {
159 qCWarning(LOG_CatalogueEventsWidget())
160 << "updateTimeZone: visualization widget not found";
161 }
162 }
163 }
164 else {
165 qCWarning(LOG_CatalogueEventsWidget())
166 << "updateTimeZone: not compatible with multiple events selected";
167 }
168 }
169
170 void updateForGraphMode(QTreeView *treeView)
171 {
172 auto selectedRows = treeView->selectionModel()->selectedRows();
173
174 if (selectedRows.count() == 1) {
175 auto event = m_Model->getEvent(selectedRows.first());
176 if (m_VisualizationWidget) {
177 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
178 if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) {
179 // TODO
180 }
181 }
182 else {
183 qCWarning(LOG_CatalogueEventsWidget())
184 << "updateGraphMode: no tab found in the visualization";
185 }
186 }
187 else {
188 qCWarning(LOG_CatalogueEventsWidget())
189 << "updateGraphMode: visualization widget not found";
190 }
191 }
192 else {
193 qCWarning(LOG_CatalogueEventsWidget())
194 << "updateGraphMode: not compatible with multiple events selected";
195 }
196 }
197 };
13 198
14 199 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
15 200 : QWidget(parent),
16 201 ui(new Ui::CatalogueEventsWidget),
17 202 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
18 203 {
19 204 ui->setupUi(this);
20 205
206 impl->m_Model = new CatalogueEventsModel{this};
207 ui->treeView->setModel(impl->m_Model);
208
209 ui->treeView->setSortingEnabled(true);
210 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
211 ui->treeView->setDragEnabled(true);
212
21 213 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
22 214 if (checked) {
23 215 ui->btnChart->setChecked(false);
216 impl->m_ZonesForTimeMode
217 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
218 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
219
220 impl->updateForTimeMode(ui->treeView);
24 221 }
25 222 });
26 223
27 224 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
28 225 if (checked) {
29 226 ui->btnTime->setChecked(false);
227 impl->m_ZoneForGraphMode
228 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
229 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
230 .value(0);
231
232 impl->updateForGraphMode(ui->treeView);
30 233 }
31 234 });
32 235
33 connect(ui->tableWidget, &QTableWidget::cellClicked, [this](auto row, auto column) {
34 auto event = ui->tableWidget->item(row, 0)->text();
35 emit this->eventSelected(event);
36 });
236 auto emitSelection = [this]() {
237 QVector<std::shared_ptr<DBEvent> > events;
238 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
37 239
38 connect(ui->tableWidget, &QTableWidget::currentItemChanged,
39 [this](auto current, auto previous) {
40 if (current && current->row() >= 0) {
41 auto event = ui->tableWidget->item(current->row(), 0)->text();
42 emit this->eventSelected(event);
240 for (auto rowIndex : ui->treeView->selectionModel()->selectedRows()) {
241
242 auto itemType = impl->m_Model->itemTypeOf(rowIndex);
243 if (itemType == CatalogueEventsModel::ItemType::Event) {
244 events << impl->m_Model->getEvent(rowIndex);
43 245 }
44 });
246 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
247 eventProducts << qMakePair(impl->m_Model->getParentEvent(rowIndex),
248 impl->m_Model->getEventProduct(rowIndex));
249 }
250 }
251
252 if (!events.isEmpty() && eventProducts.isEmpty()) {
253 emit this->eventsSelected(events);
254 }
255 else if (events.isEmpty() && !eventProducts.isEmpty()) {
256 emit this->eventProductsSelected(eventProducts);
257 }
258 else {
259 emit this->selectionCleared();
260 }
261 };
45 262
46 connect(ui->tableWidget, &QTableWidget::itemSelectionChanged, [this]() {
47 auto selection = ui->tableWidget->selectedRanges();
48 auto isNotMultiSelection
49 = selection.isEmpty() || (selection.count() == 1 && selection.first().rowCount() == 1);
263 connect(ui->treeView, &QTreeView::clicked, emitSelection);
264 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, emitSelection);
265
266 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
267 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
50 268 ui->btnChart->setEnabled(isNotMultiSelection);
51 269 ui->btnTime->setEnabled(isNotMultiSelection);
270
271 if (isNotMultiSelection && ui->btnTime->isChecked()) {
272 impl->updateForTimeMode(ui->treeView);
273 }
274 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
275 impl->updateForGraphMode(ui->treeView);
276 }
52 277 });
53 278
54 Q_ASSERT(impl->columnNames().count() == (int)CatalogueEventsWidgetPrivate::Column::NbColumn);
55 ui->tableWidget->setColumnCount((int)CatalogueEventsWidgetPrivate::Column::NbColumn);
56 ui->tableWidget->setHorizontalHeaderLabels(impl->columnNames());
57 ui->tableWidget->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
58 ui->tableWidget->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
59 ui->tableWidget->horizontalHeader()->setSortIndicatorShown(true);
279 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
280 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
281 ui->treeView->header()->setSortIndicatorShown(true);
60 282 }
61 283
62 284 CatalogueEventsWidget::~CatalogueEventsWidget()
63 285 {
64 286 delete ui;
65 287 }
66 288
67 void CatalogueEventsWidget::populateWithCatalogue(const QString &catalogue)
289 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
68 290 {
69 ui->tableWidget->clearContents();
70 ui->tableWidget->setRowCount(0);
291 impl->m_VisualizationWidget = visualization;
292 }
71 293
72 // TODO
73 impl->addEventItem(
74 {catalogue + " - Event 1", "12/12/2012 12:12", "12/12/2042 12:52", "cloud", "mfi/b_gse42"},
75 ui->tableWidget);
76 impl->addEventItem(
77 {catalogue + " - Event 2", "12/12/2012 12:10", "12/12/2042 12:42", "Acloud", "mfi/b_gse1"},
78 ui->tableWidget);
79 impl->addEventItem(
80 {catalogue + " - Event 3", "12/12/2012 12:22", "12/12/2042 12:12", "Gcloud", "mfi/b_gse2"},
81 ui->tableWidget);
82 impl->addEventItem(
83 {catalogue + " - Event 4", "12/12/2012 12:00", "12/12/2042 12:62", "Bcloud", "mfi/b_gse3"},
84 ui->tableWidget);
85 }
86
87 void CatalogueEventsWidget::CatalogueEventsWidgetPrivate::addEventItem(const QStringList &data,
88 QTableWidget *tableWidget)
294 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
89 295 {
90 tableWidget->setSortingEnabled(false);
91 auto row = tableWidget->rowCount();
92 tableWidget->setRowCount(row + 1);
296 impl->m_Model->refreshEvent(event);
297 }
298
299 void CatalogueEventsWidget::populateWithCatalogues(
300 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
301 {
302 QSet<QUuid> eventIds;
303 QVector<std::shared_ptr<DBEvent> > events;
93 304
94 for (auto i = 0; i < (int)Column::NbColumn; ++i) {
95 auto item = new QTableWidgetItem(data.value(i));
96 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable);
97 tableWidget->setItem(row, i, item);
305 for (auto catalogue : catalogues) {
306 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
307 for (auto event : catalogueEvents) {
308 if (!eventIds.contains(event->getUniqId())) {
309 events << event;
310 eventIds.insert(event->getUniqId());
98 311 }
99 tableWidget->setSortingEnabled(true);
312 }
313 }
314
315 impl->setEvents(events, ui->treeView);
100 316 }
@@ -1,22 +1,83
1 1 #include "Catalogue/CatalogueExplorer.h"
2 2 #include "ui_CatalogueExplorer.h"
3 3
4 #include <Visualization/VisualizationWidget.h>
5
6 #include <DBCatalogue.h>
7 #include <DBEvent.h>
8
9 struct CatalogueExplorer::CatalogueExplorerPrivate {
10 };
11
4 12 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
5 13 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
6 ui(new Ui::CatalogueExplorer)
14 ui(new Ui::CatalogueExplorer),
15 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>()}
7 16 {
8 17 ui->setupUi(this);
9 18
10 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto name) {
11 ui->inspector->setCatalogue(name);
12 ui->events->populateWithCatalogue(name);
19 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
20 if (catalogues.count() == 1) {
21 ui->inspector->setCatalogue(catalogues.first());
22 }
23 else {
24 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
25 }
26
27 ui->events->populateWithCatalogues(catalogues);
13 28 });
14 29
15 connect(ui->events, &CatalogueEventsWidget::eventSelected,
16 [this](auto name) { ui->inspector->setEvent(name); });
30 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
31 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
32 });
33
34 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected,
35 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
36
37 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected,
38 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
39
40 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared,
41 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
42
43 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
44 if (events.count() == 1) {
45 ui->inspector->setEvent(events.first());
46 }
47 else {
48 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
49 }
50 });
51
52 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
53 if (eventProducts.count() == 1) {
54 ui->inspector->setEventProduct(eventProducts.first().first,
55 eventProducts.first().second);
56 }
57 else {
58 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
59 }
60 });
61
62 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
63 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
64
65 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated,
66 [this](auto catalogue) { ui->catalogues->setCatalogueChanges(catalogue, true); });
67
68 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated,
69 [this](auto event) { ui->events->setEventChanges(event, true); });
70
71 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
72 [this](auto event, auto eventProduct) { ui->events->setEventChanges(event, true); });
17 73 }
18 74
19 75 CatalogueExplorer::~CatalogueExplorer()
20 76 {
21 77 delete ui;
22 78 }
79
80 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
81 {
82 ui->events->setVisualizationWidget(visualization);
83 }
@@ -1,36 +1,181
1 1 #include "Catalogue/CatalogueInspectorWidget.h"
2 2 #include "ui_CatalogueInspectorWidget.h"
3 3
4 #include <Common/DateUtils.h>
5 #include <DBCatalogue.h>
6 #include <DBEvent.h>
7 #include <DBEventProduct.h>
8 #include <DBTag.h>
9
10 struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate {
11 std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr;
12 std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr;
13 std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr;
14
15 void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector,
16 Ui::CatalogueInspectorWidget *ui);
17 void connectEventUpdateSignals(CatalogueInspectorWidget *inspector,
18 Ui::CatalogueInspectorWidget *ui);
19 };
20
4 21 CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent)
5 : QWidget(parent), ui(new Ui::CatalogueInspectorWidget)
22 : QWidget(parent),
23 ui(new Ui::CatalogueInspectorWidget),
24 impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()}
6 25 {
7 26 ui->setupUi(this);
8 27 showPage(Page::Empty);
28
29 impl->connectCatalogueUpdateSignals(this, ui);
30 impl->connectEventUpdateSignals(this, ui);
9 31 }
10 32
11 33 CatalogueInspectorWidget::~CatalogueInspectorWidget()
12 34 {
13 35 delete ui;
14 36 }
15 37
38 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals(
39 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
40 {
41 connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() {
42 if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) {
43 m_DisplayedCatalogue->setName(ui->leCatalogueName->text());
44 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
45 }
46 });
47
48 connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() {
49 if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) {
50 m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text());
51 emit inspector->catalogueUpdated(m_DisplayedCatalogue);
52 }
53 });
54 }
55
56 void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals(
57 CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui)
58 {
59 connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() {
60 if (ui->leEventName->text() != m_DisplayedEvent->getName()) {
61 m_DisplayedEvent->setName(ui->leEventName->text());
62 emit inspector->eventUpdated(m_DisplayedEvent);
63 }
64 });
65
66 connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() {
67 auto tags = ui->leEventTags->text().split(QRegExp("\\s+"));
68 std::list<QString> tagNames;
69 for (auto tag : tags) {
70 tagNames.push_back(tag);
71 }
72
73 if (m_DisplayedEvent->getTagsNames() != tagNames) {
74 m_DisplayedEvent->setTagsNames(tagNames);
75 emit inspector->eventUpdated(m_DisplayedEvent);
76 }
77 });
78
79 connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() {
80 if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) {
81 m_DisplayedEventProduct->setProductId(ui->leEventProduct->text());
82 emit inspector->eventProductUpdated(m_DisplayedEvent, m_DisplayedEventProduct);
83 }
84 });
85
86 connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
87 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime());
88 if (time != m_DisplayedEventProduct->getTStart()) {
89 m_DisplayedEventProduct->setTStart(time);
90 emit inspector->eventProductUpdated(m_DisplayedEvent, m_DisplayedEventProduct);
91 }
92 });
93
94 connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() {
95 auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime());
96 if (time != m_DisplayedEventProduct->getTEnd()) {
97 m_DisplayedEventProduct->setTEnd(time);
98 emit inspector->eventProductUpdated(m_DisplayedEvent, m_DisplayedEventProduct);
99 }
100 });
101 }
102
16 103 void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page)
17 104 {
18 105 ui->stackedWidget->setCurrentIndex(static_cast<int>(page));
19 106 }
20 107
21 108 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
22 109 {
23 110 return static_cast<Page>(ui->stackedWidget->currentIndex());
24 111 }
25 112
26 void CatalogueInspectorWidget::setEvent(const QString &event)
113 void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event)
114 {
115 impl->m_DisplayedEvent = event;
116
117 blockSignals(true);
118
119 showPage(Page::EventProperties);
120 ui->leEventName->setEnabled(true);
121 ui->leEventName->setText(event->getName());
122 ui->leEventProduct->setEnabled(false);
123 ui->leEventProduct->setText(
124 QString::number(event->getEventProducts().size()).append(" product(s)"));
125
126 QString tagList;
127 auto tags = event->getTagsNames();
128 for (auto tag : tags) {
129 tagList += tag;
130 tagList += ' ';
131 }
132
133 ui->leEventTags->setEnabled(true);
134 ui->leEventTags->setText(tagList);
135
136 ui->dateTimeEventTStart->setEnabled(false);
137 ui->dateTimeEventTEnd->setEnabled(false);
138
139 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart()));
140 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd()));
141
142 blockSignals(false);
143 }
144
145 void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event,
146 const std::shared_ptr<DBEventProduct> &eventProduct)
27 147 {
148 impl->m_DisplayedEventProduct = eventProduct;
149
150 blockSignals(true);
151
28 152 showPage(Page::EventProperties);
29 ui->leEventName->setText(event);
153 ui->leEventName->setEnabled(false);
154 ui->leEventName->setText(event->getName());
155 ui->leEventProduct->setEnabled(true);
156 ui->leEventProduct->setText(eventProduct->getProductId());
157
158 ui->leEventTags->setEnabled(false);
159 ui->leEventTags->clear();
160
161 ui->dateTimeEventTStart->setEnabled(true);
162 ui->dateTimeEventTEnd->setEnabled(true);
163
164 ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart()));
165 ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd()));
166
167 blockSignals(false);
30 168 }
31 169
32 void CatalogueInspectorWidget::setCatalogue(const QString &catalogue)
170 void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue)
33 171 {
172 impl->m_DisplayedCatalogue = catalogue;
173
174 blockSignals(true);
175
34 176 showPage(Page::CatalogueProperties);
35 ui->leCatalogueName->setText(catalogue);
177 ui->leCatalogueName->setText(catalogue->getName());
178 ui->leCatalogueAuthor->setText(catalogue->getAuthor());
179
180 blockSignals(false);
36 181 }
@@ -1,101 +1,247
1 1 #include "Catalogue/CatalogueSideBarWidget.h"
2 2 #include "ui_CatalogueSideBarWidget.h"
3 #include <SqpApplication.h>
4
5 #include <Catalogue/CatalogueController.h>
6 #include <Catalogue/CatalogueTreeWidgetItem.h>
7 #include <CatalogueDao.h>
8 #include <ComparaisonPredicate.h>
9 #include <DBCatalogue.h>
10
11 #include <QMenu>
12
13 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
14
3 15
4 16 constexpr auto ALL_EVENT_ITEM_TYPE = QTreeWidgetItem::UserType;
5 17 constexpr auto TRASH_ITEM_TYPE = QTreeWidgetItem::UserType + 1;
6 18 constexpr auto CATALOGUE_ITEM_TYPE = QTreeWidgetItem::UserType + 2;
7 19 constexpr auto DATABASE_ITEM_TYPE = QTreeWidgetItem::UserType + 3;
8 20
9 21
10 22 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
23
11 24 void configureTreeWidget(QTreeWidget *treeWidget);
12 25 QTreeWidgetItem *addDatabaseItem(const QString &name, QTreeWidget *treeWidget);
13 void addCatalogueItem(const QString &name, QTreeWidgetItem *parentDatabaseItem);
26 QTreeWidgetItem *getDatabaseItem(const QString &name, QTreeWidget *treeWidget);
27 void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
28 QTreeWidgetItem *parentDatabaseItem);
29
30 CatalogueTreeWidgetItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
31 QTreeWidget *treeWidget) const;
14 32 };
15 33
16 34 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
17 35 : QWidget(parent),
18 36 ui(new Ui::CatalogueSideBarWidget),
19 37 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
20 38 {
21 39 ui->setupUi(this);
22 40 impl->configureTreeWidget(ui->treeWidget);
23 41
24 auto emitSelection = [this](auto item) {
25 switch (item->type()) {
42 ui->treeWidget->setColumnCount(2);
43 ui->treeWidget->header()->setStretchLastSection(false);
44 ui->treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
45 ui->treeWidget->header()->setSectionResizeMode(0, QHeaderView::Stretch);
46
47 auto emitSelection = [this]() {
48
49 auto selectedItems = ui->treeWidget->selectedItems();
50 if (selectedItems.isEmpty()) {
51 emit this->selectionCleared();
52 }
53 else {
54 QVector<std::shared_ptr<DBCatalogue> > catalogues;
55 QStringList databases;
56 int selectionType = selectedItems.first()->type();
57
58 for (auto item : ui->treeWidget->selectedItems()) {
59 if (item->type() == selectionType) {
60 switch (selectionType) {
26 61 case CATALOGUE_ITEM_TYPE:
27 emit this->catalogueSelected(item->text(0));
62 catalogues.append(
63 static_cast<CatalogueTreeWidgetItem *>(item)->catalogue());
64 break;
65 case DATABASE_ITEM_TYPE:
66 selectionType = DATABASE_ITEM_TYPE;
67 databases.append(item->text(0));
68 case ALL_EVENT_ITEM_TYPE: // fallthrough
69 case TRASH_ITEM_TYPE: // fallthrough
70 default:
71 break;
72 }
73 }
74 else {
75 // Incoherent multi selection
76 selectionType = -1;
77 break;
78 }
79 }
80
81 switch (selectionType) {
82 case CATALOGUE_ITEM_TYPE:
83 emit this->catalogueSelected(catalogues);
84 break;
85 case DATABASE_ITEM_TYPE:
86 emit this->databaseSelected(databases);
28 87 break;
29 88 case ALL_EVENT_ITEM_TYPE:
30 89 emit this->allEventsSelected();
31 90 break;
32 91 case TRASH_ITEM_TYPE:
33 92 emit this->trashSelected();
34 93 break;
35 case DATABASE_ITEM_TYPE:
36 94 default:
95 emit this->selectionCleared();
37 96 break;
38 97 }
98 }
99
100
39 101 };
40 102
41 103 connect(ui->treeWidget, &QTreeWidget::itemClicked, emitSelection);
42 104 connect(ui->treeWidget, &QTreeWidget::currentItemChanged, emitSelection);
105 connect(ui->treeWidget, &QTreeWidget::itemChanged,
106 [emitSelection, this](auto item, auto column) {
107 auto selectedItems = ui->treeWidget->selectedItems();
108 qDebug() << "ITEM CHANGED" << column;
109 if (selectedItems.contains(item) && column == 0) {
110 emitSelection();
111 }
112 });
113
114 ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
115 connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this,
116 &CatalogueSideBarWidget::onContextMenuRequested);
43 117 }
44 118
45 119 CatalogueSideBarWidget::~CatalogueSideBarWidget()
46 120 {
47 121 delete ui;
48 122 }
49 123
124 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
125 bool hasChanges)
126 {
127 if (auto catalogueItem = impl->getCatalogueItem(catalogue, ui->treeWidget)) {
128 catalogueItem->setHasChanges(hasChanges);
129 catalogueItem->refresh();
130 }
131 }
132
133 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
134 {
135 QMenu menu{this};
136
137 auto currentItem = ui->treeWidget->currentItem();
138 switch (currentItem->type()) {
139 case CATALOGUE_ITEM_TYPE:
140 menu.addAction("Rename",
141 [this, currentItem]() { ui->treeWidget->editItem(currentItem); });
142 break;
143 case DATABASE_ITEM_TYPE:
144 break;
145 case ALL_EVENT_ITEM_TYPE:
146 break;
147 case TRASH_ITEM_TYPE:
148 menu.addAction("Empty Trash", []() {
149 // TODO
150 });
151 break;
152 default:
153 break;
154 }
155
156 if (!menu.isEmpty()) {
157 menu.exec(ui->treeWidget->mapToGlobal(pos));
158 }
159 }
160
50 161 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(
51 162 QTreeWidget *treeWidget)
52 163 {
53 auto allEventsItem = new QTreeWidgetItem({"All Events"}, ALL_EVENT_ITEM_TYPE);
164 auto allEventsItem = new QTreeWidgetItem{{"All Events"}, ALL_EVENT_ITEM_TYPE};
54 165 allEventsItem->setIcon(0, QIcon(":/icones/allEvents.png"));
55 166 treeWidget->addTopLevelItem(allEventsItem);
56 167
57 auto trashItem = new QTreeWidgetItem({"Trash"}, TRASH_ITEM_TYPE);
168 auto trashItem = new QTreeWidgetItem{{"Trash"}, TRASH_ITEM_TYPE};
58 169 trashItem->setIcon(0, QIcon(":/icones/trash.png"));
59 170 treeWidget->addTopLevelItem(trashItem);
60 171
61 auto separator = new QFrame(treeWidget);
172 auto separator = new QFrame{treeWidget};
62 173 separator->setFrameShape(QFrame::HLine);
63
64 auto separatorItem = new QTreeWidgetItem();
174 auto separatorItem = new QTreeWidgetItem{};
65 175 separatorItem->setFlags(Qt::NoItemFlags);
66 176 treeWidget->addTopLevelItem(separatorItem);
67 177 treeWidget->setItemWidget(separatorItem, 0, separator);
68 178
69 // Test
70 auto db = addDatabaseItem("Database 1", treeWidget);
71 addCatalogueItem("Catalogue 1", db);
72 addCatalogueItem("Catalogue 2", db);
73 addCatalogueItem("Catalogue 3", db);
74 addCatalogueItem("Catalogue 4", db);
179 auto db = addDatabaseItem("Default", treeWidget);
75 180
76 auto db2 = addDatabaseItem("Database 2", treeWidget);
77 addCatalogueItem("Catalogue A", db2);
78 addCatalogueItem("Catalogue B", db2);
79 addCatalogueItem("Catalogue C", db2);
181 auto catalogues = sqpApp->catalogueController().getCatalogues("Default");
182 for (auto catalogue : catalogues) {
183 addCatalogueItem(catalogue, db);
184 }
80 185
81 186 treeWidget->expandAll();
82 187 }
83 188
84 189 QTreeWidgetItem *
85 190 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name,
86 191 QTreeWidget *treeWidget)
87 192 {
88 auto databaseItem = new QTreeWidgetItem({name}, DATABASE_ITEM_TYPE);
89 databaseItem->setIcon(0, QIcon(":/icones/database.png"));
193 auto databaseItem = new QTreeWidgetItem{{name}, DATABASE_ITEM_TYPE};
194 databaseItem->setIcon(0, QIcon{":/icones/database.png"});
90 195 treeWidget->addTopLevelItem(databaseItem);
91 196
92 197 return databaseItem;
93 198 }
94 199
200 QTreeWidgetItem *
201 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name,
202 QTreeWidget *treeWidget)
203 {
204 for (auto i = 0; i < treeWidget->topLevelItemCount(); ++i) {
205 auto item = treeWidget->topLevelItem(i);
206 if (item->type() == DATABASE_ITEM_TYPE && item->text(0) == name) {
207 return item;
208 }
209 }
210
211 return nullptr;
212 }
213
95 214 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
96 const QString &name, QTreeWidgetItem *parentDatabaseItem)
215 const std::shared_ptr<DBCatalogue> &catalogue, QTreeWidgetItem *parentDatabaseItem)
97 216 {
98 auto catalogueItem = new QTreeWidgetItem({name}, CATALOGUE_ITEM_TYPE);
99 catalogueItem->setIcon(0, QIcon(":/icones/catalogue.png"));
217 auto catalogueItem = new CatalogueTreeWidgetItem{catalogue, CATALOGUE_ITEM_TYPE};
218 catalogueItem->setIcon(0, QIcon{":/icones/catalogue.png"});
100 219 parentDatabaseItem->addChild(catalogueItem);
101 220 }
221
222 CatalogueTreeWidgetItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
223 const std::shared_ptr<DBCatalogue> &catalogue, QTreeWidget *treeWidget) const
224 {
225 for (auto i = 0; i < treeWidget->topLevelItemCount(); ++i) {
226 auto item = treeWidget->topLevelItem(i);
227 if (item->type() == DATABASE_ITEM_TYPE) {
228 for (auto j = 0; j < item->childCount(); ++j) {
229 auto childItem = item->child(j);
230 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
231 auto catalogueItem = static_cast<CatalogueTreeWidgetItem *>(childItem);
232 if (catalogueItem->catalogue() == catalogue) {
233 return catalogueItem;
234 }
235 }
236 else {
237 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
238 "structure. A database item should "
239 "only contain catalogues.";
240 Q_ASSERT(false);
241 }
242 }
243 }
244 }
245
246 return nullptr;
247 }
@@ -1,212 +1,217
1 1 #include "SqpApplication.h"
2 2
3 3 #include <Actions/ActionsGuiController.h>
4 4 #include <Catalogue/CatalogueController.h>
5 5 #include <Data/IDataProvider.h>
6 6 #include <DataSource/DataSourceController.h>
7 7 #include <DragAndDrop/DragDropGuiController.h>
8 8 #include <Network/NetworkController.h>
9 9 #include <QThread>
10 10 #include <Time/TimeController.h>
11 11 #include <Variable/Variable.h>
12 12 #include <Variable/VariableController.h>
13 13 #include <Variable/VariableModel.h>
14 14 #include <Visualization/VisualizationController.h>
15 15
16 16 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
17 17
18 18 class SqpApplication::SqpApplicationPrivate {
19 19 public:
20 20 SqpApplicationPrivate()
21 21 : m_DataSourceController{std::make_unique<DataSourceController>()},
22 22 m_VariableController{std::make_unique<VariableController>()},
23 23 m_TimeController{std::make_unique<TimeController>()},
24 24 m_NetworkController{std::make_unique<NetworkController>()},
25 25 m_VisualizationController{std::make_unique<VisualizationController>()},
26 26 m_DragDropGuiController{std::make_unique<DragDropGuiController>()},
27 27 m_CatalogueController{std::make_unique<CatalogueController>()},
28 28 m_ActionsGuiController{std::make_unique<ActionsGuiController>()},
29 29 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
30 30 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
31 31 {
32 32 // /////////////////////////////// //
33 33 // Connections between controllers //
34 34 // /////////////////////////////// //
35 35
36 36 // VariableController <-> DataSourceController
37 37 connect(m_DataSourceController.get(),
38 38 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
39 39 std::shared_ptr<IDataProvider>)),
40 40 m_VariableController.get(),
41 41 SLOT(createVariable(const QString &, const QVariantHash &,
42 42 std::shared_ptr<IDataProvider>)));
43 43
44 44 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
45 45 m_DataSourceController.get(), &DataSourceController::requestVariable);
46 46
47 47 // VariableController <-> VisualizationController
48 48 connect(m_VariableController.get(),
49 49 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
50 50 m_VisualizationController.get(),
51 51 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
52 52
53 53 connect(m_VariableController.get(),
54 54 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
55 55 m_VisualizationController.get(),
56 56 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
57 57
58 58
59 59 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
60 60 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
61 61 m_NetworkController->moveToThread(&m_NetworkControllerThread);
62 62 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
63 63 m_VariableController->moveToThread(&m_VariableControllerThread);
64 64 m_VariableControllerThread.setObjectName("VariableControllerThread");
65 65 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
66 66 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
67 67 m_CatalogueController->moveToThread(&m_CatalogueControllerThread);
68 68 m_CatalogueControllerThread.setObjectName("CatalogueControllerThread");
69 69
70 70
71 71 // Additionnal init
72 72 m_VariableController->setTimeController(m_TimeController.get());
73 73 }
74 74
75 75 virtual ~SqpApplicationPrivate()
76 76 {
77 77 m_DataSourceControllerThread.quit();
78 78 m_DataSourceControllerThread.wait();
79 79
80 80 m_NetworkControllerThread.quit();
81 81 m_NetworkControllerThread.wait();
82 82
83 83 m_VariableControllerThread.quit();
84 84 m_VariableControllerThread.wait();
85 85
86 86 m_VisualizationControllerThread.quit();
87 87 m_VisualizationControllerThread.wait();
88 88
89 89 m_CatalogueControllerThread.quit();
90 90 m_CatalogueControllerThread.wait();
91 91 }
92 92
93 93 std::unique_ptr<DataSourceController> m_DataSourceController;
94 94 std::unique_ptr<VariableController> m_VariableController;
95 95 std::unique_ptr<TimeController> m_TimeController;
96 96 std::unique_ptr<NetworkController> m_NetworkController;
97 97 std::unique_ptr<VisualizationController> m_VisualizationController;
98 98 std::unique_ptr<CatalogueController> m_CatalogueController;
99 99
100 100 QThread m_DataSourceControllerThread;
101 101 QThread m_NetworkControllerThread;
102 102 QThread m_VariableControllerThread;
103 103 QThread m_VisualizationControllerThread;
104 104 QThread m_CatalogueControllerThread;
105 105
106 106 std::unique_ptr<DragDropGuiController> m_DragDropGuiController;
107 107 std::unique_ptr<ActionsGuiController> m_ActionsGuiController;
108 108
109 109 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
110 110 SqpApplication::PlotsCursorMode m_PlotCursorMode;
111 111 };
112 112
113 113
114 114 SqpApplication::SqpApplication(int &argc, char **argv)
115 115 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
116 116 {
117 117 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
118 118
119 119 connect(&impl->m_DataSourceControllerThread, &QThread::started,
120 120 impl->m_DataSourceController.get(), &DataSourceController::initialize);
121 121 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
122 122 impl->m_DataSourceController.get(), &DataSourceController::finalize);
123 123
124 124 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
125 125 &NetworkController::initialize);
126 126 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
127 127 &NetworkController::finalize);
128 128
129 129 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
130 130 &VariableController::initialize);
131 131 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
132 132 &VariableController::finalize);
133 133
134 134 connect(&impl->m_VisualizationControllerThread, &QThread::started,
135 135 impl->m_VisualizationController.get(), &VisualizationController::initialize);
136 136 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
137 137 impl->m_VisualizationController.get(), &VisualizationController::finalize);
138 138
139 139 connect(&impl->m_CatalogueControllerThread, &QThread::started,
140 140 impl->m_CatalogueController.get(), &CatalogueController::initialize);
141 141 connect(&impl->m_CatalogueControllerThread, &QThread::finished,
142 142 impl->m_CatalogueController.get(), &CatalogueController::finalize);
143 143
144 144 impl->m_DataSourceControllerThread.start();
145 145 impl->m_NetworkControllerThread.start();
146 146 impl->m_VariableControllerThread.start();
147 147 impl->m_VisualizationControllerThread.start();
148 148 impl->m_CatalogueControllerThread.start();
149 149 }
150 150
151 151 SqpApplication::~SqpApplication()
152 152 {
153 153 }
154 154
155 155 void SqpApplication::initialize()
156 156 {
157 157 }
158 158
159 159 DataSourceController &SqpApplication::dataSourceController() noexcept
160 160 {
161 161 return *impl->m_DataSourceController;
162 162 }
163 163
164 164 NetworkController &SqpApplication::networkController() noexcept
165 165 {
166 166 return *impl->m_NetworkController;
167 167 }
168 168
169 169 TimeController &SqpApplication::timeController() noexcept
170 170 {
171 171 return *impl->m_TimeController;
172 172 }
173 173
174 174 VariableController &SqpApplication::variableController() noexcept
175 175 {
176 176 return *impl->m_VariableController;
177 177 }
178 178
179 179 VisualizationController &SqpApplication::visualizationController() noexcept
180 180 {
181 181 return *impl->m_VisualizationController;
182 182 }
183 183
184 CatalogueController &SqpApplication::catalogueController() noexcept
185 {
186 return *impl->m_CatalogueController;
187 }
188
184 189 DragDropGuiController &SqpApplication::dragDropGuiController() noexcept
185 190 {
186 191 return *impl->m_DragDropGuiController;
187 192 }
188 193
189 194 ActionsGuiController &SqpApplication::actionsGuiController() noexcept
190 195 {
191 196 return *impl->m_ActionsGuiController;
192 197 }
193 198
194 199 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
195 200 {
196 201 return impl->m_PlotInterractionMode;
197 202 }
198 203
199 204 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
200 205 {
201 206 impl->m_PlotInterractionMode = mode;
202 207 }
203 208
204 209 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
205 210 {
206 211 return impl->m_PlotCursorMode;
207 212 }
208 213
209 214 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
210 215 {
211 216 impl->m_PlotCursorMode = mode;
212 217 }
@@ -1,329 +1,354
1 1 #include "Visualization/VisualizationTabWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationTabWidget.h"
4 4
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7
8 8 #include "Visualization/MacScrollBarStyle.h"
9 9
10 10 #include "Variable/VariableController.h"
11 11
12 12 #include "Common/MimeTypesDef.h"
13 13
14 14 #include "DragAndDrop/DragDropGuiController.h"
15 15 #include "SqpApplication.h"
16 16
17 17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18 18
19 19 namespace {
20 20
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
22 /// the tab
23 QString defaultZoneName(const QLayout &layout)
24 {
25 auto count = 0;
26 for (auto i = 0; i < layout.count(); ++i) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
28 count++;
29 }
30 }
31
32 return QObject::tr("Zone %1").arg(count + 1);
33 }
34
35 21 /**
36 22 * Applies a function to all zones of the tab represented by its layout
37 23 * @param layout the layout that contains zones
38 24 * @param fun the function to apply to each zone
39 25 */
40 26 template <typename Fun>
41 27 void processZones(QLayout &layout, Fun fun)
42 28 {
43 29 for (auto i = 0; i < layout.count(); ++i) {
44 30 if (auto item = layout.itemAt(i)) {
45 31 if (auto visualizationZoneWidget
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
32 = qobject_cast<VisualizationZoneWidget *>(item->widget())) {
47 33 fun(*visualizationZoneWidget);
48 34 }
49 35 }
50 36 }
51 37 }
52 38
39 /// Generates a default name for a new zone, according to the number of zones already displayed in
40 /// the tab
41 QString defaultZoneName(QLayout &layout)
42 {
43 QSet<QString> existingNames;
44 processZones(layout,
45 [&existingNames](auto &zoneWidget) { existingNames.insert(zoneWidget.name()); });
46
47 int zoneNum = 1;
48 QString name;
49 do {
50 name = QObject::tr("Zone ").append(QString::number(zoneNum));
51 ++zoneNum;
52 } while (existingNames.contains(name));
53
54 return name;
55 }
56
53 57 } // namespace
54 58
55 59 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
56 60 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
57 61
58 62 QString m_Name;
59 63
60 64 #ifdef Q_OS_MAC
61 65 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 66 #endif
63 67
64 68 void dropGraph(int index, VisualizationTabWidget *tabWidget);
65 69 void dropZone(int index, VisualizationTabWidget *tabWidget);
66 70 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
67 71 VisualizationTabWidget *tabWidget);
68 72 };
69 73
70 74 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
71 75 : QWidget{parent},
72 76 ui{new Ui::VisualizationTabWidget},
73 77 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
74 78 {
75 79 ui->setupUi(this);
76 80
77 81 #ifdef Q_OS_MAC
78 82 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 83 #endif
80 84
81 85 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
82 86 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
83 87 ui->dragDropContainer->layout()->setSpacing(0);
84 88 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
85 89 VisualizationDragDropContainer::DropBehavior::Inserted);
86 90 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
87 91 VisualizationDragDropContainer::DropBehavior::Inserted);
88 92 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
89 93 VisualizationDragDropContainer::DropBehavior::Inserted);
90 94
91 95 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
92 96 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
93 97 ui->dragDropContainer);
94 98 });
95 99
96 100 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
97 101 &VisualizationTabWidget::dropMimeData);
98 102
99 103 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
100 104
101 105 // Widget is deleted when closed
102 106 setAttribute(Qt::WA_DeleteOnClose);
103 107 }
104 108
105 109 VisualizationTabWidget::~VisualizationTabWidget()
106 110 {
107 111 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
108 112 delete ui;
109 113 }
110 114
111 115 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
112 116 {
113 117 ui->dragDropContainer->addDragWidget(zoneWidget);
114 118 }
115 119
116 120 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
117 121 {
118 122 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
119 123 }
120 124
125 QStringList VisualizationTabWidget::availableZoneWidgets() const
126 {
127 QStringList zones;
128 processZones(tabLayout(),
129 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
130
131 return zones;
132 }
133
134 VisualizationZoneWidget *VisualizationTabWidget::getZoneWithName(const QString &zoneName)
135 {
136 VisualizationZoneWidget *result = nullptr;
137 processZones(tabLayout(), [&zoneName, &result](VisualizationZoneWidget &zoneWidget) {
138 if (!result && zoneWidget.name() == zoneName) {
139 result = &zoneWidget;
140 }
141 });
142
143 return result;
144 }
145
121 146 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
122 147 {
123 148 return createZone({variable}, -1);
124 149 }
125 150
126 151 VisualizationZoneWidget *
127 152 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
128 153 {
129 154 auto zoneWidget = createEmptyZone(index);
130 155
131 156 // Creates a new graph into the zone
132 157 zoneWidget->createGraph(variables, index);
133 158
134 159 return zoneWidget;
135 160 }
136 161
137 162 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
138 163 {
139 164 auto zoneWidget
140 165 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
141 166 this->insertZone(index, zoneWidget);
142 167
143 168 return zoneWidget;
144 169 }
145 170
146 171 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
147 172 {
148 173 if (visitor) {
149 174 visitor->visitEnter(this);
150 175
151 176 // Apply visitor to zone children: widgets different from zones are not visited (no action)
152 177 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
153 178 zoneWidget.accept(visitor);
154 179 });
155 180
156 181 visitor->visitLeave(this);
157 182 }
158 183 else {
159 184 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
160 185 }
161 186 }
162 187
163 188 bool VisualizationTabWidget::canDrop(const Variable &variable) const
164 189 {
165 190 // A tab can always accomodate a variable
166 191 Q_UNUSED(variable);
167 192 return true;
168 193 }
169 194
170 195 bool VisualizationTabWidget::contains(const Variable &variable) const
171 196 {
172 197 Q_UNUSED(variable);
173 198 return false;
174 199 }
175 200
176 201 QString VisualizationTabWidget::name() const
177 202 {
178 203 return impl->m_Name;
179 204 }
180 205
181 206 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
182 207 {
183 208 // Closes zones in the tab
184 209 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
185 210
186 211 QWidget::closeEvent(event);
187 212 }
188 213
189 214 QLayout &VisualizationTabWidget::tabLayout() const noexcept
190 215 {
191 216 return *ui->dragDropContainer->layout();
192 217 }
193 218
194 219 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
195 220 {
196 221 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
197 222 impl->dropGraph(index, this);
198 223 }
199 224 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
200 225 impl->dropZone(index, this);
201 226 }
202 227 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
203 228 auto variables = sqpApp->variableController().variablesForMimeData(
204 229 mimeData->data(MIME_TYPE_VARIABLE_LIST));
205 230 impl->dropVariables(variables, index, this);
206 231 }
207 232 else {
208 233 qCWarning(LOG_VisualizationZoneWidget())
209 234 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
210 235 }
211 236 }
212 237
213 238 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
214 239 int index, VisualizationTabWidget *tabWidget)
215 240 {
216 241 auto &helper = sqpApp->dragDropGuiController();
217 242
218 243 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
219 244 if (!graphWidget) {
220 245 qCWarning(LOG_VisualizationZoneWidget())
221 246 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
222 247 "found or invalid.");
223 248 Q_ASSERT(false);
224 249 return;
225 250 }
226 251
227 252 auto parentDragDropContainer
228 253 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
229 254 if (!parentDragDropContainer) {
230 255 qCWarning(LOG_VisualizationZoneWidget())
231 256 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
232 257 "the dropped graph is not found.");
233 258 Q_ASSERT(false);
234 259 return;
235 260 }
236 261
237 262 auto nbGraph = parentDragDropContainer->countDragWidget();
238 263
239 264 const auto &variables = graphWidget->variables();
240 265
241 266 if (!variables.isEmpty()) {
242 267 // Abort the requests for the variables (if any)
243 268 // Commented, because it's not sure if it's needed or not
244 269 // for (const auto& var : variables)
245 270 //{
246 271 // sqpApp->variableController().onAbortProgressRequested(var);
247 272 //}
248 273
249 274 if (nbGraph == 1) {
250 275 // This is the only graph in the previous zone, close the zone
251 276 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
252 277 }
253 278 else {
254 279 // Close the graph
255 280 helper.delayedCloseWidget(graphWidget);
256 281 }
257 282
258 283 auto zoneWidget = tabWidget->createZone(variables, index);
259 284 auto firstGraph = zoneWidget->firstGraph();
260 285 if (firstGraph) {
261 286 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
262 287 }
263 288 else {
264 289 qCWarning(LOG_VisualizationZoneWidget())
265 290 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
266 291 Q_ASSERT(false);
267 292 }
268 293 }
269 294 else {
270 295 // The graph is empty, create an empty zone and move the graph inside
271 296
272 297 auto parentZoneWidget = graphWidget->parentZoneWidget();
273 298
274 299 parentDragDropContainer->layout()->removeWidget(graphWidget);
275 300
276 301 auto zoneWidget = tabWidget->createEmptyZone(index);
277 302 zoneWidget->addGraph(graphWidget);
278 303
279 304 // Close the old zone if it was the only graph inside
280 305 if (nbGraph == 1) {
281 306 helper.delayedCloseWidget(parentZoneWidget);
282 307 }
283 308 }
284 309 }
285 310
286 311 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
287 312 int index, VisualizationTabWidget *tabWidget)
288 313 {
289 314 auto &helper = sqpApp->dragDropGuiController();
290 315
291 316 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
292 317 if (!zoneWidget) {
293 318 qCWarning(LOG_VisualizationZoneWidget())
294 319 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
295 320 "found or invalid.");
296 321 Q_ASSERT(false);
297 322 return;
298 323 }
299 324
300 325 auto parentDragDropContainer
301 326 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
302 327 if (!parentDragDropContainer) {
303 328 qCWarning(LOG_VisualizationZoneWidget())
304 329 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
305 330 "the dropped zone is not found.");
306 331 Q_ASSERT(false);
307 332 return;
308 333 }
309 334
310 335 // Simple move of the zone, no variable operation associated
311 336 parentDragDropContainer->layout()->removeWidget(zoneWidget);
312 337 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
313 338 }
314 339
315 340 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
316 341 const QList<std::shared_ptr<Variable> > &variables, int index,
317 342 VisualizationTabWidget *tabWidget)
318 343 {
319 344 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
320 345 // compatible variable here
321 346 if (variables.count() > 1) {
322 347 qCWarning(LOG_VisualizationZoneWidget())
323 348 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
324 349 "aborted.");
325 350 return;
326 351 }
327 352
328 353 tabWidget->createZone(variables, index);
329 354 }
@@ -1,215 +1,224
1 1 #include "Visualization/VisualizationWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationActionManager.h"
4 4 #include "Visualization/VisualizationGraphWidget.h"
5 5 #include "Visualization/VisualizationSelectionZoneItem.h"
6 6 #include "Visualization/VisualizationSelectionZoneManager.h"
7 7 #include "Visualization/VisualizationTabWidget.h"
8 8 #include "Visualization/VisualizationZoneWidget.h"
9 9 #include "Visualization/operations/FindVariableOperation.h"
10 10 #include "Visualization/operations/GenerateVariableMenuOperation.h"
11 11 #include "Visualization/operations/RemoveVariableOperation.h"
12 12 #include "Visualization/operations/RescaleAxeOperation.h"
13 13 #include "Visualization/qcustomplot.h"
14 14
15 15 #include "ui_VisualizationWidget.h"
16 16
17 17 #include "DragAndDrop/DragDropGuiController.h"
18 18 #include "SqpApplication.h"
19 19
20 20 #include <QToolButton>
21 21
22 22 #include <memory>
23 23
24 24 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
25 25
26 26 struct VisualizationWidget::VisualizationWidgetPrivate {
27 27 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
28 28 VisualizationActionManager m_ActionManager;
29 29
30 30 VisualizationWidgetPrivate()
31 31 : m_ZoneSelectionManager(std::make_unique<VisualizationSelectionZoneManager>())
32 32 {
33 33 }
34 34 };
35 35
36 36 VisualizationWidget::VisualizationWidget(QWidget *parent)
37 37 : QWidget{parent},
38 38 ui{new Ui::VisualizationWidget},
39 39 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
40 40 {
41 41 ui->setupUi(this);
42 42
43 43 auto addTabViewButton = new QToolButton{ui->tabWidget};
44 44 addTabViewButton->setText(tr("Add View"));
45 45 addTabViewButton->setCursor(Qt::ArrowCursor);
46 46 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
47 47
48 48 auto enableMinimumCornerWidgetSize = [this](bool enable) {
49 49
50 50 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
51 51 auto width = enable ? tabViewCornerWidget->width() : 0;
52 52 auto height = enable ? tabViewCornerWidget->height() : 0;
53 53 tabViewCornerWidget->setMinimumHeight(height);
54 54 tabViewCornerWidget->setMinimumWidth(width);
55 55 ui->tabWidget->setMinimumHeight(height);
56 56 ui->tabWidget->setMinimumWidth(width);
57 57 };
58 58
59 59 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
60 60 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
61 61 ui->tabWidget};
62 62 auto index = ui->tabWidget->addTab(widget, widget->name());
63 63 if (ui->tabWidget->count() > 0) {
64 64 enableMinimumCornerWidgetSize(false);
65 65 }
66 66 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
67 67 };
68 68
69 69 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
70 70 if (ui->tabWidget->count() == 1) {
71 71 enableMinimumCornerWidgetSize(true);
72 72 }
73 73
74 74 // Removes widget from tab and closes it
75 75 auto widget = ui->tabWidget->widget(index);
76 76 ui->tabWidget->removeTab(index);
77 77 if (widget) {
78 78 widget->close();
79 79 }
80 80
81 81 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
82 82
83 83 };
84 84
85 85 ui->tabWidget->setTabsClosable(true);
86 86
87 87 connect(addTabViewButton, &QToolButton::clicked, addTabView);
88 88 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
89 89
90 90 sqpApp->dragDropGuiController().addDragDropTabBar(ui->tabWidget->tabBar());
91 91
92 92 // Actions
93 93 impl->m_ActionManager.installSelectionZoneActions();
94 94
95 95 auto removeZoneAction = new QAction("Remove selected zone(s)");
96 96 removeZoneAction->setShortcut(QKeySequence::Delete);
97 97 connect(removeZoneAction, &QAction::triggered, [this]() {
98 98 auto selection = impl->m_ZoneSelectionManager->selectedItems();
99 99 for (auto selectionZone : selection) {
100 100 if (auto graph = selectionZone->parentGraphWidget()) {
101 101 graph->removeSelectionZone(selectionZone);
102 102 }
103 103 }
104 104 });
105 105 addAction(removeZoneAction);
106 106
107 107 // Adds default tab
108 108 addTabView();
109 109 }
110 110
111 111 VisualizationWidget::~VisualizationWidget()
112 112 {
113 113 sqpApp->dragDropGuiController().removeDragDropTabBar(ui->tabWidget->tabBar());
114 114 delete ui;
115 115 }
116 116
117 117 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
118 118 {
119 119 return *impl->m_ZoneSelectionManager.get();
120 120 }
121 121
122 VisualizationTabWidget *VisualizationWidget::currentTabWidget() const
123 {
124 if (auto tab = qobject_cast<VisualizationTabWidget *>(ui->tabWidget->currentWidget())) {
125 return tab;
126 }
127
128 return nullptr;
129 }
130
122 131 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
123 132 {
124 133 if (visitor) {
125 134 visitor->visitEnter(this);
126 135
127 136 // Apply visitor for tab children
128 137 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
129 138 // Widgets different from tabs are not visited (no action)
130 139 if (auto visualizationTabWidget
131 140 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
132 141 visualizationTabWidget->accept(visitor);
133 142 }
134 143 }
135 144
136 145 visitor->visitLeave(this);
137 146 }
138 147 else {
139 148 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
140 149 }
141 150 }
142 151
143 152 bool VisualizationWidget::canDrop(const Variable &variable) const
144 153 {
145 154 // The main widget can never accomodate a variable
146 155 Q_UNUSED(variable);
147 156 return false;
148 157 }
149 158
150 159 bool VisualizationWidget::contains(const Variable &variable) const
151 160 {
152 161 Q_UNUSED(variable);
153 162 return false;
154 163 }
155 164
156 165 QString VisualizationWidget::name() const
157 166 {
158 167 return QStringLiteral("MainView");
159 168 }
160 169
161 170 void VisualizationWidget::attachVariableMenu(
162 171 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
163 172 {
164 173 // Menu is generated only if there is a single variable
165 174 if (variables.size() == 1) {
166 175 if (auto variable = variables.first()) {
167 176 // Gets the containers of the variable
168 177 FindVariableOperation findVariableOperation{variable};
169 178 accept(&findVariableOperation);
170 179 auto variableContainers = findVariableOperation.result();
171 180
172 181 // Generates the actions that make it possible to visualize the variable
173 182 GenerateVariableMenuOperation generateVariableMenuOperation{
174 183 menu, variable, std::move(variableContainers)};
175 184 accept(&generateVariableMenuOperation);
176 185 }
177 186 else {
178 187 qCCritical(LOG_VisualizationWidget()) << tr(
179 188 "Can't generate the menu relative to the visualization: the variable is null");
180 189 }
181 190 }
182 191 else {
183 192 qCDebug(LOG_VisualizationWidget())
184 193 << tr("No generation of the menu related to the visualization: several variables are "
185 194 "selected");
186 195 }
187 196 }
188 197
189 198 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
190 199 {
191 200 // Calls the operation of removing all references to the variable in the visualization
192 201 auto removeVariableOperation = RemoveVariableOperation{variable};
193 202 accept(&removeVariableOperation);
194 203 }
195 204
196 205 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
197 206 const SqpRange &range) noexcept
198 207 {
199 208 // Calls the operation of rescaling all graph that contrains variable in the visualization
200 209 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
201 210 accept(&rescaleVariableOperation);
202 211 }
203 212
204 213 void VisualizationWidget::closeEvent(QCloseEvent *event)
205 214 {
206 215 // Closes tabs in the widget
207 216 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
208 217 if (auto visualizationTabWidget
209 218 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
210 219 visualizationTabWidget->close();
211 220 }
212 221 }
213 222
214 223 QWidget::closeEvent(event);
215 224 }
@@ -1,587 +1,601
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 "Visualization/VisualizationWidget.h"
7 7 #include "ui_VisualizationZoneWidget.h"
8 8
9 9 #include "Common/MimeTypesDef.h"
10 10 #include "Common/VisualizationDef.h"
11 11
12 12 #include <Data/SqpRange.h>
13 13 #include <Time/TimeController.h>
14 14 #include <Variable/Variable.h>
15 15 #include <Variable/VariableController.h>
16 16
17 17 #include <Visualization/operations/FindVariableOperation.h>
18 18
19 19 #include <DragAndDrop/DragDropGuiController.h>
20 20 #include <QUuid>
21 21 #include <SqpApplication.h>
22 22 #include <cmath>
23 23
24 24 #include <QLayout>
25 25
26 26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27 27
28 28 namespace {
29 29
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
34 {
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
39 }
40 }
41
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
44
45 30 /**
46 31 * Applies a function to all graphs of the zone represented by its layout
47 32 * @param layout the layout that contains graphs
48 33 * @param fun the function to apply to each graph
49 34 */
50 35 template <typename Fun>
51 36 void processGraphs(QLayout &layout, Fun fun)
52 37 {
53 38 for (auto i = 0; i < layout.count(); ++i) {
54 39 if (auto item = layout.itemAt(i)) {
55 40 if (auto visualizationGraphWidget
56 41 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
57 42 fun(*visualizationGraphWidget);
58 43 }
59 44 }
60 45 }
61 46 }
62 47
48 /// Generates a default name for a new graph, according to the number of graphs already displayed in
49 /// the zone
50 QString defaultGraphName(QLayout &layout)
51 {
52 QSet<QString> existingNames;
53 processGraphs(
54 layout, [&existingNames](auto &graphWidget) { existingNames.insert(graphWidget.name()); });
55
56 int zoneNum = 1;
57 QString name;
58 do {
59 name = QObject::tr("Graph ").append(QString::number(zoneNum));
60 ++zoneNum;
61 } while (existingNames.contains(name));
62
63 return name;
64 }
65
63 66 } // namespace
64 67
65 68 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66 69
67 70 explicit VisualizationZoneWidgetPrivate()
68 71 : m_SynchronisationGroupId{QUuid::createUuid()},
69 72 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 73 {
71 74 }
72 75 QUuid m_SynchronisationGroupId;
73 76 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74 77
75 78 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
76 79 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
77 80 VisualizationZoneWidget *zoneWidget);
78 81 };
79 82
80 83 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
81 84 : VisualizationDragWidget{parent},
82 85 ui{new Ui::VisualizationZoneWidget},
83 86 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
84 87 {
85 88 ui->setupUi(this);
86 89
87 90 ui->zoneNameLabel->setText(name);
88 91
89 92 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
90 93 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
91 94 VisualizationDragDropContainer::DropBehavior::Inserted);
92 95 ui->dragDropContainer->setMimeType(
93 96 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
94 97 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
95 98 VisualizationDragDropContainer::DropBehavior::Merged);
96 99 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
97 100 VisualizationDragDropContainer::DropBehavior::Forbidden);
98 101 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
99 102 VisualizationDragDropContainer::DropBehavior::Forbidden);
100 103 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
101 104 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
102 105 ui->dragDropContainer);
103 106 });
104 107
105 108 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
106 109 if (!mimeData) {
107 110 return false;
108 111 }
109 112
110 113 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
111 114 auto variables = sqpApp->variableController().variablesForMimeData(
112 115 mimeData->data(MIME_TYPE_VARIABLE_LIST));
113 116
114 117 if (variables.count() != 1) {
115 118 return false;
116 119 }
117 120 auto variable = variables.first();
118 121
119 122 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
120 123 return graphWidget->canDrop(*variable);
121 124 }
122 125 }
123 126
124 127 return true;
125 128 };
126 129 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
127 130
128 131 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
129 132 &VisualizationZoneWidget::dropMimeData);
130 133 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
131 134 &VisualizationZoneWidget::dropMimeDataOnGraph);
132 135
133 136 // 'Close' options : widget is deleted when closed
134 137 setAttribute(Qt::WA_DeleteOnClose);
135 138 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
136 139 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
137 140
138 141 // Synchronisation id
139 142 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
140 143 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
141 144 }
142 145
143 146 VisualizationZoneWidget::~VisualizationZoneWidget()
144 147 {
145 148 delete ui;
146 149 }
147 150
151 void VisualizationZoneWidget::setZoneRange(const SqpRange &range)
152 {
153 if (auto graph = firstGraph()) {
154 graph->setGraphRange(range);
155 }
156 else {
157 qCWarning(LOG_VisualizationZoneWidget())
158 << tr("setZoneRange:Cannot set the range of an empty zone.");
159 }
160 }
161
148 162 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
149 163 {
150 164 // Synchronize new graph with others in the zone
151 165 impl->m_Synchronizer->addGraph(*graphWidget);
152 166
153 167 ui->dragDropContainer->addDragWidget(graphWidget);
154 168 }
155 169
156 170 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
157 171 {
158 172 // Synchronize new graph with others in the zone
159 173 impl->m_Synchronizer->addGraph(*graphWidget);
160 174
161 175 ui->dragDropContainer->insertDragWidget(index, graphWidget);
162 176 }
163 177
164 178 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
165 179 {
166 180 return createGraph(variable, -1);
167 181 }
168 182
169 183 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
170 184 int index)
171 185 {
172 186 auto graphWidget
173 187 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
174 188
175 189
176 190 // Set graph properties
177 191 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
178 192 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
179 193
180 194
181 195 // Lambda to synchronize zone widget
182 196 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
183 197 const SqpRange &oldGraphRange) {
184 198
185 199 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
186 200 auto frameLayout = ui->dragDropContainer->layout();
187 201 for (auto i = 0; i < frameLayout->count(); ++i) {
188 202 auto graphChild
189 203 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
190 204 if (graphChild && (graphChild != graphWidget)) {
191 205
192 206 auto graphChildRange = graphChild->graphRange();
193 207 switch (zoomType) {
194 208 case AcquisitionZoomType::ZoomIn: {
195 209 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
196 210 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
197 211 graphChildRange.m_TStart += deltaLeft;
198 212 graphChildRange.m_TEnd -= deltaRight;
199 213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
200 214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
201 215 << deltaLeft;
202 216 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
203 217 << deltaRight;
204 218 qCDebug(LOG_VisualizationZoneWidget())
205 219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
206 220
207 221 break;
208 222 }
209 223
210 224 case AcquisitionZoomType::ZoomOut: {
211 225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
212 226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
213 227 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
214 228 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
215 229 << deltaLeft;
216 230 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
217 231 << deltaRight;
218 232 qCDebug(LOG_VisualizationZoneWidget())
219 233 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220 234 graphChildRange.m_TStart -= deltaLeft;
221 235 graphChildRange.m_TEnd += deltaRight;
222 236 break;
223 237 }
224 238 case AcquisitionZoomType::PanRight: {
225 239 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
226 240 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
227 241 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
228 242 graphChildRange.m_TStart += deltaLeft;
229 243 graphChildRange.m_TEnd += deltaRight;
230 244 qCDebug(LOG_VisualizationZoneWidget())
231 245 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
232 246 break;
233 247 }
234 248 case AcquisitionZoomType::PanLeft: {
235 249 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
236 250 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
237 251 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
238 252 graphChildRange.m_TStart -= deltaLeft;
239 253 graphChildRange.m_TEnd -= deltaRight;
240 254 break;
241 255 }
242 256 case AcquisitionZoomType::Unknown: {
243 257 qCDebug(LOG_VisualizationZoneWidget())
244 258 << tr("Impossible to synchronize: zoom type unknown");
245 259 break;
246 260 }
247 261 default:
248 262 qCCritical(LOG_VisualizationZoneWidget())
249 263 << tr("Impossible to synchronize: zoom type not take into account");
250 264 // No action
251 265 break;
252 266 }
253 267 graphChild->enableAcquisition(false);
254 268 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
255 269 << graphChild->graphRange();
256 270 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
257 271 << graphChildRange;
258 272 qCDebug(LOG_VisualizationZoneWidget())
259 273 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
260 274 graphChild->setGraphRange(graphChildRange);
261 275 graphChild->enableAcquisition(true);
262 276 }
263 277 }
264 278 };
265 279
266 280 // connection for synchronization
267 281 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
268 282 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
269 283 &VisualizationZoneWidget::onVariableAdded);
270 284 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
271 285 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
272 286
273 287 auto range = SqpRange{};
274 288 if (auto firstGraph = this->firstGraph()) {
275 289 // Case of a new graph in a existant zone
276 290 range = firstGraph->graphRange();
277 291 }
278 292 else {
279 293 // Case of a new graph as the first of the zone
280 294 range = variable->range();
281 295 }
282 296
283 297 this->insertGraph(index, graphWidget);
284 298
285 299 graphWidget->addVariable(variable, range);
286 300 graphWidget->setYRange(variable);
287 301
288 302 return graphWidget;
289 303 }
290 304
291 305 VisualizationGraphWidget *
292 306 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
293 307 {
294 308 if (variables.isEmpty()) {
295 309 return nullptr;
296 310 }
297 311
298 312 auto graphWidget = createGraph(variables.first(), index);
299 313 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
300 314 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
301 315 }
302 316
303 317 return graphWidget;
304 318 }
305 319
306 320 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
307 321 {
308 322 VisualizationGraphWidget *firstGraph = nullptr;
309 323 auto layout = ui->dragDropContainer->layout();
310 324 if (layout->count() > 0) {
311 325 if (auto visualizationGraphWidget
312 326 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
313 327 firstGraph = visualizationGraphWidget;
314 328 }
315 329 }
316 330
317 331 return firstGraph;
318 332 }
319 333
320 334 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
321 335 {
322 336 if (visitor) {
323 337 visitor->visitEnter(this);
324 338
325 339 // Apply visitor to graph children: widgets different from graphs are not visited (no
326 340 // action)
327 341 processGraphs(
328 342 *ui->dragDropContainer->layout(),
329 343 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
330 344
331 345 visitor->visitLeave(this);
332 346 }
333 347 else {
334 348 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
335 349 }
336 350 }
337 351
338 352 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
339 353 {
340 354 // A tab can always accomodate a variable
341 355 Q_UNUSED(variable);
342 356 return true;
343 357 }
344 358
345 359 bool VisualizationZoneWidget::contains(const Variable &variable) const
346 360 {
347 361 Q_UNUSED(variable);
348 362 return false;
349 363 }
350 364
351 365 QString VisualizationZoneWidget::name() const
352 366 {
353 367 return ui->zoneNameLabel->text();
354 368 }
355 369
356 370 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
357 371 {
358 372 Q_UNUSED(position);
359 373
360 374 auto mimeData = new QMimeData;
361 375 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
362 376
363 377 if (auto firstGraph = this->firstGraph()) {
364 378 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
365 379 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
366 380 }
367 381
368 382 return mimeData;
369 383 }
370 384
371 385 bool VisualizationZoneWidget::isDragAllowed() const
372 386 {
373 387 return true;
374 388 }
375 389
376 390 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
377 391 const QPointF &plotPosition,
378 392 VisualizationGraphWidget *graphWidget)
379 393 {
380 394 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
381 395 VisualizationGraphWidget &processedGraph) {
382 396
383 397 switch (sqpApp->plotsCursorMode()) {
384 398 case SqpApplication::PlotsCursorMode::Vertical:
385 399 processedGraph.removeHorizontalCursor();
386 400 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
387 401 break;
388 402 case SqpApplication::PlotsCursorMode::Temporal:
389 403 processedGraph.addVerticalCursor(plotPosition.x());
390 404 processedGraph.removeHorizontalCursor();
391 405 break;
392 406 case SqpApplication::PlotsCursorMode::Horizontal:
393 407 processedGraph.removeVerticalCursor();
394 408 if (&processedGraph == graphWidget) {
395 409 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
396 410 }
397 411 else {
398 412 processedGraph.removeHorizontalCursor();
399 413 }
400 414 break;
401 415 case SqpApplication::PlotsCursorMode::Cross:
402 416 if (&processedGraph == graphWidget) {
403 417 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
404 418 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
405 419 }
406 420 else {
407 421 processedGraph.removeHorizontalCursor();
408 422 processedGraph.removeVerticalCursor();
409 423 }
410 424 break;
411 425 case SqpApplication::PlotsCursorMode::NoCursor:
412 426 processedGraph.removeHorizontalCursor();
413 427 processedGraph.removeVerticalCursor();
414 428 break;
415 429 }
416 430
417 431
418 432 });
419 433 }
420 434
421 435 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
422 436 {
423 437 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
424 438 processedGraph.removeHorizontalCursor();
425 439 processedGraph.removeVerticalCursor();
426 440 });
427 441 }
428 442
429 443 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
430 444 {
431 445 // Closes graphs in the zone
432 446 processGraphs(*ui->dragDropContainer->layout(),
433 447 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
434 448
435 449 // Delete synchronization group from variable controller
436 450 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
437 451 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
438 452
439 453 QWidget::closeEvent(event);
440 454 }
441 455
442 456 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
443 457 {
444 458 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
445 459 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
446 460 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
447 461 }
448 462
449 463 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
450 464 {
451 465 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
452 466 Q_ARG(std::shared_ptr<Variable>, variable),
453 467 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
454 468 }
455 469
456 470 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
457 471 {
458 472 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
459 473 impl->dropGraph(index, this);
460 474 }
461 475 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
462 476 auto variables = sqpApp->variableController().variablesForMimeData(
463 477 mimeData->data(MIME_TYPE_VARIABLE_LIST));
464 478 impl->dropVariables(variables, index, this);
465 479 }
466 480 else {
467 481 qCWarning(LOG_VisualizationZoneWidget())
468 482 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
469 483 }
470 484 }
471 485
472 486 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
473 487 const QMimeData *mimeData)
474 488 {
475 489 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
476 490 if (!graphWidget) {
477 491 qCWarning(LOG_VisualizationZoneWidget())
478 492 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
479 493 "drop aborted");
480 494 Q_ASSERT(false);
481 495 return;
482 496 }
483 497
484 498 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
485 499 auto variables = sqpApp->variableController().variablesForMimeData(
486 500 mimeData->data(MIME_TYPE_VARIABLE_LIST));
487 501 for (const auto &var : variables) {
488 502 graphWidget->addVariable(var, graphWidget->graphRange());
489 503 }
490 504 }
491 505 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
492 506 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
493 507 graphWidget->setGraphRange(range);
494 508 }
495 509 else {
496 510 qCWarning(LOG_VisualizationZoneWidget())
497 511 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
498 512 }
499 513 }
500 514
501 515 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
502 516 int index, VisualizationZoneWidget *zoneWidget)
503 517 {
504 518 auto &helper = sqpApp->dragDropGuiController();
505 519
506 520 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
507 521 if (!graphWidget) {
508 522 qCWarning(LOG_VisualizationZoneWidget())
509 523 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
510 524 "found or invalid.");
511 525 Q_ASSERT(false);
512 526 return;
513 527 }
514 528
515 529 auto parentDragDropContainer
516 530 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
517 531 if (!parentDragDropContainer) {
518 532 qCWarning(LOG_VisualizationZoneWidget())
519 533 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
520 534 "the dropped graph is not found.");
521 535 Q_ASSERT(false);
522 536 return;
523 537 }
524 538
525 539 const auto &variables = graphWidget->variables();
526 540
527 541 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
528 542 // The drop didn't occur in the same zone
529 543
530 544 // Abort the requests for the variables (if any)
531 545 // Commented, because it's not sure if it's needed or not
532 546 // for (const auto& var : variables)
533 547 //{
534 548 // sqpApp->variableController().onAbortProgressRequested(var);
535 549 //}
536 550
537 551 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
538 552 auto nbGraph = parentDragDropContainer->countDragWidget();
539 553 if (nbGraph == 1) {
540 554 // This is the only graph in the previous zone, close the zone
541 555 helper.delayedCloseWidget(previousParentZoneWidget);
542 556 }
543 557 else {
544 558 // Close the graph
545 559 helper.delayedCloseWidget(graphWidget);
546 560 }
547 561
548 562 // Creates the new graph in the zone
549 563 auto newGraphWidget = zoneWidget->createGraph(variables, index);
550 564 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
551 565 }
552 566 else {
553 567 // The drop occurred in the same zone or the graph is empty
554 568 // Simple move of the graph, no variable operation associated
555 569 parentDragDropContainer->layout()->removeWidget(graphWidget);
556 570
557 571 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
558 572 // The graph is empty and dropped in a different zone.
559 573 // Take the range of the first graph in the zone (if existing).
560 574 auto layout = zoneWidget->ui->dragDropContainer->layout();
561 575 if (layout->count() > 0) {
562 576 if (auto visualizationGraphWidget
563 577 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
564 578 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
565 579 }
566 580 }
567 581 }
568 582
569 583 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
570 584 }
571 585 }
572 586
573 587 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
574 588 const QList<std::shared_ptr<Variable> > &variables, int index,
575 589 VisualizationZoneWidget *zoneWidget)
576 590 {
577 591 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
578 592 // compatible variable here
579 593 if (variables.count() > 1) {
580 594 qCWarning(LOG_VisualizationZoneWidget())
581 595 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
582 596 "aborted.");
583 597 return;
584 598 }
585 599
586 600 zoneWidget->createGraph(variables, index);
587 601 }
@@ -1,139 +1,142
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>CatalogueEventsWidget</class>
4 4 <widget class="QWidget" name="CatalogueEventsWidget">
5 5 <property name="geometry">
6 6 <rect>
7 7 <x>0</x>
8 8 <y>0</y>
9 9 <width>566</width>
10 10 <height>258</height>
11 11 </rect>
12 12 </property>
13 13 <property name="windowTitle">
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout">
17 17 <property name="leftMargin">
18 18 <number>0</number>
19 19 </property>
20 20 <property name="topMargin">
21 21 <number>0</number>
22 22 </property>
23 23 <property name="rightMargin">
24 24 <number>0</number>
25 25 </property>
26 26 <property name="bottomMargin">
27 27 <number>0</number>
28 28 </property>
29 29 <item>
30 30 <layout class="QHBoxLayout" name="horizontalLayout">
31 31 <item>
32 32 <widget class="QToolButton" name="btnAdd">
33 33 <property name="text">
34 34 <string>+</string>
35 35 </property>
36 36 <property name="icon">
37 <iconset>
37 <iconset resource="../../resources/sqpguiresources.qrc">
38 38 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
39 39 </property>
40 40 <property name="autoRaise">
41 41 <bool>true</bool>
42 42 </property>
43 43 </widget>
44 44 </item>
45 45 <item>
46 46 <widget class="QToolButton" name="btnRemove">
47 47 <property name="text">
48 48 <string> - </string>
49 49 </property>
50 50 <property name="icon">
51 <iconset>
51 <iconset resource="../../resources/sqpguiresources.qrc">
52 52 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
53 53 </property>
54 54 <property name="autoRaise">
55 55 <bool>true</bool>
56 56 </property>
57 57 </widget>
58 58 </item>
59 59 <item>
60 60 <widget class="Line" name="line">
61 61 <property name="orientation">
62 62 <enum>Qt::Vertical</enum>
63 63 </property>
64 64 </widget>
65 65 </item>
66 66 <item>
67 67 <widget class="QToolButton" name="btnTime">
68 68 <property name="text">
69 69 <string>T</string>
70 70 </property>
71 71 <property name="icon">
72 <iconset>
72 <iconset resource="../../resources/sqpguiresources.qrc">
73 73 <normaloff>:/icones/time.png</normaloff>:/icones/time.png</iconset>
74 74 </property>
75 75 <property name="checkable">
76 76 <bool>true</bool>
77 77 </property>
78 78 <property name="autoRaise">
79 79 <bool>true</bool>
80 80 </property>
81 81 </widget>
82 82 </item>
83 83 <item>
84 84 <widget class="QToolButton" name="btnChart">
85 85 <property name="text">
86 86 <string>G</string>
87 87 </property>
88 88 <property name="icon">
89 <iconset>
89 <iconset resource="../../resources/sqpguiresources.qrc">
90 90 <normaloff>:/icones/chart.png</normaloff>:/icones/chart.png</iconset>
91 91 </property>
92 92 <property name="checkable">
93 93 <bool>true</bool>
94 94 </property>
95 95 <property name="autoRaise">
96 96 <bool>true</bool>
97 97 </property>
98 98 </widget>
99 99 </item>
100 100 <item>
101 101 <widget class="Line" name="line_2">
102 102 <property name="orientation">
103 103 <enum>Qt::Vertical</enum>
104 104 </property>
105 105 </widget>
106 106 </item>
107 107 <item>
108 108 <widget class="QLineEdit" name="lineEdit">
109 109 <property name="enabled">
110 110 <bool>false</bool>
111 111 </property>
112 112 </widget>
113 113 </item>
114 114 </layout>
115 115 </item>
116 116 <item>
117 <widget class="QTableWidget" name="tableWidget">
118 <property name="alternatingRowColors">
117 <widget class="QTreeView" name="treeView">
118 <property name="dragEnabled">
119 119 <bool>true</bool>
120 120 </property>
121 <property name="dragDropMode">
122 <enum>QAbstractItemView::DragDrop</enum>
123 </property>
124 <property name="selectionMode">
125 <enum>QAbstractItemView::ExtendedSelection</enum>
126 </property>
121 127 <property name="selectionBehavior">
122 128 <enum>QAbstractItemView::SelectRows</enum>
123 129 </property>
124 <attribute name="horizontalHeaderHighlightSections">
130 <attribute name="headerStretchLastSection">
125 131 <bool>false</bool>
126 132 </attribute>
127 <attribute name="verticalHeaderVisible">
128 <bool>false</bool>
129 </attribute>
130 <attribute name="verticalHeaderDefaultSectionSize">
131 <number>25</number>
132 </attribute>
133 133 </widget>
134 134 </item>
135 135 </layout>
136 136 </widget>
137 <resources/>
137 <resources>
138 <include location="../../resources/sqpguiresources.qrc"/>
139 <include location="../../resources/sqpguiresources.qrc"/>
140 </resources>
138 141 <connections/>
139 142 </ui>
@@ -1,214 +1,219
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>CatalogueInspectorWidget</class>
4 4 <widget class="QWidget" name="CatalogueInspectorWidget">
5 5 <property name="geometry">
6 6 <rect>
7 7 <x>0</x>
8 8 <y>0</y>
9 9 <width>400</width>
10 10 <height>300</height>
11 11 </rect>
12 12 </property>
13 13 <property name="windowTitle">
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 17 <property name="leftMargin">
18 18 <number>0</number>
19 19 </property>
20 20 <property name="topMargin">
21 21 <number>0</number>
22 22 </property>
23 23 <property name="rightMargin">
24 24 <number>0</number>
25 25 </property>
26 26 <property name="bottomMargin">
27 27 <number>0</number>
28 28 </property>
29 29 <item>
30 30 <widget class="QFrame" name="frame">
31 31 <property name="frameShape">
32 32 <enum>QFrame::Box</enum>
33 33 </property>
34 34 <property name="frameShadow">
35 35 <enum>QFrame::Sunken</enum>
36 36 </property>
37 37 <property name="lineWidth">
38 38 <number>1</number>
39 39 </property>
40 40 <layout class="QVBoxLayout" name="verticalLayout">
41 41 <property name="leftMargin">
42 42 <number>0</number>
43 43 </property>
44 44 <property name="topMargin">
45 45 <number>0</number>
46 46 </property>
47 47 <property name="rightMargin">
48 48 <number>0</number>
49 49 </property>
50 50 <property name="bottomMargin">
51 51 <number>0</number>
52 52 </property>
53 53 <item>
54 54 <widget class="QStackedWidget" name="stackedWidget">
55 55 <property name="currentIndex">
56 <number>1</number>
56 <number>2</number>
57 57 </property>
58 58 <widget class="QWidget" name="emptyPage"/>
59 59 <widget class="QWidget" name="catalogueInspectorPage">
60 60 <layout class="QGridLayout" name="gridLayout_2">
61 61 <item row="1" column="0">
62 62 <widget class="QLabel" name="label_7">
63 63 <property name="text">
64 64 <string>Name</string>
65 65 </property>
66 66 </widget>
67 67 </item>
68 68 <item row="1" column="1">
69 69 <widget class="QLineEdit" name="leCatalogueName"/>
70 70 </item>
71 71 <item row="2" column="0">
72 72 <widget class="QLabel" name="label_8">
73 73 <property name="text">
74 74 <string>Author</string>
75 75 </property>
76 76 </widget>
77 77 </item>
78 78 <item row="2" column="1">
79 79 <widget class="QLineEdit" name="leCatalogueAuthor">
80 80 <property name="text">
81 81 <string/>
82 82 </property>
83 83 </widget>
84 84 </item>
85 85 <item row="3" column="1">
86 86 <spacer name="verticalSpacer_2">
87 87 <property name="orientation">
88 88 <enum>Qt::Vertical</enum>
89 89 </property>
90 90 <property name="sizeHint" stdset="0">
91 91 <size>
92 92 <width>20</width>
93 93 <height>40</height>
94 94 </size>
95 95 </property>
96 96 </spacer>
97 97 </item>
98 98 <item row="0" column="0" colspan="2">
99 99 <widget class="QLabel" name="label_9">
100 100 <property name="font">
101 101 <font>
102 102 <pointsize>10</pointsize>
103 103 <weight>75</weight>
104 104 <bold>true</bold>
105 105 </font>
106 106 </property>
107 107 <property name="text">
108 108 <string>Catalogue Properties</string>
109 109 </property>
110 110 </widget>
111 111 </item>
112 112 </layout>
113 113 </widget>
114 114 <widget class="QWidget" name="eventInspectorPage">
115 115 <layout class="QGridLayout" name="gridLayout">
116 <item row="5" column="1">
117 <widget class="QDateTimeEdit" name="dateTimeEventTEnd"/>
118 </item>
119 116 <item row="4" column="0">
120 <widget class="QLabel" name="label_4">
121 <property name="text">
122 <string>TStart</string>
123 </property>
124 </widget>
125 </item>
126 <item row="6" column="0">
127 <widget class="QLabel" name="label_6">
128 <property name="text">
129 <string>Tags</string>
130 </property>
131 </widget>
132 </item>
133 <item row="3" column="0">
134 117 <widget class="QLabel" name="label_3">
135 118 <property name="text">
136 119 <string>Product</string>
137 120 </property>
138 121 </widget>
139 122 </item>
140 <item row="3" column="1">
141 <widget class="QLineEdit" name="leEventProduct"/>
142 </item>
143 123 <item row="5" column="0">
144 <widget class="QLabel" name="label_5">
145 <property name="text">
146 <string>Tend</string>
147 </property>
148 </widget>
149 </item>
150 <item row="4" column="1">
151 <widget class="QDateTimeEdit" name="dateTimeEventTStart"/>
152 </item>
153 <item row="2" column="0">
154 <widget class="QLabel" name="label_2">
124 <widget class="QLabel" name="label_4">
155 125 <property name="text">
156 <string>Mission</string>
126 <string>TStart</string>
157 127 </property>
158 128 </widget>
159 129 </item>
160 <item row="1" column="1">
161 <widget class="QLineEdit" name="leEventName"/>
162 </item>
163 130 <item row="1" column="0">
164 131 <widget class="QLabel" name="label">
165 132 <property name="text">
166 133 <string>Name</string>
167 134 </property>
168 135 </widget>
169 136 </item>
170 <item row="2" column="1">
171 <widget class="QLineEdit" name="leEventMission"/>
172 </item>
173 <item row="6" column="1">
174 <widget class="QLineEdit" name="leEventTags"/>
137 <item row="0" column="0" colspan="2">
138 <widget class="QLabel" name="label_10">
139 <property name="font">
140 <font>
141 <pointsize>10</pointsize>
142 <weight>75</weight>
143 <bold>true</bold>
144 </font>
145 </property>
146 <property name="text">
147 <string>Event Properties</string>
148 </property>
149 </widget>
175 150 </item>
176 <item row="7" column="1">
151 <item row="8" column="1">
177 152 <spacer name="verticalSpacer">
178 153 <property name="orientation">
179 154 <enum>Qt::Vertical</enum>
180 155 </property>
181 156 <property name="sizeHint" stdset="0">
182 157 <size>
183 158 <width>20</width>
184 159 <height>40</height>
185 160 </size>
186 161 </property>
187 162 </spacer>
188 163 </item>
189 <item row="0" column="0" colspan="2">
190 <widget class="QLabel" name="label_10">
191 <property name="font">
192 <font>
193 <pointsize>10</pointsize>
194 <weight>75</weight>
195 <bold>true</bold>
196 </font>
164 <item row="1" column="1">
165 <widget class="QLineEdit" name="leEventName"/>
166 </item>
167 <item row="5" column="1">
168 <widget class="QDateTimeEdit" name="dateTimeEventTStart">
169 <property name="timeSpec">
170 <enum>Qt::UTC</enum>
171 </property>
172 </widget>
173 </item>
174 <item row="4" column="1">
175 <widget class="QLineEdit" name="leEventProduct"/>
176 </item>
177 <item row="6" column="0">
178 <widget class="QLabel" name="label_5">
179 <property name="text">
180 <string>Tend</string>
197 181 </property>
182 </widget>
183 </item>
184 <item row="6" column="1">
185 <widget class="QDateTimeEdit" name="dateTimeEventTEnd">
186 <property name="timeSpec">
187 <enum>Qt::UTC</enum>
188 </property>
189 </widget>
190 </item>
191 <item row="2" column="1">
192 <widget class="QLineEdit" name="leEventTags"/>
193 </item>
194 <item row="2" column="0">
195 <widget class="QLabel" name="label_6">
198 196 <property name="text">
199 <string>Event Properties</string>
197 <string>Tags</string>
198 </property>
199 </widget>
200 </item>
201 <item row="3" column="0" colspan="2">
202 <widget class="Line" name="line">
203 <property name="orientation">
204 <enum>Qt::Horizontal</enum>
200 205 </property>
201 206 </widget>
202 207 </item>
203 208 </layout>
204 209 </widget>
205 210 </widget>
206 211 </item>
207 212 </layout>
208 213 </widget>
209 214 </item>
210 215 </layout>
211 216 </widget>
212 217 <resources/>
213 218 <connections/>
214 219 </ui>
@@ -1,90 +1,96
1 1 <?xml version="1.0" encoding="UTF-8"?>
2 2 <ui version="4.0">
3 3 <class>CatalogueSideBarWidget</class>
4 4 <widget class="QWidget" name="CatalogueSideBarWidget">
5 5 <property name="geometry">
6 6 <rect>
7 7 <x>0</x>
8 8 <y>0</y>
9 9 <width>330</width>
10 10 <height>523</height>
11 11 </rect>
12 12 </property>
13 13 <property name="windowTitle">
14 14 <string>Form</string>
15 15 </property>
16 16 <layout class="QVBoxLayout" name="verticalLayout">
17 17 <property name="leftMargin">
18 18 <number>0</number>
19 19 </property>
20 20 <property name="topMargin">
21 21 <number>0</number>
22 22 </property>
23 23 <property name="rightMargin">
24 24 <number>0</number>
25 25 </property>
26 26 <property name="bottomMargin">
27 27 <number>0</number>
28 28 </property>
29 29 <item>
30 30 <layout class="QHBoxLayout" name="horizontalLayout">
31 31 <item>
32 32 <widget class="QToolButton" name="btnAdd">
33 33 <property name="text">
34 34 <string>+</string>
35 35 </property>
36 36 <property name="icon">
37 <iconset>
37 <iconset resource="../../resources/sqpguiresources.qrc">
38 38 <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset>
39 39 </property>
40 40 <property name="autoRaise">
41 41 <bool>true</bool>
42 42 </property>
43 43 </widget>
44 44 </item>
45 45 <item>
46 46 <widget class="QToolButton" name="btnRemove">
47 47 <property name="text">
48 48 <string> - </string>
49 49 </property>
50 50 <property name="icon">
51 <iconset>
51 <iconset resource="../../resources/sqpguiresources.qrc">
52 52 <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset>
53 53 </property>
54 54 <property name="autoRaise">
55 55 <bool>true</bool>
56 56 </property>
57 57 </widget>
58 58 </item>
59 59 <item>
60 60 <spacer name="horizontalSpacer">
61 61 <property name="orientation">
62 62 <enum>Qt::Horizontal</enum>
63 63 </property>
64 64 <property name="sizeHint" stdset="0">
65 65 <size>
66 66 <width>40</width>
67 67 <height>20</height>
68 68 </size>
69 69 </property>
70 70 </spacer>
71 71 </item>
72 72 </layout>
73 73 </item>
74 74 <item>
75 75 <widget class="QTreeWidget" name="treeWidget">
76 <property name="selectionMode">
77 <enum>QAbstractItemView::ExtendedSelection</enum>
78 </property>
76 79 <attribute name="headerVisible">
77 80 <bool>false</bool>
78 81 </attribute>
79 82 <column>
80 83 <property name="text">
81 84 <string notr="true">1</string>
82 85 </property>
83 86 </column>
84 87 </widget>
85 88 </item>
86 89 </layout>
87 90 </widget>
88 <resources/>
91 <resources>
92 <include location="../../resources/sqpguiresources.qrc"/>
93 <include location="../../resources/sqpguiresources.qrc"/>
94 </resources>
89 95 <connections/>
90 96 </ui>
General Comments 0
You need to be logged in to leave comments. Login now