Auto status change to "Under Review"
@@ -0,0 +1,35 | |||
|
1 | #ifndef SCIQLOP_CATALOGUEABSTRACTTREEITEM_H | |
|
2 | #define SCIQLOP_CATALOGUEABSTRACTTREEITEM_H | |
|
3 | ||
|
4 | #include <Common/spimpl.h> | |
|
5 | #include <QVariant> | |
|
6 | #include <QVector> | |
|
7 | ||
|
8 | class QMimeData; | |
|
9 | ||
|
10 | class CatalogueAbstractTreeItem { | |
|
11 | public: | |
|
12 | constexpr static const int DEFAULT_TYPE = -1; | |
|
13 | ||
|
14 | CatalogueAbstractTreeItem(int type = DEFAULT_TYPE); | |
|
15 | virtual ~CatalogueAbstractTreeItem(); | |
|
16 | ||
|
17 | void addChild(CatalogueAbstractTreeItem *child); | |
|
18 | QVector<CatalogueAbstractTreeItem *> children() const; | |
|
19 | CatalogueAbstractTreeItem *parent() const; | |
|
20 | ||
|
21 | int type() const; | |
|
22 | QString text(int column = 0) const; | |
|
23 | ||
|
24 | virtual QVariant data(int column, int role) const; | |
|
25 | virtual Qt::ItemFlags flags(int column) const; | |
|
26 | virtual bool setData(int column, int role, const QVariant &value); | |
|
27 | virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action); | |
|
28 | virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action); | |
|
29 | ||
|
30 | private: | |
|
31 | class CatalogueAbstractTreeItemPrivate; | |
|
32 | spimpl::unique_impl_ptr<CatalogueAbstractTreeItemPrivate> impl; | |
|
33 | }; | |
|
34 | ||
|
35 | #endif // SCIQLOP_CATALOGUEABSTRACTTREEITEM_H |
@@ -0,0 +1,23 | |||
|
1 | #ifndef SCIQLOP_CATALOGUETEXTTREEITEM_H | |
|
2 | #define SCIQLOP_CATALOGUETEXTTREEITEM_H | |
|
3 | ||
|
4 | #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h> | |
|
5 | #include <Common/spimpl.h> | |
|
6 | ||
|
7 | class CatalogueTextTreeItem : public CatalogueAbstractTreeItem { | |
|
8 | public: | |
|
9 | CatalogueTextTreeItem(const QIcon &icon, const QString &text, int type); | |
|
10 | ||
|
11 | QVariant data(int column, int role) const override; | |
|
12 | Qt::ItemFlags flags(int column) const override; | |
|
13 | ||
|
14 | QString text() const; | |
|
15 | ||
|
16 | void setEnabled(bool value); | |
|
17 | ||
|
18 | private: | |
|
19 | class CatalogueTextTreeItemPrivate; | |
|
20 | spimpl::unique_impl_ptr<CatalogueTextTreeItemPrivate> impl; | |
|
21 | }; | |
|
22 | ||
|
23 | #endif // SCIQLOP_CATALOGUETEXTTREEITEM_H |
@@ -0,0 +1,28 | |||
|
1 | #ifndef SCIQLOP_CATALOGUETREEITEM_H | |
|
2 | #define SCIQLOP_CATALOGUETREEITEM_H | |
|
3 | ||
|
4 | #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h> | |
|
5 | #include <Common/spimpl.h> | |
|
6 | ||
|
7 | class DBCatalogue; | |
|
8 | ||
|
9 | ||
|
10 | class CatalogueTreeItem : public CatalogueAbstractTreeItem { | |
|
11 | public: | |
|
12 | CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon, int type); | |
|
13 | ||
|
14 | QVariant data(int column, int role) const override; | |
|
15 | bool setData(int column, int role, const QVariant &value) override; | |
|
16 | Qt::ItemFlags flags(int column) const override; | |
|
17 | bool canDropMimeData(const QMimeData *data, Qt::DropAction action) override; | |
|
18 | bool dropMimeData(const QMimeData *data, Qt::DropAction action) override; | |
|
19 | ||
|
20 | /// Returns the catalogue represented by the item | |
|
21 | std::shared_ptr<DBCatalogue> catalogue() const; | |
|
22 | ||
|
23 | private: | |
|
24 | class CatalogueTreeItemPrivate; | |
|
25 | spimpl::unique_impl_ptr<CatalogueTreeItemPrivate> impl; | |
|
26 | }; | |
|
27 | ||
|
28 | #endif // SCIQLOP_CATALOGUETREEITEM_H |
@@ -0,0 +1,56 | |||
|
1 | #ifndef SCIQLOP_CATALOGUETREEMODEL_H | |
|
2 | #define SCIQLOP_CATALOGUETREEMODEL_H | |
|
3 | ||
|
4 | #include <Common/spimpl.h> | |
|
5 | #include <QAbstractItemModel> | |
|
6 | ||
|
7 | class CatalogueAbstractTreeItem; | |
|
8 | ||
|
9 | /** | |
|
10 | * @brief Model to display catalogue items based on QTreeWidgetItem | |
|
11 | * @warning Do not use the method QTreeWidgetItem::treeWidget for an item added to this model or the | |
|
12 | * application will crash | |
|
13 | */ | |
|
14 | class CatalogueTreeModel : public QAbstractItemModel { | |
|
15 | Q_OBJECT | |
|
16 | ||
|
17 | signals: | |
|
18 | void itemRenamed(const QModelIndex &index); | |
|
19 | void itemDropped(const QModelIndex &parentIndex); | |
|
20 | ||
|
21 | public: | |
|
22 | CatalogueTreeModel(QObject *parent = nullptr); | |
|
23 | ||
|
24 | enum class Column { Name, Validation, Count }; | |
|
25 | ||
|
26 | QModelIndex addTopLevelItem(CatalogueAbstractTreeItem *item); | |
|
27 | QVector<CatalogueAbstractTreeItem *> topLevelItems() const; | |
|
28 | ||
|
29 | void addChildItem(CatalogueAbstractTreeItem *child, const QModelIndex &parentIndex); | |
|
30 | ||
|
31 | CatalogueAbstractTreeItem *item(const QModelIndex &index) const; | |
|
32 | QModelIndex indexOf(CatalogueAbstractTreeItem *item, int column = 0) const; | |
|
33 | ||
|
34 | // model | |
|
35 | QModelIndex index(int row, int column, | |
|
36 | const QModelIndex &parent = QModelIndex()) const override; | |
|
37 | QModelIndex parent(const QModelIndex &index) const override; | |
|
38 | int rowCount(const QModelIndex &parent) const override; | |
|
39 | int columnCount(const QModelIndex &parent) const override; | |
|
40 | Qt::ItemFlags flags(const QModelIndex &index) const override; | |
|
41 | QVariant data(const QModelIndex &index, int role) const override; | |
|
42 | bool setData(const QModelIndex &index, const QVariant &value, int role) override; | |
|
43 | ||
|
44 | bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, | |
|
45 | const QModelIndex &parent) const override; | |
|
46 | bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, | |
|
47 | const QModelIndex &parent) override; | |
|
48 | Qt::DropActions supportedDropActions() const; | |
|
49 | QStringList mimeTypes() const; | |
|
50 | ||
|
51 | private: | |
|
52 | class CatalogueTreeModelPrivate; | |
|
53 | spimpl::unique_impl_ptr<CatalogueTreeModelPrivate> impl; | |
|
54 | }; | |
|
55 | ||
|
56 | #endif // CATALOGUETREEMODEL_H |
@@ -0,0 +1,81 | |||
|
1 | #include "Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h" | |
|
2 | ||
|
3 | struct CatalogueAbstractTreeItem::CatalogueAbstractTreeItemPrivate { | |
|
4 | int m_Type; | |
|
5 | QVector<CatalogueAbstractTreeItem *> m_Children; | |
|
6 | CatalogueAbstractTreeItem *m_Parent = nullptr; | |
|
7 | ||
|
8 | CatalogueAbstractTreeItemPrivate(int type) : m_Type(type) {} | |
|
9 | }; | |
|
10 | ||
|
11 | CatalogueAbstractTreeItem::CatalogueAbstractTreeItem(int type) | |
|
12 | : impl{spimpl::make_unique_impl<CatalogueAbstractTreeItemPrivate>(type)} | |
|
13 | { | |
|
14 | } | |
|
15 | ||
|
16 | CatalogueAbstractTreeItem::~CatalogueAbstractTreeItem() | |
|
17 | { | |
|
18 | qDeleteAll(impl->m_Children); | |
|
19 | } | |
|
20 | ||
|
21 | void CatalogueAbstractTreeItem::addChild(CatalogueAbstractTreeItem *child) | |
|
22 | { | |
|
23 | impl->m_Children << child; | |
|
24 | child->impl->m_Parent = this; | |
|
25 | } | |
|
26 | ||
|
27 | QVector<CatalogueAbstractTreeItem *> CatalogueAbstractTreeItem::children() const | |
|
28 | { | |
|
29 | return impl->m_Children; | |
|
30 | } | |
|
31 | ||
|
32 | CatalogueAbstractTreeItem *CatalogueAbstractTreeItem::parent() const | |
|
33 | { | |
|
34 | return impl->m_Parent; | |
|
35 | } | |
|
36 | ||
|
37 | int CatalogueAbstractTreeItem::type() const | |
|
38 | { | |
|
39 | return impl->m_Type; | |
|
40 | } | |
|
41 | ||
|
42 | QString CatalogueAbstractTreeItem::text(int column) const | |
|
43 | { | |
|
44 | return data(0, Qt::DisplayRole).toString(); | |
|
45 | } | |
|
46 | ||
|
47 | QVariant CatalogueAbstractTreeItem::data(int column, int role) const | |
|
48 | { | |
|
49 | Q_UNUSED(column); | |
|
50 | Q_UNUSED(role); | |
|
51 | return QVariant(); | |
|
52 | } | |
|
53 | ||
|
54 | Qt::ItemFlags CatalogueAbstractTreeItem::flags(int column) const | |
|
55 | { | |
|
56 | Q_UNUSED(column); | |
|
57 | return Qt::NoItemFlags; | |
|
58 | } | |
|
59 | ||
|
60 | bool CatalogueAbstractTreeItem::setData(int column, int role, const QVariant &value) | |
|
61 | { | |
|
62 | Q_UNUSED(column); | |
|
63 | Q_UNUSED(role); | |
|
64 | Q_UNUSED(value); | |
|
65 | ||
|
66 | return false; | |
|
67 | } | |
|
68 | ||
|
69 | bool CatalogueAbstractTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action) | |
|
70 | { | |
|
71 | Q_UNUSED(data); | |
|
72 | Q_UNUSED(action); | |
|
73 | return false; | |
|
74 | } | |
|
75 | ||
|
76 | bool CatalogueAbstractTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action) | |
|
77 | { | |
|
78 | Q_UNUSED(data); | |
|
79 | Q_UNUSED(action); | |
|
80 | return false; | |
|
81 | } |
@@ -0,0 +1,59 | |||
|
1 | #include "Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h" | |
|
2 | ||
|
3 | #include <QIcon> | |
|
4 | ||
|
5 | struct CatalogueTextTreeItem::CatalogueTextTreeItemPrivate { | |
|
6 | ||
|
7 | QString m_Text; | |
|
8 | QIcon m_Icon; | |
|
9 | bool m_IsEnabled = true; | |
|
10 | ||
|
11 | CatalogueTextTreeItemPrivate(const QIcon &icon, const QString &text) | |
|
12 | : m_Text(text), m_Icon(icon) | |
|
13 | { | |
|
14 | } | |
|
15 | }; | |
|
16 | ||
|
17 | ||
|
18 | CatalogueTextTreeItem::CatalogueTextTreeItem(const QIcon &icon, const QString &text, int type) | |
|
19 | : CatalogueAbstractTreeItem(type), | |
|
20 | impl{spimpl::make_unique_impl<CatalogueTextTreeItemPrivate>(icon, text)} | |
|
21 | { | |
|
22 | } | |
|
23 | ||
|
24 | QVariant CatalogueTextTreeItem::data(int column, int role) const | |
|
25 | { | |
|
26 | if (column > 0) { | |
|
27 | return QVariant(); | |
|
28 | } | |
|
29 | ||
|
30 | switch (role) { | |
|
31 | case Qt::DisplayRole: | |
|
32 | return impl->m_Text; | |
|
33 | case Qt::DecorationRole: | |
|
34 | return impl->m_Icon; | |
|
35 | } | |
|
36 | ||
|
37 | return QVariant(); | |
|
38 | } | |
|
39 | ||
|
40 | Qt::ItemFlags CatalogueTextTreeItem::flags(int column) const | |
|
41 | { | |
|
42 | Q_UNUSED(column); | |
|
43 | ||
|
44 | if (!impl->m_IsEnabled) { | |
|
45 | return Qt::NoItemFlags; | |
|
46 | } | |
|
47 | ||
|
48 | return Qt::ItemIsEnabled | Qt::ItemIsSelectable; | |
|
49 | } | |
|
50 | ||
|
51 | QString CatalogueTextTreeItem::text() const | |
|
52 | { | |
|
53 | return impl->m_Text; | |
|
54 | } | |
|
55 | ||
|
56 | void CatalogueTextTreeItem::setEnabled(bool value) | |
|
57 | { | |
|
58 | impl->m_IsEnabled = value; | |
|
59 | } |
@@ -0,0 +1,201 | |||
|
1 | #include "Catalogue/CatalogueTreeModel.h" | |
|
2 | #include <Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.h> | |
|
3 | ||
|
4 | #include <QMimeData> | |
|
5 | #include <memory> | |
|
6 | ||
|
7 | #include <Common/MimeTypesDef.h> | |
|
8 | ||
|
9 | struct CatalogueTreeModel::CatalogueTreeModelPrivate { | |
|
10 | std::unique_ptr<CatalogueAbstractTreeItem> m_RootItem = nullptr; | |
|
11 | ||
|
12 | CatalogueTreeModelPrivate() : m_RootItem{std::make_unique<CatalogueAbstractTreeItem>()} {} | |
|
13 | }; | |
|
14 | ||
|
15 | CatalogueTreeModel::CatalogueTreeModel(QObject *parent) | |
|
16 | : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueTreeModelPrivate>()} | |
|
17 | { | |
|
18 | } | |
|
19 | ||
|
20 | QModelIndex CatalogueTreeModel::addTopLevelItem(CatalogueAbstractTreeItem *item) | |
|
21 | { | |
|
22 | auto nbTopLevelItems = impl->m_RootItem->children().count(); | |
|
23 | beginInsertRows(QModelIndex(), nbTopLevelItems, nbTopLevelItems); | |
|
24 | impl->m_RootItem->addChild(item); | |
|
25 | endInsertRows(); | |
|
26 | ||
|
27 | emit dataChanged(QModelIndex(), QModelIndex()); | |
|
28 | ||
|
29 | return index(nbTopLevelItems, 0); | |
|
30 | } | |
|
31 | ||
|
32 | QVector<CatalogueAbstractTreeItem *> CatalogueTreeModel::topLevelItems() const | |
|
33 | { | |
|
34 | return impl->m_RootItem->children(); | |
|
35 | } | |
|
36 | ||
|
37 | void CatalogueTreeModel::addChildItem(CatalogueAbstractTreeItem *child, | |
|
38 | const QModelIndex &parentIndex) | |
|
39 | { | |
|
40 | auto parentItem = item(parentIndex); | |
|
41 | int c = parentItem->children().count(); | |
|
42 | beginInsertRows(parentIndex, c, c); | |
|
43 | parentItem->addChild(child); | |
|
44 | endInsertRows(); | |
|
45 | ||
|
46 | emit dataChanged(parentIndex, parentIndex); | |
|
47 | } | |
|
48 | ||
|
49 | CatalogueAbstractTreeItem *CatalogueTreeModel::item(const QModelIndex &index) const | |
|
50 | { | |
|
51 | return static_cast<CatalogueAbstractTreeItem *>(index.internalPointer()); | |
|
52 | } | |
|
53 | ||
|
54 | QModelIndex CatalogueTreeModel::indexOf(CatalogueAbstractTreeItem *item, int column) const | |
|
55 | { | |
|
56 | auto parentItem = item->parent(); | |
|
57 | if (!parentItem) { | |
|
58 | return QModelIndex(); | |
|
59 | } | |
|
60 | ||
|
61 | auto row = parentItem->children().indexOf(item); | |
|
62 | return createIndex(row, column, item); | |
|
63 | } | |
|
64 | ||
|
65 | QModelIndex CatalogueTreeModel::index(int row, int column, const QModelIndex &parent) const | |
|
66 | { | |
|
67 | if (column > 0) { | |
|
68 | int a = 0; | |
|
69 | } | |
|
70 | ||
|
71 | if (!hasIndex(row, column, parent)) { | |
|
72 | return QModelIndex(); | |
|
73 | } | |
|
74 | ||
|
75 | CatalogueAbstractTreeItem *parentItem = nullptr; | |
|
76 | ||
|
77 | if (!parent.isValid()) { | |
|
78 | parentItem = impl->m_RootItem.get(); | |
|
79 | } | |
|
80 | else { | |
|
81 | parentItem = item(parent); | |
|
82 | } | |
|
83 | ||
|
84 | auto childItem = parentItem->children().value(row); | |
|
85 | if (childItem) { | |
|
86 | return createIndex(row, column, childItem); | |
|
87 | } | |
|
88 | ||
|
89 | return QModelIndex(); | |
|
90 | } | |
|
91 | ||
|
92 | ||
|
93 | QModelIndex CatalogueTreeModel::parent(const QModelIndex &index) const | |
|
94 | { | |
|
95 | if (!index.isValid()) { | |
|
96 | return QModelIndex(); | |
|
97 | } | |
|
98 | ||
|
99 | auto childItem = item(index); | |
|
100 | auto parentItem = childItem->parent(); | |
|
101 | ||
|
102 | if (parentItem == nullptr || parentItem->parent() == nullptr) { | |
|
103 | return QModelIndex(); | |
|
104 | } | |
|
105 | ||
|
106 | auto row = parentItem->parent()->children().indexOf(parentItem); | |
|
107 | return createIndex(row, 0, parentItem); | |
|
108 | } | |
|
109 | ||
|
110 | int CatalogueTreeModel::rowCount(const QModelIndex &parent) const | |
|
111 | { | |
|
112 | CatalogueAbstractTreeItem *parentItem = nullptr; | |
|
113 | ||
|
114 | if (!parent.isValid()) { | |
|
115 | parentItem = impl->m_RootItem.get(); | |
|
116 | } | |
|
117 | else { | |
|
118 | parentItem = item(parent); | |
|
119 | } | |
|
120 | ||
|
121 | return parentItem->children().count(); | |
|
122 | } | |
|
123 | ||
|
124 | int CatalogueTreeModel::columnCount(const QModelIndex &parent) const | |
|
125 | { | |
|
126 | return (int)Column::Count; | |
|
127 | } | |
|
128 | ||
|
129 | Qt::ItemFlags CatalogueTreeModel::flags(const QModelIndex &index) const | |
|
130 | { | |
|
131 | auto treeItem = item(index); | |
|
132 | if (treeItem) { | |
|
133 | return treeItem->flags(index.column()); | |
|
134 | } | |
|
135 | ||
|
136 | return Qt::NoItemFlags; | |
|
137 | } | |
|
138 | ||
|
139 | QVariant CatalogueTreeModel::data(const QModelIndex &index, int role) const | |
|
140 | { | |
|
141 | auto treeItem = item(index); | |
|
142 | if (treeItem) { | |
|
143 | return treeItem->data(index.column(), role); | |
|
144 | } | |
|
145 | ||
|
146 | return QModelIndex(); | |
|
147 | } | |
|
148 | ||
|
149 | bool CatalogueTreeModel::setData(const QModelIndex &index, const QVariant &value, int role) | |
|
150 | { | |
|
151 | auto treeItem = item(index); | |
|
152 | if (treeItem) { | |
|
153 | auto result = treeItem->setData(index.column(), role, value); | |
|
154 | ||
|
155 | if (result && index.column() == (int)Column::Name) { | |
|
156 | emit itemRenamed(index); | |
|
157 | } | |
|
158 | ||
|
159 | return result; | |
|
160 | } | |
|
161 | ||
|
162 | return false; | |
|
163 | } | |
|
164 | bool CatalogueTreeModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, | |
|
165 | int column, const QModelIndex &parent) const | |
|
166 | { | |
|
167 | auto draggedIndex = parent; | |
|
168 | auto draggedItem = item(draggedIndex); | |
|
169 | if (draggedItem) { | |
|
170 | return draggedItem->canDropMimeData(data, action); | |
|
171 | } | |
|
172 | ||
|
173 | return false; | |
|
174 | } | |
|
175 | ||
|
176 | bool CatalogueTreeModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, | |
|
177 | int column, const QModelIndex &parent) | |
|
178 | { | |
|
179 | bool result = false; | |
|
180 | ||
|
181 | auto draggedIndex = parent; | |
|
182 | auto draggedItem = item(draggedIndex); | |
|
183 | if (draggedItem) { | |
|
184 | result = draggedItem->dropMimeData(data, action); | |
|
185 | if (result) { | |
|
186 | emit itemDropped(draggedIndex); | |
|
187 | } | |
|
188 | } | |
|
189 | ||
|
190 | return result; | |
|
191 | } | |
|
192 | ||
|
193 | Qt::DropActions CatalogueTreeModel::supportedDropActions() const | |
|
194 | { | |
|
195 | return Qt::CopyAction | Qt::MoveAction; | |
|
196 | } | |
|
197 | ||
|
198 | QStringList CatalogueTreeModel::mimeTypes() const | |
|
199 | { | |
|
200 | return {MIME_TYPE_EVENT_LIST}; | |
|
201 | } |
@@ -1,65 +1,66 | |||
|
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 | #ifndef SCIQLOP_MAINWINDOW_H |
|
23 | 23 | #define SCIQLOP_MAINWINDOW_H |
|
24 | 24 | |
|
25 | 25 | #include <QListWidgetItem> |
|
26 | 26 | #include <QLoggingCategory> |
|
27 | 27 | #include <QMainWindow> |
|
28 | 28 | #include <QProgressBar> |
|
29 | 29 | #include <QProgressDialog> |
|
30 | 30 | #include <QThread> |
|
31 | 31 | #include <QVBoxLayout> |
|
32 | 32 | #include <QWidget> |
|
33 | 33 | |
|
34 | 34 | #include <Common/spimpl.h> |
|
35 | 35 | |
|
36 | 36 | #include <memory> |
|
37 | 37 | |
|
38 | 38 | Q_DECLARE_LOGGING_CATEGORY(LOG_MainWindow) |
|
39 | 39 | |
|
40 | 40 | namespace Ui { |
|
41 | 41 | class MainWindow; |
|
42 | 42 | } // namespace Ui |
|
43 | 43 | |
|
44 | 44 | |
|
45 | 45 | class MainWindow : public QMainWindow { |
|
46 | 46 | Q_OBJECT |
|
47 | 47 | |
|
48 | 48 | public: |
|
49 | 49 | explicit MainWindow(QWidget *parent = 0); |
|
50 | 50 | virtual ~MainWindow(); |
|
51 | 51 | public slots: |
|
52 | 52 | |
|
53 | 53 | protected: |
|
54 | 54 | void changeEvent(QEvent *e); |
|
55 | void closeEvent(QCloseEvent *event); | |
|
55 | 56 | |
|
56 | 57 | private: |
|
57 | 58 | std::unique_ptr<Ui::MainWindow> m_Ui; |
|
58 | 59 | // QWidget *m_progressWidget; |
|
59 | 60 | // QVBoxLayout *m_progressLayout; |
|
60 | 61 | // QList<QLopService*> m_qlopServices; |
|
61 | 62 | class MainWindowPrivate; |
|
62 | 63 | spimpl::unique_impl_ptr<MainWindowPrivate> impl; |
|
63 | 64 | }; |
|
64 | 65 | |
|
65 | 66 | #endif // SCIQLOP_MAINWINDOW_H |
@@ -1,89 +1,91 | |||
|
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 | 28 | #include <Plugin/PluginManager.h> |
|
29 | 29 | #include <QDir> |
|
30 | 30 | #include <QtPlugin> |
|
31 | 31 | |
|
32 | 32 | #include <QLoggingCategory> |
|
33 | 33 | |
|
34 | 34 | Q_LOGGING_CATEGORY(LOG_Main, "Main") |
|
35 | 35 | |
|
36 | 36 | namespace { |
|
37 | 37 | |
|
38 | 38 | const auto PLUGIN_DIRECTORY_NAME = QStringLiteral("plugins"); |
|
39 | 39 | |
|
40 | 40 | |
|
41 | 41 | } // namespace |
|
42 | 42 | |
|
43 | 43 | int main(int argc, char *argv[]) |
|
44 | 44 | { |
|
45 | 45 | #ifdef QT_STATICPLUGIN |
|
46 | 46 | Q_IMPORT_PLUGIN(MockPlugin) |
|
47 | 47 | Q_IMPORT_PLUGIN(AmdaPlugin) |
|
48 | 48 | Q_INIT_RESOURCE(amdaresources); |
|
49 | 49 | #endif |
|
50 | 50 | Q_INIT_RESOURCE(sqpguiresources); |
|
51 | 51 | |
|
52 | SqpApplication a{argc, argv}; | |
|
53 | 52 | SqpApplication::setOrganizationName("LPP"); |
|
54 | 53 | SqpApplication::setOrganizationDomain("lpp.fr"); |
|
55 | 54 | SqpApplication::setApplicationName("SciQLop"); |
|
55 | ||
|
56 | SqpApplication a{argc, argv}; | |
|
57 | ||
|
56 | 58 | MainWindow w; |
|
57 | 59 | w.show(); |
|
58 | 60 | |
|
59 | 61 | // Loads plugins |
|
60 | 62 | auto pluginDir = QDir{a.applicationDirPath()}; |
|
61 | 63 | auto pluginLookupPath = { |
|
62 | 64 | a.applicationDirPath(), |
|
63 | 65 | a.applicationDirPath() + "/" + PLUGIN_DIRECTORY_NAME, |
|
64 | 66 | a.applicationDirPath() + "/../lib64/SciQlop", |
|
65 | 67 | a.applicationDirPath() + "/../lib64/sciqlop", |
|
66 | 68 | a.applicationDirPath() + "/../lib/SciQlop", |
|
67 | 69 | a.applicationDirPath() + "/../lib/sciqlop", |
|
68 | 70 | a.applicationDirPath() + "/../plugins", |
|
69 | 71 | }; |
|
70 | 72 | |
|
71 | 73 | #if _WIN32 || _WIN64 |
|
72 | 74 | pluginDir.mkdir(PLUGIN_DIRECTORY_NAME); |
|
73 | 75 | pluginDir.cd(PLUGIN_DIRECTORY_NAME); |
|
74 | 76 | #endif |
|
75 | 77 | |
|
76 | 78 | PluginManager pluginManager{}; |
|
77 | 79 | |
|
78 | 80 | for (auto &&path : pluginLookupPath) { |
|
79 | 81 | QDir directory{path}; |
|
80 | 82 | if (directory.exists()) { |
|
81 | 83 | qCDebug(LOG_Main()) |
|
82 | 84 | << QObject::tr("Plugin directory: %1").arg(directory.absolutePath()); |
|
83 | 85 | pluginManager.loadPlugins(directory); |
|
84 | 86 | } |
|
85 | 87 | } |
|
86 | 88 | pluginManager.loadStaticPlugins(); |
|
87 | 89 | |
|
88 | 90 | return a.exec(); |
|
89 | 91 | } |
@@ -1,366 +1,405 | |||
|
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 | #include <Catalogue/CatalogueController.h> | |
|
25 | 26 | #include <Catalogue/CatalogueExplorer.h> |
|
26 | 27 | #include <DataSource/DataSourceController.h> |
|
27 | 28 | #include <DataSource/DataSourceWidget.h> |
|
28 | 29 | #include <Settings/SqpSettingsDialog.h> |
|
29 | 30 | #include <Settings/SqpSettingsGeneralWidget.h> |
|
30 | 31 | #include <SidePane/SqpSidePane.h> |
|
31 | 32 | #include <SqpApplication.h> |
|
32 | 33 | #include <Time/TimeController.h> |
|
33 | 34 | #include <TimeWidget/TimeWidget.h> |
|
34 | 35 | #include <Variable/Variable.h> |
|
35 | 36 | #include <Variable/VariableController.h> |
|
36 | 37 | #include <Visualization/VisualizationController.h> |
|
37 | 38 | |
|
38 | 39 | #include <QAction> |
|
40 | #include <QCloseEvent> | |
|
39 | 41 | #include <QDate> |
|
40 | 42 | #include <QDir> |
|
41 | 43 | #include <QFileDialog> |
|
44 | #include <QMessageBox> | |
|
42 | 45 | #include <QToolBar> |
|
43 | 46 | #include <QToolButton> |
|
44 | 47 | #include <memory.h> |
|
45 | 48 | |
|
46 | 49 | #include "iostream" |
|
47 | 50 | |
|
48 | 51 | Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow") |
|
49 | 52 | |
|
50 | 53 | namespace { |
|
51 | 54 | const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0; |
|
52 | 55 | const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1; |
|
53 | 56 | const auto VIEWPLITTERINDEX = 2; |
|
54 | 57 | const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3; |
|
55 | 58 | const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4; |
|
56 | 59 | } |
|
57 | 60 | |
|
58 | 61 | class MainWindow::MainWindowPrivate { |
|
59 | 62 | public: |
|
60 | 63 | explicit MainWindowPrivate(MainWindow *mainWindow) |
|
61 | 64 | : m_LastOpenLeftInspectorSize{}, |
|
62 | 65 | m_LastOpenRightInspectorSize{}, |
|
63 | 66 | m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}}, |
|
64 | 67 | m_SettingsDialog{new SqpSettingsDialog{mainWindow}}, |
|
65 | 68 | m_CatalogExplorer{new CatalogueExplorer{mainWindow}} |
|
66 | 69 | { |
|
67 | 70 | } |
|
68 | 71 | |
|
69 | 72 | QSize m_LastOpenLeftInspectorSize; |
|
70 | 73 | QSize m_LastOpenRightInspectorSize; |
|
71 | 74 | /// General settings widget. MainWindow has the ownership |
|
72 | 75 | SqpSettingsGeneralWidget *m_GeneralSettingsWidget; |
|
73 | 76 | /// Settings dialog. MainWindow has the ownership |
|
74 | 77 | SqpSettingsDialog *m_SettingsDialog; |
|
75 | 78 | /// Catalogue dialog. MainWindow has the ownership |
|
76 | 79 | CatalogueExplorer *m_CatalogExplorer; |
|
80 | ||
|
81 | bool checkDataToSave(QWidget *parentWidget); | |
|
77 | 82 | }; |
|
78 | 83 | |
|
79 | 84 | MainWindow::MainWindow(QWidget *parent) |
|
80 | 85 | : QMainWindow{parent}, |
|
81 | 86 | m_Ui{new Ui::MainWindow}, |
|
82 | 87 | impl{spimpl::make_unique_impl<MainWindowPrivate>(this)} |
|
83 | 88 | { |
|
84 | 89 | m_Ui->setupUi(this); |
|
85 | 90 | |
|
86 | 91 | m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false); |
|
87 | 92 | m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false); |
|
88 | 93 | |
|
89 | 94 | impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view); |
|
90 | 95 | |
|
91 | 96 | |
|
92 | 97 | auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane(); |
|
93 | 98 | auto openLeftInspectorAction = new QAction{QIcon{ |
|
94 | 99 | ":/icones/previous.png", |
|
95 | 100 | }, |
|
96 | 101 | tr("Show/hide the left inspector"), this}; |
|
97 | 102 | |
|
98 | 103 | |
|
99 | 104 | auto spacerLeftTop = new QWidget{}; |
|
100 | 105 | spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
101 | 106 | |
|
102 | 107 | auto spacerLeftBottom = new QWidget{}; |
|
103 | 108 | spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
104 | 109 | |
|
105 | 110 | leftSidePane->addWidget(spacerLeftTop); |
|
106 | 111 | leftSidePane->addAction(openLeftInspectorAction); |
|
107 | 112 | leftSidePane->addWidget(spacerLeftBottom); |
|
108 | 113 | |
|
109 | 114 | |
|
110 | 115 | auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane(); |
|
111 | 116 | auto openRightInspectorAction = new QAction{QIcon{ |
|
112 | 117 | ":/icones/next.png", |
|
113 | 118 | }, |
|
114 | 119 | tr("Show/hide the right inspector"), this}; |
|
115 | 120 | |
|
116 | 121 | auto spacerRightTop = new QWidget{}; |
|
117 | 122 | spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
118 | 123 | |
|
119 | 124 | auto spacerRightBottom = new QWidget{}; |
|
120 | 125 | spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); |
|
121 | 126 | |
|
122 | 127 | rightSidePane->addWidget(spacerRightTop); |
|
123 | 128 | rightSidePane->addAction(openRightInspectorAction); |
|
124 | 129 | rightSidePane->addWidget(spacerRightBottom); |
|
125 | 130 | |
|
126 | 131 | openLeftInspectorAction->setCheckable(true); |
|
127 | 132 | openRightInspectorAction->setCheckable(true); |
|
128 | 133 | |
|
129 | 134 | auto openInspector = [this](bool checked, bool right, auto action) { |
|
130 | 135 | |
|
131 | 136 | action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"}); |
|
132 | 137 | |
|
133 | 138 | auto &lastInspectorSize |
|
134 | 139 | = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize; |
|
135 | 140 | |
|
136 | 141 | auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size() |
|
137 | 142 | : m_Ui->leftMainInspectorWidget->size(); |
|
138 | 143 | |
|
139 | 144 | // Update of the last opened geometry |
|
140 | 145 | if (checked) { |
|
141 | 146 | lastInspectorSize = nextInspectorSize; |
|
142 | 147 | } |
|
143 | 148 | |
|
144 | 149 | auto startSize = lastInspectorSize; |
|
145 | 150 | auto endSize = startSize; |
|
146 | 151 | endSize.setWidth(0); |
|
147 | 152 | |
|
148 | 153 | auto splitterInspectorIndex |
|
149 | 154 | = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX; |
|
150 | 155 | |
|
151 | 156 | auto currentSizes = m_Ui->splitter->sizes(); |
|
152 | 157 | if (checked) { |
|
153 | 158 | // adjust sizes individually here, e.g. |
|
154 | 159 | currentSizes[splitterInspectorIndex] -= lastInspectorSize.width(); |
|
155 | 160 | currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width(); |
|
156 | 161 | m_Ui->splitter->setSizes(currentSizes); |
|
157 | 162 | } |
|
158 | 163 | else { |
|
159 | 164 | // adjust sizes individually here, e.g. |
|
160 | 165 | currentSizes[splitterInspectorIndex] += lastInspectorSize.width(); |
|
161 | 166 | currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width(); |
|
162 | 167 | m_Ui->splitter->setSizes(currentSizes); |
|
163 | 168 | } |
|
164 | 169 | |
|
165 | 170 | }; |
|
166 | 171 | |
|
167 | 172 | |
|
168 | 173 | connect(openLeftInspectorAction, &QAction::triggered, |
|
169 | 174 | [openInspector, openLeftInspectorAction](bool checked) { |
|
170 | 175 | openInspector(checked, false, openLeftInspectorAction); |
|
171 | 176 | }); |
|
172 | 177 | connect(openRightInspectorAction, &QAction::triggered, |
|
173 | 178 | [openInspector, openRightInspectorAction](bool checked) { |
|
174 | 179 | openInspector(checked, true, openRightInspectorAction); |
|
175 | 180 | }); |
|
176 | 181 | |
|
177 | 182 | // //////////////// // |
|
178 | 183 | // Menu and Toolbar // |
|
179 | 184 | // //////////////// // |
|
180 | 185 | this->menuBar()->addAction(tr("File")); |
|
181 | 186 | auto toolsMenu = this->menuBar()->addMenu(tr("Tools")); |
|
182 | 187 | toolsMenu->addAction(tr("Settings..."), [this]() { |
|
183 | 188 | // Loads settings |
|
184 | 189 | impl->m_SettingsDialog->loadSettings(); |
|
185 | 190 | |
|
186 | 191 | // Open settings dialog and save settings if the dialog is accepted |
|
187 | 192 | if (impl->m_SettingsDialog->exec() == QDialog::Accepted) { |
|
188 | 193 | impl->m_SettingsDialog->saveSettings(); |
|
189 | 194 | } |
|
190 | 195 | |
|
191 | 196 | }); |
|
192 | 197 | |
|
193 | 198 | auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar")); |
|
194 | 199 | |
|
195 | 200 | auto timeWidget = new TimeWidget{}; |
|
196 | 201 | mainToolBar->addWidget(timeWidget); |
|
197 | 202 | |
|
198 | 203 | // Interaction modes |
|
199 | 204 | auto actionPointerMode = new QAction{QIcon(":/icones/pointer.png"), "Move", this}; |
|
200 | 205 | actionPointerMode->setCheckable(true); |
|
201 | 206 | actionPointerMode->setChecked(sqpApp->plotsInteractionMode() |
|
202 | 207 | == SqpApplication::PlotsInteractionMode::None); |
|
203 | 208 | connect(actionPointerMode, &QAction::triggered, |
|
204 | 209 | []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); }); |
|
205 | 210 | |
|
206 | 211 | auto actionZoomMode = new QAction{QIcon(":/icones/zoom.png"), "Zoom", this}; |
|
207 | 212 | actionZoomMode->setCheckable(true); |
|
208 | 213 | actionZoomMode->setChecked(sqpApp->plotsInteractionMode() |
|
209 | 214 | == SqpApplication::PlotsInteractionMode::ZoomBox); |
|
210 | 215 | connect(actionZoomMode, &QAction::triggered, []() { |
|
211 | 216 | sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox); |
|
212 | 217 | }); |
|
213 | 218 | |
|
214 | 219 | auto actionOrganisationMode = new QAction{QIcon(":/icones/drag.png"), "Organize", this}; |
|
215 | 220 | actionOrganisationMode->setCheckable(true); |
|
216 | 221 | actionOrganisationMode->setChecked(sqpApp->plotsInteractionMode() |
|
217 | 222 | == SqpApplication::PlotsInteractionMode::DragAndDrop); |
|
218 | 223 | connect(actionOrganisationMode, &QAction::triggered, []() { |
|
219 | 224 | sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop); |
|
220 | 225 | }); |
|
221 | 226 | |
|
222 | 227 | auto actionZonesMode = new QAction{QIcon(":/icones/rectangle.png"), "Zones", this}; |
|
223 | 228 | actionZonesMode->setCheckable(true); |
|
224 | 229 | actionZonesMode->setChecked(sqpApp->plotsInteractionMode() |
|
225 | 230 | == SqpApplication::PlotsInteractionMode::SelectionZones); |
|
226 | 231 | connect(actionZonesMode, &QAction::triggered, []() { |
|
227 | 232 | sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones); |
|
228 | 233 | }); |
|
229 | 234 | |
|
230 | 235 | auto modeActionGroup = new QActionGroup{this}; |
|
231 | 236 | modeActionGroup->addAction(actionZoomMode); |
|
232 | 237 | modeActionGroup->addAction(actionZonesMode); |
|
233 | 238 | modeActionGroup->addAction(actionOrganisationMode); |
|
234 | 239 | modeActionGroup->addAction(actionPointerMode); |
|
235 | 240 | modeActionGroup->setExclusive(true); |
|
236 | 241 | |
|
237 | 242 | mainToolBar->addSeparator(); |
|
238 | 243 | mainToolBar->addAction(actionPointerMode); |
|
239 | 244 | mainToolBar->addAction(actionZoomMode); |
|
240 | 245 | mainToolBar->addAction(actionOrganisationMode); |
|
241 | 246 | mainToolBar->addAction(actionZonesMode); |
|
242 | 247 | mainToolBar->addSeparator(); |
|
243 | 248 | |
|
244 | 249 | // Cursors |
|
245 | 250 | auto btnCursor = new QToolButton{this}; |
|
246 | 251 | btnCursor->setIcon(QIcon(":/icones/cursor.png")); |
|
247 | 252 | btnCursor->setText("Cursor"); |
|
248 | 253 | btnCursor->setToolTip("Cursor"); |
|
249 | 254 | btnCursor->setPopupMode(QToolButton::InstantPopup); |
|
250 | 255 | auto cursorMenu = new QMenu("CursorMenu", this); |
|
251 | 256 | btnCursor->setMenu(cursorMenu); |
|
252 | 257 | |
|
253 | 258 | auto noCursorAction = cursorMenu->addAction("No Cursor"); |
|
254 | 259 | noCursorAction->setCheckable(true); |
|
255 | 260 | noCursorAction->setChecked(sqpApp->plotsCursorMode() |
|
256 | 261 | == SqpApplication::PlotsCursorMode::NoCursor); |
|
257 | 262 | connect(noCursorAction, &QAction::triggered, |
|
258 | 263 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); }); |
|
259 | 264 | |
|
260 | 265 | cursorMenu->addSeparator(); |
|
261 | 266 | auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor"); |
|
262 | 267 | verticalCursorAction->setCheckable(true); |
|
263 | 268 | verticalCursorAction->setChecked(sqpApp->plotsCursorMode() |
|
264 | 269 | == SqpApplication::PlotsCursorMode::Vertical); |
|
265 | 270 | connect(verticalCursorAction, &QAction::triggered, |
|
266 | 271 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); }); |
|
267 | 272 | |
|
268 | 273 | auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor"); |
|
269 | 274 | temporalCursorAction->setCheckable(true); |
|
270 | 275 | temporalCursorAction->setChecked(sqpApp->plotsCursorMode() |
|
271 | 276 | == SqpApplication::PlotsCursorMode::Temporal); |
|
272 | 277 | connect(temporalCursorAction, &QAction::triggered, |
|
273 | 278 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); }); |
|
274 | 279 | |
|
275 | 280 | auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor"); |
|
276 | 281 | horizontalCursorAction->setCheckable(true); |
|
277 | 282 | horizontalCursorAction->setChecked(sqpApp->plotsCursorMode() |
|
278 | 283 | == SqpApplication::PlotsCursorMode::Horizontal); |
|
279 | 284 | connect(horizontalCursorAction, &QAction::triggered, |
|
280 | 285 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); }); |
|
281 | 286 | |
|
282 | 287 | auto crossCursorAction = cursorMenu->addAction("Cross Cursor"); |
|
283 | 288 | crossCursorAction->setCheckable(true); |
|
284 | 289 | crossCursorAction->setChecked(sqpApp->plotsCursorMode() |
|
285 | 290 | == SqpApplication::PlotsCursorMode::Cross); |
|
286 | 291 | connect(crossCursorAction, &QAction::triggered, |
|
287 | 292 | []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); }); |
|
288 | 293 | |
|
289 | 294 | mainToolBar->addWidget(btnCursor); |
|
290 | 295 | |
|
291 | 296 | auto cursorModeActionGroup = new QActionGroup{this}; |
|
292 | 297 | cursorModeActionGroup->setExclusive(true); |
|
293 | 298 | cursorModeActionGroup->addAction(noCursorAction); |
|
294 | 299 | cursorModeActionGroup->addAction(verticalCursorAction); |
|
295 | 300 | cursorModeActionGroup->addAction(temporalCursorAction); |
|
296 | 301 | cursorModeActionGroup->addAction(horizontalCursorAction); |
|
297 | 302 | cursorModeActionGroup->addAction(crossCursorAction); |
|
298 | 303 | |
|
299 | 304 | // Catalog |
|
300 | 305 | mainToolBar->addSeparator(); |
|
301 | 306 | mainToolBar->addAction(QIcon(":/icones/catalogue.png"), "Catalogues", |
|
302 | 307 | [this]() { impl->m_CatalogExplorer->show(); }); |
|
303 | 308 | |
|
304 | 309 | // //////// // |
|
305 | 310 | // Settings // |
|
306 | 311 | // //////// // |
|
307 | 312 | |
|
308 | 313 | // Registers "general settings" widget to the settings dialog |
|
309 | 314 | impl->m_SettingsDialog->registerWidget(QStringLiteral("General"), |
|
310 | 315 | impl->m_GeneralSettingsWidget); |
|
311 | 316 | |
|
312 | 317 | // /////////// // |
|
313 | 318 | // Connections // |
|
314 | 319 | // /////////// // |
|
315 | 320 | |
|
316 | 321 | // Controllers / controllers connections |
|
317 | 322 | connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpRange)), &sqpApp->variableController(), |
|
318 | 323 | SLOT(onDateTimeOnSelection(SqpRange))); |
|
319 | 324 | |
|
320 | 325 | // Widgets / controllers connections |
|
321 | 326 | |
|
322 | 327 | // DataSource |
|
323 | 328 | connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)), |
|
324 | 329 | m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *))); |
|
325 | 330 | |
|
326 | 331 | // Time |
|
327 | 332 | connect(timeWidget, SIGNAL(timeUpdated(SqpRange)), &sqpApp->timeController(), |
|
328 | 333 | SLOT(onTimeToUpdate(SqpRange))); |
|
329 | 334 | |
|
330 | 335 | // Visualization |
|
331 | 336 | connect(&sqpApp->visualizationController(), |
|
332 | 337 | SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view, |
|
333 | 338 | SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>))); |
|
334 | 339 | |
|
335 | 340 | connect(&sqpApp->visualizationController(), |
|
336 | 341 | SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), m_Ui->view, |
|
337 | 342 | SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpRange &))); |
|
338 | 343 | |
|
339 | 344 | // Widgets / widgets connections |
|
340 | 345 | |
|
341 | 346 | // For the following connections, we use DirectConnection to allow each widget that can |
|
342 | 347 | // potentially attach a menu to the variable's menu to do so before this menu is displayed. |
|
343 | 348 | // The order of connections is also important, since it determines the order in which each |
|
344 | 349 | // widget will attach its menu |
|
345 | 350 | connect( |
|
346 | 351 | m_Ui->variableInspectorWidget, |
|
347 | 352 | SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)), |
|
348 | 353 | m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)), |
|
349 | 354 | Qt::DirectConnection); |
|
350 | 355 | } |
|
351 | 356 | |
|
352 | 357 | MainWindow::~MainWindow() |
|
353 | 358 | { |
|
354 | 359 | } |
|
355 | 360 | |
|
356 | 361 | void MainWindow::changeEvent(QEvent *e) |
|
357 | 362 | { |
|
358 | 363 | QMainWindow::changeEvent(e); |
|
359 | 364 | switch (e->type()) { |
|
360 | 365 | case QEvent::LanguageChange: |
|
361 | 366 | m_Ui->retranslateUi(this); |
|
362 | 367 | break; |
|
363 | 368 | default: |
|
364 | 369 | break; |
|
365 | 370 | } |
|
366 | 371 | } |
|
372 | ||
|
373 | void MainWindow::closeEvent(QCloseEvent *event) | |
|
374 | { | |
|
375 | if (!impl->checkDataToSave(this)) { | |
|
376 | event->ignore(); | |
|
377 | } | |
|
378 | else { | |
|
379 | event->accept(); | |
|
380 | } | |
|
381 | } | |
|
382 | ||
|
383 | bool MainWindow::MainWindowPrivate::checkDataToSave(QWidget *parentWidget) | |
|
384 | { | |
|
385 | auto hasChanges = sqpApp->catalogueController().hasChanges(); | |
|
386 | if (hasChanges) { | |
|
387 | // There are some unsaved changes | |
|
388 | switch (QMessageBox::question( | |
|
389 | parentWidget, "Save changes", | |
|
390 | tr("The catalogue controller unsaved changes.\nDo you want to save them ?"), | |
|
391 | QMessageBox::SaveAll | QMessageBox::Discard | QMessageBox::Cancel, | |
|
392 | QMessageBox::SaveAll)) { | |
|
393 | case QMessageBox::SaveAll: | |
|
394 | sqpApp->catalogueController().saveAll(); | |
|
395 | break; | |
|
396 | case QMessageBox::Discard: | |
|
397 | break; | |
|
398 | case QMessageBox::Cancel: | |
|
399 | default: | |
|
400 | return false; | |
|
401 | } | |
|
402 | } | |
|
403 | ||
|
404 | return true; | |
|
405 | } |
@@ -1,75 +1,83 | |||
|
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 | 14 | #include <memory> |
|
15 | 15 | |
|
16 | 16 | class DBCatalogue; |
|
17 | 17 | class DBEvent; |
|
18 | class DBEventProduct; | |
|
18 | 19 | |
|
19 | 20 | Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController) |
|
20 | 21 | |
|
21 | 22 | class DataSourceItem; |
|
22 | 23 | class Variable; |
|
23 | 24 | |
|
24 | 25 | /** |
|
25 | 26 | * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI |
|
26 | 27 | * library. |
|
27 | 28 | */ |
|
28 | 29 | class SCIQLOP_CORE_EXPORT CatalogueController : public QObject { |
|
29 | 30 | Q_OBJECT |
|
30 | 31 | public: |
|
31 | 32 | explicit CatalogueController(QObject *parent = 0); |
|
32 | 33 | virtual ~CatalogueController(); |
|
33 | 34 | |
|
34 | 35 | // DB |
|
35 | 36 | QStringList getRepositories() const; |
|
36 | 37 | void addDB(const QString &dbPath); |
|
37 | 38 | void saveDB(const QString &destinationPath, const QString &repository); |
|
38 | 39 | |
|
39 | 40 | // Event |
|
40 | 41 | /// retrieveEvents with empty repository retrieve them from the default repository |
|
41 | 42 | std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const; |
|
42 | 43 | std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const; |
|
43 | 44 | std::list<std::shared_ptr<DBEvent> > |
|
44 | 45 | retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const; |
|
45 | 46 | void addEvent(std::shared_ptr<DBEvent> event); |
|
46 | 47 | void updateEvent(std::shared_ptr<DBEvent> event); |
|
48 | void updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct); | |
|
47 | 49 | void removeEvent(std::shared_ptr<DBEvent> event); |
|
48 | 50 | // void trashEvent(std::shared_ptr<DBEvent> event); |
|
49 |
// void restore( |
|
|
51 | // void restore(std::shared_ptr<DBEvent> event); | |
|
50 | 52 | void saveEvent(std::shared_ptr<DBEvent> event); |
|
53 | void discardEvent(std::shared_ptr<DBEvent> event); | |
|
54 | bool eventHasChanges(std::shared_ptr<DBEvent> event) const; | |
|
51 | 55 | |
|
52 | 56 | // Catalogue |
|
53 | 57 | // bool createCatalogue(const QString &name, QVector<QUuid> eventList); |
|
54 | 58 | /// retrieveEvents with empty repository retrieve them from the default repository |
|
55 | 59 | std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository |
|
56 | 60 | = QString()) const; |
|
57 | 61 | void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue); |
|
58 | 62 | void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue); |
|
59 | 63 | void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue); |
|
60 | 64 | |
|
61 | 65 | void saveAll(); |
|
66 | bool hasChanges() const; | |
|
67 | ||
|
68 | /// Returns the MIME data associated to a list of variables | |
|
69 | QByteArray mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const; | |
|
70 | ||
|
71 | /// Returns the list of variables contained in a MIME data | |
|
72 | QVector<std::shared_ptr<DBEvent> > eventsForMimeData(const QByteArray &mimeData) const; | |
|
62 | 73 | |
|
63 | 74 | public slots: |
|
64 | 75 | /// Manage init/end of the controller |
|
65 | 76 | void initialize(); |
|
66 | void finalize(); | |
|
67 | 77 | |
|
68 | 78 | private: |
|
69 | void waitForFinish(); | |
|
70 | ||
|
71 | 79 | class CatalogueControllerPrivate; |
|
72 | 80 | spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl; |
|
73 | 81 | }; |
|
74 | 82 | |
|
75 | 83 | #endif // SCIQLOP_CATALOGUECONTROLLER_H |
@@ -1,154 +1,156 | |||
|
1 | 1 | #ifndef SCIQLOP_DATASOURCEITEM_H |
|
2 | 2 | #define SCIQLOP_DATASOURCEITEM_H |
|
3 | 3 | |
|
4 | 4 | #include "CoreGlobal.h" |
|
5 | 5 | |
|
6 | 6 | #include <Common/spimpl.h> |
|
7 | 7 | |
|
8 | 8 | #include <QVariant> |
|
9 | 9 | #include <QVector> |
|
10 | 10 | |
|
11 | 11 | class DataSourceItemAction; |
|
12 | 12 | |
|
13 | 13 | /** |
|
14 | 14 | * Possible types of an item |
|
15 | 15 | */ |
|
16 | 16 | enum class DataSourceItemType { NODE, PRODUCT, COMPONENT }; |
|
17 | 17 | |
|
18 | 18 | /** |
|
19 | 19 | * @brief The DataSourceItem class aims to represent a structure element of a data source. |
|
20 | 20 | * A data source has a tree structure that is made up of a main DataSourceItem object (root) |
|
21 | 21 | * containing other DataSourceItem objects (children). |
|
22 | 22 | * For each DataSourceItem can be associated a set of data representing it. |
|
23 | 23 | */ |
|
24 | 24 | class SCIQLOP_CORE_EXPORT DataSourceItem { |
|
25 | 25 | public: |
|
26 | 26 | /// Key associated with the name of the item |
|
27 | 27 | static const QString NAME_DATA_KEY; |
|
28 | 28 | /// Key associated with the plugin of the item |
|
29 | 29 | static const QString PLUGIN_DATA_KEY; |
|
30 | /// Key associated with a unique id of the plugin | |
|
31 | static const QString ID_DATA_KEY; | |
|
30 | 32 | |
|
31 | 33 | explicit DataSourceItem(DataSourceItemType type, const QString &name); |
|
32 | 34 | explicit DataSourceItem(DataSourceItemType type, QVariantHash data = {}); |
|
33 | 35 | |
|
34 | 36 | std::unique_ptr<DataSourceItem> clone() const; |
|
35 | 37 | |
|
36 | 38 | /// @return the actions of the item as a vector |
|
37 | 39 | QVector<DataSourceItemAction *> actions() const noexcept; |
|
38 | 40 | |
|
39 | 41 | /** |
|
40 | 42 | * Adds an action to the item. The item takes ownership of the action, and the action is |
|
41 | 43 | * automatically associated to the item |
|
42 | 44 | * @param action the action to add |
|
43 | 45 | */ |
|
44 | 46 | void addAction(std::unique_ptr<DataSourceItemAction> action) noexcept; |
|
45 | 47 | |
|
46 | 48 | /** |
|
47 | 49 | * Adds a child to the item. The item takes ownership of the child. |
|
48 | 50 | * @param child the child to add |
|
49 | 51 | */ |
|
50 | 52 | void appendChild(std::unique_ptr<DataSourceItem> child) noexcept; |
|
51 | 53 | |
|
52 | 54 | /** |
|
53 | 55 | * Returns the item's child associated to an index |
|
54 | 56 | * @param childIndex the index to search |
|
55 | 57 | * @return a pointer to the child if index is valid, nullptr otherwise |
|
56 | 58 | */ |
|
57 | 59 | DataSourceItem *child(int childIndex) const noexcept; |
|
58 | 60 | |
|
59 | 61 | int childCount() const noexcept; |
|
60 | 62 | |
|
61 | 63 | /** |
|
62 | 64 | * Get the data associated to a key |
|
63 | 65 | * @param key the key to search |
|
64 | 66 | * @return the data found if key is valid, default QVariant otherwise |
|
65 | 67 | */ |
|
66 | 68 | QVariant data(const QString &key) const noexcept; |
|
67 | 69 | |
|
68 | 70 | /// Gets all data |
|
69 | 71 | QVariantHash data() const noexcept; |
|
70 | 72 | |
|
71 | 73 | /** |
|
72 | 74 | * Merge in the item the source item passed as parameter. |
|
73 | 75 | * |
|
74 | 76 | * The merge is done by adding as child of the item the complete tree represented by the source |
|
75 | 77 | * item. If a part of the tree already exists in the item (based on the name of the nodes), it |
|
76 | 78 | * is merged by completing the existing tree by items "leaves" (products, components or nodes |
|
77 | 79 | * with no child). |
|
78 | 80 | * |
|
79 | 81 | * For example, with item representing the tree: |
|
80 | 82 | * R (root node) |
|
81 | 83 | * - N1 (node) |
|
82 | 84 | * -- N11 (node) |
|
83 | 85 | * --- P1 (product) |
|
84 | 86 | * --- P2 (product) |
|
85 | 87 | * - N2 (node) |
|
86 | 88 | * |
|
87 | 89 | * and the source item representing the tree: |
|
88 | 90 | * N1 (root node) |
|
89 | 91 | * - N11 (node) |
|
90 | 92 | * -- P3 (product) |
|
91 | 93 | * - N12 (node) |
|
92 | 94 | * |
|
93 | 95 | * The leaves of the source item to merge into the item are N1/N11/P3 and N1/N12 => we therefore |
|
94 | 96 | * have the following merge result: |
|
95 | 97 | * R |
|
96 | 98 | * - N1 |
|
97 | 99 | * -- N11 |
|
98 | 100 | * --- P1 |
|
99 | 101 | * --- P2 |
|
100 | 102 | * --- P3 (added leaf) |
|
101 | 103 | * -- N12 (added leaf) |
|
102 | 104 | * |
|
103 | 105 | * @param item the source item |
|
104 | 106 | * @remarks No control is performed on products or components that are merged into the same tree |
|
105 | 107 | * part (two products or components may have the same name) |
|
106 | 108 | * @remarks the merge is made by copy (source item is not changed and still exists after the |
|
107 | 109 | * operation) |
|
108 | 110 | */ |
|
109 | 111 | void merge(const DataSourceItem &item); |
|
110 | 112 | |
|
111 | 113 | bool isRoot() const noexcept; |
|
112 | 114 | |
|
113 | 115 | QString name() const noexcept; |
|
114 | 116 | |
|
115 | 117 | /** |
|
116 | 118 | * Get the item's parent |
|
117 | 119 | * @return a pointer to the parent if it exists, nullptr if the item is a root |
|
118 | 120 | */ |
|
119 | 121 | DataSourceItem *parentItem() const noexcept; |
|
120 | 122 | |
|
121 | 123 | /** |
|
122 | 124 | * Gets the item's root |
|
123 | 125 | * @return the top parent, the item itself if it's the root item |
|
124 | 126 | */ |
|
125 | 127 | const DataSourceItem &rootItem() const noexcept; |
|
126 | 128 | |
|
127 | 129 | /** |
|
128 | 130 | * Sets or appends a value to a key |
|
129 | 131 | * @param key the key |
|
130 | 132 | * @param value the value |
|
131 | 133 | * @param append if true, the value is added to the values already existing for the key, |
|
132 | 134 | * otherwise it replaces the existing values |
|
133 | 135 | */ |
|
134 | 136 | void setData(const QString &key, const QVariant &value, bool append = false) noexcept; |
|
135 | 137 | |
|
136 | 138 | DataSourceItemType type() const noexcept; |
|
137 | 139 | |
|
138 | 140 | /** |
|
139 | 141 | * @brief Searches the first child matching the specified data. |
|
140 | 142 | * @param data The data to search. |
|
141 | 143 | * @param recursive So the search recursively. |
|
142 | 144 | * @return the item matching the data or nullptr if it was not found. |
|
143 | 145 | */ |
|
144 | 146 | DataSourceItem *findItem(const QVariantHash &data, bool recursive); |
|
145 | 147 | |
|
146 | 148 | bool operator==(const DataSourceItem &other); |
|
147 | 149 | bool operator!=(const DataSourceItem &other); |
|
148 | 150 | |
|
149 | 151 | private: |
|
150 | 152 | class DataSourceItemPrivate; |
|
151 | 153 | spimpl::unique_impl_ptr<DataSourceItemPrivate> impl; |
|
152 | 154 | }; |
|
153 | 155 | |
|
154 | 156 | #endif // SCIQLOP_DATASOURCEITEMMODEL_H |
@@ -1,296 +1,420 | |||
|
1 | 1 | #include <Catalogue/CatalogueController.h> |
|
2 | 2 | |
|
3 | 3 | #include <Variable/Variable.h> |
|
4 | 4 | |
|
5 | 5 | #include <CatalogueDao.h> |
|
6 | 6 | |
|
7 | 7 | #include <ComparaisonPredicate.h> |
|
8 | 8 | #include <CompoundPredicate.h> |
|
9 | 9 | #include <DBCatalogue.h> |
|
10 | 10 | #include <DBEvent.h> |
|
11 | 11 | #include <DBEventProduct.h> |
|
12 | 12 | #include <DBTag.h> |
|
13 | 13 | #include <IRequestPredicate.h> |
|
14 | 14 | |
|
15 | #include <QDataStream> | |
|
15 | 16 | #include <QMutex> |
|
16 | 17 | #include <QThread> |
|
17 | 18 | |
|
18 | 19 | #include <QDir> |
|
19 | 20 | #include <QStandardPaths> |
|
20 | 21 | |
|
21 | 22 | Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController") |
|
22 | 23 | |
|
23 | 24 | namespace { |
|
24 | 25 | |
|
25 | static QString REPOSITORY_WORK_SUFFIX = QString{"work"}; | |
|
26 | static QString REPOSITORY_TRASH_SUFFIX = QString{"trash"}; | |
|
26 | static QString REPOSITORY_WORK_SUFFIX = QString{"_work"}; | |
|
27 | static QString REPOSITORY_TRASH_SUFFIX = QString{"_trash"}; | |
|
27 | 28 | } |
|
28 | 29 | |
|
29 | 30 | class CatalogueController::CatalogueControllerPrivate { |
|
30 | 31 | |
|
31 | 32 | public: |
|
32 | 33 | explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {} |
|
33 | 34 | |
|
34 | QMutex m_WorkingMutex; | |
|
35 | 35 | CatalogueDao m_CatalogueDao; |
|
36 | 36 | |
|
37 | 37 | QStringList m_RepositoryList; |
|
38 | 38 | CatalogueController *m_Q; |
|
39 | 39 | |
|
40 | QSet<QString> m_EventKeysWithChanges; | |
|
41 | ||
|
42 | QString eventUniqueKey(const std::shared_ptr<DBEvent> &event) const; | |
|
43 | ||
|
40 | 44 | void copyDBtoDB(const QString &dbFrom, const QString &dbTo); |
|
41 | 45 | QString toWorkRepository(QString repository); |
|
42 | 46 | QString toSyncRepository(QString repository); |
|
47 | void savAllDB(); | |
|
48 | ||
|
49 | void saveEvent(std::shared_ptr<DBEvent> event, bool persist = true); | |
|
50 | void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue, bool persist = true); | |
|
43 | 51 | }; |
|
44 | 52 | |
|
45 | 53 | CatalogueController::CatalogueController(QObject *parent) |
|
46 | 54 | : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)} |
|
47 | 55 | { |
|
48 | 56 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction") |
|
49 | 57 | << QThread::currentThread(); |
|
50 | 58 | } |
|
51 | 59 | |
|
52 | 60 | CatalogueController::~CatalogueController() |
|
53 | 61 | { |
|
54 | 62 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction") |
|
55 | 63 | << QThread::currentThread(); |
|
56 | this->waitForFinish(); | |
|
57 | 64 | } |
|
58 | 65 | |
|
59 | 66 | QStringList CatalogueController::getRepositories() const |
|
60 | 67 | { |
|
61 | 68 | return impl->m_RepositoryList; |
|
62 | 69 | } |
|
63 | 70 | |
|
64 | 71 | void CatalogueController::addDB(const QString &dbPath) |
|
65 | 72 | { |
|
66 | 73 | QDir dbDir(dbPath); |
|
67 | 74 | if (dbDir.exists()) { |
|
68 | 75 | auto dirName = dbDir.dirName(); |
|
69 | 76 | |
|
70 | 77 | if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName) |
|
71 | 78 | != impl->m_RepositoryList.cend()) { |
|
72 | 79 | qCCritical(LOG_CatalogueController()) |
|
73 | 80 | << tr("Impossible to addDB that is already loaded"); |
|
74 | 81 | } |
|
75 | 82 | |
|
76 | 83 | if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) { |
|
77 | 84 | qCCritical(LOG_CatalogueController()) |
|
78 | 85 | << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath); |
|
79 | 86 | } |
|
80 | 87 | else { |
|
81 | 88 | impl->m_RepositoryList << dirName; |
|
82 | 89 | impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName)); |
|
83 | 90 | } |
|
84 | 91 | } |
|
85 | 92 | else { |
|
86 | 93 | qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ") |
|
87 | 94 | << dbPath; |
|
88 | 95 | } |
|
89 | 96 | } |
|
90 | 97 | |
|
91 | 98 | void CatalogueController::saveDB(const QString &destinationPath, const QString &repository) |
|
92 | 99 | { |
|
93 | 100 | if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) { |
|
94 | 101 | qCCritical(LOG_CatalogueController()) |
|
95 | 102 | << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath); |
|
96 | 103 | } |
|
97 | 104 | } |
|
98 | 105 | |
|
99 | 106 | std::list<std::shared_ptr<DBEvent> > |
|
100 | 107 | CatalogueController::retrieveEvents(const QString &repository) const |
|
101 | 108 | { |
|
102 | 109 | QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository; |
|
103 | 110 | |
|
104 | 111 | auto eventsShared = std::list<std::shared_ptr<DBEvent> >{}; |
|
105 | 112 | auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName)); |
|
106 | 113 | for (auto event : events) { |
|
107 | 114 | eventsShared.push_back(std::make_shared<DBEvent>(event)); |
|
108 | 115 | } |
|
109 | 116 | return eventsShared; |
|
110 | 117 | } |
|
111 | 118 | |
|
112 | 119 | std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const |
|
113 | 120 | { |
|
114 | 121 | auto eventsShared = std::list<std::shared_ptr<DBEvent> >{}; |
|
115 | 122 | for (auto repository : impl->m_RepositoryList) { |
|
116 | 123 | eventsShared.splice(eventsShared.end(), retrieveEvents(repository)); |
|
117 | 124 | } |
|
118 | 125 | |
|
119 | 126 | return eventsShared; |
|
120 | 127 | } |
|
121 | 128 | |
|
122 | 129 | std::list<std::shared_ptr<DBEvent> > |
|
123 | 130 | CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const |
|
124 | 131 | { |
|
125 | 132 | auto eventsShared = std::list<std::shared_ptr<DBEvent> >{}; |
|
126 | 133 | auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue); |
|
127 | 134 | for (auto event : events) { |
|
128 | 135 | eventsShared.push_back(std::make_shared<DBEvent>(event)); |
|
129 | 136 | } |
|
130 | 137 | return eventsShared; |
|
131 | 138 | } |
|
132 | 139 | |
|
133 | 140 | void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event) |
|
134 | 141 | { |
|
135 |
event->setRepository(impl->to |
|
|
142 | event->setRepository(impl->toWorkRepository(event->getRepository())); | |
|
143 | ||
|
144 | auto uniqueId = impl->eventUniqueKey(event); | |
|
145 | impl->m_EventKeysWithChanges.insert(uniqueId); | |
|
136 | 146 | |
|
137 | 147 | impl->m_CatalogueDao.updateEvent(*event); |
|
138 | 148 | } |
|
139 | 149 | |
|
150 | void CatalogueController::updateEventProduct(std::shared_ptr<DBEventProduct> eventProduct) | |
|
151 | { | |
|
152 | impl->m_CatalogueDao.updateEventProduct(*eventProduct); | |
|
153 | } | |
|
154 | ||
|
140 | 155 | void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event) |
|
141 | 156 | { |
|
142 | 157 | // Remove it from both repository and repository_work |
|
143 | 158 | event->setRepository(impl->toWorkRepository(event->getRepository())); |
|
144 | 159 | impl->m_CatalogueDao.removeEvent(*event); |
|
145 | 160 | event->setRepository(impl->toSyncRepository(event->getRepository())); |
|
146 | 161 | impl->m_CatalogueDao.removeEvent(*event); |
|
162 | impl->savAllDB(); | |
|
147 | 163 | } |
|
148 | 164 | |
|
149 | 165 | void CatalogueController::addEvent(std::shared_ptr<DBEvent> event) |
|
150 | 166 | { |
|
151 | 167 | event->setRepository(impl->toWorkRepository(event->getRepository())); |
|
152 | 168 | |
|
153 | impl->m_CatalogueDao.addEvent(*event); | |
|
169 | auto eventTemp = *event; | |
|
170 | impl->m_CatalogueDao.addEvent(eventTemp); | |
|
154 | 171 | |
|
155 | 172 | // Call update is necessary at the creation of add Event if it has some tags or some event |
|
156 | 173 | // products |
|
157 | 174 | if (!event->getEventProducts().empty() || !event->getTags().empty()) { |
|
158 | impl->m_CatalogueDao.updateEvent(*event); | |
|
175 | ||
|
176 | auto eventProductsTemp = eventTemp.getEventProducts(); | |
|
177 | auto eventProductTempUpdated = std::list<DBEventProduct>{}; | |
|
178 | for (auto eventProductTemp : eventProductsTemp) { | |
|
179 | eventProductTemp.setEvent(eventTemp); | |
|
180 | eventProductTempUpdated.push_back(eventProductTemp); | |
|
181 | } | |
|
182 | eventTemp.setEventProducts(eventProductTempUpdated); | |
|
183 | ||
|
184 | impl->m_CatalogueDao.updateEvent(eventTemp); | |
|
159 | 185 | } |
|
160 | 186 | } |
|
161 | 187 | |
|
162 | 188 | void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event) |
|
163 | 189 | { |
|
164 | impl->m_CatalogueDao.moveEvent(*event, impl->toSyncRepository(event->getRepository()), true); | |
|
190 | impl->saveEvent(event, true); | |
|
191 | impl->m_EventKeysWithChanges.remove(impl->eventUniqueKey(event)); | |
|
192 | } | |
|
193 | ||
|
194 | void CatalogueController::discardEvent(std::shared_ptr<DBEvent> event) | |
|
195 | { | |
|
196 | auto uniqIdPredicate = std::make_shared<ComparaisonPredicate>( | |
|
197 | QString{"uniqId"}, event->getUniqId(), ComparaisonOperation::EQUALEQUAL); | |
|
198 | ||
|
199 | auto syncRepositoryPredicate = std::make_shared<ComparaisonPredicate>( | |
|
200 | QString{"repository"}, impl->toSyncRepository(event->getRepository()), | |
|
201 | ComparaisonOperation::EQUALEQUAL); | |
|
202 | ||
|
203 | auto syncPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND); | |
|
204 | syncPred->AddRequestPredicate(uniqIdPredicate); | |
|
205 | syncPred->AddRequestPredicate(syncRepositoryPredicate); | |
|
206 | ||
|
207 | ||
|
208 | auto workRepositoryPredicate = std::make_shared<ComparaisonPredicate>( | |
|
209 | QString{"repository"}, impl->toWorkRepository(event->getRepository()), | |
|
210 | ComparaisonOperation::EQUALEQUAL); | |
|
211 | ||
|
212 | auto workPred = std::make_shared<CompoundPredicate>(CompoundOperation::AND); | |
|
213 | workPred->AddRequestPredicate(uniqIdPredicate); | |
|
214 | workPred->AddRequestPredicate(workRepositoryPredicate); | |
|
215 | ||
|
216 | ||
|
217 | auto syncEvent = impl->m_CatalogueDao.getEvent(syncPred); | |
|
218 | impl->m_CatalogueDao.copyEvent(syncEvent, impl->toWorkRepository(event->getRepository()), true); | |
|
219 | ||
|
220 | auto workEvent = impl->m_CatalogueDao.getEvent(workPred); | |
|
221 | *event = workEvent; | |
|
222 | impl->m_EventKeysWithChanges.remove(impl->eventUniqueKey(event)); | |
|
223 | } | |
|
224 | ||
|
225 | bool CatalogueController::eventHasChanges(std::shared_ptr<DBEvent> event) const | |
|
226 | { | |
|
227 | return impl->m_EventKeysWithChanges.contains(impl->eventUniqueKey(event)); | |
|
165 | 228 | } |
|
166 | 229 | |
|
167 | 230 | std::list<std::shared_ptr<DBCatalogue> > |
|
168 | 231 | CatalogueController::retrieveCatalogues(const QString &repository) const |
|
169 | 232 | { |
|
170 | 233 | QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository; |
|
171 | 234 | |
|
172 | 235 | auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{}; |
|
173 | 236 | auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName)); |
|
174 | 237 | for (auto catalogue : catalogues) { |
|
175 | 238 | cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue)); |
|
176 | 239 | } |
|
177 | 240 | return cataloguesShared; |
|
178 | 241 | } |
|
179 | 242 | |
|
180 | 243 | void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue) |
|
181 | 244 | { |
|
182 |
catalogue->setRepository(impl->to |
|
|
245 | catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository())); | |
|
183 | 246 | |
|
184 | 247 | impl->m_CatalogueDao.updateCatalogue(*catalogue); |
|
185 | 248 | } |
|
186 | 249 | |
|
187 | 250 | void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue) |
|
188 | 251 | { |
|
189 | 252 | // Remove it from both repository and repository_work |
|
190 | 253 | catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository())); |
|
191 | 254 | impl->m_CatalogueDao.removeCatalogue(*catalogue); |
|
192 | 255 | catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository())); |
|
193 | 256 | impl->m_CatalogueDao.removeCatalogue(*catalogue); |
|
194 | 257 | } |
|
195 | 258 | |
|
196 | 259 | void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue) |
|
197 | 260 | { |
|
198 |
impl-> |
|
|
199 | impl->toSyncRepository(catalogue->getRepository()), true); | |
|
261 | impl->saveCatalogue(catalogue, true); | |
|
200 | 262 | } |
|
201 | 263 | |
|
202 | 264 | void CatalogueController::saveAll() |
|
203 | 265 | { |
|
204 | 266 | for (auto repository : impl->m_RepositoryList) { |
|
205 | 267 | // Save Event |
|
206 | 268 | auto events = this->retrieveEvents(repository); |
|
207 | 269 | for (auto event : events) { |
|
208 |
|
|
|
270 | impl->saveEvent(event, false); | |
|
209 | 271 | } |
|
210 | 272 | |
|
211 | 273 | // Save Catalogue |
|
212 | 274 | auto catalogues = this->retrieveCatalogues(repository); |
|
213 | 275 | for (auto catalogue : catalogues) { |
|
214 |
|
|
|
276 | impl->saveCatalogue(catalogue, false); | |
|
277 | } | |
|
278 | } | |
|
279 | ||
|
280 | impl->savAllDB(); | |
|
281 | impl->m_EventKeysWithChanges.clear(); | |
|
282 | } | |
|
283 | ||
|
284 | bool CatalogueController::hasChanges() const | |
|
285 | { | |
|
286 | return !impl->m_EventKeysWithChanges.isEmpty(); // TODO: catalogues | |
|
287 | } | |
|
288 | ||
|
289 | QByteArray | |
|
290 | CatalogueController::mimeDataForEvents(const QVector<std::shared_ptr<DBEvent> > &events) const | |
|
291 | { | |
|
292 | auto encodedData = QByteArray{}; | |
|
293 | ||
|
294 | QMap<QString, QVariantList> idsPerRepository; | |
|
295 | for (auto event : events) { | |
|
296 | idsPerRepository[event->getRepository()] << event->getUniqId(); | |
|
297 | } | |
|
298 | ||
|
299 | QDataStream stream{&encodedData, QIODevice::WriteOnly}; | |
|
300 | stream << idsPerRepository; | |
|
301 | ||
|
302 | return encodedData; | |
|
303 | } | |
|
304 | ||
|
305 | QVector<std::shared_ptr<DBEvent> > | |
|
306 | CatalogueController::eventsForMimeData(const QByteArray &mimeData) const | |
|
307 | { | |
|
308 | auto events = QVector<std::shared_ptr<DBEvent> >{}; | |
|
309 | QDataStream stream{mimeData}; | |
|
310 | ||
|
311 | QMap<QString, QVariantList> idsPerRepository; | |
|
312 | stream >> idsPerRepository; | |
|
313 | ||
|
314 | for (auto it = idsPerRepository.cbegin(); it != idsPerRepository.cend(); ++it) { | |
|
315 | auto repository = it.key(); | |
|
316 | auto allRepositoryEvent = retrieveEvents(repository); | |
|
317 | for (auto uuid : it.value()) { | |
|
318 | for (auto repositoryEvent : allRepositoryEvent) { | |
|
319 | if (uuid.toUuid() == repositoryEvent->getUniqId()) { | |
|
320 | events << repositoryEvent; | |
|
321 | } | |
|
322 | } | |
|
215 | 323 | } |
|
216 | 324 | } |
|
325 | ||
|
326 | return events; | |
|
217 | 327 | } |
|
218 | 328 | |
|
219 | 329 | void CatalogueController::initialize() |
|
220 | 330 | { |
|
221 | 331 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController init") |
|
222 | 332 | << QThread::currentThread(); |
|
223 | impl->m_WorkingMutex.lock(); | |
|
333 | ||
|
224 | 334 | impl->m_CatalogueDao.initialize(); |
|
225 | 335 | auto defaultRepositoryLocation |
|
226 | 336 | = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); |
|
227 | 337 | |
|
228 | 338 | QDir defaultRepositoryLocationDir; |
|
229 | 339 | if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) { |
|
230 | 340 | defaultRepositoryLocationDir.cd(defaultRepositoryLocation); |
|
231 | 341 | auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT); |
|
232 | 342 | qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ") |
|
233 | 343 | << defaultRepository; |
|
234 | 344 | this->addDB(defaultRepository); |
|
235 | 345 | } |
|
236 | 346 | else { |
|
237 | 347 | qCWarning(LOG_CatalogueController()) |
|
238 | 348 | << tr("Cannot load the persistent default repository from ") |
|
239 | 349 | << defaultRepositoryLocation; |
|
240 | 350 | } |
|
241 | 351 | |
|
242 | 352 | qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END"); |
|
243 | 353 | } |
|
244 | 354 | |
|
245 | void CatalogueController::finalize() | |
|
246 | { | |
|
247 | impl->m_WorkingMutex.unlock(); | |
|
248 | } | |
|
249 | ||
|
250 | void CatalogueController::waitForFinish() | |
|
355 | QString CatalogueController::CatalogueControllerPrivate::eventUniqueKey( | |
|
356 | const std::shared_ptr<DBEvent> &event) const | |
|
251 | 357 | { |
|
252 | QMutexLocker locker{&impl->m_WorkingMutex}; | |
|
358 | return event->getUniqId().toString().append(event->getRepository()); | |
|
253 | 359 | } |
|
254 | 360 | |
|
255 | 361 | void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom, |
|
256 | 362 | const QString &dbTo) |
|
257 | 363 | { |
|
258 | auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{}; | |
|
364 | // auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{}; | |
|
259 | 365 | auto catalogues = m_CatalogueDao.getCatalogues(dbFrom); |
|
366 | auto events = m_CatalogueDao.getEvents(dbFrom); | |
|
260 | 367 | for (auto catalogue : catalogues) { |
|
261 | cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue)); | |
|
368 | m_CatalogueDao.copyCatalogue(catalogue, dbTo, true); | |
|
262 | 369 | } |
|
263 | 370 | |
|
264 | auto eventsShared = std::list<std::shared_ptr<DBEvent> >{}; | |
|
265 | auto events = m_CatalogueDao.getEvents(dbFrom); | |
|
266 | 371 | for (auto event : events) { |
|
267 | eventsShared.push_back(std::make_shared<DBEvent>(event)); | |
|
268 | } | |
|
269 | ||
|
270 | for (auto catalogue : cataloguesShared) { | |
|
271 | m_CatalogueDao.copyCatalogue(*catalogue, dbTo, true); | |
|
272 | } | |
|
273 | ||
|
274 | for (auto event : eventsShared) { | |
|
275 | m_CatalogueDao.copyEvent(*event, dbTo, true); | |
|
372 | m_CatalogueDao.copyEvent(event, dbTo, true); | |
|
276 | 373 | } |
|
277 | 374 | } |
|
278 | 375 | |
|
279 | 376 | QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository) |
|
280 | 377 | { |
|
281 | 378 | auto syncRepository = toSyncRepository(repository); |
|
282 | 379 | |
|
283 |
return QString("%1 |
|
|
380 | return QString("%1%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX); | |
|
284 | 381 | } |
|
285 | 382 | |
|
286 | 383 | QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository) |
|
287 | 384 | { |
|
288 | 385 | auto syncRepository = repository; |
|
289 | 386 | if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) { |
|
290 | 387 | syncRepository.remove(REPOSITORY_WORK_SUFFIX); |
|
291 | 388 | } |
|
292 | 389 | else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) { |
|
293 | 390 | syncRepository.remove(REPOSITORY_TRASH_SUFFIX); |
|
294 | 391 | } |
|
295 | 392 | return syncRepository; |
|
296 | 393 | } |
|
394 | ||
|
395 | void CatalogueController::CatalogueControllerPrivate::savAllDB() | |
|
396 | { | |
|
397 | for (auto repository : m_RepositoryList) { | |
|
398 | auto defaultRepositoryLocation | |
|
399 | = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation); | |
|
400 | m_CatalogueDao.saveDB(defaultRepositoryLocation, repository); | |
|
401 | } | |
|
402 | } | |
|
403 | ||
|
404 | void CatalogueController::CatalogueControllerPrivate::saveEvent(std::shared_ptr<DBEvent> event, | |
|
405 | bool persist) | |
|
406 | { | |
|
407 | m_CatalogueDao.copyEvent(*event, toSyncRepository(event->getRepository()), true); | |
|
408 | if (persist) { | |
|
409 | savAllDB(); | |
|
410 | } | |
|
411 | } | |
|
412 | ||
|
413 | void CatalogueController::CatalogueControllerPrivate::saveCatalogue( | |
|
414 | std::shared_ptr<DBCatalogue> catalogue, bool persist) | |
|
415 | { | |
|
416 | m_CatalogueDao.copyCatalogue(*catalogue, toSyncRepository(catalogue->getRepository()), true); | |
|
417 | if (persist) { | |
|
418 | savAllDB(); | |
|
419 | } | |
|
420 | } |
@@ -1,186 +1,187 | |||
|
1 | 1 | #include <DataSource/DataSourceItem.h> |
|
2 | 2 | #include <DataSource/DataSourceItemAction.h> |
|
3 | 3 | #include <DataSource/DataSourceItemMergeHelper.h> |
|
4 | 4 | |
|
5 | 5 | #include <QVector> |
|
6 | 6 | |
|
7 | 7 | const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name"); |
|
8 | 8 | const QString DataSourceItem::PLUGIN_DATA_KEY = QStringLiteral("plugin"); |
|
9 | const QString DataSourceItem::ID_DATA_KEY = QStringLiteral("uuid"); | |
|
9 | 10 | |
|
10 | 11 | struct DataSourceItem::DataSourceItemPrivate { |
|
11 | 12 | explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data) |
|
12 | 13 | : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{} |
|
13 | 14 | { |
|
14 | 15 | } |
|
15 | 16 | |
|
16 | 17 | DataSourceItem *m_Parent; |
|
17 | 18 | std::vector<std::unique_ptr<DataSourceItem> > m_Children; |
|
18 | 19 | DataSourceItemType m_Type; |
|
19 | 20 | QVariantHash m_Data; |
|
20 | 21 | std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions; |
|
21 | 22 | }; |
|
22 | 23 | |
|
23 | 24 | DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name) |
|
24 | 25 | : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}} |
|
25 | 26 | { |
|
26 | 27 | } |
|
27 | 28 | |
|
28 | 29 | DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data) |
|
29 | 30 | : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))} |
|
30 | 31 | { |
|
31 | 32 | } |
|
32 | 33 | |
|
33 | 34 | std::unique_ptr<DataSourceItem> DataSourceItem::clone() const |
|
34 | 35 | { |
|
35 | 36 | auto result = std::make_unique<DataSourceItem>(impl->m_Type, impl->m_Data); |
|
36 | 37 | |
|
37 | 38 | // Clones children |
|
38 | 39 | for (const auto &child : impl->m_Children) { |
|
39 | 40 | result->appendChild(std::move(child->clone())); |
|
40 | 41 | } |
|
41 | 42 | |
|
42 | 43 | // Clones actions |
|
43 | 44 | for (const auto &action : impl->m_Actions) { |
|
44 | 45 | result->addAction(std::move(action->clone())); |
|
45 | 46 | } |
|
46 | 47 | |
|
47 | 48 | return result; |
|
48 | 49 | } |
|
49 | 50 | |
|
50 | 51 | QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept |
|
51 | 52 | { |
|
52 | 53 | auto result = QVector<DataSourceItemAction *>{}; |
|
53 | 54 | |
|
54 | 55 | std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions), |
|
55 | 56 | std::back_inserter(result), [](const auto &action) { return action.get(); }); |
|
56 | 57 | |
|
57 | 58 | return result; |
|
58 | 59 | } |
|
59 | 60 | |
|
60 | 61 | void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept |
|
61 | 62 | { |
|
62 | 63 | action->setDataSourceItem(this); |
|
63 | 64 | impl->m_Actions.push_back(std::move(action)); |
|
64 | 65 | } |
|
65 | 66 | |
|
66 | 67 | void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept |
|
67 | 68 | { |
|
68 | 69 | child->impl->m_Parent = this; |
|
69 | 70 | impl->m_Children.push_back(std::move(child)); |
|
70 | 71 | } |
|
71 | 72 | |
|
72 | 73 | DataSourceItem *DataSourceItem::child(int childIndex) const noexcept |
|
73 | 74 | { |
|
74 | 75 | if (childIndex < 0 || childIndex >= childCount()) { |
|
75 | 76 | return nullptr; |
|
76 | 77 | } |
|
77 | 78 | else { |
|
78 | 79 | return impl->m_Children.at(childIndex).get(); |
|
79 | 80 | } |
|
80 | 81 | } |
|
81 | 82 | |
|
82 | 83 | int DataSourceItem::childCount() const noexcept |
|
83 | 84 | { |
|
84 | 85 | return impl->m_Children.size(); |
|
85 | 86 | } |
|
86 | 87 | |
|
87 | 88 | QVariant DataSourceItem::data(const QString &key) const noexcept |
|
88 | 89 | { |
|
89 | 90 | return impl->m_Data.value(key); |
|
90 | 91 | } |
|
91 | 92 | |
|
92 | 93 | QVariantHash DataSourceItem::data() const noexcept |
|
93 | 94 | { |
|
94 | 95 | return impl->m_Data; |
|
95 | 96 | } |
|
96 | 97 | |
|
97 | 98 | void DataSourceItem::merge(const DataSourceItem &item) |
|
98 | 99 | { |
|
99 | 100 | DataSourceItemMergeHelper::merge(item, *this); |
|
100 | 101 | } |
|
101 | 102 | |
|
102 | 103 | bool DataSourceItem::isRoot() const noexcept |
|
103 | 104 | { |
|
104 | 105 | return impl->m_Parent == nullptr; |
|
105 | 106 | } |
|
106 | 107 | |
|
107 | 108 | QString DataSourceItem::name() const noexcept |
|
108 | 109 | { |
|
109 | 110 | return data(NAME_DATA_KEY).toString(); |
|
110 | 111 | } |
|
111 | 112 | |
|
112 | 113 | DataSourceItem *DataSourceItem::parentItem() const noexcept |
|
113 | 114 | { |
|
114 | 115 | return impl->m_Parent; |
|
115 | 116 | } |
|
116 | 117 | |
|
117 | 118 | const DataSourceItem &DataSourceItem::rootItem() const noexcept |
|
118 | 119 | { |
|
119 | 120 | return isRoot() ? *this : parentItem()->rootItem(); |
|
120 | 121 | } |
|
121 | 122 | |
|
122 | 123 | void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept |
|
123 | 124 | { |
|
124 | 125 | auto it = impl->m_Data.constFind(key); |
|
125 | 126 | if (append && it != impl->m_Data.constEnd()) { |
|
126 | 127 | // Case of an existing value to which we want to add to the new value |
|
127 | 128 | if (it->canConvert<QVariantList>()) { |
|
128 | 129 | auto variantList = it->value<QVariantList>(); |
|
129 | 130 | variantList.append(value); |
|
130 | 131 | |
|
131 | 132 | impl->m_Data.insert(key, variantList); |
|
132 | 133 | } |
|
133 | 134 | else { |
|
134 | 135 | impl->m_Data.insert(key, QVariantList{*it, value}); |
|
135 | 136 | } |
|
136 | 137 | } |
|
137 | 138 | else { |
|
138 | 139 | // Other cases : |
|
139 | 140 | // - new value in map OR |
|
140 | 141 | // - replacement of an existing value (not appending) |
|
141 | 142 | impl->m_Data.insert(key, value); |
|
142 | 143 | } |
|
143 | 144 | } |
|
144 | 145 | |
|
145 | 146 | DataSourceItemType DataSourceItem::type() const noexcept |
|
146 | 147 | { |
|
147 | 148 | return impl->m_Type; |
|
148 | 149 | } |
|
149 | 150 | |
|
150 | 151 | DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursive) |
|
151 | 152 | { |
|
152 | 153 | for (const auto &child : impl->m_Children) { |
|
153 | 154 | if (child->impl->m_Data == data) { |
|
154 | 155 | return child.get(); |
|
155 | 156 | } |
|
156 | 157 | |
|
157 | 158 | if (recursive) { |
|
158 | 159 | if (auto foundItem = child->findItem(data, true)) { |
|
159 | 160 | return foundItem; |
|
160 | 161 | } |
|
161 | 162 | } |
|
162 | 163 | } |
|
163 | 164 | |
|
164 | 165 | return nullptr; |
|
165 | 166 | } |
|
166 | 167 | |
|
167 | 168 | bool DataSourceItem::operator==(const DataSourceItem &other) |
|
168 | 169 | { |
|
169 | 170 | // Compares items' attributes |
|
170 | 171 | if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) { |
|
171 | 172 | // Compares contents of items' children |
|
172 | 173 | return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children), |
|
173 | 174 | std::cbegin(other.impl->m_Children), std::cend(other.impl->m_Children), |
|
174 | 175 | [](const auto &itemChild, const auto &otherChild) { |
|
175 | 176 | return *itemChild == *otherChild; |
|
176 | 177 | }); |
|
177 | 178 | } |
|
178 | 179 | else { |
|
179 | 180 | return false; |
|
180 | 181 | } |
|
181 | 182 | } |
|
182 | 183 | |
|
183 | 184 | bool DataSourceItem::operator!=(const DataSourceItem &other) |
|
184 | 185 | { |
|
185 | 186 | return !(*this == other); |
|
186 | 187 | } |
@@ -1,17 +1,19 | |||
|
1 | 1 | #ifndef SCIQLOP_CATALOGUEACTIONMANAGER_H |
|
2 | 2 | #define SCIQLOP_CATALOGUEACTIONMANAGER_H |
|
3 | 3 | |
|
4 | 4 | #include <Common/spimpl.h> |
|
5 | 5 | |
|
6 | class CatalogueExplorer; | |
|
7 | ||
|
6 | 8 | class CatalogueActionManager { |
|
7 | 9 | public: |
|
8 | CatalogueActionManager(); | |
|
10 | CatalogueActionManager(CatalogueExplorer *catalogueExplorer); | |
|
9 | 11 | |
|
10 | 12 | void installSelectionZoneActions(); |
|
11 | 13 | |
|
12 | 14 | private: |
|
13 | 15 | class CatalogueActionManagerPrivate; |
|
14 | 16 | spimpl::unique_impl_ptr<CatalogueActionManagerPrivate> impl; |
|
15 | 17 | }; |
|
16 | 18 | |
|
17 | 19 | #endif // SCIQLOP_CATALOGUEACTIONMANAGER_H |
@@ -1,68 +1,68 | |||
|
1 | 1 | #ifndef SCIQLOP_CATALOGUEEVENTSMODEL_H |
|
2 | 2 | #define SCIQLOP_CATALOGUEEVENTSMODEL_H |
|
3 | 3 | |
|
4 | 4 | #include <Common/spimpl.h> |
|
5 | 5 | #include <QAbstractItemModel> |
|
6 | 6 | #include <QLoggingCategory> |
|
7 | 7 | #include <unordered_set> |
|
8 | 8 | |
|
9 | 9 | class DBEvent; |
|
10 | 10 | class DBEventProduct; |
|
11 | 11 | |
|
12 | 12 | Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsModel) |
|
13 | 13 | |
|
14 | 14 | class CatalogueEventsModel : public QAbstractItemModel { |
|
15 | 15 | Q_OBJECT |
|
16 | 16 | |
|
17 | 17 | signals: |
|
18 | 18 | void modelSorted(); |
|
19 | 19 | |
|
20 | 20 | public: |
|
21 | 21 | CatalogueEventsModel(QObject *parent = nullptr); |
|
22 | 22 | |
|
23 | 23 | enum class Column { Name, TStart, TEnd, Tags, Product, Validation, NbColumn }; |
|
24 | 24 | |
|
25 | 25 | void setEvents(const QVector<std::shared_ptr<DBEvent> > &events); |
|
26 | 26 | void addEvent(const std::shared_ptr<DBEvent> &event); |
|
27 | 27 | void removeEvent(const std::shared_ptr<DBEvent> &event); |
|
28 | 28 | QVector<std::shared_ptr<DBEvent> > events() const; |
|
29 | 29 | |
|
30 | 30 | enum class ItemType { Root, Event, EventProduct }; |
|
31 | 31 | ItemType itemTypeOf(const QModelIndex &index) const; |
|
32 | 32 | std::shared_ptr<DBEvent> getEvent(const QModelIndex &index) const; |
|
33 | 33 | std::shared_ptr<DBEvent> getParentEvent(const QModelIndex &index) const; |
|
34 | 34 | std::shared_ptr<DBEventProduct> getEventProduct(const QModelIndex &index) const; |
|
35 | 35 | |
|
36 | 36 | /// Refresh the data for the specified event |
|
37 | void refreshEvent(const std::shared_ptr<DBEvent> &event); | |
|
37 | void refreshEvent(const std::shared_ptr<DBEvent> &event, bool refreshEventProducts = false); | |
|
38 | 38 | |
|
39 | 39 | /// Returns a QModelIndex which represent the specified event |
|
40 | 40 | QModelIndex indexOf(const std::shared_ptr<DBEvent> &event) const; |
|
41 | 41 | |
|
42 | 42 | /// Marks a change flag on the specified event to allow sorting on the validation column |
|
43 | 43 | void setEventHasChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges); |
|
44 | 44 | |
|
45 | 45 | /// Returns true if the specified event has unsaved changes |
|
46 | 46 | bool eventsHasChanges(const std::shared_ptr<DBEvent> &event) const; |
|
47 | 47 | |
|
48 | 48 | // Model |
|
49 | 49 | QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; |
|
50 | 50 | QModelIndex parent(const QModelIndex &index) const; |
|
51 | 51 | int rowCount(const QModelIndex &parent = QModelIndex()) const override; |
|
52 | 52 | int columnCount(const QModelIndex &parent = QModelIndex()) const override; |
|
53 | 53 | Qt::ItemFlags flags(const QModelIndex &index) const override; |
|
54 | 54 | QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; |
|
55 | 55 | QVariant headerData(int section, Qt::Orientation orientation, |
|
56 | 56 | int role = Qt::DisplayRole) const override; |
|
57 | 57 | void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; |
|
58 | 58 | |
|
59 | 59 | Qt::DropActions supportedDragActions() const override; |
|
60 | 60 | QStringList mimeTypes() const override; |
|
61 | 61 | QMimeData *mimeData(const QModelIndexList &indexes) const override; |
|
62 | 62 | |
|
63 | 63 | private: |
|
64 | 64 | class CatalogueEventsModelPrivate; |
|
65 | 65 | spimpl::unique_impl_ptr<CatalogueEventsModelPrivate> impl; |
|
66 | 66 | }; |
|
67 | 67 | |
|
68 | 68 | #endif // SCIQLOP_CATALOGUEEVENTSMODEL_H |
@@ -1,48 +1,58 | |||
|
1 | 1 | #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H |
|
2 | 2 | #define SCIQLOP_CATALOGUEEVENTSWIDGET_H |
|
3 | 3 | |
|
4 | 4 | #include <Common/spimpl.h> |
|
5 | 5 | #include <QLoggingCategory> |
|
6 | 6 | #include <QWidget> |
|
7 | 7 | |
|
8 | 8 | class DBCatalogue; |
|
9 | 9 | class DBEvent; |
|
10 | 10 | class DBEventProduct; |
|
11 | 11 | class VisualizationWidget; |
|
12 | 12 | |
|
13 | 13 | namespace Ui { |
|
14 | 14 | class CatalogueEventsWidget; |
|
15 | 15 | } |
|
16 | 16 | |
|
17 | 17 | Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsWidget) |
|
18 | 18 | |
|
19 | 19 | class CatalogueEventsWidget : public QWidget { |
|
20 | 20 | Q_OBJECT |
|
21 | 21 | |
|
22 | 22 | signals: |
|
23 | 23 | void eventsSelected(const QVector<std::shared_ptr<DBEvent> > &event); |
|
24 | 24 | void eventProductsSelected( |
|
25 | 25 | const QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > |
|
26 | 26 | &eventproducts); |
|
27 | 27 | void selectionCleared(); |
|
28 | 28 | |
|
29 | 29 | public: |
|
30 | 30 | explicit CatalogueEventsWidget(QWidget *parent = 0); |
|
31 | 31 | virtual ~CatalogueEventsWidget(); |
|
32 | 32 | |
|
33 | 33 | void setVisualizationWidget(VisualizationWidget *visualization); |
|
34 | 34 | |
|
35 | void addEvent(const std::shared_ptr<DBEvent> &event); | |
|
35 | 36 | void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges); |
|
36 | 37 | |
|
38 | QVector<std::shared_ptr<DBCatalogue> > displayedCatalogues() const; | |
|
39 | bool isAllEventsDisplayed() const; | |
|
40 | bool isEventDisplayed(const std::shared_ptr<DBEvent> &event) const; | |
|
41 | ||
|
37 | 42 | public slots: |
|
38 | 43 | void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues); |
|
39 | 44 | void populateWithAllEvents(); |
|
45 | void clear(); | |
|
46 | void refresh(); | |
|
40 | 47 | |
|
41 | 48 | private: |
|
42 | 49 | Ui::CatalogueEventsWidget *ui; |
|
43 | 50 | |
|
44 | 51 | class CatalogueEventsWidgetPrivate; |
|
45 | 52 | spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl; |
|
53 | ||
|
54 | private slots: | |
|
55 | void emitSelection(); | |
|
46 | 56 | }; |
|
47 | 57 | |
|
48 | 58 | #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H |
@@ -1,29 +1,35 | |||
|
1 | 1 | #ifndef SCIQLOP_CATALOGUEEXPLORER_H |
|
2 | 2 | #define SCIQLOP_CATALOGUEEXPLORER_H |
|
3 | 3 | |
|
4 | 4 | #include <Common/spimpl.h> |
|
5 | 5 | #include <QDialog> |
|
6 | 6 | |
|
7 | 7 | namespace Ui { |
|
8 | 8 | class CatalogueExplorer; |
|
9 | 9 | } |
|
10 | 10 | |
|
11 | class CatalogueEventsWidget; | |
|
12 | class CatalogueSideBarWidget; | |
|
13 | ||
|
11 | 14 | class VisualizationWidget; |
|
12 | 15 | |
|
13 | 16 | class CatalogueExplorer : public QDialog { |
|
14 | 17 | Q_OBJECT |
|
15 | 18 | |
|
16 | 19 | public: |
|
17 | 20 | explicit CatalogueExplorer(QWidget *parent = 0); |
|
18 | 21 | virtual ~CatalogueExplorer(); |
|
19 | 22 | |
|
20 | 23 | void setVisualizationWidget(VisualizationWidget *visualization); |
|
21 | 24 | |
|
25 | CatalogueEventsWidget &eventsWidget() const; | |
|
26 | CatalogueSideBarWidget &sideBarWidget() const; | |
|
27 | ||
|
22 | 28 | private: |
|
23 | 29 | Ui::CatalogueExplorer *ui; |
|
24 | 30 | |
|
25 | 31 | class CatalogueExplorerPrivate; |
|
26 | 32 | spimpl::unique_impl_ptr<CatalogueExplorerPrivate> impl; |
|
27 | 33 | }; |
|
28 | 34 | |
|
29 | 35 | #endif // SCIQLOP_CATALOGUEEXPLORER_H |
@@ -1,43 +1,46 | |||
|
1 | 1 | #ifndef SCIQLOP_CATALOGUESIDEBARWIDGET_H |
|
2 | 2 | #define SCIQLOP_CATALOGUESIDEBARWIDGET_H |
|
3 | 3 | |
|
4 | 4 | #include <Common/spimpl.h> |
|
5 | 5 | #include <QLoggingCategory> |
|
6 | 6 | #include <QTreeWidgetItem> |
|
7 | 7 | #include <QWidget> |
|
8 | 8 | |
|
9 | 9 | class DBCatalogue; |
|
10 | 10 | |
|
11 | 11 | namespace Ui { |
|
12 | 12 | class CatalogueSideBarWidget; |
|
13 | 13 | } |
|
14 | 14 | |
|
15 | 15 | Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget) |
|
16 | 16 | |
|
17 | 17 | class CatalogueSideBarWidget : public QWidget { |
|
18 | 18 | Q_OBJECT |
|
19 | 19 | |
|
20 | 20 | signals: |
|
21 | 21 | void catalogueSelected(const QVector<std::shared_ptr<DBCatalogue> > &catalogues); |
|
22 | 22 | void databaseSelected(const QStringList &databases); |
|
23 | 23 | void allEventsSelected(); |
|
24 | 24 | void trashSelected(); |
|
25 | 25 | void selectionCleared(); |
|
26 | 26 | |
|
27 | 27 | public: |
|
28 | 28 | explicit CatalogueSideBarWidget(QWidget *parent = 0); |
|
29 | 29 | virtual ~CatalogueSideBarWidget(); |
|
30 | 30 | |
|
31 | void addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue, const QString &repository); | |
|
31 | 32 | void setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, bool hasChanges); |
|
32 | 33 | |
|
34 | QVector<std::shared_ptr<DBCatalogue> > getCatalogues(const QString &repository) const; | |
|
35 | ||
|
33 | 36 | private: |
|
34 | 37 | Ui::CatalogueSideBarWidget *ui; |
|
35 | 38 | |
|
36 | 39 | class CatalogueSideBarWidgetPrivate; |
|
37 | 40 | spimpl::unique_impl_ptr<CatalogueSideBarWidgetPrivate> impl; |
|
38 | 41 | |
|
39 | 42 | private slots: |
|
40 | 43 | void onContextMenuRequested(const QPoint &pos); |
|
41 | 44 | }; |
|
42 | 45 | |
|
43 | 46 | #endif // SCIQLOP_CATALOGUESIDEBARWIDGET_H |
@@ -1,35 +1,36 | |||
|
1 | 1 | #ifndef SCIQLOP_CREATEEVENTDIALOG_H |
|
2 | 2 | #define SCIQLOP_CREATEEVENTDIALOG_H |
|
3 | 3 | |
|
4 | 4 | #include <Common/spimpl.h> |
|
5 | 5 | #include <QDialog> |
|
6 | 6 | #include <memory> |
|
7 | 7 | |
|
8 | 8 | namespace Ui { |
|
9 | 9 | class CreateEventDialog; |
|
10 | 10 | } |
|
11 | 11 | |
|
12 | 12 | class DBCatalogue; |
|
13 | 13 | |
|
14 | 14 | class CreateEventDialog : public QDialog { |
|
15 | 15 | Q_OBJECT |
|
16 | 16 | |
|
17 | 17 | public: |
|
18 | explicit CreateEventDialog(QWidget *parent = 0); | |
|
18 | explicit CreateEventDialog(const QVector<std::shared_ptr<DBCatalogue> > &catalogues, | |
|
19 | QWidget *parent = 0); | |
|
19 | 20 | virtual ~CreateEventDialog(); |
|
20 | 21 | |
|
21 | 22 | void hideCatalogueChoice(); |
|
22 | 23 | |
|
23 | 24 | QString eventName() const; |
|
24 | 25 | |
|
25 | 26 | std::shared_ptr<DBCatalogue> selectedCatalogue() const; |
|
26 | 27 | QString catalogueName() const; |
|
27 | 28 | |
|
28 | 29 | private: |
|
29 | 30 | Ui::CreateEventDialog *ui; |
|
30 | 31 | |
|
31 | 32 | class CreateEventDialogPrivate; |
|
32 | 33 | spimpl::unique_impl_ptr<CreateEventDialogPrivate> impl; |
|
33 | 34 | }; |
|
34 | 35 | |
|
35 | 36 | #endif // SCIQLOP_CREATEEVENTDIALOG_H |
@@ -1,143 +1,147 | |||
|
1 | 1 | qxorm_dep = dependency('QxOrm', required : true, fallback:['QxOrm','qxorm_dep']) |
|
2 | 2 | catalogueapi_dep = dependency('CatalogueAPI', required : true, fallback:['CatalogueAPI','CatalogueAPI_dep']) |
|
3 | 3 | |
|
4 | 4 | gui_moc_headers = [ |
|
5 | 5 | 'include/DataSource/DataSourceWidget.h', |
|
6 | 6 | 'include/Settings/SqpSettingsDialog.h', |
|
7 | 7 | 'include/Settings/SqpSettingsGeneralWidget.h', |
|
8 | 8 | 'include/SidePane/SqpSidePane.h', |
|
9 | 9 | 'include/SqpApplication.h', |
|
10 | 10 | 'include/DragAndDrop/DragDropScroller.h', |
|
11 | 11 | 'include/DragAndDrop/DragDropTabSwitcher.h', |
|
12 | 12 | 'include/TimeWidget/TimeWidget.h', |
|
13 | 13 | 'include/Variable/VariableInspectorWidget.h', |
|
14 | 14 | 'include/Variable/RenameVariableDialog.h', |
|
15 | 15 | 'include/Visualization/qcustomplot.h', |
|
16 | 16 | 'include/Visualization/VisualizationGraphWidget.h', |
|
17 | 17 | 'include/Visualization/VisualizationTabWidget.h', |
|
18 | 18 | 'include/Visualization/VisualizationWidget.h', |
|
19 | 19 | 'include/Visualization/VisualizationZoneWidget.h', |
|
20 | 20 | 'include/Visualization/VisualizationDragDropContainer.h', |
|
21 | 21 | 'include/Visualization/VisualizationDragWidget.h', |
|
22 | 22 | 'include/Visualization/ColorScaleEditor.h', |
|
23 | 23 | 'include/Actions/SelectionZoneAction.h', |
|
24 | 24 | 'include/Visualization/VisualizationMultiZoneSelectionDialog.h', |
|
25 | 25 | 'include/Catalogue/CatalogueExplorer.h', |
|
26 | 26 | 'include/Catalogue/CatalogueEventsWidget.h', |
|
27 | 27 | 'include/Catalogue/CatalogueSideBarWidget.h', |
|
28 | 28 | 'include/Catalogue/CatalogueInspectorWidget.h', |
|
29 | 29 | 'include/Catalogue/CatalogueEventsModel.h', |
|
30 | 'include/Catalogue/CreateEventDialog.h' | |
|
30 | 'include/Catalogue/CreateEventDialog.h', | |
|
31 | 'include/Catalogue/CatalogueTreeModel.h' | |
|
31 | 32 | ] |
|
32 | 33 | |
|
33 | 34 | gui_ui_files = [ |
|
34 | 35 | 'ui/DataSource/DataSourceWidget.ui', |
|
35 | 36 | 'ui/Settings/SqpSettingsDialog.ui', |
|
36 | 37 | 'ui/Settings/SqpSettingsGeneralWidget.ui', |
|
37 | 38 | 'ui/SidePane/SqpSidePane.ui', |
|
38 | 39 | 'ui/TimeWidget/TimeWidget.ui', |
|
39 | 40 | 'ui/Variable/VariableInspectorWidget.ui', |
|
40 | 41 | 'ui/Variable/RenameVariableDialog.ui', |
|
41 | 42 | 'ui/Variable/VariableMenuHeaderWidget.ui', |
|
42 | 43 | 'ui/Visualization/VisualizationGraphWidget.ui', |
|
43 | 44 | 'ui/Visualization/VisualizationTabWidget.ui', |
|
44 | 45 | 'ui/Visualization/VisualizationWidget.ui', |
|
45 | 46 | 'ui/Visualization/VisualizationZoneWidget.ui', |
|
46 | 47 | 'ui/Visualization/ColorScaleEditor.ui', |
|
47 | 48 | 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui', |
|
48 | 49 | 'ui/Catalogue/CatalogueExplorer.ui', |
|
49 | 50 | 'ui/Catalogue/CatalogueEventsWidget.ui', |
|
50 | 51 | 'ui/Catalogue/CatalogueSideBarWidget.ui', |
|
51 | 52 | 'ui/Catalogue/CatalogueInspectorWidget.ui', |
|
52 | 53 | 'ui/Catalogue/CreateEventDialog.ui' |
|
53 | 54 | ] |
|
54 | 55 | |
|
55 | 56 | gui_qresources = ['resources/sqpguiresources.qrc'] |
|
56 | 57 | |
|
57 | 58 | rcc_gen = generator(rcc, |
|
58 | 59 | output : 'qrc_@BASENAME@.cpp', |
|
59 | 60 | arguments : [ |
|
60 | 61 | '--output', |
|
61 | 62 | '@OUTPUT@', |
|
62 | 63 | '@INPUT@', |
|
63 | 64 | '@EXTRA_ARGS@']) |
|
64 | 65 | |
|
65 | 66 | rcc_files = rcc_gen.process(gui_qresources, extra_args : ['-name', 'sqpguiresources']) |
|
66 | 67 | |
|
67 | 68 | gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers, |
|
68 | 69 | ui_files : gui_ui_files) |
|
69 | 70 | |
|
70 | 71 | gui_sources = [ |
|
71 | 72 | 'src/SqpApplication.cpp', |
|
72 | 73 | 'src/DragAndDrop/DragDropGuiController.cpp', |
|
73 | 74 | 'src/DragAndDrop/DragDropScroller.cpp', |
|
74 | 75 | 'src/DragAndDrop/DragDropTabSwitcher.cpp', |
|
75 | 76 | 'src/Common/ColorUtils.cpp', |
|
76 | 77 | 'src/Common/VisualizationDef.cpp', |
|
77 | 78 | 'src/DataSource/DataSourceTreeWidgetItem.cpp', |
|
78 | 79 | 'src/DataSource/DataSourceTreeWidgetHelper.cpp', |
|
79 | 80 | 'src/DataSource/DataSourceWidget.cpp', |
|
80 | 81 | 'src/DataSource/DataSourceTreeWidget.cpp', |
|
81 | 82 | 'src/Settings/SqpSettingsDialog.cpp', |
|
82 | 83 | 'src/Settings/SqpSettingsGeneralWidget.cpp', |
|
83 | 84 | 'src/SidePane/SqpSidePane.cpp', |
|
84 | 85 | 'src/TimeWidget/TimeWidget.cpp', |
|
85 | 86 | 'src/Variable/VariableInspectorWidget.cpp', |
|
86 | 87 | 'src/Variable/VariableInspectorTableView.cpp', |
|
87 | 88 | 'src/Variable/VariableMenuHeaderWidget.cpp', |
|
88 | 89 | 'src/Variable/RenameVariableDialog.cpp', |
|
89 | 90 | 'src/Visualization/VisualizationGraphHelper.cpp', |
|
90 | 91 | 'src/Visualization/VisualizationGraphRenderingDelegate.cpp', |
|
91 | 92 | 'src/Visualization/VisualizationGraphWidget.cpp', |
|
92 | 93 | 'src/Visualization/VisualizationTabWidget.cpp', |
|
93 | 94 | 'src/Visualization/VisualizationWidget.cpp', |
|
94 | 95 | 'src/Visualization/VisualizationZoneWidget.cpp', |
|
95 | 96 | 'src/Visualization/qcustomplot.cpp', |
|
96 | 97 | 'src/Visualization/QCustomPlotSynchronizer.cpp', |
|
97 | 98 | 'src/Visualization/operations/FindVariableOperation.cpp', |
|
98 | 99 | 'src/Visualization/operations/GenerateVariableMenuOperation.cpp', |
|
99 | 100 | 'src/Visualization/operations/MenuBuilder.cpp', |
|
100 | 101 | 'src/Visualization/operations/RemoveVariableOperation.cpp', |
|
101 | 102 | 'src/Visualization/operations/RescaleAxeOperation.cpp', |
|
102 | 103 | 'src/Visualization/VisualizationDragDropContainer.cpp', |
|
103 | 104 | 'src/Visualization/VisualizationDragWidget.cpp', |
|
104 | 105 | 'src/Visualization/AxisRenderingUtils.cpp', |
|
105 | 106 | 'src/Visualization/PlottablesRenderingUtils.cpp', |
|
106 | 107 | 'src/Visualization/MacScrollBarStyle.cpp', |
|
107 | 108 | 'src/Visualization/VisualizationCursorItem.cpp', |
|
108 | 109 | 'src/Visualization/ColorScaleEditor.cpp', |
|
109 | 110 | 'src/Visualization/SqpColorScale.cpp', |
|
110 | 111 | 'src/Visualization/QCPColorMapIterator.cpp', |
|
111 | 112 | 'src/Visualization/VisualizationSelectionZoneItem.cpp', |
|
112 | 113 | 'src/Visualization/VisualizationSelectionZoneManager.cpp', |
|
113 | 114 | 'src/Actions/SelectionZoneAction.cpp', |
|
114 | 115 | 'src/Actions/ActionsGuiController.cpp', |
|
115 | 116 | 'src/Visualization/VisualizationActionManager.cpp', |
|
116 | 117 | 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp', |
|
117 | 118 | 'src/Catalogue/CatalogueExplorer.cpp', |
|
118 | 119 | 'src/Catalogue/CatalogueEventsWidget.cpp', |
|
119 | 120 | 'src/Catalogue/CatalogueSideBarWidget.cpp', |
|
120 | 121 | 'src/Catalogue/CatalogueInspectorWidget.cpp', |
|
121 |
'src/Catalogue/CatalogueTree |
|
|
122 | 'src/Catalogue/CatalogueTreeItems/CatalogueAbstractTreeItem.cpp', | |
|
123 | 'src/Catalogue/CatalogueTreeItems/CatalogueTreeItem.cpp', | |
|
124 | 'src/Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.cpp', | |
|
122 | 125 | 'src/Catalogue/CatalogueEventsModel.cpp', |
|
123 | 126 | 'src/Catalogue/CatalogueExplorerHelper.cpp', |
|
124 | 127 | 'src/Catalogue/CatalogueActionManager.cpp', |
|
125 | 'src/Catalogue/CreateEventDialog.cpp' | |
|
128 | 'src/Catalogue/CreateEventDialog.cpp', | |
|
129 | 'src/Catalogue/CatalogueTreeModel.cpp' | |
|
126 | 130 | ] |
|
127 | 131 | |
|
128 | 132 | gui_inc = include_directories(['include']) |
|
129 | 133 | |
|
130 | 134 | sciqlop_gui_lib = library('sciqlopgui', |
|
131 | 135 | gui_sources, |
|
132 | 136 | gui_moc_files, |
|
133 | 137 | rcc_files, |
|
134 | 138 | include_directories : [gui_inc], |
|
135 | 139 | dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep], |
|
136 | 140 | install : true |
|
137 | 141 | ) |
|
138 | 142 | |
|
139 | 143 | sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib, |
|
140 | 144 | include_directories : gui_inc, |
|
141 | 145 | dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep]) |
|
142 | 146 | |
|
143 | 147 |
@@ -1,107 +1,136 | |||
|
1 | 1 | #include "Catalogue/CatalogueActionManager.h" |
|
2 | 2 | |
|
3 | 3 | #include <Actions/ActionsGuiController.h> |
|
4 | 4 | #include <Catalogue/CatalogueController.h> |
|
5 | #include <DataSource/DataSourceItem.h> | |
|
5 | 6 | #include <SqpApplication.h> |
|
6 | 7 | #include <Variable/Variable.h> |
|
7 | 8 | #include <Visualization/VisualizationGraphWidget.h> |
|
8 | 9 | #include <Visualization/VisualizationSelectionZoneItem.h> |
|
9 | 10 | |
|
11 | #include <Catalogue/CatalogueEventsWidget.h> | |
|
12 | #include <Catalogue/CatalogueExplorer.h> | |
|
13 | #include <Catalogue/CatalogueSideBarWidget.h> | |
|
10 | 14 | #include <Catalogue/CreateEventDialog.h> |
|
11 | 15 | |
|
16 | #include <CatalogueDao.h> | |
|
12 | 17 | #include <DBCatalogue.h> |
|
13 | 18 | #include <DBEvent.h> |
|
14 | 19 | #include <DBEventProduct.h> |
|
15 | 20 | |
|
16 | 21 | #include <QBoxLayout> |
|
17 | 22 | #include <QComboBox> |
|
18 | 23 | #include <QDialog> |
|
19 | 24 | #include <QDialogButtonBox> |
|
20 | 25 | #include <QLineEdit> |
|
21 | 26 | #include <memory> |
|
22 | 27 | |
|
23 | 28 | struct CatalogueActionManager::CatalogueActionManagerPrivate { |
|
29 | ||
|
30 | CatalogueExplorer *m_CatalogueExplorer = nullptr; | |
|
31 | ||
|
32 | CatalogueActionManagerPrivate(CatalogueExplorer *catalogueExplorer) | |
|
33 | : m_CatalogueExplorer(catalogueExplorer) | |
|
34 | { | |
|
35 | } | |
|
36 | ||
|
24 | 37 | void createEventFromZones(const QString &eventName, |
|
25 | 38 | const QVector<VisualizationSelectionZoneItem *> &zones, |
|
26 | 39 | const std::shared_ptr<DBCatalogue> &catalogue = nullptr) |
|
27 | 40 | { |
|
28 | 41 | auto event = std::make_shared<DBEvent>(); |
|
29 | 42 | event->setName(eventName); |
|
30 | 43 | |
|
31 | 44 | std::list<DBEventProduct> productList; |
|
32 | 45 | for (auto zone : zones) { |
|
33 | 46 | auto graph = zone->parentGraphWidget(); |
|
34 | 47 | for (auto var : graph->variables()) { |
|
35 | 48 | auto eventProduct = std::make_shared<DBEventProduct>(); |
|
36 | 49 | eventProduct->setEvent(*event); |
|
37 | 50 | |
|
38 | 51 | auto zoneRange = zone->range(); |
|
39 | 52 | eventProduct->setTStart(zoneRange.m_TStart); |
|
40 | 53 | eventProduct->setTEnd(zoneRange.m_TEnd); |
|
41 | 54 | |
|
42 |
eventProduct->setProductId( |
|
|
55 | eventProduct->setProductId( | |
|
56 | var->metadata().value(DataSourceItem::ID_DATA_KEY, "UnknownID").toString()); | |
|
43 | 57 | |
|
44 | 58 | productList.push_back(*eventProduct); |
|
45 | 59 | } |
|
46 | 60 | } |
|
47 | 61 | |
|
48 | 62 | event->setEventProducts(productList); |
|
49 | 63 | |
|
50 | 64 | sqpApp->catalogueController().addEvent(event); |
|
51 | 65 | |
|
66 | ||
|
52 | 67 | if (catalogue) { |
|
53 | 68 | // TODO |
|
54 | 69 | // catalogue->addEvent(event); |
|
70 | m_CatalogueExplorer->sideBarWidget().setCatalogueChanges(catalogue, true); | |
|
71 | if (m_CatalogueExplorer->eventsWidget().displayedCatalogues().contains(catalogue)) { | |
|
72 | m_CatalogueExplorer->eventsWidget().addEvent(event); | |
|
73 | m_CatalogueExplorer->eventsWidget().setEventChanges(event, true); | |
|
74 | } | |
|
75 | } | |
|
76 | else if (m_CatalogueExplorer->eventsWidget().isAllEventsDisplayed()) { | |
|
77 | m_CatalogueExplorer->eventsWidget().addEvent(event); | |
|
78 | m_CatalogueExplorer->eventsWidget().setEventChanges(event, true); | |
|
55 | 79 | } |
|
56 | 80 | } |
|
57 | 81 | }; |
|
58 | 82 | |
|
59 | CatalogueActionManager::CatalogueActionManager() | |
|
60 | : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>()} | |
|
83 | CatalogueActionManager::CatalogueActionManager(CatalogueExplorer *catalogueExplorer) | |
|
84 | : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>(catalogueExplorer)} | |
|
61 | 85 | { |
|
62 | 86 | } |
|
63 | 87 | |
|
64 | 88 | void CatalogueActionManager::installSelectionZoneActions() |
|
65 | 89 | { |
|
66 | 90 | auto &actionController = sqpApp->actionsGuiController(); |
|
67 | 91 | |
|
68 | 92 | auto createEventEnableFuntion = [](auto zones) { |
|
69 | 93 | QSet<VisualizationGraphWidget *> usedGraphs; |
|
70 | 94 | for (auto zone : zones) { |
|
71 | 95 | auto graph = zone->parentGraphWidget(); |
|
72 | 96 | if (!usedGraphs.contains(graph)) { |
|
73 | 97 | usedGraphs.insert(graph); |
|
74 | 98 | } |
|
75 | 99 | else { |
|
76 | 100 | return false; |
|
77 | 101 | } |
|
78 | 102 | } |
|
79 | 103 | |
|
80 | 104 | return true; |
|
81 | 105 | }; |
|
82 | 106 | |
|
83 | 107 | auto createEventAction = actionController.addSectionZoneAction( |
|
84 | 108 | {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) { |
|
85 |
CreateEventDialog dialog |
|
|
109 | CreateEventDialog dialog( | |
|
110 | impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT)); | |
|
86 | 111 | dialog.hideCatalogueChoice(); |
|
87 | 112 | if (dialog.exec() == QDialog::Accepted) { |
|
88 | 113 | impl->createEventFromZones(dialog.eventName(), zones); |
|
89 | 114 | } |
|
90 | 115 | }); |
|
91 | 116 | createEventAction->setEnableFunction(createEventEnableFuntion); |
|
92 | 117 | |
|
93 | 118 | auto createEventInCatalogueAction = actionController.addSectionZoneAction( |
|
94 | 119 | {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) { |
|
95 |
CreateEventDialog dialog |
|
|
120 | CreateEventDialog dialog( | |
|
121 | impl->m_CatalogueExplorer->sideBarWidget().getCatalogues(REPOSITORY_DEFAULT)); | |
|
96 | 122 | if (dialog.exec() == QDialog::Accepted) { |
|
97 | 123 | auto selectedCatalogue = dialog.selectedCatalogue(); |
|
98 | 124 | if (!selectedCatalogue) { |
|
99 | 125 | selectedCatalogue = std::make_shared<DBCatalogue>(); |
|
100 | 126 | selectedCatalogue->setName(dialog.catalogueName()); |
|
127 | // sqpApp->catalogueController().addCatalogue(selectedCatalogue); TODO | |
|
128 | impl->m_CatalogueExplorer->sideBarWidget().addCatalogue(selectedCatalogue, | |
|
129 | REPOSITORY_DEFAULT); | |
|
101 | 130 | } |
|
102 | 131 | |
|
103 | 132 | impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue); |
|
104 | 133 | } |
|
105 | 134 | }); |
|
106 | 135 | createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion); |
|
107 | 136 | } |
@@ -1,442 +1,461 | |||
|
1 | 1 | #include "Catalogue/CatalogueEventsModel.h" |
|
2 | 2 | |
|
3 | #include <Catalogue/CatalogueController.h> | |
|
3 | 4 | #include <Common/DateUtils.h> |
|
4 | 5 | #include <Common/MimeTypesDef.h> |
|
5 | 6 | #include <DBEvent.h> |
|
6 | 7 | #include <DBEventProduct.h> |
|
7 | 8 | #include <DBTag.h> |
|
8 | 9 | #include <Data/SqpRange.h> |
|
9 | 10 | #include <SqpApplication.h> |
|
10 | 11 | #include <Time/TimeController.h> |
|
11 | 12 | |
|
12 | 13 | #include <list> |
|
13 | 14 | #include <unordered_map> |
|
14 | 15 | |
|
15 | 16 | #include <QHash> |
|
16 | 17 | #include <QMimeData> |
|
17 | 18 | |
|
18 | 19 | Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel") |
|
19 | 20 | |
|
20 | 21 | const auto EVENT_ITEM_TYPE = 1; |
|
21 | 22 | const auto EVENT_PRODUCT_ITEM_TYPE = 2; |
|
22 | 23 | |
|
23 | 24 | struct CatalogueEventsModel::CatalogueEventsModelPrivate { |
|
24 | 25 | QVector<std::shared_ptr<DBEvent> > m_Events; |
|
25 | 26 | std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts; |
|
26 | std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges; | |
|
27 | 27 | |
|
28 | 28 | QStringList columnNames() |
|
29 | 29 | { |
|
30 | 30 | return QStringList{tr("Event"), tr("TStart"), tr("TEnd"), |
|
31 | 31 | tr("Tags"), tr("Product"), tr("")}; |
|
32 | 32 | } |
|
33 | 33 | |
|
34 | 34 | QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const |
|
35 | 35 | { |
|
36 | 36 | if (col == (int)CatalogueEventsModel::Column::Validation) { |
|
37 | return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true | |
|
38 | : QVariant(); | |
|
37 | auto hasChanges = sqpApp->catalogueController().eventHasChanges(event); | |
|
38 | return hasChanges ? true : QVariant(); | |
|
39 | 39 | } |
|
40 | 40 | |
|
41 | 41 | return eventData(col, event); |
|
42 | 42 | } |
|
43 | 43 | |
|
44 | 44 | QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const |
|
45 | 45 | { |
|
46 | 46 | switch (static_cast<Column>(col)) { |
|
47 | 47 | case CatalogueEventsModel::Column::Name: |
|
48 | 48 | return event->getName(); |
|
49 | 49 | case CatalogueEventsModel::Column::TStart: |
|
50 | 50 | return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart()) |
|
51 | 51 | : QVariant{}; |
|
52 | 52 | case CatalogueEventsModel::Column::TEnd: |
|
53 | 53 | return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd()) |
|
54 | 54 | : QVariant{}; |
|
55 | 55 | case CatalogueEventsModel::Column::Product: |
|
56 | 56 | return QString::number(nbEventProducts(event)) + " product(s)"; |
|
57 | 57 | case CatalogueEventsModel::Column::Tags: { |
|
58 | 58 | QString tagList; |
|
59 | 59 | auto tags = event->getTags(); |
|
60 | 60 | for (auto tag : tags) { |
|
61 | 61 | tagList += tag.getName(); |
|
62 | 62 | tagList += ' '; |
|
63 | 63 | } |
|
64 | 64 | |
|
65 | 65 | return tagList; |
|
66 | 66 | } |
|
67 | 67 | case CatalogueEventsModel::Column::Validation: |
|
68 | 68 | return QVariant(); |
|
69 | 69 | default: |
|
70 | 70 | break; |
|
71 | 71 | } |
|
72 | 72 | |
|
73 | 73 | Q_ASSERT(false); |
|
74 | 74 | return QStringLiteral("Unknown Data"); |
|
75 | 75 | } |
|
76 | 76 | |
|
77 | 77 | void parseEventProduct(const std::shared_ptr<DBEvent> &event) |
|
78 | 78 | { |
|
79 | 79 | for (auto product : event->getEventProducts()) { |
|
80 | 80 | m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product)); |
|
81 | 81 | } |
|
82 | 82 | } |
|
83 | 83 | |
|
84 | 84 | int nbEventProducts(const std::shared_ptr<DBEvent> &event) const |
|
85 | 85 | { |
|
86 | 86 | auto eventProductsIt = m_EventProducts.find(event.get()); |
|
87 | 87 | if (eventProductsIt != m_EventProducts.cend()) { |
|
88 | 88 | return m_EventProducts.at(event.get()).count(); |
|
89 | 89 | } |
|
90 | 90 | else { |
|
91 | 91 | return 0; |
|
92 | 92 | } |
|
93 | 93 | } |
|
94 | 94 | |
|
95 | 95 | QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const |
|
96 | 96 | { |
|
97 | 97 | switch (static_cast<Column>(col)) { |
|
98 | 98 | case CatalogueEventsModel::Column::Name: |
|
99 | 99 | return eventProduct->getProductId(); |
|
100 | 100 | case CatalogueEventsModel::Column::TStart: |
|
101 | 101 | return DateUtils::dateTime(eventProduct->getTStart()); |
|
102 | 102 | case CatalogueEventsModel::Column::TEnd: |
|
103 | 103 | return DateUtils::dateTime(eventProduct->getTEnd()); |
|
104 | 104 | case CatalogueEventsModel::Column::Product: |
|
105 | 105 | return eventProduct->getProductId(); |
|
106 | 106 | case CatalogueEventsModel::Column::Tags: |
|
107 | 107 | return QString(); |
|
108 | 108 | case CatalogueEventsModel::Column::Validation: |
|
109 | 109 | return QVariant(); |
|
110 | 110 | default: |
|
111 | 111 | break; |
|
112 | 112 | } |
|
113 | 113 | |
|
114 | 114 | Q_ASSERT(false); |
|
115 | 115 | return QStringLiteral("Unknown Data"); |
|
116 | 116 | } |
|
117 | ||
|
118 | void refreshChildrenOfIndex(CatalogueEventsModel *model, const QModelIndex &index) const | |
|
119 | { | |
|
120 | auto childCount = model->rowCount(index); | |
|
121 | auto colCount = model->columnCount(); | |
|
122 | emit model->dataChanged(model->index(0, 0, index), | |
|
123 | model->index(childCount, colCount, index)); | |
|
124 | } | |
|
117 | 125 | }; |
|
118 | 126 | |
|
119 | 127 | CatalogueEventsModel::CatalogueEventsModel(QObject *parent) |
|
120 | 128 | : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()} |
|
121 | 129 | { |
|
122 | 130 | } |
|
123 | 131 | |
|
124 | 132 | void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events) |
|
125 | 133 | { |
|
126 | 134 | beginResetModel(); |
|
127 | 135 | |
|
128 | 136 | impl->m_Events = events; |
|
129 | 137 | impl->m_EventProducts.clear(); |
|
130 | impl->m_EventsWithChanges.clear(); | |
|
131 | 138 | for (auto event : events) { |
|
132 | 139 | impl->parseEventProduct(event); |
|
133 | 140 | } |
|
134 | 141 | |
|
135 | 142 | endResetModel(); |
|
136 | 143 | } |
|
137 | 144 | |
|
138 | 145 | std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const |
|
139 | 146 | { |
|
140 | 147 | if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) { |
|
141 | 148 | return impl->m_Events.value(index.row()); |
|
142 | 149 | } |
|
143 | 150 | else { |
|
144 | 151 | return nullptr; |
|
145 | 152 | } |
|
146 | 153 | } |
|
147 | 154 | |
|
148 | 155 | std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const |
|
149 | 156 | { |
|
150 | 157 | if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) { |
|
151 | 158 | return getEvent(index.parent()); |
|
152 | 159 | } |
|
153 | 160 | else { |
|
154 | 161 | return nullptr; |
|
155 | 162 | } |
|
156 | 163 | } |
|
157 | 164 | |
|
158 | 165 | std::shared_ptr<DBEventProduct> |
|
159 | 166 | CatalogueEventsModel::getEventProduct(const QModelIndex &index) const |
|
160 | 167 | { |
|
161 | 168 | if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) { |
|
162 | 169 | auto event = static_cast<DBEvent *>(index.internalPointer()); |
|
163 | 170 | return impl->m_EventProducts.at(event).value(index.row()); |
|
164 | 171 | } |
|
165 | 172 | else { |
|
166 | 173 | return nullptr; |
|
167 | 174 | } |
|
168 | 175 | } |
|
169 | 176 | |
|
170 | 177 | void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event) |
|
171 | 178 | { |
|
172 |
beginInsertRows(QModelIndex(), impl->m_Events.count() |
|
|
179 | beginInsertRows(QModelIndex(), impl->m_Events.count(), impl->m_Events.count()); | |
|
173 | 180 | impl->m_Events.append(event); |
|
174 | 181 | impl->parseEventProduct(event); |
|
175 | 182 | endInsertRows(); |
|
183 | ||
|
184 | // Also refreshes its children event products | |
|
185 | auto eventIndex = index(impl->m_Events.count(), 0); | |
|
186 | impl->refreshChildrenOfIndex(this, eventIndex); | |
|
176 | 187 | } |
|
177 | 188 | |
|
178 | 189 | void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event) |
|
179 | 190 | { |
|
180 | 191 | auto index = impl->m_Events.indexOf(event); |
|
181 | 192 | if (index >= 0) { |
|
182 | 193 | beginRemoveRows(QModelIndex(), index, index); |
|
183 | 194 | impl->m_Events.removeAt(index); |
|
184 | 195 | impl->m_EventProducts.erase(event.get()); |
|
185 | impl->m_EventsWithChanges.erase(event); | |
|
186 | 196 | endRemoveRows(); |
|
187 | 197 | } |
|
188 | 198 | } |
|
189 | 199 | |
|
190 | 200 | QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const |
|
191 | 201 | { |
|
192 | 202 | return impl->m_Events; |
|
193 | 203 | } |
|
194 | 204 | |
|
195 |
void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event |
|
|
205 | void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event, | |
|
206 | bool refreshEventProducts) | |
|
196 | 207 | { |
|
197 | 208 | auto eventIndex = indexOf(event); |
|
198 | 209 | if (eventIndex.isValid()) { |
|
199 | 210 | |
|
211 | if (refreshEventProducts) { | |
|
212 | // Reparse the associated event products | |
|
213 | ||
|
214 | auto nbEventProducts = impl->nbEventProducts(event); | |
|
215 | auto newNbOfEventProducts = event->getEventProducts().size(); | |
|
216 | if (newNbOfEventProducts < nbEventProducts) { | |
|
217 | beginRemoveRows(eventIndex, newNbOfEventProducts, nbEventProducts - 1); | |
|
218 | impl->m_EventProducts.erase(event.get()); | |
|
219 | impl->parseEventProduct(event); | |
|
220 | endRemoveRows(); | |
|
221 | } | |
|
222 | else if (newNbOfEventProducts > nbEventProducts) { | |
|
223 | beginInsertRows(eventIndex, nbEventProducts, newNbOfEventProducts - 1); | |
|
224 | impl->m_EventProducts.erase(event.get()); | |
|
225 | impl->parseEventProduct(event); | |
|
226 | endInsertRows(); | |
|
227 | } | |
|
228 | else { // newNbOfEventProducts == nbEventProducts | |
|
229 | impl->m_EventProducts.erase(event.get()); | |
|
230 | impl->parseEventProduct(event); | |
|
231 | } | |
|
232 | } | |
|
233 | ||
|
200 | 234 | // Refreshes the event line |
|
201 | 235 | auto colCount = columnCount(); |
|
202 | 236 | emit dataChanged(eventIndex, index(eventIndex.row(), colCount)); |
|
203 | 237 | |
|
204 | 238 | // Also refreshes its children event products |
|
205 | auto childCount = rowCount(eventIndex); | |
|
206 | emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex)); | |
|
239 | impl->refreshChildrenOfIndex(this, eventIndex); | |
|
207 | 240 | } |
|
208 | 241 | else { |
|
209 | 242 | qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found."; |
|
210 | 243 | } |
|
211 | 244 | } |
|
212 | 245 | |
|
213 | 246 | QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const |
|
214 | 247 | { |
|
215 | 248 | auto row = impl->m_Events.indexOf(event); |
|
216 | 249 | if (row >= 0) { |
|
217 | 250 | return index(row, 0); |
|
218 | 251 | } |
|
219 | 252 | |
|
220 | 253 | return QModelIndex(); |
|
221 | 254 | } |
|
222 | 255 | |
|
223 | void CatalogueEventsModel::setEventHasChanges(const std::shared_ptr<DBEvent> &event, | |
|
224 | bool hasChanges) | |
|
225 | { | |
|
226 | if (hasChanges) { | |
|
227 | impl->m_EventsWithChanges.insert(event); | |
|
228 | } | |
|
229 | else { | |
|
230 | impl->m_EventsWithChanges.erase(event); | |
|
231 | } | |
|
232 | } | |
|
233 | ||
|
234 | bool CatalogueEventsModel::eventsHasChanges(const std::shared_ptr<DBEvent> &event) const | |
|
235 | { | |
|
236 | return impl->m_EventsWithChanges.find(event) != impl->m_EventsWithChanges.cend(); | |
|
237 | } | |
|
238 | ||
|
239 | 256 | QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const |
|
240 | 257 | { |
|
241 | 258 | if (!hasIndex(row, column, parent)) { |
|
242 | 259 | return QModelIndex(); |
|
243 | 260 | } |
|
244 | 261 | |
|
245 | 262 | switch (itemTypeOf(parent)) { |
|
246 | 263 | case CatalogueEventsModel::ItemType::Root: |
|
247 | 264 | return createIndex(row, column); |
|
248 | 265 | case CatalogueEventsModel::ItemType::Event: { |
|
249 | 266 | auto event = getEvent(parent); |
|
250 | 267 | return createIndex(row, column, event.get()); |
|
251 | 268 | } |
|
252 | 269 | case CatalogueEventsModel::ItemType::EventProduct: |
|
253 | 270 | break; |
|
254 | 271 | default: |
|
255 | 272 | break; |
|
256 | 273 | } |
|
257 | 274 | |
|
258 | 275 | return QModelIndex(); |
|
259 | 276 | } |
|
260 | 277 | |
|
261 | 278 | QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const |
|
262 | 279 | { |
|
263 | 280 | switch (itemTypeOf(index)) { |
|
264 | 281 | case CatalogueEventsModel::ItemType::EventProduct: { |
|
265 | 282 | auto parentEvent = static_cast<DBEvent *>(index.internalPointer()); |
|
266 | 283 | auto it |
|
267 | 284 | = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(), |
|
268 | 285 | [parentEvent](auto event) { return event.get() == parentEvent; }); |
|
269 | 286 | |
|
270 | 287 | if (it != impl->m_Events.cend()) { |
|
271 | 288 | return createIndex(it - impl->m_Events.cbegin(), 0); |
|
272 | 289 | } |
|
273 | 290 | else { |
|
274 | 291 | return QModelIndex(); |
|
275 | 292 | } |
|
276 | 293 | } |
|
277 | 294 | case CatalogueEventsModel::ItemType::Root: |
|
278 | 295 | break; |
|
279 | 296 | case CatalogueEventsModel::ItemType::Event: |
|
280 | 297 | break; |
|
281 | 298 | default: |
|
282 | 299 | break; |
|
283 | 300 | } |
|
284 | 301 | |
|
285 | 302 | return QModelIndex(); |
|
286 | 303 | } |
|
287 | 304 | |
|
288 | 305 | int CatalogueEventsModel::rowCount(const QModelIndex &parent) const |
|
289 | 306 | { |
|
290 | 307 | if (parent.column() > 0) { |
|
291 | 308 | return 0; |
|
292 | 309 | } |
|
293 | 310 | |
|
294 | 311 | switch (itemTypeOf(parent)) { |
|
295 | 312 | case CatalogueEventsModel::ItemType::Root: |
|
296 | 313 | return impl->m_Events.count(); |
|
297 | 314 | case CatalogueEventsModel::ItemType::Event: { |
|
298 | 315 | auto event = getEvent(parent); |
|
299 | 316 | return impl->m_EventProducts[event.get()].count(); |
|
300 | 317 | } |
|
301 | 318 | case CatalogueEventsModel::ItemType::EventProduct: |
|
302 | 319 | break; |
|
303 | 320 | default: |
|
304 | 321 | break; |
|
305 | 322 | } |
|
306 | 323 | |
|
307 | 324 | return 0; |
|
308 | 325 | } |
|
309 | 326 | |
|
310 | 327 | int CatalogueEventsModel::columnCount(const QModelIndex &parent) const |
|
311 | 328 | { |
|
312 | 329 | return static_cast<int>(CatalogueEventsModel::Column::NbColumn); |
|
313 | 330 | } |
|
314 | 331 | |
|
315 | 332 | Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const |
|
316 | 333 | { |
|
317 | 334 | return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled; |
|
318 | 335 | } |
|
319 | 336 | |
|
320 | 337 | QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const |
|
321 | 338 | { |
|
322 | 339 | if (index.isValid()) { |
|
323 | 340 | |
|
324 | 341 | auto type = itemTypeOf(index); |
|
325 | 342 | if (type == CatalogueEventsModel::ItemType::Event) { |
|
326 | 343 | auto event = getEvent(index); |
|
327 | 344 | switch (role) { |
|
328 | 345 | case Qt::DisplayRole: |
|
329 | 346 | return impl->eventData(index.column(), event); |
|
330 | 347 | break; |
|
331 | 348 | } |
|
332 | 349 | } |
|
333 | 350 | else if (type == CatalogueEventsModel::ItemType::EventProduct) { |
|
334 | 351 | auto product = getEventProduct(index); |
|
335 | 352 | switch (role) { |
|
336 | 353 | case Qt::DisplayRole: |
|
337 | 354 | return impl->eventProductData(index.column(), product); |
|
338 | 355 | break; |
|
339 | 356 | } |
|
340 | 357 | } |
|
341 | 358 | } |
|
342 | 359 | |
|
343 | 360 | return QVariant{}; |
|
344 | 361 | } |
|
345 | 362 | |
|
346 | 363 | QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const |
|
347 | 364 | { |
|
348 | 365 | if (orientation == Qt::Horizontal && role == Qt::DisplayRole) { |
|
349 | 366 | return impl->columnNames().value(section); |
|
350 | 367 | } |
|
351 | 368 | |
|
352 | 369 | return QVariant(); |
|
353 | 370 | } |
|
354 | 371 | |
|
355 | 372 | void CatalogueEventsModel::sort(int column, Qt::SortOrder order) |
|
356 | 373 | { |
|
374 | beginResetModel(); | |
|
357 | 375 | std::sort(impl->m_Events.begin(), impl->m_Events.end(), |
|
358 | 376 | [this, column, order](auto e1, auto e2) { |
|
359 | 377 | auto data1 = impl->sortData(column, e1); |
|
360 | 378 | auto data2 = impl->sortData(column, e2); |
|
361 | 379 | |
|
362 | 380 | auto result = data1.toString() < data2.toString(); |
|
363 | 381 | |
|
364 | 382 | return order == Qt::AscendingOrder ? result : !result; |
|
365 | 383 | }); |
|
366 | 384 | |
|
367 | emit dataChanged(QModelIndex(), QModelIndex()); | |
|
385 | endResetModel(); | |
|
368 | 386 | emit modelSorted(); |
|
369 | 387 | } |
|
370 | 388 | |
|
371 | 389 | Qt::DropActions CatalogueEventsModel::supportedDragActions() const |
|
372 | 390 | { |
|
373 |
return Qt::CopyAction |
|
|
391 | return Qt::CopyAction; | |
|
374 | 392 | } |
|
375 | 393 | |
|
376 | 394 | QStringList CatalogueEventsModel::mimeTypes() const |
|
377 | 395 | { |
|
378 | 396 | return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE}; |
|
379 | 397 | } |
|
380 | 398 | |
|
381 | 399 | QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const |
|
382 | 400 | { |
|
383 | 401 | auto mimeData = new QMimeData; |
|
384 | 402 | |
|
385 | 403 | bool isFirst = true; |
|
386 | 404 | |
|
387 | 405 | QVector<std::shared_ptr<DBEvent> > eventList; |
|
388 | 406 | QVector<std::shared_ptr<DBEventProduct> > eventProductList; |
|
389 | 407 | |
|
390 | 408 | SqpRange firstTimeRange; |
|
391 | 409 | for (const auto &index : indexes) { |
|
392 | 410 | if (index.column() == 0) { // only the first column |
|
393 | 411 | |
|
394 | 412 | auto type = itemTypeOf(index); |
|
395 | 413 | if (type == ItemType::Event) { |
|
396 | 414 | auto event = getEvent(index); |
|
397 | 415 | eventList << event; |
|
398 | 416 | |
|
399 | 417 | if (isFirst) { |
|
400 | 418 | isFirst = false; |
|
401 | 419 | firstTimeRange.m_TStart = event->getTStart(); |
|
402 | 420 | firstTimeRange.m_TEnd = event->getTEnd(); |
|
403 | 421 | } |
|
404 | 422 | } |
|
405 | 423 | else if (type == ItemType::EventProduct) { |
|
406 | 424 | auto product = getEventProduct(index); |
|
407 | 425 | eventProductList << product; |
|
408 | 426 | |
|
409 | 427 | if (isFirst) { |
|
410 | 428 | isFirst = false; |
|
411 | 429 | firstTimeRange.m_TStart = product->getTStart(); |
|
412 | 430 | firstTimeRange.m_TEnd = product->getTEnd(); |
|
413 | 431 | } |
|
414 | 432 | } |
|
415 | 433 | } |
|
416 | 434 | } |
|
417 | 435 | |
|
418 | auto eventsEncodedData | |
|
419 |
= |
|
|
420 | mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData); | |
|
436 | if (!eventList.isEmpty() && eventProductList.isEmpty()) { | |
|
437 | auto eventsEncodedData = sqpApp->catalogueController().mimeDataForEvents(eventList); | |
|
438 | mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData); | |
|
439 | } | |
|
421 | 440 | |
|
422 | 441 | if (eventList.count() + eventProductList.count() == 1) { |
|
423 | 442 | // No time range MIME data if multiple events are dragged |
|
424 | 443 | auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange); |
|
425 | 444 | mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData); |
|
426 | 445 | } |
|
427 | 446 | |
|
428 | 447 | return mimeData; |
|
429 | 448 | } |
|
430 | 449 | |
|
431 | 450 | CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const |
|
432 | 451 | { |
|
433 | 452 | if (!index.isValid()) { |
|
434 | 453 | return ItemType::Root; |
|
435 | 454 | } |
|
436 | 455 | else if (index.internalPointer() == nullptr) { |
|
437 | 456 | return ItemType::Event; |
|
438 | 457 | } |
|
439 | 458 | else { |
|
440 | 459 | return ItemType::EventProduct; |
|
441 | 460 | } |
|
442 | 461 | } |
@@ -1,360 +1,460 | |||
|
1 | 1 | #include "Catalogue/CatalogueEventsWidget.h" |
|
2 | 2 | #include "ui_CatalogueEventsWidget.h" |
|
3 | 3 | |
|
4 | 4 | #include <Catalogue/CatalogueController.h> |
|
5 | 5 | #include <Catalogue/CatalogueEventsModel.h> |
|
6 | 6 | #include <Catalogue/CatalogueExplorerHelper.h> |
|
7 | 7 | #include <CatalogueDao.h> |
|
8 | 8 | #include <DBCatalogue.h> |
|
9 | 9 | #include <SqpApplication.h> |
|
10 | 10 | #include <Visualization/VisualizationTabWidget.h> |
|
11 | 11 | #include <Visualization/VisualizationWidget.h> |
|
12 | 12 | #include <Visualization/VisualizationZoneWidget.h> |
|
13 | 13 | |
|
14 | 14 | #include <QDialog> |
|
15 | 15 | #include <QDialogButtonBox> |
|
16 | 16 | #include <QListWidget> |
|
17 | #include <QMessageBox> | |
|
17 | 18 | |
|
18 | 19 | Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget") |
|
19 | 20 | |
|
20 | 21 | /// Fixed size of the validation column |
|
21 | 22 | const auto VALIDATION_COLUMN_SIZE = 35; |
|
22 | 23 | |
|
23 | 24 | struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate { |
|
24 | 25 | |
|
25 | 26 | CatalogueEventsModel *m_Model = nullptr; |
|
26 | 27 | QStringList m_ZonesForTimeMode; |
|
27 | 28 | QString m_ZoneForGraphMode; |
|
29 | QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues; | |
|
28 | 30 | |
|
29 | 31 | VisualizationWidget *m_VisualizationWidget = nullptr; |
|
30 | 32 | |
|
31 |
void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, |
|
|
33 | void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget) | |
|
32 | 34 | { |
|
33 | treeView->setSortingEnabled(false); | |
|
35 | widget->ui->treeView->setSortingEnabled(false); | |
|
34 | 36 | m_Model->setEvents(events); |
|
35 | treeView->setSortingEnabled(true); | |
|
37 | widget->ui->treeView->setSortingEnabled(true); | |
|
38 | ||
|
39 | for (auto event : events) { | |
|
40 | if (sqpApp->catalogueController().eventHasChanges(event)) { | |
|
41 | auto index = m_Model->indexOf(event); | |
|
42 | widget->setEventChanges(event, true); | |
|
43 | } | |
|
44 | } | |
|
36 | 45 | } |
|
37 | 46 | |
|
38 | 47 | void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView) |
|
39 | 48 | { |
|
40 | 49 | treeView->setSortingEnabled(false); |
|
41 | 50 | m_Model->addEvent(event); |
|
42 | 51 | treeView->setSortingEnabled(true); |
|
43 | 52 | } |
|
44 | 53 | |
|
45 | 54 | void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView) |
|
46 | 55 | { |
|
47 | 56 | treeView->setSortingEnabled(false); |
|
48 | 57 | m_Model->removeEvent(event); |
|
49 | 58 | treeView->setSortingEnabled(true); |
|
50 | 59 | } |
|
51 | 60 | |
|
52 | 61 | QStringList getAvailableVisualizationZoneList() const |
|
53 | 62 | { |
|
54 | 63 | if (m_VisualizationWidget) { |
|
55 | 64 | if (auto tab = m_VisualizationWidget->currentTabWidget()) { |
|
56 | 65 | return tab->availableZoneWidgets(); |
|
57 | 66 | } |
|
58 | 67 | } |
|
59 | 68 | |
|
60 | 69 | return QStringList{}; |
|
61 | 70 | } |
|
62 | 71 | |
|
63 | 72 | QStringList selectZone(QWidget *parent, const QStringList &selectedZones, |
|
64 | 73 | bool allowMultiSelection, const QPoint &location) |
|
65 | 74 | { |
|
66 | 75 | auto availableZones = getAvailableVisualizationZoneList(); |
|
67 | 76 | if (availableZones.isEmpty()) { |
|
68 | 77 | return QStringList{}; |
|
69 | 78 | } |
|
70 | 79 | |
|
71 | 80 | QDialog d(parent, Qt::Tool); |
|
72 | 81 | d.setWindowTitle("Choose a zone"); |
|
73 | 82 | auto layout = new QVBoxLayout{&d}; |
|
74 | 83 | layout->setContentsMargins(0, 0, 0, 0); |
|
75 | 84 | auto listWidget = new QListWidget{&d}; |
|
76 | 85 | layout->addWidget(listWidget); |
|
77 | 86 | |
|
78 | 87 | QSet<QListWidgetItem *> checkedItems; |
|
79 | 88 | for (auto zone : availableZones) { |
|
80 | 89 | auto item = new QListWidgetItem{zone}; |
|
81 | 90 | item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable); |
|
82 | 91 | if (selectedZones.contains(zone)) { |
|
83 | 92 | item->setCheckState(Qt::Checked); |
|
84 | 93 | checkedItems << item; |
|
85 | 94 | } |
|
86 | 95 | else { |
|
87 | 96 | item->setCheckState(Qt::Unchecked); |
|
88 | 97 | } |
|
89 | 98 | |
|
90 | 99 | listWidget->addItem(item); |
|
91 | 100 | } |
|
92 | 101 | |
|
93 | 102 | auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d}; |
|
94 | 103 | layout->addWidget(buttonBox); |
|
95 | 104 | |
|
96 | 105 | QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept); |
|
97 | 106 | QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject); |
|
98 | 107 | |
|
99 | 108 | QObject::connect(listWidget, &QListWidget::itemChanged, |
|
100 | 109 | [&checkedItems, allowMultiSelection, listWidget](auto item) { |
|
101 | 110 | if (item->checkState() == Qt::Checked) { |
|
102 | 111 | if (!allowMultiSelection) { |
|
103 | 112 | for (auto checkedItem : checkedItems) { |
|
104 | 113 | listWidget->blockSignals(true); |
|
105 | 114 | checkedItem->setCheckState(Qt::Unchecked); |
|
106 | 115 | listWidget->blockSignals(false); |
|
107 | 116 | } |
|
108 | 117 | |
|
109 | 118 | checkedItems.clear(); |
|
110 | 119 | } |
|
111 | 120 | checkedItems << item; |
|
112 | 121 | } |
|
113 | 122 | else { |
|
114 | 123 | checkedItems.remove(item); |
|
115 | 124 | } |
|
116 | 125 | }); |
|
117 | 126 | |
|
118 | 127 | QStringList result; |
|
119 | 128 | |
|
120 | 129 | d.setMinimumWidth(120); |
|
121 | 130 | d.resize(d.minimumSizeHint()); |
|
122 | 131 | d.move(location); |
|
123 | 132 | if (d.exec() == QDialog::Accepted) { |
|
124 | 133 | for (auto item : checkedItems) { |
|
125 | 134 | result += item->text(); |
|
126 | 135 | } |
|
127 | 136 | } |
|
128 | 137 | else { |
|
129 | 138 | result = selectedZones; |
|
130 | 139 | } |
|
131 | 140 | |
|
132 | 141 | return result; |
|
133 | 142 | } |
|
134 | 143 | |
|
135 | 144 | void updateForTimeMode(QTreeView *treeView) |
|
136 | 145 | { |
|
137 | 146 | auto selectedRows = treeView->selectionModel()->selectedRows(); |
|
138 | 147 | |
|
139 | 148 | if (selectedRows.count() == 1) { |
|
140 | 149 | auto event = m_Model->getEvent(selectedRows.first()); |
|
141 | 150 | if (event) { |
|
142 | 151 | if (m_VisualizationWidget) { |
|
143 | 152 | if (auto tab = m_VisualizationWidget->currentTabWidget()) { |
|
144 | 153 | |
|
145 | 154 | for (auto zoneName : m_ZonesForTimeMode) { |
|
146 | 155 | if (auto zone = tab->getZoneWithName(zoneName)) { |
|
147 | 156 | SqpRange eventRange; |
|
148 | 157 | eventRange.m_TStart = event->getTStart(); |
|
149 | 158 | eventRange.m_TEnd = event->getTEnd(); |
|
150 | 159 | zone->setZoneRange(eventRange); |
|
151 | 160 | } |
|
152 | 161 | } |
|
153 | 162 | } |
|
154 | 163 | else { |
|
155 | 164 | qCWarning(LOG_CatalogueEventsWidget()) |
|
156 | 165 | << "updateTimeZone: no tab found in the visualization"; |
|
157 | 166 | } |
|
158 | 167 | } |
|
159 | 168 | else { |
|
160 | 169 | qCWarning(LOG_CatalogueEventsWidget()) |
|
161 | 170 | << "updateTimeZone: visualization widget not found"; |
|
162 | 171 | } |
|
163 | 172 | } |
|
164 | 173 | } |
|
165 | 174 | else { |
|
166 | 175 | qCWarning(LOG_CatalogueEventsWidget()) |
|
167 | 176 | << "updateTimeZone: not compatible with multiple events selected"; |
|
168 | 177 | } |
|
169 | 178 | } |
|
170 | 179 | |
|
171 | 180 | void updateForGraphMode(QTreeView *treeView) |
|
172 | 181 | { |
|
173 | 182 | auto selectedRows = treeView->selectionModel()->selectedRows(); |
|
174 | 183 | |
|
175 | 184 | if (selectedRows.count() == 1) { |
|
176 | 185 | auto event = m_Model->getEvent(selectedRows.first()); |
|
177 | 186 | if (m_VisualizationWidget) { |
|
178 | 187 | if (auto tab = m_VisualizationWidget->currentTabWidget()) { |
|
179 | 188 | if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) { |
|
180 | 189 | // TODO |
|
181 | 190 | } |
|
182 | 191 | } |
|
183 | 192 | else { |
|
184 | 193 | qCWarning(LOG_CatalogueEventsWidget()) |
|
185 | 194 | << "updateGraphMode: no tab found in the visualization"; |
|
186 | 195 | } |
|
187 | 196 | } |
|
188 | 197 | else { |
|
189 | 198 | qCWarning(LOG_CatalogueEventsWidget()) |
|
190 | 199 | << "updateGraphMode: visualization widget not found"; |
|
191 | 200 | } |
|
192 | 201 | } |
|
193 | 202 | else { |
|
194 | 203 | qCWarning(LOG_CatalogueEventsWidget()) |
|
195 | 204 | << "updateGraphMode: not compatible with multiple events selected"; |
|
196 | 205 | } |
|
197 | 206 | } |
|
207 | ||
|
208 | void getSelectedItems( | |
|
209 | QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events, | |
|
210 | QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts) | |
|
211 | { | |
|
212 | for (auto rowIndex : treeView->selectionModel()->selectedRows()) { | |
|
213 | auto itemType = m_Model->itemTypeOf(rowIndex); | |
|
214 | if (itemType == CatalogueEventsModel::ItemType::Event) { | |
|
215 | events << m_Model->getEvent(rowIndex); | |
|
216 | } | |
|
217 | else if (itemType == CatalogueEventsModel::ItemType::EventProduct) { | |
|
218 | eventProducts << qMakePair(m_Model->getParentEvent(rowIndex), | |
|
219 | m_Model->getEventProduct(rowIndex)); | |
|
220 | } | |
|
221 | } | |
|
222 | } | |
|
198 | 223 | }; |
|
199 | 224 | |
|
200 | 225 | CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent) |
|
201 | 226 | : QWidget(parent), |
|
202 | 227 | ui(new Ui::CatalogueEventsWidget), |
|
203 | 228 | impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()} |
|
204 | 229 | { |
|
205 | 230 | ui->setupUi(this); |
|
206 | 231 | |
|
207 | 232 | impl->m_Model = new CatalogueEventsModel{this}; |
|
208 | 233 | ui->treeView->setModel(impl->m_Model); |
|
209 | 234 | |
|
210 | 235 | ui->treeView->setSortingEnabled(true); |
|
211 | 236 | ui->treeView->setDragDropMode(QAbstractItemView::DragDrop); |
|
212 | 237 | ui->treeView->setDragEnabled(true); |
|
213 | 238 | |
|
214 | 239 | connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) { |
|
215 | 240 | if (checked) { |
|
216 | 241 | ui->btnChart->setChecked(false); |
|
217 | 242 | impl->m_ZonesForTimeMode |
|
218 | 243 | = impl->selectZone(this, impl->m_ZonesForTimeMode, true, |
|
219 | 244 | this->mapToGlobal(ui->btnTime->frameGeometry().center())); |
|
220 | 245 | |
|
221 | 246 | impl->updateForTimeMode(ui->treeView); |
|
222 | 247 | } |
|
223 | 248 | }); |
|
224 | 249 | |
|
225 | 250 | connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) { |
|
226 | 251 | if (checked) { |
|
227 | 252 | ui->btnTime->setChecked(false); |
|
228 | 253 | impl->m_ZoneForGraphMode |
|
229 | 254 | = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false, |
|
230 | 255 | this->mapToGlobal(ui->btnChart->frameGeometry().center())) |
|
231 | 256 | .value(0); |
|
232 | 257 | |
|
233 | 258 | impl->updateForGraphMode(ui->treeView); |
|
234 | 259 | } |
|
235 | 260 | }); |
|
236 | 261 | |
|
237 | auto emitSelection = [this]() { | |
|
262 | connect(ui->btnRemove, &QToolButton::clicked, [this]() { | |
|
238 | 263 | QVector<std::shared_ptr<DBEvent> > events; |
|
239 | 264 | QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts; |
|
265 | impl->getSelectedItems(ui->treeView, events, eventProducts); | |
|
240 | 266 | |
|
241 | for (auto rowIndex : ui->treeView->selectionModel()->selectedRows()) { | |
|
267 | if (!events.isEmpty() && eventProducts.isEmpty()) { | |
|
242 | 268 | |
|
243 | auto itemType = impl->m_Model->itemTypeOf(rowIndex); | |
|
244 | if (itemType == CatalogueEventsModel::ItemType::Event) { | |
|
245 | events << impl->m_Model->getEvent(rowIndex); | |
|
246 | } | |
|
247 | else if (itemType == CatalogueEventsModel::ItemType::EventProduct) { | |
|
248 | eventProducts << qMakePair(impl->m_Model->getParentEvent(rowIndex), | |
|
249 | impl->m_Model->getEventProduct(rowIndex)); | |
|
250 | } | |
|
251 | } | |
|
269 | if (QMessageBox::warning(this, tr("Remove Event(s)"), | |
|
270 | tr("The selected event(s) will be completly removed " | |
|
271 | "from the repository!\nAre you sure you want to continue?"), | |
|
272 | QMessageBox::Yes | QMessageBox::No, QMessageBox::No) | |
|
273 | == QMessageBox::Yes) { | |
|
252 | 274 | |
|
253 | if (!events.isEmpty() && eventProducts.isEmpty()) { | |
|
254 | emit this->eventsSelected(events); | |
|
255 | } | |
|
256 | else if (events.isEmpty() && !eventProducts.isEmpty()) { | |
|
257 | emit this->eventProductsSelected(eventProducts); | |
|
258 | } | |
|
259 | else { | |
|
260 | emit this->selectionCleared(); | |
|
275 | for (auto event : events) { | |
|
276 | sqpApp->catalogueController().removeEvent(event); | |
|
277 | impl->removeEvent(event, ui->treeView); | |
|
278 | } | |
|
279 | } | |
|
261 | 280 | } |
|
262 | }; | |
|
281 | }); | |
|
263 | 282 | |
|
264 | connect(ui->treeView, &QTreeView::clicked, emitSelection); | |
|
265 |
connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, |
|
|
283 | connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection); | |
|
284 | connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this, | |
|
285 | &CatalogueEventsWidget::emitSelection); | |
|
266 | 286 | |
|
287 | ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected | |
|
267 | 288 | connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() { |
|
268 | 289 | auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1; |
|
269 | 290 | ui->btnChart->setEnabled(isNotMultiSelection); |
|
270 | 291 | ui->btnTime->setEnabled(isNotMultiSelection); |
|
271 | 292 | |
|
272 | 293 | if (isNotMultiSelection && ui->btnTime->isChecked()) { |
|
273 | 294 | impl->updateForTimeMode(ui->treeView); |
|
274 | 295 | } |
|
275 | 296 | else if (isNotMultiSelection && ui->btnChart->isChecked()) { |
|
276 | 297 | impl->updateForGraphMode(ui->treeView); |
|
277 | 298 | } |
|
299 | ||
|
300 | QVector<std::shared_ptr<DBEvent> > events; | |
|
301 | QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts; | |
|
302 | impl->getSelectedItems(ui->treeView, events, eventProducts); | |
|
303 | ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty()); | |
|
278 | 304 | }); |
|
279 | 305 | |
|
280 | 306 | ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); |
|
281 |
ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column:: |
|
|
307 | ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags, | |
|
282 | 308 | QHeaderView::Stretch); |
|
283 | 309 | ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation, |
|
284 | 310 | QHeaderView::Fixed); |
|
311 | ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name, | |
|
312 | QHeaderView::Interactive); | |
|
285 | 313 | ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation, |
|
286 | 314 | VALIDATION_COLUMN_SIZE); |
|
287 | 315 | ui->treeView->header()->setSortIndicatorShown(true); |
|
288 | 316 | |
|
289 | 317 | connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() { |
|
290 | 318 | auto allEvents = impl->m_Model->events(); |
|
291 | 319 | for (auto event : allEvents) { |
|
292 |
setEventChanges(event, |
|
|
320 | setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event)); | |
|
293 | 321 | } |
|
294 | 322 | }); |
|
323 | ||
|
324 | populateWithAllEvents(); | |
|
295 | 325 | } |
|
296 | 326 | |
|
297 | 327 | CatalogueEventsWidget::~CatalogueEventsWidget() |
|
298 | 328 | { |
|
299 | 329 | delete ui; |
|
300 | 330 | } |
|
301 | 331 | |
|
302 | 332 | void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization) |
|
303 | 333 | { |
|
304 | 334 | impl->m_VisualizationWidget = visualization; |
|
305 | 335 | } |
|
306 | 336 | |
|
337 | void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event) | |
|
338 | { | |
|
339 | impl->addEvent(event, ui->treeView); | |
|
340 | } | |
|
341 | ||
|
307 | 342 | void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges) |
|
308 | 343 | { |
|
309 | 344 | impl->m_Model->refreshEvent(event); |
|
310 | 345 | |
|
311 | 346 | auto eventIndex = impl->m_Model->indexOf(event); |
|
312 | 347 | auto validationIndex |
|
313 | 348 | = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation); |
|
314 | 349 | |
|
315 | if (hasChanges) { | |
|
316 | if (ui->treeView->indexWidget(validationIndex) == nullptr) { | |
|
317 | auto widget = CatalogueExplorerHelper::buildValidationWidget( | |
|
318 | ui->treeView, [this, event]() { setEventChanges(event, false); }, | |
|
319 | [this, event]() { setEventChanges(event, false); }); | |
|
320 | ui->treeView->setIndexWidget(validationIndex, widget); | |
|
350 | if (validationIndex.isValid()) { | |
|
351 | if (hasChanges) { | |
|
352 | if (ui->treeView->indexWidget(validationIndex) == nullptr) { | |
|
353 | auto widget = CatalogueExplorerHelper::buildValidationWidget( | |
|
354 | ui->treeView, | |
|
355 | [this, event]() { | |
|
356 | sqpApp->catalogueController().saveEvent(event); | |
|
357 | setEventChanges(event, false); | |
|
358 | }, | |
|
359 | [this, event]() { | |
|
360 | sqpApp->catalogueController().discardEvent(event); | |
|
361 | setEventChanges(event, false); | |
|
362 | impl->m_Model->refreshEvent(event, true); | |
|
363 | emitSelection(); | |
|
364 | }); | |
|
365 | ui->treeView->setIndexWidget(validationIndex, widget); | |
|
366 | } | |
|
367 | } | |
|
368 | else { | |
|
369 | // Note: the widget is destroyed | |
|
370 | ui->treeView->setIndexWidget(validationIndex, nullptr); | |
|
321 | 371 | } |
|
322 | 372 | } |
|
323 | 373 | else { |
|
324 | // Note: the widget is destroyed | |
|
325 | ui->treeView->setIndexWidget(validationIndex, nullptr); | |
|
374 | qCWarning(LOG_CatalogueEventsWidget()) | |
|
375 | << "setEventChanges: the event is not displayed in the model."; | |
|
326 | 376 | } |
|
377 | } | |
|
327 | 378 | |
|
328 | impl->m_Model->setEventHasChanges(event, hasChanges); | |
|
379 | QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const | |
|
380 | { | |
|
381 | return impl->m_DisplayedCatalogues; | |
|
382 | } | |
|
383 | ||
|
384 | bool CatalogueEventsWidget::isAllEventsDisplayed() const | |
|
385 | { | |
|
386 | return impl->m_DisplayedCatalogues.isEmpty() && !impl->m_Model->events().isEmpty(); | |
|
387 | } | |
|
388 | ||
|
389 | bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const | |
|
390 | { | |
|
391 | return impl->m_Model->indexOf(event).isValid(); | |
|
329 | 392 | } |
|
330 | 393 | |
|
331 | 394 | void CatalogueEventsWidget::populateWithCatalogues( |
|
332 | 395 | const QVector<std::shared_ptr<DBCatalogue> > &catalogues) |
|
333 | 396 | { |
|
397 | impl->m_DisplayedCatalogues = catalogues; | |
|
398 | ||
|
334 | 399 | QSet<QUuid> eventIds; |
|
335 | 400 | QVector<std::shared_ptr<DBEvent> > events; |
|
336 | 401 | |
|
337 | 402 | for (auto catalogue : catalogues) { |
|
338 | 403 | auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue); |
|
339 | 404 | for (auto event : catalogueEvents) { |
|
340 | 405 | if (!eventIds.contains(event->getUniqId())) { |
|
341 | 406 | events << event; |
|
342 | 407 | eventIds.insert(event->getUniqId()); |
|
343 | 408 | } |
|
344 | 409 | } |
|
345 | 410 | } |
|
346 | 411 | |
|
347 |
impl->setEvents(events, |
|
|
412 | impl->setEvents(events, this); | |
|
348 | 413 | } |
|
349 | 414 | |
|
350 | 415 | void CatalogueEventsWidget::populateWithAllEvents() |
|
351 | 416 | { |
|
417 | impl->m_DisplayedCatalogues.clear(); | |
|
418 | ||
|
352 | 419 | auto allEvents = sqpApp->catalogueController().retrieveAllEvents(); |
|
353 | 420 | |
|
354 | 421 | QVector<std::shared_ptr<DBEvent> > events; |
|
355 | 422 | for (auto event : allEvents) { |
|
356 | 423 | events << event; |
|
357 | 424 | } |
|
358 | 425 | |
|
359 |
impl->setEvents(events, |
|
|
426 | impl->setEvents(events, this); | |
|
427 | } | |
|
428 | ||
|
429 | void CatalogueEventsWidget::clear() | |
|
430 | { | |
|
431 | impl->m_DisplayedCatalogues.clear(); | |
|
432 | impl->setEvents({}, this); | |
|
433 | } | |
|
434 | ||
|
435 | void CatalogueEventsWidget::refresh() | |
|
436 | { | |
|
437 | if (impl->m_DisplayedCatalogues.isEmpty()) { | |
|
438 | populateWithAllEvents(); | |
|
439 | } | |
|
440 | else { | |
|
441 | populateWithCatalogues(impl->m_DisplayedCatalogues); | |
|
442 | } | |
|
443 | } | |
|
444 | ||
|
445 | void CatalogueEventsWidget::emitSelection() | |
|
446 | { | |
|
447 | QVector<std::shared_ptr<DBEvent> > events; | |
|
448 | QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts; | |
|
449 | impl->getSelectedItems(ui->treeView, events, eventProducts); | |
|
450 | ||
|
451 | if (!events.isEmpty() && eventProducts.isEmpty()) { | |
|
452 | emit eventsSelected(events); | |
|
453 | } | |
|
454 | else if (events.isEmpty() && !eventProducts.isEmpty()) { | |
|
455 | emit eventProductsSelected(eventProducts); | |
|
456 | } | |
|
457 | else { | |
|
458 | emit selectionCleared(); | |
|
459 | } | |
|
360 | 460 | } |
@@ -1,95 +1,126 | |||
|
1 | 1 | #include "Catalogue/CatalogueExplorer.h" |
|
2 | 2 | #include "ui_CatalogueExplorer.h" |
|
3 | 3 | |
|
4 | 4 | #include <Catalogue/CatalogueActionManager.h> |
|
5 | 5 | #include <Catalogue/CatalogueController.h> |
|
6 | 6 | #include <SqpApplication.h> |
|
7 | 7 | #include <Visualization/VisualizationWidget.h> |
|
8 | 8 | |
|
9 | 9 | #include <DBCatalogue.h> |
|
10 | 10 | #include <DBEvent.h> |
|
11 | 11 | |
|
12 | 12 | struct CatalogueExplorer::CatalogueExplorerPrivate { |
|
13 | 13 | CatalogueActionManager m_ActionManager; |
|
14 | ||
|
15 | CatalogueExplorerPrivate(CatalogueExplorer *catalogueExplorer) | |
|
16 | : m_ActionManager(catalogueExplorer) | |
|
17 | { | |
|
18 | } | |
|
14 | 19 | }; |
|
15 | 20 | |
|
16 | 21 | CatalogueExplorer::CatalogueExplorer(QWidget *parent) |
|
17 | 22 | : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint), |
|
18 | 23 | ui(new Ui::CatalogueExplorer), |
|
19 | impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>()} | |
|
24 | impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>(this)} | |
|
20 | 25 | { |
|
21 | 26 | ui->setupUi(this); |
|
22 | 27 | |
|
23 | 28 | impl->m_ActionManager.installSelectionZoneActions(); |
|
24 | 29 | |
|
25 | 30 | connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) { |
|
26 | 31 | if (catalogues.count() == 1) { |
|
27 | 32 | ui->inspector->setCatalogue(catalogues.first()); |
|
28 | 33 | } |
|
29 | 34 | else { |
|
30 | 35 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); |
|
31 | 36 | } |
|
32 | 37 | |
|
33 | 38 | ui->events->populateWithCatalogues(catalogues); |
|
34 | 39 | }); |
|
35 | 40 | |
|
36 | 41 | connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) { |
|
37 | 42 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); |
|
38 | 43 | }); |
|
39 | 44 | |
|
40 | connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, | |
|
41 |
|
|
|
45 | connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected, [this]() { | |
|
46 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); | |
|
47 | ui->events->clear(); | |
|
48 | }); | |
|
42 | 49 | |
|
43 | 50 | connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() { |
|
44 | 51 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); |
|
45 | 52 | ui->events->populateWithAllEvents(); |
|
46 | 53 | }); |
|
47 | 54 | |
|
48 |
connect(ui->catalogues, &CatalogueSideBarWidget::select |
|
|
49 | [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); }); | |
|
55 | connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databaseList) { | |
|
56 | QVector<std::shared_ptr<DBCatalogue> > catalogueList; | |
|
57 | for (auto database : databaseList) { | |
|
58 | catalogueList.append(ui->catalogues->getCatalogues(database)); | |
|
59 | } | |
|
60 | ui->events->populateWithCatalogues(catalogueList); | |
|
61 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); | |
|
62 | }); | |
|
63 | ||
|
64 | connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared, [this]() { | |
|
65 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); | |
|
66 | ui->events->clear(); | |
|
67 | }); | |
|
50 | 68 | |
|
51 | 69 | connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) { |
|
52 | 70 | if (events.count() == 1) { |
|
53 | 71 | ui->inspector->setEvent(events.first()); |
|
54 | 72 | } |
|
55 | 73 | else { |
|
56 | 74 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); |
|
57 | 75 | } |
|
58 | 76 | }); |
|
59 | 77 | |
|
60 | 78 | connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) { |
|
61 | 79 | if (eventProducts.count() == 1) { |
|
62 | 80 | ui->inspector->setEventProduct(eventProducts.first().first, |
|
63 | 81 | eventProducts.first().second); |
|
64 | 82 | } |
|
65 | 83 | else { |
|
66 | 84 | ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); |
|
67 | 85 | } |
|
68 | 86 | }); |
|
69 | 87 | |
|
70 | 88 | connect(ui->events, &CatalogueEventsWidget::selectionCleared, |
|
71 | 89 | [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); }); |
|
72 | 90 | |
|
73 | 91 | connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) { |
|
74 | 92 | sqpApp->catalogueController().updateCatalogue(catalogue); |
|
75 | 93 | ui->catalogues->setCatalogueChanges(catalogue, true); |
|
76 | 94 | }); |
|
77 | 95 | |
|
78 | 96 | connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) { |
|
79 | 97 | sqpApp->catalogueController().updateEvent(event); |
|
80 | 98 | ui->events->setEventChanges(event, true); |
|
81 | 99 | }); |
|
82 | 100 | |
|
83 | 101 | connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated, |
|
84 |
[this](auto event, auto eventProduct) { |
|
|
102 | [this](auto event, auto eventProduct) { | |
|
103 | sqpApp->catalogueController().updateEventProduct(eventProduct); | |
|
104 | ui->events->setEventChanges(event, true); | |
|
105 | }); | |
|
85 | 106 | } |
|
86 | 107 | |
|
87 | 108 | CatalogueExplorer::~CatalogueExplorer() |
|
88 | 109 | { |
|
89 | 110 | delete ui; |
|
90 | 111 | } |
|
91 | 112 | |
|
92 | 113 | void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization) |
|
93 | 114 | { |
|
94 | 115 | ui->events->setVisualizationWidget(visualization); |
|
95 | 116 | } |
|
117 | ||
|
118 | CatalogueEventsWidget &CatalogueExplorer::eventsWidget() const | |
|
119 | { | |
|
120 | return *ui->events; | |
|
121 | } | |
|
122 | ||
|
123 | CatalogueSideBarWidget &CatalogueExplorer::sideBarWidget() const | |
|
124 | { | |
|
125 | return *ui->catalogues; | |
|
126 | } |
@@ -1,181 +1,211 | |||
|
1 | 1 | #include "Catalogue/CatalogueInspectorWidget.h" |
|
2 | 2 | #include "ui_CatalogueInspectorWidget.h" |
|
3 | 3 | |
|
4 | 4 | #include <Common/DateUtils.h> |
|
5 | 5 | #include <DBCatalogue.h> |
|
6 | 6 | #include <DBEvent.h> |
|
7 | 7 | #include <DBEventProduct.h> |
|
8 | 8 | #include <DBTag.h> |
|
9 | 9 | |
|
10 | 10 | struct CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate { |
|
11 | 11 | std::shared_ptr<DBCatalogue> m_DisplayedCatalogue = nullptr; |
|
12 | 12 | std::shared_ptr<DBEvent> m_DisplayedEvent = nullptr; |
|
13 | 13 | std::shared_ptr<DBEventProduct> m_DisplayedEventProduct = nullptr; |
|
14 | 14 | |
|
15 | 15 | void connectCatalogueUpdateSignals(CatalogueInspectorWidget *inspector, |
|
16 | 16 | Ui::CatalogueInspectorWidget *ui); |
|
17 | 17 | void connectEventUpdateSignals(CatalogueInspectorWidget *inspector, |
|
18 | 18 | Ui::CatalogueInspectorWidget *ui); |
|
19 | 19 | }; |
|
20 | 20 | |
|
21 | 21 | CatalogueInspectorWidget::CatalogueInspectorWidget(QWidget *parent) |
|
22 | 22 | : QWidget(parent), |
|
23 | 23 | ui(new Ui::CatalogueInspectorWidget), |
|
24 | 24 | impl{spimpl::make_unique_impl<CatalogueInspectorWidgetPrivate>()} |
|
25 | 25 | { |
|
26 | 26 | ui->setupUi(this); |
|
27 | 27 | showPage(Page::Empty); |
|
28 | 28 | |
|
29 | 29 | impl->connectCatalogueUpdateSignals(this, ui); |
|
30 | 30 | impl->connectEventUpdateSignals(this, ui); |
|
31 | 31 | } |
|
32 | 32 | |
|
33 | 33 | CatalogueInspectorWidget::~CatalogueInspectorWidget() |
|
34 | 34 | { |
|
35 | 35 | delete ui; |
|
36 | 36 | } |
|
37 | 37 | |
|
38 | 38 | void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectCatalogueUpdateSignals( |
|
39 | 39 | CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui) |
|
40 | 40 | { |
|
41 | 41 | connect(ui->leCatalogueName, &QLineEdit::editingFinished, [ui, inspector, this]() { |
|
42 | 42 | if (ui->leCatalogueName->text() != m_DisplayedCatalogue->getName()) { |
|
43 | 43 | m_DisplayedCatalogue->setName(ui->leCatalogueName->text()); |
|
44 | 44 | emit inspector->catalogueUpdated(m_DisplayedCatalogue); |
|
45 | 45 | } |
|
46 | 46 | }); |
|
47 | 47 | |
|
48 | 48 | connect(ui->leCatalogueAuthor, &QLineEdit::editingFinished, [ui, inspector, this]() { |
|
49 | 49 | if (ui->leCatalogueAuthor->text() != m_DisplayedCatalogue->getAuthor()) { |
|
50 | 50 | m_DisplayedCatalogue->setAuthor(ui->leCatalogueAuthor->text()); |
|
51 | 51 | emit inspector->catalogueUpdated(m_DisplayedCatalogue); |
|
52 | 52 | } |
|
53 | 53 | }); |
|
54 | 54 | } |
|
55 | 55 | |
|
56 | 56 | void CatalogueInspectorWidget::CatalogueInspectorWidgetPrivate::connectEventUpdateSignals( |
|
57 | 57 | CatalogueInspectorWidget *inspector, Ui::CatalogueInspectorWidget *ui) |
|
58 | 58 | { |
|
59 | 59 | connect(ui->leEventName, &QLineEdit::editingFinished, [ui, inspector, this]() { |
|
60 | 60 | if (ui->leEventName->text() != m_DisplayedEvent->getName()) { |
|
61 | 61 | m_DisplayedEvent->setName(ui->leEventName->text()); |
|
62 | 62 | emit inspector->eventUpdated(m_DisplayedEvent); |
|
63 | 63 | } |
|
64 | 64 | }); |
|
65 | 65 | |
|
66 | 66 | connect(ui->leEventTags, &QLineEdit::editingFinished, [ui, inspector, this]() { |
|
67 | 67 | auto tags = ui->leEventTags->text().split(QRegExp("\\s+")); |
|
68 | 68 | std::list<QString> tagNames; |
|
69 | 69 | for (auto tag : tags) { |
|
70 | 70 | tagNames.push_back(tag); |
|
71 | 71 | } |
|
72 | 72 | |
|
73 | 73 | if (m_DisplayedEvent->getTagsNames() != tagNames) { |
|
74 | 74 | m_DisplayedEvent->setTagsNames(tagNames); |
|
75 | 75 | emit inspector->eventUpdated(m_DisplayedEvent); |
|
76 | 76 | } |
|
77 | 77 | }); |
|
78 | 78 | |
|
79 | 79 | connect(ui->leEventProduct, &QLineEdit::editingFinished, [ui, inspector, this]() { |
|
80 | 80 | if (ui->leEventProduct->text() != m_DisplayedEventProduct->getProductId()) { |
|
81 | auto oldProductId = m_DisplayedEventProduct->getProductId(); | |
|
81 | 82 | m_DisplayedEventProduct->setProductId(ui->leEventProduct->text()); |
|
82 | emit inspector->eventProductUpdated(m_DisplayedEvent, m_DisplayedEventProduct); | |
|
83 | ||
|
84 | auto eventProducts = m_DisplayedEvent->getEventProducts(); | |
|
85 | for (auto &eventProduct : eventProducts) { | |
|
86 | if (eventProduct.getProductId() == oldProductId) { | |
|
87 | eventProduct.setProductId(m_DisplayedEventProduct->getProductId()); | |
|
88 | } | |
|
89 | } | |
|
90 | m_DisplayedEvent->setEventProducts(eventProducts); | |
|
91 | ||
|
92 | emit inspector->eventUpdated(m_DisplayedEvent); | |
|
83 | 93 | } |
|
84 | 94 | }); |
|
85 | 95 | |
|
86 | 96 | connect(ui->dateTimeEventTStart, &QDateTimeEdit::editingFinished, [ui, inspector, this]() { |
|
87 | 97 | auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTStart->dateTime()); |
|
88 | 98 | if (time != m_DisplayedEventProduct->getTStart()) { |
|
89 | 99 | m_DisplayedEventProduct->setTStart(time); |
|
90 | emit inspector->eventProductUpdated(m_DisplayedEvent, m_DisplayedEventProduct); | |
|
100 | ||
|
101 | auto eventProducts = m_DisplayedEvent->getEventProducts(); | |
|
102 | for (auto &eventProduct : eventProducts) { | |
|
103 | if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) { | |
|
104 | eventProduct.setTStart(m_DisplayedEventProduct->getTStart()); | |
|
105 | } | |
|
106 | } | |
|
107 | m_DisplayedEvent->setEventProducts(eventProducts); | |
|
108 | ||
|
109 | emit inspector->eventUpdated(m_DisplayedEvent); | |
|
91 | 110 | } |
|
92 | 111 | }); |
|
93 | 112 | |
|
94 | 113 | connect(ui->dateTimeEventTEnd, &QDateTimeEdit::editingFinished, [ui, inspector, this]() { |
|
95 | 114 | auto time = DateUtils::secondsSinceEpoch(ui->dateTimeEventTEnd->dateTime()); |
|
96 | 115 | if (time != m_DisplayedEventProduct->getTEnd()) { |
|
97 | 116 | m_DisplayedEventProduct->setTEnd(time); |
|
98 | emit inspector->eventProductUpdated(m_DisplayedEvent, m_DisplayedEventProduct); | |
|
117 | ||
|
118 | auto eventProducts = m_DisplayedEvent->getEventProducts(); | |
|
119 | for (auto &eventProduct : eventProducts) { | |
|
120 | if (eventProduct.getProductId() == m_DisplayedEventProduct->getProductId()) { | |
|
121 | eventProduct.setTEnd(m_DisplayedEventProduct->getTEnd()); | |
|
122 | } | |
|
123 | } | |
|
124 | m_DisplayedEvent->setEventProducts(eventProducts); | |
|
125 | ||
|
126 | emit inspector->eventUpdated(m_DisplayedEvent); | |
|
99 | 127 | } |
|
100 | 128 | }); |
|
101 | 129 | } |
|
102 | 130 | |
|
103 | 131 | void CatalogueInspectorWidget::showPage(CatalogueInspectorWidget::Page page) |
|
104 | 132 | { |
|
105 | 133 | ui->stackedWidget->setCurrentIndex(static_cast<int>(page)); |
|
106 | 134 | } |
|
107 | 135 | |
|
108 | 136 | CatalogueInspectorWidget::Page CatalogueInspectorWidget::currentPage() const |
|
109 | 137 | { |
|
110 | 138 | return static_cast<Page>(ui->stackedWidget->currentIndex()); |
|
111 | 139 | } |
|
112 | 140 | |
|
113 | 141 | void CatalogueInspectorWidget::setEvent(const std::shared_ptr<DBEvent> &event) |
|
114 | 142 | { |
|
115 | 143 | impl->m_DisplayedEvent = event; |
|
116 | 144 | |
|
117 | 145 | blockSignals(true); |
|
118 | 146 | |
|
119 | 147 | showPage(Page::EventProperties); |
|
120 | 148 | ui->leEventName->setEnabled(true); |
|
121 | 149 | ui->leEventName->setText(event->getName()); |
|
122 | 150 | ui->leEventProduct->setEnabled(false); |
|
123 | 151 | ui->leEventProduct->setText( |
|
124 | 152 | QString::number(event->getEventProducts().size()).append(" product(s)")); |
|
125 | 153 | |
|
126 | 154 | QString tagList; |
|
127 | 155 | auto tags = event->getTagsNames(); |
|
128 | 156 | for (auto tag : tags) { |
|
129 | 157 | tagList += tag; |
|
130 | 158 | tagList += ' '; |
|
131 | 159 | } |
|
132 | 160 | |
|
133 | 161 | ui->leEventTags->setEnabled(true); |
|
134 | 162 | ui->leEventTags->setText(tagList); |
|
135 | 163 | |
|
136 | 164 | ui->dateTimeEventTStart->setEnabled(false); |
|
137 | 165 | ui->dateTimeEventTEnd->setEnabled(false); |
|
138 | 166 | |
|
139 | 167 | ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(event->getTStart())); |
|
140 | 168 | ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(event->getTEnd())); |
|
141 | 169 | |
|
142 | 170 | blockSignals(false); |
|
143 | 171 | } |
|
144 | 172 | |
|
145 | 173 | void CatalogueInspectorWidget::setEventProduct(const std::shared_ptr<DBEvent> &event, |
|
146 | 174 | const std::shared_ptr<DBEventProduct> &eventProduct) |
|
147 | 175 | { |
|
176 | ||
|
177 | impl->m_DisplayedEvent = event; | |
|
148 | 178 | impl->m_DisplayedEventProduct = eventProduct; |
|
149 | 179 | |
|
150 | 180 | blockSignals(true); |
|
151 | 181 | |
|
152 | 182 | showPage(Page::EventProperties); |
|
153 | 183 | ui->leEventName->setEnabled(false); |
|
154 | 184 | ui->leEventName->setText(event->getName()); |
|
155 |
ui->leEventProduct->setEnabled( |
|
|
185 | ui->leEventProduct->setEnabled(false); | |
|
156 | 186 | ui->leEventProduct->setText(eventProduct->getProductId()); |
|
157 | 187 | |
|
158 | 188 | ui->leEventTags->setEnabled(false); |
|
159 | 189 | ui->leEventTags->clear(); |
|
160 | 190 | |
|
161 | 191 | ui->dateTimeEventTStart->setEnabled(true); |
|
162 | 192 | ui->dateTimeEventTEnd->setEnabled(true); |
|
163 | 193 | |
|
164 | 194 | ui->dateTimeEventTStart->setDateTime(DateUtils::dateTime(eventProduct->getTStart())); |
|
165 | 195 | ui->dateTimeEventTEnd->setDateTime(DateUtils::dateTime(eventProduct->getTEnd())); |
|
166 | 196 | |
|
167 | 197 | blockSignals(false); |
|
168 | 198 | } |
|
169 | 199 | |
|
170 | 200 | void CatalogueInspectorWidget::setCatalogue(const std::shared_ptr<DBCatalogue> &catalogue) |
|
171 | 201 | { |
|
172 | 202 | impl->m_DisplayedCatalogue = catalogue; |
|
173 | 203 | |
|
174 | 204 | blockSignals(true); |
|
175 | 205 | |
|
176 | 206 | showPage(Page::CatalogueProperties); |
|
177 | 207 | ui->leCatalogueName->setText(catalogue->getName()); |
|
178 | 208 | ui->leCatalogueAuthor->setText(catalogue->getAuthor()); |
|
179 | 209 | |
|
180 | 210 | blockSignals(false); |
|
181 | 211 | } |
@@ -1,250 +1,337 | |||
|
1 | 1 | #include "Catalogue/CatalogueSideBarWidget.h" |
|
2 | 2 | #include "ui_CatalogueSideBarWidget.h" |
|
3 | 3 | #include <SqpApplication.h> |
|
4 | 4 | |
|
5 | 5 | #include <Catalogue/CatalogueController.h> |
|
6 |
#include <Catalogue/Catalogue |
|
|
6 | #include <Catalogue/CatalogueExplorerHelper.h> | |
|
7 | #include <Catalogue/CatalogueTreeItems/CatalogueTextTreeItem.h> | |
|
8 | #include <Catalogue/CatalogueTreeItems/CatalogueTreeItem.h> | |
|
9 | #include <Catalogue/CatalogueTreeModel.h> | |
|
7 | 10 | #include <CatalogueDao.h> |
|
8 | 11 | #include <ComparaisonPredicate.h> |
|
9 | 12 | #include <DBCatalogue.h> |
|
10 | 13 | |
|
11 | 14 | #include <QMenu> |
|
12 | 15 | |
|
13 | 16 | Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget") |
|
14 | 17 | |
|
15 | 18 | |
|
16 |
constexpr auto ALL_EVENT_ITEM_TYPE = |
|
|
17 |
constexpr auto TRASH_ITEM_TYPE = |
|
|
18 |
constexpr auto CATALOGUE_ITEM_TYPE = |
|
|
19 |
constexpr auto DATABASE_ITEM_TYPE = |
|
|
19 | constexpr auto ALL_EVENT_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 1; | |
|
20 | constexpr auto TRASH_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 2; | |
|
21 | constexpr auto CATALOGUE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 3; | |
|
22 | constexpr auto DATABASE_ITEM_TYPE = CatalogueAbstractTreeItem::DEFAULT_TYPE + 4; | |
|
20 | 23 | |
|
21 | 24 | |
|
22 | 25 | struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate { |
|
23 | 26 | |
|
24 | void configureTreeWidget(QTreeWidget *treeWidget); | |
|
25 | QTreeWidgetItem *addDatabaseItem(const QString &name, QTreeWidget *treeWidget); | |
|
26 | QTreeWidgetItem *getDatabaseItem(const QString &name, QTreeWidget *treeWidget); | |
|
27 | CatalogueTreeModel *m_TreeModel = nullptr; | |
|
28 | ||
|
29 | void configureTreeWidget(QTreeView *treeView); | |
|
30 | QModelIndex addDatabaseItem(const QString &name); | |
|
31 | CatalogueAbstractTreeItem *getDatabaseItem(const QString &name); | |
|
27 | 32 | void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue, |
|
28 |
|
|
|
33 | const QModelIndex &databaseIndex); | |
|
34 | ||
|
35 | CatalogueTreeItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue) const; | |
|
36 | void setHasChanges(bool value, const QModelIndex &index, QTreeView *treeView); | |
|
37 | bool hasChanges(const QModelIndex &index, QTreeView *treeView); | |
|
38 | ||
|
39 | int selectionType(QTreeView *treeView) const | |
|
40 | { | |
|
41 | auto selectedItems = treeView->selectionModel()->selectedRows(); | |
|
42 | if (selectedItems.isEmpty()) { | |
|
43 | return CatalogueAbstractTreeItem::DEFAULT_TYPE; | |
|
44 | } | |
|
45 | else { | |
|
46 | auto firstIndex = selectedItems.first(); | |
|
47 | auto firstItem = m_TreeModel->item(firstIndex); | |
|
48 | if (!firstItem) { | |
|
49 | Q_ASSERT(false); | |
|
50 | return CatalogueAbstractTreeItem::DEFAULT_TYPE; | |
|
51 | } | |
|
52 | auto selectionType = firstItem->type(); | |
|
53 | ||
|
54 | for (auto itemIndex : selectedItems) { | |
|
55 | auto item = m_TreeModel->item(itemIndex); | |
|
56 | if (!item || item->type() != selectionType) { | |
|
57 | // Incoherent multi selection | |
|
58 | selectionType = CatalogueAbstractTreeItem::DEFAULT_TYPE; | |
|
59 | break; | |
|
60 | } | |
|
61 | } | |
|
62 | ||
|
63 | return selectionType; | |
|
64 | } | |
|
65 | } | |
|
66 | ||
|
67 | QVector<std::shared_ptr<DBCatalogue> > selectedCatalogues(QTreeView *treeView) const | |
|
68 | { | |
|
69 | QVector<std::shared_ptr<DBCatalogue> > catalogues; | |
|
70 | auto selectedItems = treeView->selectionModel()->selectedRows(); | |
|
71 | for (auto itemIndex : selectedItems) { | |
|
72 | auto item = m_TreeModel->item(itemIndex); | |
|
73 | if (item && item->type() == CATALOGUE_ITEM_TYPE) { | |
|
74 | catalogues.append(static_cast<CatalogueTreeItem *>(item)->catalogue()); | |
|
75 | } | |
|
76 | } | |
|
29 | 77 | |
|
30 | CatalogueTreeWidgetItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue, | |
|
31 | QTreeWidget *treeWidget) const; | |
|
78 | return catalogues; | |
|
79 | } | |
|
80 | ||
|
81 | QStringList selectedRepositories(QTreeView *treeView) const | |
|
82 | { | |
|
83 | QStringList repositories; | |
|
84 | auto selectedItems = treeView->selectionModel()->selectedRows(); | |
|
85 | for (auto itemIndex : selectedItems) { | |
|
86 | auto item = m_TreeModel->item(itemIndex); | |
|
87 | if (item && item->type() == DATABASE_ITEM_TYPE) { | |
|
88 | repositories.append(item->text()); | |
|
89 | } | |
|
90 | } | |
|
91 | ||
|
92 | return repositories; | |
|
93 | } | |
|
32 | 94 | }; |
|
33 | 95 | |
|
34 | 96 | CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent) |
|
35 | 97 | : QWidget(parent), |
|
36 | 98 | ui(new Ui::CatalogueSideBarWidget), |
|
37 | 99 | impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()} |
|
38 | 100 | { |
|
39 | 101 | ui->setupUi(this); |
|
40 | impl->configureTreeWidget(ui->treeWidget); | |
|
41 | 102 | |
|
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); | |
|
103 | impl->m_TreeModel = new CatalogueTreeModel(this); | |
|
104 | ui->treeView->setModel(impl->m_TreeModel); | |
|
105 | ||
|
106 | impl->configureTreeWidget(ui->treeView); | |
|
107 | ||
|
108 | ui->treeView->header()->setStretchLastSection(false); | |
|
109 | ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents); | |
|
110 | ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch); | |
|
46 | 111 | |
|
47 | 112 | auto emitSelection = [this]() { |
|
48 | 113 | |
|
49 | auto selectedItems = ui->treeWidget->selectedItems(); | |
|
50 | if (selectedItems.isEmpty()) { | |
|
51 | emit this->selectionCleared(); | |
|
114 | auto selectionType = impl->selectionType(ui->treeView); | |
|
115 | ||
|
116 | switch (selectionType) { | |
|
117 | case CATALOGUE_ITEM_TYPE: | |
|
118 | emit this->catalogueSelected(impl->selectedCatalogues(ui->treeView)); | |
|
119 | break; | |
|
120 | case DATABASE_ITEM_TYPE: | |
|
121 | emit this->databaseSelected(impl->selectedRepositories(ui->treeView)); | |
|
122 | break; | |
|
123 | case ALL_EVENT_ITEM_TYPE: | |
|
124 | emit this->allEventsSelected(); | |
|
125 | break; | |
|
126 | case TRASH_ITEM_TYPE: | |
|
127 | emit this->trashSelected(); | |
|
128 | break; | |
|
129 | default: | |
|
130 | emit this->selectionCleared(); | |
|
131 | break; | |
|
52 | 132 | } |
|
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) { | |
|
61 | case CATALOGUE_ITEM_TYPE: | |
|
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 | } | |
|
133 | }; | |
|
80 | 134 | |
|
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); | |
|
87 | break; | |
|
88 | case ALL_EVENT_ITEM_TYPE: | |
|
89 | emit this->allEventsSelected(); | |
|
90 | break; | |
|
91 | case TRASH_ITEM_TYPE: | |
|
92 | emit this->trashSelected(); | |
|
93 | break; | |
|
94 | default: | |
|
95 | emit this->selectionCleared(); | |
|
96 | break; | |
|
97 | } | |
|
135 | connect(ui->treeView, &QTreeView::clicked, emitSelection); | |
|
136 | connect(ui->treeView->selectionModel(), &QItemSelectionModel::currentChanged, emitSelection); | |
|
137 | connect(impl->m_TreeModel, &CatalogueTreeModel::itemRenamed, [emitSelection, this](auto index) { | |
|
138 | auto selectedIndexes = ui->treeView->selectionModel()->selectedRows(); | |
|
139 | if (selectedIndexes.contains(index)) { | |
|
140 | emitSelection(); | |
|
98 | 141 | } |
|
99 | 142 | |
|
143 | auto item = impl->m_TreeModel->item(index); | |
|
144 | impl->setHasChanges(true, index, ui->treeView); | |
|
145 | }); | |
|
100 | 146 | |
|
101 | }; | |
|
102 | ||
|
103 | connect(ui->treeWidget, &QTreeWidget::itemClicked, emitSelection); | |
|
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, | |
|
147 | ui->treeView->setContextMenuPolicy(Qt::CustomContextMenu); | |
|
148 | connect(ui->treeView, &QTreeView::customContextMenuRequested, this, | |
|
116 | 149 | &CatalogueSideBarWidget::onContextMenuRequested); |
|
117 | 150 | } |
|
118 | 151 | |
|
119 | 152 | CatalogueSideBarWidget::~CatalogueSideBarWidget() |
|
120 | 153 | { |
|
121 | 154 | delete ui; |
|
122 | 155 | } |
|
123 | 156 | |
|
157 | void CatalogueSideBarWidget::addCatalogue(const std::shared_ptr<DBCatalogue> &catalogue, | |
|
158 | const QString &repository) | |
|
159 | { | |
|
160 | auto repositoryItem = impl->getDatabaseItem(repository); | |
|
161 | impl->addCatalogueItem(catalogue, impl->m_TreeModel->indexOf(repositoryItem)); | |
|
162 | } | |
|
163 | ||
|
124 | 164 | void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue, |
|
125 | 165 | bool hasChanges) |
|
126 | 166 | { |
|
127 |
if (auto catalogueItem = impl->getCatalogueItem(catalogue |
|
|
128 | catalogueItem->setHasChanges(hasChanges); | |
|
129 | catalogueItem->refresh(); | |
|
167 | if (auto catalogueItem = impl->getCatalogueItem(catalogue)) { | |
|
168 | auto index = impl->m_TreeModel->indexOf(catalogueItem); | |
|
169 | impl->setHasChanges(hasChanges, index, ui->treeView); | |
|
170 | // catalogueItem->refresh(); | |
|
130 | 171 | } |
|
131 | 172 | } |
|
132 | 173 | |
|
174 | QVector<std::shared_ptr<DBCatalogue> > | |
|
175 | CatalogueSideBarWidget::getCatalogues(const QString &repository) const | |
|
176 | { | |
|
177 | QVector<std::shared_ptr<DBCatalogue> > result; | |
|
178 | auto repositoryItem = impl->getDatabaseItem(repository); | |
|
179 | for (auto child : repositoryItem->children()) { | |
|
180 | if (child->type() == CATALOGUE_ITEM_TYPE) { | |
|
181 | auto catalogueItem = static_cast<CatalogueTreeItem *>(child); | |
|
182 | result << catalogueItem->catalogue(); | |
|
183 | } | |
|
184 | else { | |
|
185 | qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogues: invalid structure"; | |
|
186 | } | |
|
187 | } | |
|
188 | ||
|
189 | return result; | |
|
190 | } | |
|
191 | ||
|
133 | 192 | void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos) |
|
134 | 193 | { |
|
135 | 194 | QMenu menu{this}; |
|
136 | 195 | |
|
137 |
auto currentI |
|
|
196 | auto currentIndex = ui->treeView->currentIndex(); | |
|
197 | auto currentItem = impl->m_TreeModel->item(currentIndex); | |
|
198 | if (!currentItem) { | |
|
199 | return; | |
|
200 | } | |
|
201 | ||
|
138 | 202 | switch (currentItem->type()) { |
|
139 | 203 | case CATALOGUE_ITEM_TYPE: |
|
140 | menu.addAction("Rename", | |
|
141 | [this, currentItem]() { ui->treeWidget->editItem(currentItem); }); | |
|
204 | menu.addAction("Rename", [this, currentIndex]() { ui->treeView->edit(currentIndex); }); | |
|
142 | 205 | break; |
|
143 | 206 | case DATABASE_ITEM_TYPE: |
|
144 | 207 | break; |
|
145 | 208 | case ALL_EVENT_ITEM_TYPE: |
|
146 | 209 | break; |
|
147 | 210 | case TRASH_ITEM_TYPE: |
|
148 | 211 | menu.addAction("Empty Trash", []() { |
|
149 | 212 | // TODO |
|
150 | 213 | }); |
|
151 | 214 | break; |
|
152 | 215 | default: |
|
153 | 216 | break; |
|
154 | 217 | } |
|
155 | 218 | |
|
156 | 219 | if (!menu.isEmpty()) { |
|
157 |
menu.exec(ui->tree |
|
|
220 | menu.exec(ui->treeView->mapToGlobal(pos)); | |
|
158 | 221 | } |
|
159 | 222 | } |
|
160 | 223 | |
|
161 | void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget( | |
|
162 | QTreeWidget *treeWidget) | |
|
224 | void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(QTreeView *treeView) | |
|
163 | 225 | { |
|
164 | auto allEventsItem = new QTreeWidgetItem{{"All Events"}, ALL_EVENT_ITEM_TYPE}; | |
|
165 | allEventsItem->setIcon(0, QIcon(":/icones/allEvents.png")); | |
|
166 |
|
|
|
226 | auto allEventsItem = new CatalogueTextTreeItem{QIcon{":/icones/allEvents.png"}, "All Events", | |
|
227 | ALL_EVENT_ITEM_TYPE}; | |
|
228 | auto allEventIndex = m_TreeModel->addTopLevelItem(allEventsItem); | |
|
229 | treeView->setCurrentIndex(allEventIndex); | |
|
167 | 230 | |
|
168 | auto trashItem = new QTreeWidgetItem{{"Trash"}, TRASH_ITEM_TYPE}; | |
|
169 | trashItem->setIcon(0, QIcon(":/icones/trash.png")); | |
|
170 |
|
|
|
231 | auto trashItem | |
|
232 | = new CatalogueTextTreeItem{QIcon{":/icones/trash.png"}, "Trash", TRASH_ITEM_TYPE}; | |
|
233 | m_TreeModel->addTopLevelItem(trashItem); | |
|
171 | 234 | |
|
172 |
auto separator = new QFrame{tree |
|
|
235 | auto separator = new QFrame{treeView}; | |
|
173 | 236 | separator->setFrameShape(QFrame::HLine); |
|
174 |
auto separatorItem |
|
|
175 | separatorItem->setFlags(Qt::NoItemFlags); | |
|
176 | treeWidget->addTopLevelItem(separatorItem); | |
|
177 | treeWidget->setItemWidget(separatorItem, 0, separator); | |
|
237 | auto separatorItem | |
|
238 | = new CatalogueTextTreeItem{QIcon{}, QString{}, CatalogueAbstractTreeItem::DEFAULT_TYPE}; | |
|
239 | separatorItem->setEnabled(false); | |
|
240 | auto separatorIndex = m_TreeModel->addTopLevelItem(separatorItem); | |
|
241 | treeView->setIndexWidget(separatorIndex, separator); | |
|
178 | 242 | |
|
179 | 243 | auto repositories = sqpApp->catalogueController().getRepositories(); |
|
180 | 244 | for (auto dbname : repositories) { |
|
181 |
auto db = addDatabaseItem(dbname |
|
|
182 | ||
|
245 | auto dbIndex = addDatabaseItem(dbname); | |
|
183 | 246 | auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname); |
|
184 | 247 | for (auto catalogue : catalogues) { |
|
185 | addCatalogueItem(catalogue, db); | |
|
248 | addCatalogueItem(catalogue, dbIndex); | |
|
186 | 249 | } |
|
187 | 250 | } |
|
188 | 251 | |
|
189 |
tree |
|
|
252 | treeView->expandAll(); | |
|
190 | 253 | } |
|
191 | 254 | |
|
192 | QTreeWidgetItem * | |
|
193 |
CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name |
|
|
194 | QTreeWidget *treeWidget) | |
|
255 | QModelIndex | |
|
256 | CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name) | |
|
195 | 257 | { |
|
196 | auto databaseItem = new QTreeWidgetItem{{name}, DATABASE_ITEM_TYPE}; | |
|
197 | databaseItem->setIcon(0, QIcon{":/icones/database.png"}); | |
|
198 |
|
|
|
258 | auto databaseItem | |
|
259 | = new CatalogueTextTreeItem{QIcon{":/icones/database.png"}, {name}, DATABASE_ITEM_TYPE}; | |
|
260 | auto databaseIndex = m_TreeModel->addTopLevelItem(databaseItem); | |
|
199 | 261 | |
|
200 |
return databaseI |
|
|
262 | return databaseIndex; | |
|
201 | 263 | } |
|
202 | 264 | |
|
203 | QTreeWidgetItem * | |
|
204 |
CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name |
|
|
205 | QTreeWidget *treeWidget) | |
|
265 | CatalogueAbstractTreeItem * | |
|
266 | CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name) | |
|
206 | 267 | { |
|
207 |
for (auto i |
|
|
208 | auto item = treeWidget->topLevelItem(i); | |
|
209 | if (item->type() == DATABASE_ITEM_TYPE && item->text(0) == name) { | |
|
268 | for (auto item : m_TreeModel->topLevelItems()) { | |
|
269 | if (item->type() == DATABASE_ITEM_TYPE && item->text() == name) { | |
|
210 | 270 | return item; |
|
211 | 271 | } |
|
212 | 272 | } |
|
213 | 273 | |
|
214 | 274 | return nullptr; |
|
215 | 275 | } |
|
216 | 276 | |
|
217 | 277 | void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem( |
|
218 |
const std::shared_ptr<DBCatalogue> &catalogue, |
|
|
278 | const std::shared_ptr<DBCatalogue> &catalogue, const QModelIndex &databaseIndex) | |
|
219 | 279 | { |
|
220 | auto catalogueItem = new CatalogueTreeWidgetItem{catalogue, CATALOGUE_ITEM_TYPE}; | |
|
221 | catalogueItem->setIcon(0, QIcon{":/icones/catalogue.png"}); | |
|
222 |
|
|
|
280 | auto catalogueItem | |
|
281 | = new CatalogueTreeItem{catalogue, QIcon{":/icones/catalogue.png"}, CATALOGUE_ITEM_TYPE}; | |
|
282 | m_TreeModel->addChildItem(catalogueItem, databaseIndex); | |
|
223 | 283 | } |
|
224 | 284 | |
|
225 |
CatalogueTree |
|
|
226 |
const std::shared_ptr<DBCatalogue> &catalogue |
|
|
285 | CatalogueTreeItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem( | |
|
286 | const std::shared_ptr<DBCatalogue> &catalogue) const | |
|
227 | 287 | { |
|
228 |
for (auto i |
|
|
229 | auto item = treeWidget->topLevelItem(i); | |
|
288 | for (auto item : m_TreeModel->topLevelItems()) { | |
|
230 | 289 | if (item->type() == DATABASE_ITEM_TYPE) { |
|
231 |
for (auto |
|
|
232 | auto childItem = item->child(j); | |
|
290 | for (auto childItem : item->children()) { | |
|
233 | 291 | if (childItem->type() == CATALOGUE_ITEM_TYPE) { |
|
234 |
auto catalogueItem = static_cast<CatalogueTree |
|
|
292 | auto catalogueItem = static_cast<CatalogueTreeItem *>(childItem); | |
|
235 | 293 | if (catalogueItem->catalogue() == catalogue) { |
|
236 | 294 | return catalogueItem; |
|
237 | 295 | } |
|
238 | 296 | } |
|
239 | 297 | else { |
|
240 | 298 | qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree " |
|
241 | 299 | "structure. A database item should " |
|
242 | 300 | "only contain catalogues."; |
|
243 | 301 | Q_ASSERT(false); |
|
244 | 302 | } |
|
245 | 303 | } |
|
246 | 304 | } |
|
247 | 305 | } |
|
248 | 306 | |
|
249 | 307 | return nullptr; |
|
250 | 308 | } |
|
309 | ||
|
310 | void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::setHasChanges(bool value, | |
|
311 | const QModelIndex &index, | |
|
312 | QTreeView *treeView) | |
|
313 | { | |
|
314 | auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation); | |
|
315 | if (value) { | |
|
316 | if (!hasChanges(validationIndex, treeView)) { | |
|
317 | auto widget = CatalogueExplorerHelper::buildValidationWidget( | |
|
318 | treeView, [this, validationIndex, | |
|
319 | treeView]() { setHasChanges(false, validationIndex, treeView); }, | |
|
320 | [this, validationIndex, treeView]() { | |
|
321 | setHasChanges(false, validationIndex, treeView); | |
|
322 | }); | |
|
323 | treeView->setIndexWidget(validationIndex, widget); | |
|
324 | } | |
|
325 | } | |
|
326 | else { | |
|
327 | // Note: the widget is destroyed | |
|
328 | treeView->setIndexWidget(validationIndex, nullptr); | |
|
329 | } | |
|
330 | } | |
|
331 | ||
|
332 | bool CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::hasChanges(const QModelIndex &index, | |
|
333 | QTreeView *treeView) | |
|
334 | { | |
|
335 | auto validationIndex = index.sibling(index.row(), (int)CatalogueTreeModel::Column::Validation); | |
|
336 | return treeView->indexWidget(validationIndex) != nullptr; | |
|
337 | } |
@@ -1,91 +1,95 | |||
|
1 |
#include "Catalogue/CatalogueTree |
|
|
1 | #include "Catalogue/CatalogueTreeItems/CatalogueTreeItem.h" | |
|
2 | 2 | #include <Catalogue/CatalogueExplorerHelper.h> |
|
3 | 3 | |
|
4 | 4 | #include <Catalogue/CatalogueController.h> |
|
5 | #include <Common/MimeTypesDef.h> | |
|
6 | #include <QIcon> | |
|
7 | #include <QMimeData> | |
|
5 | 8 | #include <SqpApplication.h> |
|
6 | 9 | |
|
7 | 10 | #include <memory> |
|
8 | 11 | |
|
9 | 12 | #include <DBCatalogue.h> |
|
10 | 13 | |
|
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 { | |
|
14 | struct CatalogueTreeItem::CatalogueTreeItemPrivate { | |
|
15 | 15 | |
|
16 | 16 | std::shared_ptr<DBCatalogue> m_Catalogue; |
|
17 | QIcon m_Icon; | |
|
17 | 18 | |
|
18 |
CatalogueTree |
|
|
19 | CatalogueTreeItemPrivate(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon) | |
|
20 | : m_Catalogue(catalogue), m_Icon(icon) | |
|
19 | 21 | { |
|
20 | 22 | } |
|
21 | 23 | }; |
|
22 | 24 | |
|
23 | 25 | |
|
24 |
CatalogueTree |
|
|
25 | : QTreeWidgetItem(type), | |
|
26 | impl{spimpl::make_unique_impl<CatalogueTreeWidgetItemPrivate>(catalogue)} | |
|
26 | CatalogueTreeItem::CatalogueTreeItem(std::shared_ptr<DBCatalogue> catalogue, const QIcon &icon, | |
|
27 | int type) | |
|
28 | : CatalogueAbstractTreeItem(type), | |
|
29 | impl{spimpl::make_unique_impl<CatalogueTreeItemPrivate>(catalogue, icon)} | |
|
27 | 30 | { |
|
28 | setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable); | |
|
29 | 31 | } |
|
30 | 32 | |
|
31 |
QVariant CatalogueTree |
|
|
33 | QVariant CatalogueTreeItem::data(int column, int role) const | |
|
32 | 34 | { |
|
33 | 35 | if (column == 0) { |
|
34 | 36 | switch (role) { |
|
35 | 37 | case Qt::EditRole: // fallthrough |
|
36 | 38 | case Qt::DisplayRole: |
|
37 | 39 | return impl->m_Catalogue->getName(); |
|
40 | case Qt::DecorationRole: | |
|
41 | return impl->m_Icon; | |
|
38 | 42 | default: |
|
39 | 43 | break; |
|
40 | 44 | } |
|
41 | 45 | } |
|
42 | 46 | |
|
43 | return QTreeWidgetItem::data(column, role); | |
|
47 | return QVariant(); | |
|
44 | 48 | } |
|
45 | 49 | |
|
46 |
|
|
|
50 | bool CatalogueTreeItem::setData(int column, int role, const QVariant &value) | |
|
47 | 51 | { |
|
52 | bool result = false; | |
|
53 | ||
|
48 | 54 | if (role == Qt::EditRole && column == 0) { |
|
49 | 55 | auto newName = value.toString(); |
|
50 | 56 | if (newName != impl->m_Catalogue->getName()) { |
|
51 | setText(0, newName); | |
|
52 | 57 | impl->m_Catalogue->setName(newName); |
|
53 | 58 | sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue); |
|
54 |
|
|
|
59 | result = true; | |
|
55 | 60 | } |
|
56 | 61 | } |
|
57 | else { | |
|
58 | QTreeWidgetItem::setData(column, role, value); | |
|
59 | } | |
|
60 | } | |
|
61 | 62 | |
|
62 | std::shared_ptr<DBCatalogue> CatalogueTreeWidgetItem::catalogue() const | |
|
63 | { | |
|
64 | return impl->m_Catalogue; | |
|
63 | return result; | |
|
65 | 64 | } |
|
66 | 65 | |
|
67 | void CatalogueTreeWidgetItem::setHasChanges(bool value) | |
|
66 | Qt::ItemFlags CatalogueTreeItem::flags(int column) const | |
|
68 | 67 | { |
|
69 |
if ( |
|
|
70 | if (!hasChanges()) { | |
|
71 | auto widget = CatalogueExplorerHelper::buildValidationWidget( | |
|
72 | treeWidget(), [this]() { setHasChanges(false); }, | |
|
73 | [this]() { setHasChanges(false); }); | |
|
74 | treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, widget); | |
|
75 | } | |
|
68 | if (column == 0) { | |
|
69 | return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable | |
|
70 | | Qt::ItemIsDropEnabled; | |
|
76 | 71 | } |
|
77 | 72 | else { |
|
78 | // Note: the widget is destroyed | |
|
79 | treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, nullptr); | |
|
73 | return Qt::ItemIsEnabled | Qt::ItemIsSelectable; | |
|
80 | 74 | } |
|
81 | 75 | } |
|
82 | 76 | |
|
83 | bool CatalogueTreeWidgetItem::hasChanges() | |
|
77 | bool CatalogueTreeItem::canDropMimeData(const QMimeData *data, Qt::DropAction action) | |
|
84 | 78 | { |
|
85 | return treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) != nullptr; | |
|
79 | return data->hasFormat(MIME_TYPE_EVENT_LIST); | |
|
86 | 80 | } |
|
87 | 81 | |
|
88 | void CatalogueTreeWidgetItem::refresh() | |
|
82 | bool CatalogueTreeItem::dropMimeData(const QMimeData *data, Qt::DropAction action) | |
|
89 | 83 | { |
|
90 | emitDataChanged(); | |
|
84 | Q_ASSERT(canDropMimeData(data, action)); | |
|
85 | ||
|
86 | auto events = sqpApp->catalogueController().eventsForMimeData(data->data(MIME_TYPE_EVENT_LIST)); | |
|
87 | // impl->m_Catalogue->addEvents(events); TODO: move events in the new catalogue | |
|
88 | // Warning: Check that the events aren't already in the catalogue | |
|
89 | // Also check for the repository !!! | |
|
90 | } | |
|
91 | ||
|
92 | std::shared_ptr<DBCatalogue> CatalogueTreeItem::catalogue() const | |
|
93 | { | |
|
94 | return impl->m_Catalogue; | |
|
91 | 95 | } |
@@ -1,59 +1,59 | |||
|
1 | 1 | #include "Catalogue/CreateEventDialog.h" |
|
2 | 2 | #include "ui_CreateEventDialog.h" |
|
3 | 3 | |
|
4 | 4 | #include <Catalogue/CatalogueController.h> |
|
5 | 5 | #include <SqpApplication.h> |
|
6 | 6 | |
|
7 | 7 | #include <DBCatalogue.h> |
|
8 | 8 | |
|
9 | 9 | struct CreateEventDialog::CreateEventDialogPrivate { |
|
10 | 10 | QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues; |
|
11 | 11 | }; |
|
12 | 12 | |
|
13 | CreateEventDialog::CreateEventDialog(QWidget *parent) | |
|
13 | CreateEventDialog::CreateEventDialog(const QVector<std::shared_ptr<DBCatalogue> > &catalogues, | |
|
14 | QWidget *parent) | |
|
14 | 15 | : QDialog(parent), |
|
15 | 16 | ui(new Ui::CreateEventDialog), |
|
16 | 17 | impl{spimpl::make_unique_impl<CreateEventDialogPrivate>()} |
|
17 | 18 | { |
|
18 | 19 | ui->setupUi(this); |
|
19 | 20 | |
|
20 | 21 | connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); |
|
21 | 22 | connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); |
|
22 | 23 | |
|
23 | auto catalogues = sqpApp->catalogueController().retrieveCatalogues(); | |
|
24 |
for (auto cat : |
|
|
24 | impl->m_DisplayedCatalogues = catalogues; | |
|
25 | for (auto cat : impl->m_DisplayedCatalogues) { | |
|
25 | 26 | ui->cbCatalogue->addItem(cat->getName()); |
|
26 | impl->m_DisplayedCatalogues << cat; | |
|
27 | 27 | } |
|
28 | 28 | } |
|
29 | 29 | |
|
30 | 30 | CreateEventDialog::~CreateEventDialog() |
|
31 | 31 | { |
|
32 | 32 | delete ui; |
|
33 | 33 | } |
|
34 | 34 | |
|
35 | 35 | void CreateEventDialog::hideCatalogueChoice() |
|
36 | 36 | { |
|
37 | 37 | ui->cbCatalogue->hide(); |
|
38 | 38 | ui->lblCatalogue->hide(); |
|
39 | 39 | } |
|
40 | 40 | |
|
41 | 41 | QString CreateEventDialog::eventName() const |
|
42 | 42 | { |
|
43 | 43 | return ui->leEvent->text(); |
|
44 | 44 | } |
|
45 | 45 | |
|
46 | 46 | std::shared_ptr<DBCatalogue> CreateEventDialog::selectedCatalogue() const |
|
47 | 47 | { |
|
48 | 48 | auto catalogue = impl->m_DisplayedCatalogues.value(ui->cbCatalogue->currentIndex()); |
|
49 | 49 | if (!catalogue || catalogue->getName() != catalogueName()) { |
|
50 | 50 | return nullptr; |
|
51 | 51 | } |
|
52 | 52 | |
|
53 | 53 | return catalogue; |
|
54 | 54 | } |
|
55 | 55 | |
|
56 | 56 | QString CreateEventDialog::catalogueName() const |
|
57 | 57 | { |
|
58 | 58 | return ui->cbCatalogue->currentText(); |
|
59 | 59 | } |
@@ -1,217 +1,205 | |||
|
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 | m_CatalogueController->moveToThread(&m_CatalogueControllerThread); | |
|
68 | m_CatalogueControllerThread.setObjectName("CatalogueControllerThread"); | |
|
69 | ||
|
70 | 67 | |
|
71 | 68 | // Additionnal init |
|
72 | 69 | m_VariableController->setTimeController(m_TimeController.get()); |
|
73 | 70 | } |
|
74 | 71 | |
|
75 | 72 | virtual ~SqpApplicationPrivate() |
|
76 | 73 | { |
|
77 | 74 | m_DataSourceControllerThread.quit(); |
|
78 | 75 | m_DataSourceControllerThread.wait(); |
|
79 | 76 | |
|
80 | 77 | m_NetworkControllerThread.quit(); |
|
81 | 78 | m_NetworkControllerThread.wait(); |
|
82 | 79 | |
|
83 | 80 | m_VariableControllerThread.quit(); |
|
84 | 81 | m_VariableControllerThread.wait(); |
|
85 | 82 | |
|
86 | 83 | m_VisualizationControllerThread.quit(); |
|
87 | 84 | m_VisualizationControllerThread.wait(); |
|
88 | ||
|
89 | m_CatalogueControllerThread.quit(); | |
|
90 | m_CatalogueControllerThread.wait(); | |
|
91 | 85 | } |
|
92 | 86 | |
|
93 | 87 | std::unique_ptr<DataSourceController> m_DataSourceController; |
|
94 | 88 | std::unique_ptr<VariableController> m_VariableController; |
|
95 | 89 | std::unique_ptr<TimeController> m_TimeController; |
|
96 | 90 | std::unique_ptr<NetworkController> m_NetworkController; |
|
97 | 91 | std::unique_ptr<VisualizationController> m_VisualizationController; |
|
98 | 92 | std::unique_ptr<CatalogueController> m_CatalogueController; |
|
99 | 93 | |
|
100 | 94 | QThread m_DataSourceControllerThread; |
|
101 | 95 | QThread m_NetworkControllerThread; |
|
102 | 96 | QThread m_VariableControllerThread; |
|
103 | 97 | QThread m_VisualizationControllerThread; |
|
104 | QThread m_CatalogueControllerThread; | |
|
105 | 98 | |
|
106 | 99 | std::unique_ptr<DragDropGuiController> m_DragDropGuiController; |
|
107 | 100 | std::unique_ptr<ActionsGuiController> m_ActionsGuiController; |
|
108 | 101 | |
|
109 | 102 | SqpApplication::PlotsInteractionMode m_PlotInterractionMode; |
|
110 | 103 | SqpApplication::PlotsCursorMode m_PlotCursorMode; |
|
111 | 104 | }; |
|
112 | 105 | |
|
113 | 106 | |
|
114 | 107 | SqpApplication::SqpApplication(int &argc, char **argv) |
|
115 | 108 | : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()} |
|
116 | 109 | { |
|
117 | 110 | qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread(); |
|
118 | 111 | |
|
119 | 112 | connect(&impl->m_DataSourceControllerThread, &QThread::started, |
|
120 | 113 | impl->m_DataSourceController.get(), &DataSourceController::initialize); |
|
121 | 114 | connect(&impl->m_DataSourceControllerThread, &QThread::finished, |
|
122 | 115 | impl->m_DataSourceController.get(), &DataSourceController::finalize); |
|
123 | 116 | |
|
124 | 117 | connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(), |
|
125 | 118 | &NetworkController::initialize); |
|
126 | 119 | connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(), |
|
127 | 120 | &NetworkController::finalize); |
|
128 | 121 | |
|
129 | 122 | connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(), |
|
130 | 123 | &VariableController::initialize); |
|
131 | 124 | connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(), |
|
132 | 125 | &VariableController::finalize); |
|
133 | 126 | |
|
134 | 127 | connect(&impl->m_VisualizationControllerThread, &QThread::started, |
|
135 | 128 | impl->m_VisualizationController.get(), &VisualizationController::initialize); |
|
136 | 129 | connect(&impl->m_VisualizationControllerThread, &QThread::finished, |
|
137 | 130 | impl->m_VisualizationController.get(), &VisualizationController::finalize); |
|
138 | 131 | |
|
139 | connect(&impl->m_CatalogueControllerThread, &QThread::started, | |
|
140 | impl->m_CatalogueController.get(), &CatalogueController::initialize); | |
|
141 | connect(&impl->m_CatalogueControllerThread, &QThread::finished, | |
|
142 | impl->m_CatalogueController.get(), &CatalogueController::finalize); | |
|
143 | ||
|
144 | 132 | impl->m_DataSourceControllerThread.start(); |
|
145 | 133 | impl->m_NetworkControllerThread.start(); |
|
146 | 134 | impl->m_VariableControllerThread.start(); |
|
147 | 135 | impl->m_VisualizationControllerThread.start(); |
|
148 |
impl->m_CatalogueController |
|
|
136 | impl->m_CatalogueController->initialize(); | |
|
149 | 137 | } |
|
150 | 138 | |
|
151 | 139 | SqpApplication::~SqpApplication() |
|
152 | 140 | { |
|
153 | 141 | } |
|
154 | 142 | |
|
155 | 143 | void SqpApplication::initialize() |
|
156 | 144 | { |
|
157 | 145 | } |
|
158 | 146 | |
|
159 | 147 | DataSourceController &SqpApplication::dataSourceController() noexcept |
|
160 | 148 | { |
|
161 | 149 | return *impl->m_DataSourceController; |
|
162 | 150 | } |
|
163 | 151 | |
|
164 | 152 | NetworkController &SqpApplication::networkController() noexcept |
|
165 | 153 | { |
|
166 | 154 | return *impl->m_NetworkController; |
|
167 | 155 | } |
|
168 | 156 | |
|
169 | 157 | TimeController &SqpApplication::timeController() noexcept |
|
170 | 158 | { |
|
171 | 159 | return *impl->m_TimeController; |
|
172 | 160 | } |
|
173 | 161 | |
|
174 | 162 | VariableController &SqpApplication::variableController() noexcept |
|
175 | 163 | { |
|
176 | 164 | return *impl->m_VariableController; |
|
177 | 165 | } |
|
178 | 166 | |
|
179 | 167 | VisualizationController &SqpApplication::visualizationController() noexcept |
|
180 | 168 | { |
|
181 | 169 | return *impl->m_VisualizationController; |
|
182 | 170 | } |
|
183 | 171 | |
|
184 | 172 | CatalogueController &SqpApplication::catalogueController() noexcept |
|
185 | 173 | { |
|
186 | 174 | return *impl->m_CatalogueController; |
|
187 | 175 | } |
|
188 | 176 | |
|
189 | 177 | DragDropGuiController &SqpApplication::dragDropGuiController() noexcept |
|
190 | 178 | { |
|
191 | 179 | return *impl->m_DragDropGuiController; |
|
192 | 180 | } |
|
193 | 181 | |
|
194 | 182 | ActionsGuiController &SqpApplication::actionsGuiController() noexcept |
|
195 | 183 | { |
|
196 | 184 | return *impl->m_ActionsGuiController; |
|
197 | 185 | } |
|
198 | 186 | |
|
199 | 187 | SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const |
|
200 | 188 | { |
|
201 | 189 | return impl->m_PlotInterractionMode; |
|
202 | 190 | } |
|
203 | 191 | |
|
204 | 192 | void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode) |
|
205 | 193 | { |
|
206 | 194 | impl->m_PlotInterractionMode = mode; |
|
207 | 195 | } |
|
208 | 196 | |
|
209 | 197 | SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const |
|
210 | 198 | { |
|
211 | 199 | return impl->m_PlotCursorMode; |
|
212 | 200 | } |
|
213 | 201 | |
|
214 | 202 | void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode) |
|
215 | 203 | { |
|
216 | 204 | impl->m_PlotCursorMode = mode; |
|
217 | 205 | } |
@@ -1,142 +1,148 | |||
|
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 | <property name="enabled"> | |
|
34 | <bool>false</bool> | |
|
35 | </property> | |
|
33 | 36 | <property name="text"> |
|
34 | 37 | <string>+</string> |
|
35 | 38 | </property> |
|
36 | 39 | <property name="icon"> |
|
37 | 40 | <iconset resource="../../resources/sqpguiresources.qrc"> |
|
38 | 41 | <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset> |
|
39 | 42 | </property> |
|
40 | 43 | <property name="autoRaise"> |
|
41 | 44 | <bool>true</bool> |
|
42 | 45 | </property> |
|
43 | 46 | </widget> |
|
44 | 47 | </item> |
|
45 | 48 | <item> |
|
46 | 49 | <widget class="QToolButton" name="btnRemove"> |
|
47 | 50 | <property name="text"> |
|
48 | 51 | <string> - </string> |
|
49 | 52 | </property> |
|
50 | 53 | <property name="icon"> |
|
51 | 54 | <iconset resource="../../resources/sqpguiresources.qrc"> |
|
52 | 55 | <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset> |
|
53 | 56 | </property> |
|
54 | 57 | <property name="autoRaise"> |
|
55 | 58 | <bool>true</bool> |
|
56 | 59 | </property> |
|
57 | 60 | </widget> |
|
58 | 61 | </item> |
|
59 | 62 | <item> |
|
60 | 63 | <widget class="Line" name="line"> |
|
61 | 64 | <property name="orientation"> |
|
62 | 65 | <enum>Qt::Vertical</enum> |
|
63 | 66 | </property> |
|
64 | 67 | </widget> |
|
65 | 68 | </item> |
|
66 | 69 | <item> |
|
67 | 70 | <widget class="QToolButton" name="btnTime"> |
|
68 | 71 | <property name="text"> |
|
69 | 72 | <string>T</string> |
|
70 | 73 | </property> |
|
71 | 74 | <property name="icon"> |
|
72 | 75 | <iconset resource="../../resources/sqpguiresources.qrc"> |
|
73 | 76 | <normaloff>:/icones/time.png</normaloff>:/icones/time.png</iconset> |
|
74 | 77 | </property> |
|
75 | 78 | <property name="checkable"> |
|
76 | 79 | <bool>true</bool> |
|
77 | 80 | </property> |
|
78 | 81 | <property name="autoRaise"> |
|
79 | 82 | <bool>true</bool> |
|
80 | 83 | </property> |
|
81 | 84 | </widget> |
|
82 | 85 | </item> |
|
83 | 86 | <item> |
|
84 | 87 | <widget class="QToolButton" name="btnChart"> |
|
88 | <property name="enabled"> | |
|
89 | <bool>false</bool> | |
|
90 | </property> | |
|
85 | 91 | <property name="text"> |
|
86 | 92 | <string>G</string> |
|
87 | 93 | </property> |
|
88 | 94 | <property name="icon"> |
|
89 | 95 | <iconset resource="../../resources/sqpguiresources.qrc"> |
|
90 | 96 | <normaloff>:/icones/chart.png</normaloff>:/icones/chart.png</iconset> |
|
91 | 97 | </property> |
|
92 | 98 | <property name="checkable"> |
|
93 | 99 | <bool>true</bool> |
|
94 | 100 | </property> |
|
95 | 101 | <property name="autoRaise"> |
|
96 | 102 | <bool>true</bool> |
|
97 | 103 | </property> |
|
98 | 104 | </widget> |
|
99 | 105 | </item> |
|
100 | 106 | <item> |
|
101 | 107 | <widget class="Line" name="line_2"> |
|
102 | 108 | <property name="orientation"> |
|
103 | 109 | <enum>Qt::Vertical</enum> |
|
104 | 110 | </property> |
|
105 | 111 | </widget> |
|
106 | 112 | </item> |
|
107 | 113 | <item> |
|
108 | 114 | <widget class="QLineEdit" name="lineEdit"> |
|
109 | 115 | <property name="enabled"> |
|
110 | 116 | <bool>false</bool> |
|
111 | 117 | </property> |
|
112 | 118 | </widget> |
|
113 | 119 | </item> |
|
114 | 120 | </layout> |
|
115 | 121 | </item> |
|
116 | 122 | <item> |
|
117 | 123 | <widget class="QTreeView" name="treeView"> |
|
118 | 124 | <property name="dragEnabled"> |
|
119 | 125 | <bool>true</bool> |
|
120 | 126 | </property> |
|
121 | 127 | <property name="dragDropMode"> |
|
122 | 128 | <enum>QAbstractItemView::DragDrop</enum> |
|
123 | 129 | </property> |
|
124 | 130 | <property name="selectionMode"> |
|
125 | 131 | <enum>QAbstractItemView::ExtendedSelection</enum> |
|
126 | 132 | </property> |
|
127 | 133 | <property name="selectionBehavior"> |
|
128 | 134 | <enum>QAbstractItemView::SelectRows</enum> |
|
129 | 135 | </property> |
|
130 | 136 | <attribute name="headerStretchLastSection"> |
|
131 | 137 | <bool>false</bool> |
|
132 | 138 | </attribute> |
|
133 | 139 | </widget> |
|
134 | 140 | </item> |
|
135 | 141 | </layout> |
|
136 | 142 | </widget> |
|
137 | 143 | <resources> |
|
138 | 144 | <include location="../../resources/sqpguiresources.qrc"/> |
|
139 | 145 | <include location="../../resources/sqpguiresources.qrc"/> |
|
140 | 146 | </resources> |
|
141 | 147 | <connections/> |
|
142 | 148 | </ui> |
@@ -1,96 +1,106 | |||
|
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 | <property name="enabled"> | |
|
34 | <bool>false</bool> | |
|
35 | </property> | |
|
33 | 36 | <property name="text"> |
|
34 | 37 | <string>+</string> |
|
35 | 38 | </property> |
|
36 | 39 | <property name="icon"> |
|
37 | 40 | <iconset resource="../../resources/sqpguiresources.qrc"> |
|
38 | 41 | <normaloff>:/icones/add.png</normaloff>:/icones/add.png</iconset> |
|
39 | 42 | </property> |
|
40 | 43 | <property name="autoRaise"> |
|
41 | 44 | <bool>true</bool> |
|
42 | 45 | </property> |
|
43 | 46 | </widget> |
|
44 | 47 | </item> |
|
45 | 48 | <item> |
|
46 | 49 | <widget class="QToolButton" name="btnRemove"> |
|
50 | <property name="enabled"> | |
|
51 | <bool>false</bool> | |
|
52 | </property> | |
|
47 | 53 | <property name="text"> |
|
48 | 54 | <string> - </string> |
|
49 | 55 | </property> |
|
50 | 56 | <property name="icon"> |
|
51 | 57 | <iconset resource="../../resources/sqpguiresources.qrc"> |
|
52 | 58 | <normaloff>:/icones/remove.png</normaloff>:/icones/remove.png</iconset> |
|
53 | 59 | </property> |
|
54 | 60 | <property name="autoRaise"> |
|
55 | 61 | <bool>true</bool> |
|
56 | 62 | </property> |
|
57 | 63 | </widget> |
|
58 | 64 | </item> |
|
59 | 65 | <item> |
|
60 | 66 | <spacer name="horizontalSpacer"> |
|
61 | 67 | <property name="orientation"> |
|
62 | 68 | <enum>Qt::Horizontal</enum> |
|
63 | 69 | </property> |
|
64 | 70 | <property name="sizeHint" stdset="0"> |
|
65 | 71 | <size> |
|
66 | 72 | <width>40</width> |
|
67 | 73 | <height>20</height> |
|
68 | 74 | </size> |
|
69 | 75 | </property> |
|
70 | 76 | </spacer> |
|
71 | 77 | </item> |
|
72 | 78 | </layout> |
|
73 | 79 | </item> |
|
74 | 80 | <item> |
|
75 |
<widget class="QTree |
|
|
81 | <widget class="QTreeView" name="treeView"> | |
|
82 | <property name="acceptDrops"> | |
|
83 | <bool>true</bool> | |
|
84 | </property> | |
|
85 | <property name="dragDropMode"> | |
|
86 | <enum>QAbstractItemView::DragDrop</enum> | |
|
87 | </property> | |
|
76 | 88 | <property name="selectionMode"> |
|
77 | 89 | <enum>QAbstractItemView::ExtendedSelection</enum> |
|
78 | 90 | </property> |
|
79 | 91 | <attribute name="headerVisible"> |
|
80 | 92 | <bool>false</bool> |
|
81 | 93 | </attribute> |
|
82 | <column> | |
|
83 | <property name="text"> | |
|
84 | <string notr="true">1</string> | |
|
85 | </property> | |
|
86 | </column> | |
|
94 | <attribute name="headerStretchLastSection"> | |
|
95 | <bool>false</bool> | |
|
96 | </attribute> | |
|
87 | 97 | </widget> |
|
88 | 98 | </item> |
|
89 | 99 | </layout> |
|
90 | 100 | </widget> |
|
91 | 101 | <resources> |
|
92 | 102 | <include location="../../resources/sqpguiresources.qrc"/> |
|
93 | 103 | <include location="../../resources/sqpguiresources.qrc"/> |
|
94 | 104 | </resources> |
|
95 | 105 | <connections/> |
|
96 | 106 | </ui> |
@@ -1,78 +1,79 | |||
|
1 | 1 | #include "AmdaPlugin.h" |
|
2 | 2 | #include "AmdaDefs.h" |
|
3 | 3 | #include "AmdaParser.h" |
|
4 | 4 | #include "AmdaProvider.h" |
|
5 | 5 | #include "AmdaServer.h" |
|
6 | 6 | |
|
7 | 7 | #include <DataSource/DataSourceController.h> |
|
8 | 8 | #include <DataSource/DataSourceItem.h> |
|
9 | 9 | #include <DataSource/DataSourceItemAction.h> |
|
10 | 10 | |
|
11 | 11 | #include <SqpApplication.h> |
|
12 | 12 | |
|
13 | 13 | Q_LOGGING_CATEGORY(LOG_AmdaPlugin, "AmdaPlugin") |
|
14 | 14 | |
|
15 | 15 | namespace { |
|
16 | 16 | |
|
17 | 17 | /// Path of the file used to generate the data source item for AMDA |
|
18 | 18 | const auto JSON_FILE_PATH = QStringLiteral(":/samples/AmdaSampleV3.json"); |
|
19 | 19 | |
|
20 | 20 | void associateActions(DataSourceItem &item, const QUuid &dataSourceUid) |
|
21 | 21 | { |
|
22 | 22 | auto addLoadAction = [&item, dataSourceUid](const QString &label) { |
|
23 | 23 | item.addAction( |
|
24 | 24 | std::make_unique<DataSourceItemAction>(label, [dataSourceUid](DataSourceItem &item) { |
|
25 | 25 | if (auto app = sqpApp) { |
|
26 | 26 | app->dataSourceController().loadProductItem(dataSourceUid, item); |
|
27 | 27 | } |
|
28 | 28 | })); |
|
29 | 29 | }; |
|
30 | 30 | |
|
31 | 31 | const auto itemType = item.type(); |
|
32 | 32 | if (itemType == DataSourceItemType::PRODUCT || itemType == DataSourceItemType::COMPONENT) { |
|
33 | 33 | // Adds plugin name to item metadata |
|
34 | 34 | item.setData(DataSourceItem::PLUGIN_DATA_KEY, AmdaServer::instance().name()); |
|
35 | 35 | |
|
36 | 36 | // Adds load action |
|
37 | 37 | auto actionLabel = QObject::tr( |
|
38 | 38 | itemType == DataSourceItemType::PRODUCT ? "Load %1 product" : "Load %1 component"); |
|
39 | 39 | addLoadAction(actionLabel.arg(item.name())); |
|
40 | item.setData(DataSourceItem::ID_DATA_KEY, item.data(AMDA_XML_ID_KEY)); | |
|
40 | 41 | } |
|
41 | 42 | |
|
42 | 43 | auto count = item.childCount(); |
|
43 | 44 | for (auto i = 0; i < count; ++i) { |
|
44 | 45 | if (auto child = item.child(i)) { |
|
45 | 46 | associateActions(*child, dataSourceUid); |
|
46 | 47 | } |
|
47 | 48 | } |
|
48 | 49 | } |
|
49 | 50 | |
|
50 | 51 | } // namespace |
|
51 | 52 | |
|
52 | 53 | void AmdaPlugin::initialize() |
|
53 | 54 | { |
|
54 | 55 | if (auto app = sqpApp) { |
|
55 | 56 | auto dataSourceName = AmdaServer::instance().name(); |
|
56 | 57 | |
|
57 | 58 | // Registers to the data source controller |
|
58 | 59 | auto &dataSourceController = app->dataSourceController(); |
|
59 | 60 | auto dataSourceUid = dataSourceController.registerDataSource(dataSourceName); |
|
60 | 61 | |
|
61 | 62 | // Sets data source tree |
|
62 | 63 | if (auto dataSourceItem = AmdaParser::readJson(JSON_FILE_PATH)) { |
|
63 | 64 | dataSourceItem->setData(DataSourceItem::NAME_DATA_KEY, dataSourceName); |
|
64 | 65 | |
|
65 | 66 | associateActions(*dataSourceItem, dataSourceUid); |
|
66 | 67 | dataSourceController.setDataSourceItem(dataSourceUid, std::move(dataSourceItem)); |
|
67 | 68 | } |
|
68 | 69 | else { |
|
69 | 70 | qCCritical(LOG_AmdaPlugin()) << tr("No data source item could be generated for AMDA"); |
|
70 | 71 | } |
|
71 | 72 | |
|
72 | 73 | // Sets data provider |
|
73 | 74 | dataSourceController.setDataProvider(dataSourceUid, std::make_unique<AmdaProvider>()); |
|
74 | 75 | } |
|
75 | 76 | else { |
|
76 | 77 | qCWarning(LOG_AmdaPlugin()) << tr("Can't access to SciQlop application"); |
|
77 | 78 | } |
|
78 | 79 | } |
@@ -1,118 +1,119 | |||
|
1 | 1 | #include "MockPlugin.h" |
|
2 | 2 | #include "CosinusProvider.h" |
|
3 | 3 | #include "MockDefs.h" |
|
4 | 4 | |
|
5 | 5 | #include <DataSource/DataSourceController.h> |
|
6 | 6 | #include <DataSource/DataSourceItem.h> |
|
7 | 7 | #include <DataSource/DataSourceItemAction.h> |
|
8 | 8 | |
|
9 | 9 | #include <SqpApplication.h> |
|
10 | 10 | |
|
11 | 11 | Q_LOGGING_CATEGORY(LOG_MockPlugin, "MockPlugin") |
|
12 | 12 | |
|
13 | 13 | namespace { |
|
14 | 14 | |
|
15 | 15 | /// Name of the data source |
|
16 | 16 | const auto DATA_SOURCE_NAME = QStringLiteral("MMS"); |
|
17 | 17 | |
|
18 | 18 | /// Creates the data provider relative to the plugin |
|
19 | 19 | std::unique_ptr<IDataProvider> createDataProvider() noexcept |
|
20 | 20 | { |
|
21 | 21 | return std::make_unique<CosinusProvider>(); |
|
22 | 22 | } |
|
23 | 23 | |
|
24 | 24 | std::unique_ptr<DataSourceItem> createProductItem(const QVariantHash &data, |
|
25 | 25 | const QUuid &dataSourceUid) |
|
26 | 26 | { |
|
27 | 27 | auto result = std::make_unique<DataSourceItem>(DataSourceItemType::PRODUCT, data); |
|
28 | 28 | |
|
29 | 29 | // Adds plugin name to product metadata |
|
30 | 30 | result->setData(DataSourceItem::PLUGIN_DATA_KEY, DATA_SOURCE_NAME); |
|
31 | result->setData(DataSourceItem::ID_DATA_KEY, data.value(DataSourceItem::NAME_DATA_KEY)); | |
|
31 | 32 | |
|
32 | 33 | auto productName = data.value(DataSourceItem::NAME_DATA_KEY).toString(); |
|
33 | 34 | |
|
34 | 35 | // Add action to load product from DataSourceController |
|
35 | 36 | result->addAction(std::make_unique<DataSourceItemAction>( |
|
36 | 37 | QObject::tr("Load %1 product").arg(productName), |
|
37 | 38 | [productName, dataSourceUid](DataSourceItem &item) { |
|
38 | 39 | if (auto app = sqpApp) { |
|
39 | 40 | app->dataSourceController().loadProductItem(dataSourceUid, item); |
|
40 | 41 | } |
|
41 | 42 | })); |
|
42 | 43 | |
|
43 | 44 | return result; |
|
44 | 45 | } |
|
45 | 46 | |
|
46 | 47 | /// Creates the data source item relative to the plugin |
|
47 | 48 | std::unique_ptr<DataSourceItem> createDataSourceItem(const QUuid &dataSourceUid) noexcept |
|
48 | 49 | { |
|
49 | 50 | // Magnetic field products |
|
50 | 51 | auto magneticFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, |
|
51 | 52 | QStringLiteral("_Magnetic field")); |
|
52 | 53 | magneticFieldFolder->appendChild( |
|
53 | 54 | createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 10 Hz")}, |
|
54 | 55 | {COSINUS_TYPE_KEY, "scalar"}, |
|
55 | 56 | {COSINUS_FREQUENCY_KEY, 10.}}, |
|
56 | 57 | dataSourceUid)); |
|
57 | 58 | magneticFieldFolder->appendChild( |
|
58 | 59 | createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 60 Hz")}, |
|
59 | 60 | {COSINUS_TYPE_KEY, "scalar"}, |
|
60 | 61 | {COSINUS_FREQUENCY_KEY, 60.}}, |
|
61 | 62 | dataSourceUid)); |
|
62 | 63 | magneticFieldFolder->appendChild( |
|
63 | 64 | createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Scalar 100 Hz")}, |
|
64 | 65 | {COSINUS_TYPE_KEY, "scalar"}, |
|
65 | 66 | {COSINUS_FREQUENCY_KEY, 100.}}, |
|
66 | 67 | dataSourceUid)); |
|
67 | 68 | magneticFieldFolder->appendChild( |
|
68 | 69 | createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 10 Hz")}, |
|
69 | 70 | {COSINUS_TYPE_KEY, "vector"}, |
|
70 | 71 | {COSINUS_FREQUENCY_KEY, 10.}}, |
|
71 | 72 | dataSourceUid)); |
|
72 | 73 | magneticFieldFolder->appendChild( |
|
73 | 74 | createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 60 Hz")}, |
|
74 | 75 | {COSINUS_TYPE_KEY, "vector"}, |
|
75 | 76 | {COSINUS_FREQUENCY_KEY, 60.}}, |
|
76 | 77 | dataSourceUid)); |
|
77 | 78 | magneticFieldFolder->appendChild( |
|
78 | 79 | createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Vector 100 Hz")}, |
|
79 | 80 | {COSINUS_TYPE_KEY, "vector"}, |
|
80 | 81 | {COSINUS_FREQUENCY_KEY, 100.}}, |
|
81 | 82 | dataSourceUid)); |
|
82 | 83 | magneticFieldFolder->appendChild( |
|
83 | 84 | createProductItem({{DataSourceItem::NAME_DATA_KEY, QStringLiteral("Spectrogram 1 Hz")}, |
|
84 | 85 | {COSINUS_TYPE_KEY, "spectrogram"}, |
|
85 | 86 | {COSINUS_FREQUENCY_KEY, 1.}}, |
|
86 | 87 | dataSourceUid)); |
|
87 | 88 | |
|
88 | 89 | // Electric field products |
|
89 | 90 | auto electricFieldFolder = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, |
|
90 | 91 | QStringLiteral("_Electric field")); |
|
91 | 92 | |
|
92 | 93 | // Root |
|
93 | 94 | auto root = std::make_unique<DataSourceItem>(DataSourceItemType::NODE, DATA_SOURCE_NAME); |
|
94 | 95 | root->appendChild(std::move(magneticFieldFolder)); |
|
95 | 96 | root->appendChild(std::move(electricFieldFolder)); |
|
96 | 97 | |
|
97 | 98 | return root; |
|
98 | 99 | } |
|
99 | 100 | |
|
100 | 101 | } // namespace |
|
101 | 102 | |
|
102 | 103 | void MockPlugin::initialize() |
|
103 | 104 | { |
|
104 | 105 | if (auto app = sqpApp) { |
|
105 | 106 | // Registers to the data source controller |
|
106 | 107 | auto &dataSourceController = app->dataSourceController(); |
|
107 | 108 | auto dataSourceUid = dataSourceController.registerDataSource(DATA_SOURCE_NAME); |
|
108 | 109 | |
|
109 | 110 | // Sets data source tree |
|
110 | 111 | dataSourceController.setDataSourceItem(dataSourceUid, createDataSourceItem(dataSourceUid)); |
|
111 | 112 | |
|
112 | 113 | // Sets data provider |
|
113 | 114 | dataSourceController.setDataProvider(dataSourceUid, createDataProvider()); |
|
114 | 115 | } |
|
115 | 116 | else { |
|
116 | 117 | qCWarning(LOG_MockPlugin()) << tr("Can't access to SciQlop application"); |
|
117 | 118 | } |
|
118 | 119 | } |
|
1 | NO CONTENT: file was removed |
General Comments 3
Status change > Approved
You need to be logged in to leave comments.
Login now