##// 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 }
@@ -4,3 +4,5 CMakeLists.txt.user
4 4 core/src/Version.cpp
5 5 core/include/Version.h
6 6 3rdparty/
7 subprojects/CatalogueAPI/
8 subprojects/QxOrm/
@@ -25,6 +25,7
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
@@ -41,6 +42,13 const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins");
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");
@@ -75,6 +83,7 int main(int argc, char *argv[])
75 83 pluginManager.loadPlugins(directory);
76 84 }
77 85 }
86 pluginManager.loadStaticPlugins();
78 87
79 88 return a.exec();
80 89 }
@@ -86,6 +86,8 MainWindow::MainWindow(QWidget *parent)
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{
@@ -11,17 +11,19
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
@@ -29,12 +31,28 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
@@ -15,6 +15,7 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
@@ -25,11 +25,16 public:
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
@@ -4,6 +4,13
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
@@ -12,10 +19,18
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)
@@ -32,12 +47,106 CatalogueController::~CatalogueController()
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
@@ -6,3 +6,4 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");
@@ -95,6 +95,15 struct PluginManager::PluginManagerPrivate {
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 };
@@ -118,6 +127,11 void PluginManager::loadPlugins(const QDir &pluginDir)
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();
@@ -669,7 +669,7 AcquisitionZoomType VariableController::getZoomType(const SqpRange &range, const
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 }
@@ -40,7 +40,7 ExternalProject_Add(
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}"
@@ -75,6 +75,16 INSTALL(TARGETS ${SQPGUI_LIBRARY_NAME}
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.
@@ -2,24 +2,40
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;
@@ -1,12 +1,15
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
@@ -14,8 +17,13 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,15 +1,27
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();
@@ -19,14 +31,19 public:
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
@@ -2,30 +2,42
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
@@ -22,6 +22,7 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
@@ -45,6 +46,7 public:
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
@@ -15,7 +15,7 class VisualizationMultiZoneSelectionDialog : public QDialog {
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;
@@ -25,11 +25,19 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.
@@ -30,6 +30,8 public:
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;
@@ -1,6 +1,7
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
@@ -27,6 +28,10 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
@@ -1,4 +1,7
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',
@@ -103,7 +106,9 gui_sources = [
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'])
@@ -112,11 +117,11 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
@@ -25,5 +25,7
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,15 +1,200
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),
@@ -18,45 +203,82 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
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()
@@ -64,37 +286,31 CatalogueEventsWidget::~CatalogueEventsWidget()
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,11 +1,33
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()
@@ -13,6 +35,71 CatalogueInspectorWidget::~CatalogueInspectorWidget()
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));
@@ -23,14 +110,72 CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const
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,5 +1,17
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;
@@ -8,9 +20,15 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)
@@ -21,10 +39,51 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
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();
@@ -32,14 +91,29 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
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()
@@ -47,36 +121,67 CatalogueSideBarWidget::~CatalogueSideBarWidget()
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 }
@@ -85,17 +190,58 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 }
@@ -181,6 +181,11 VisualizationController &SqpApplication::visualizationController() noexcept
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;
@@ -18,20 +18,6 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
@@ -43,13 +29,31 void processZones(QLayout &layout, Fun fun)
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 {
@@ -118,6 +122,27 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zone
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);
@@ -119,6 +119,15 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() c
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) {
@@ -27,21 +27,6 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
@@ -60,6 +45,24 void processGraphs(QLayout &layout, Fun fun)
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 {
@@ -145,6 +148,17 VisualizationZoneWidget::~VisualizationZoneWidget()
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
@@ -34,7 +34,7
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">
@@ -48,7 +48,7
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">
@@ -69,7 +69,7
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">
@@ -86,7 +86,7
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">
@@ -114,26 +114,29
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>
@@ -53,7 +53,7
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">
@@ -113,53 +113,20
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">
@@ -167,13 +134,21
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>
@@ -186,17 +161,47
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>
@@ -34,7 +34,7
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">
@@ -48,7 +48,7
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">
@@ -73,6 +73,9
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>
@@ -85,6 +88,9
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