##// END OF EJS Templates
Merge branch 'feature/CatalogueGuiPart3' into develop
trabillard -
r1197:c3afe020c8f9 merge
parent child
Show More
@@ -0,0 +1,17
1 #ifndef SCIQLOP_CATALOGUEACTIONMANAGER_H
2 #define SCIQLOP_CATALOGUEACTIONMANAGER_H
3
4 #include <Common/spimpl.h>
5
6 class CatalogueActionManager {
7 public:
8 CatalogueActionManager();
9
10 void installSelectionZoneActions();
11
12 private:
13 class CatalogueActionManagerPrivate;
14 spimpl::unique_impl_ptr<CatalogueActionManagerPrivate> impl;
15 };
16
17 #endif // SCIQLOP_CATALOGUEACTIONMANAGER_H
@@ -0,0 +1,13
1 #ifndef SCIQLOP_CATALOGUEEXPLORERHELPER_H
2 #define SCIQLOP_CATALOGUEEXPLORERHELPER_H
3
4 #include <QWidget>
5
6 #include <functional>
7
8 struct CatalogueExplorerHelper {
9 static QWidget *buildValidationWidget(QWidget *parent, std::function<void()> save,
10 std::function<void()> discard);
11 };
12
13 #endif // SCIQLOP_CATALOGUEEXPLORERHELPER_H
@@ -0,0 +1,35
1 #ifndef SCIQLOP_CREATEEVENTDIALOG_H
2 #define SCIQLOP_CREATEEVENTDIALOG_H
3
4 #include <Common/spimpl.h>
5 #include <QDialog>
6 #include <memory>
7
8 namespace Ui {
9 class CreateEventDialog;
10 }
11
12 class DBCatalogue;
13
14 class CreateEventDialog : public QDialog {
15 Q_OBJECT
16
17 public:
18 explicit CreateEventDialog(QWidget *parent = 0);
19 virtual ~CreateEventDialog();
20
21 void hideCatalogueChoice();
22
23 QString eventName() const;
24
25 std::shared_ptr<DBCatalogue> selectedCatalogue() const;
26 QString catalogueName() const;
27
28 private:
29 Ui::CreateEventDialog *ui;
30
31 class CreateEventDialogPrivate;
32 spimpl::unique_impl_ptr<CreateEventDialogPrivate> impl;
33 };
34
35 #endif // SCIQLOP_CREATEEVENTDIALOG_H
@@ -0,0 +1,107
1 #include "Catalogue/CatalogueActionManager.h"
2
3 #include <Actions/ActionsGuiController.h>
4 #include <Catalogue/CatalogueController.h>
5 #include <SqpApplication.h>
6 #include <Variable/Variable.h>
7 #include <Visualization/VisualizationGraphWidget.h>
8 #include <Visualization/VisualizationSelectionZoneItem.h>
9
10 #include <Catalogue/CreateEventDialog.h>
11
12 #include <DBCatalogue.h>
13 #include <DBEvent.h>
14 #include <DBEventProduct.h>
15
16 #include <QBoxLayout>
17 #include <QComboBox>
18 #include <QDialog>
19 #include <QDialogButtonBox>
20 #include <QLineEdit>
21 #include <memory>
22
23 struct CatalogueActionManager::CatalogueActionManagerPrivate {
24 void createEventFromZones(const QString &eventName,
25 const QVector<VisualizationSelectionZoneItem *> &zones,
26 const std::shared_ptr<DBCatalogue> &catalogue = nullptr)
27 {
28 auto event = std::make_shared<DBEvent>();
29 event->setName(eventName);
30
31 std::list<DBEventProduct> productList;
32 for (auto zone : zones) {
33 auto graph = zone->parentGraphWidget();
34 for (auto var : graph->variables()) {
35 auto eventProduct = std::make_shared<DBEventProduct>();
36 eventProduct->setEvent(*event);
37
38 auto zoneRange = zone->range();
39 eventProduct->setTStart(zoneRange.m_TStart);
40 eventProduct->setTEnd(zoneRange.m_TEnd);
41
42 eventProduct->setProductId(var->metadata().value("id", "TODO").toString()); // todo
43
44 productList.push_back(*eventProduct);
45 }
46 }
47
48 event->setEventProducts(productList);
49
50 sqpApp->catalogueController().addEvent(event);
51
52 if (catalogue) {
53 // TODO
54 // catalogue->addEvent(event);
55 }
56 }
57 };
58
59 CatalogueActionManager::CatalogueActionManager()
60 : impl{spimpl::make_unique_impl<CatalogueActionManagerPrivate>()}
61 {
62 }
63
64 void CatalogueActionManager::installSelectionZoneActions()
65 {
66 auto &actionController = sqpApp->actionsGuiController();
67
68 auto createEventEnableFuntion = [](auto zones) {
69 QSet<VisualizationGraphWidget *> usedGraphs;
70 for (auto zone : zones) {
71 auto graph = zone->parentGraphWidget();
72 if (!usedGraphs.contains(graph)) {
73 usedGraphs.insert(graph);
74 }
75 else {
76 return false;
77 }
78 }
79
80 return true;
81 };
82
83 auto createEventAction = actionController.addSectionZoneAction(
84 {QObject::tr("Catalogues")}, QObject::tr("New Event..."), [this](auto zones) {
85 CreateEventDialog dialog;
86 dialog.hideCatalogueChoice();
87 if (dialog.exec() == QDialog::Accepted) {
88 impl->createEventFromZones(dialog.eventName(), zones);
89 }
90 });
91 createEventAction->setEnableFunction(createEventEnableFuntion);
92
93 auto createEventInCatalogueAction = actionController.addSectionZoneAction(
94 {QObject::tr("Catalogues")}, QObject::tr("New Event in Catalogue..."), [this](auto zones) {
95 CreateEventDialog dialog;
96 if (dialog.exec() == QDialog::Accepted) {
97 auto selectedCatalogue = dialog.selectedCatalogue();
98 if (!selectedCatalogue) {
99 selectedCatalogue = std::make_shared<DBCatalogue>();
100 selectedCatalogue->setName(dialog.catalogueName());
101 }
102
103 impl->createEventFromZones(dialog.eventName(), zones, selectedCatalogue);
104 }
105 });
106 createEventInCatalogueAction->setEnableFunction(createEventEnableFuntion);
107 }
@@ -0,0 +1,32
1 #include "Catalogue/CatalogueExplorerHelper.h"
2
3 #include <QBoxLayout>
4 #include <QToolButton>
5
6 const auto VALIDATION_BUTTON_ICON_SIZE = 12;
7
8 QWidget *CatalogueExplorerHelper::buildValidationWidget(QWidget *parent, std::function<void()> save,
9 std::function<void()> discard)
10 {
11 auto widget = new QWidget{parent};
12
13 auto layout = new QHBoxLayout{widget};
14 layout->setContentsMargins(0, 0, 0, 0);
15 layout->setSpacing(0);
16
17 auto btnValid = new QToolButton{widget};
18 btnValid->setIcon(QIcon{":/icones/save"});
19 btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
20 btnValid->setAutoRaise(true);
21 QObject::connect(btnValid, &QToolButton::clicked, save);
22 layout->addWidget(btnValid);
23
24 auto btnDiscard = new QToolButton{widget};
25 btnDiscard->setIcon(QIcon{":/icones/discard"});
26 btnDiscard->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
27 btnDiscard->setAutoRaise(true);
28 QObject::connect(btnDiscard, &QToolButton::clicked, discard);
29 layout->addWidget(btnDiscard);
30
31 return widget;
32 }
@@ -0,0 +1,59
1 #include "Catalogue/CreateEventDialog.h"
2 #include "ui_CreateEventDialog.h"
3
4 #include <Catalogue/CatalogueController.h>
5 #include <SqpApplication.h>
6
7 #include <DBCatalogue.h>
8
9 struct CreateEventDialog::CreateEventDialogPrivate {
10 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
11 };
12
13 CreateEventDialog::CreateEventDialog(QWidget *parent)
14 : QDialog(parent),
15 ui(new Ui::CreateEventDialog),
16 impl{spimpl::make_unique_impl<CreateEventDialogPrivate>()}
17 {
18 ui->setupUi(this);
19
20 connect(ui->buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
21 connect(ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
22
23 auto catalogues = sqpApp->catalogueController().retrieveCatalogues();
24 for (auto cat : catalogues) {
25 ui->cbCatalogue->addItem(cat->getName());
26 impl->m_DisplayedCatalogues << cat;
27 }
28 }
29
30 CreateEventDialog::~CreateEventDialog()
31 {
32 delete ui;
33 }
34
35 void CreateEventDialog::hideCatalogueChoice()
36 {
37 ui->cbCatalogue->hide();
38 ui->lblCatalogue->hide();
39 }
40
41 QString CreateEventDialog::eventName() const
42 {
43 return ui->leEvent->text();
44 }
45
46 std::shared_ptr<DBCatalogue> CreateEventDialog::selectedCatalogue() const
47 {
48 auto catalogue = impl->m_DisplayedCatalogues.value(ui->cbCatalogue->currentIndex());
49 if (!catalogue || catalogue->getName() != catalogueName()) {
50 return nullptr;
51 }
52
53 return catalogue;
54 }
55
56 QString CreateEventDialog::catalogueName() const
57 {
58 return ui->cbCatalogue->currentText();
59 }
@@ -0,0 +1,55
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
3 <class>CreateEventDialog</class>
4 <widget class="QDialog" name="CreateEventDialog">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>324</width>
10 <height>93</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>New Event</string>
15 </property>
16 <layout class="QGridLayout" name="gridLayout">
17 <item row="0" column="0">
18 <widget class="QLabel" name="label">
19 <property name="text">
20 <string>Event Name</string>
21 </property>
22 </widget>
23 </item>
24 <item row="0" column="1">
25 <widget class="QLineEdit" name="leEvent"/>
26 </item>
27 <item row="1" column="0">
28 <widget class="QLabel" name="lblCatalogue">
29 <property name="text">
30 <string>Catalogue</string>
31 </property>
32 </widget>
33 </item>
34 <item row="1" column="1">
35 <widget class="QComboBox" name="cbCatalogue">
36 <property name="editable">
37 <bool>true</bool>
38 </property>
39 <property name="insertPolicy">
40 <enum>QComboBox::NoInsert</enum>
41 </property>
42 </widget>
43 </item>
44 <item row="2" column="0" colspan="2">
45 <widget class="QDialogButtonBox" name="buttonBox">
46 <property name="standardButtons">
47 <set>QDialogButtonBox::Ok</set>
48 </property>
49 </widget>
50 </item>
51 </layout>
52 </widget>
53 <resources/>
54 <connections/>
55 </ui>
@@ -1,74 +1,75
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 18
19 19 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueController)
20 20
21 21 class DataSourceItem;
22 22 class Variable;
23 23
24 24 /**
25 25 * @brief The CatalogueController class aims to handle catalogues and event using the CatalogueAPI
26 26 * library.
27 27 */
28 28 class SCIQLOP_CORE_EXPORT CatalogueController : public QObject {
29 29 Q_OBJECT
30 30 public:
31 31 explicit CatalogueController(QObject *parent = 0);
32 32 virtual ~CatalogueController();
33 33
34 34 // DB
35 35 QStringList getRepositories() const;
36 36 void addDB(const QString &dbPath);
37 37 void saveDB(const QString &destinationPath, const QString &repository);
38 38
39 39 // Event
40 40 /// retrieveEvents with empty repository retrieve them from the default repository
41 41 std::list<std::shared_ptr<DBEvent> > retrieveEvents(const QString &repository) const;
42 42 std::list<std::shared_ptr<DBEvent> > retrieveAllEvents() const;
43 43 std::list<std::shared_ptr<DBEvent> >
44 44 retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const;
45 45 void addEvent(std::shared_ptr<DBEvent> event);
46 46 void updateEvent(std::shared_ptr<DBEvent> event);
47 47 void removeEvent(std::shared_ptr<DBEvent> event);
48 48 // void trashEvent(std::shared_ptr<DBEvent> event);
49 49 // void restore(QUuid eventId);
50 50 void saveEvent(std::shared_ptr<DBEvent> event);
51 51
52 52 // Catalogue
53 53 // bool createCatalogue(const QString &name, QVector<QUuid> eventList);
54 54 /// retrieveEvents with empty repository retrieve them from the default repository
55 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository) const;
55 std::list<std::shared_ptr<DBCatalogue> > retrieveCatalogues(const QString &repository
56 = QString()) const;
56 57 void updateCatalogue(std::shared_ptr<DBCatalogue> catalogue);
57 58 void removeCatalogue(std::shared_ptr<DBCatalogue> catalogue);
58 59 void saveCatalogue(std::shared_ptr<DBCatalogue> catalogue);
59 60
60 61 void saveAll();
61 62
62 63 public slots:
63 64 /// Manage init/end of the controller
64 65 void initialize();
65 66 void finalize();
66 67
67 68 private:
68 69 void waitForFinish();
69 70
70 71 class CatalogueControllerPrivate;
71 72 spimpl::unique_impl_ptr<CatalogueControllerPrivate> impl;
72 73 };
73 74
74 75 #endif // SCIQLOP_CATALOGUECONTROLLER_H
@@ -1,287 +1,296
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 15 #include <QMutex>
16 16 #include <QThread>
17 17
18 18 #include <QDir>
19 19 #include <QStandardPaths>
20 20
21 21 Q_LOGGING_CATEGORY(LOG_CatalogueController, "CatalogueController")
22 22
23 23 namespace {
24 24
25 25 static QString REPOSITORY_WORK_SUFFIX = QString{"work"};
26 26 static QString REPOSITORY_TRASH_SUFFIX = QString{"trash"};
27 27 }
28 28
29 29 class CatalogueController::CatalogueControllerPrivate {
30 30
31 31 public:
32 32 explicit CatalogueControllerPrivate(CatalogueController *parent) : m_Q{parent} {}
33 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 40 void copyDBtoDB(const QString &dbFrom, const QString &dbTo);
41 41 QString toWorkRepository(QString repository);
42 42 QString toSyncRepository(QString repository);
43 43 };
44 44
45 45 CatalogueController::CatalogueController(QObject *parent)
46 46 : impl{spimpl::make_unique_impl<CatalogueControllerPrivate>(this)}
47 47 {
48 48 qCDebug(LOG_CatalogueController()) << tr("CatalogueController construction")
49 49 << QThread::currentThread();
50 50 }
51 51
52 52 CatalogueController::~CatalogueController()
53 53 {
54 54 qCDebug(LOG_CatalogueController()) << tr("CatalogueController destruction")
55 55 << QThread::currentThread();
56 56 this->waitForFinish();
57 57 }
58 58
59 59 QStringList CatalogueController::getRepositories() const
60 60 {
61 61 return impl->m_RepositoryList;
62 62 }
63 63
64 64 void CatalogueController::addDB(const QString &dbPath)
65 65 {
66 66 QDir dbDir(dbPath);
67 67 if (dbDir.exists()) {
68 68 auto dirName = dbDir.dirName();
69 69
70 70 if (std::find(impl->m_RepositoryList.cbegin(), impl->m_RepositoryList.cend(), dirName)
71 71 != impl->m_RepositoryList.cend()) {
72 72 qCCritical(LOG_CatalogueController())
73 73 << tr("Impossible to addDB that is already loaded");
74 74 }
75 75
76 76 if (!impl->m_CatalogueDao.addDB(dbPath, dirName)) {
77 77 qCCritical(LOG_CatalogueController())
78 78 << tr("Impossible to addDB %1 from %2 ").arg(dirName, dbPath);
79 79 }
80 80 else {
81 81 impl->m_RepositoryList << dirName;
82 82 impl->copyDBtoDB(dirName, impl->toWorkRepository(dirName));
83 83 }
84 84 }
85 85 else {
86 86 qCCritical(LOG_CatalogueController()) << tr("Impossible to addDB that not exists: ")
87 87 << dbPath;
88 88 }
89 89 }
90 90
91 91 void CatalogueController::saveDB(const QString &destinationPath, const QString &repository)
92 92 {
93 93 if (!impl->m_CatalogueDao.saveDB(destinationPath, repository)) {
94 94 qCCritical(LOG_CatalogueController())
95 95 << tr("Impossible to saveDB %1 from %2 ").arg(repository, destinationPath);
96 96 }
97 97 }
98 98
99 99 std::list<std::shared_ptr<DBEvent> >
100 100 CatalogueController::retrieveEvents(const QString &repository) const
101 101 {
102 102 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
103 103
104 104 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
105 105 auto events = impl->m_CatalogueDao.getEvents(impl->toWorkRepository(dbDireName));
106 106 for (auto event : events) {
107 107 eventsShared.push_back(std::make_shared<DBEvent>(event));
108 108 }
109 109 return eventsShared;
110 110 }
111 111
112 112 std::list<std::shared_ptr<DBEvent> > CatalogueController::retrieveAllEvents() const
113 113 {
114 114 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
115 115 for (auto repository : impl->m_RepositoryList) {
116 116 eventsShared.splice(eventsShared.end(), retrieveEvents(repository));
117 117 }
118 118
119 119 return eventsShared;
120 120 }
121 121
122 122 std::list<std::shared_ptr<DBEvent> >
123 123 CatalogueController::retrieveEventsFromCatalogue(std::shared_ptr<DBCatalogue> catalogue) const
124 124 {
125 125 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
126 126 auto events = impl->m_CatalogueDao.getCatalogueEvents(*catalogue);
127 127 for (auto event : events) {
128 128 eventsShared.push_back(std::make_shared<DBEvent>(event));
129 129 }
130 130 return eventsShared;
131 131 }
132 132
133 133 void CatalogueController::updateEvent(std::shared_ptr<DBEvent> event)
134 134 {
135 135 event->setRepository(impl->toSyncRepository(event->getRepository()));
136 136
137 137 impl->m_CatalogueDao.updateEvent(*event);
138 138 }
139 139
140 140 void CatalogueController::removeEvent(std::shared_ptr<DBEvent> event)
141 141 {
142 142 // Remove it from both repository and repository_work
143 143 event->setRepository(impl->toWorkRepository(event->getRepository()));
144 144 impl->m_CatalogueDao.removeEvent(*event);
145 145 event->setRepository(impl->toSyncRepository(event->getRepository()));
146 146 impl->m_CatalogueDao.removeEvent(*event);
147 147 }
148 148
149 149 void CatalogueController::addEvent(std::shared_ptr<DBEvent> event)
150 150 {
151 event->setRepository(impl->toSyncRepository(event->getRepository()));
151 event->setRepository(impl->toWorkRepository(event->getRepository()));
152 152
153 153 impl->m_CatalogueDao.addEvent(*event);
154 154
155 155 // Call update is necessary at the creation of add Event if it has some tags or some event
156 156 // products
157 157 if (!event->getEventProducts().empty() || !event->getTags().empty()) {
158 158 impl->m_CatalogueDao.updateEvent(*event);
159 159 }
160 160 }
161 161
162 162 void CatalogueController::saveEvent(std::shared_ptr<DBEvent> event)
163 163 {
164 164 impl->m_CatalogueDao.moveEvent(*event, impl->toSyncRepository(event->getRepository()), true);
165 165 }
166 166
167 167 std::list<std::shared_ptr<DBCatalogue> >
168 168 CatalogueController::retrieveCatalogues(const QString &repository) const
169 169 {
170 170 QString dbDireName = repository.isEmpty() ? REPOSITORY_DEFAULT : repository;
171 171
172 172 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
173 173 auto catalogues = impl->m_CatalogueDao.getCatalogues(impl->toWorkRepository(dbDireName));
174 174 for (auto catalogue : catalogues) {
175 175 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
176 176 }
177 177 return cataloguesShared;
178 178 }
179 179
180 180 void CatalogueController::updateCatalogue(std::shared_ptr<DBCatalogue> catalogue)
181 181 {
182 182 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
183 183
184 184 impl->m_CatalogueDao.updateCatalogue(*catalogue);
185 185 }
186 186
187 187 void CatalogueController::removeCatalogue(std::shared_ptr<DBCatalogue> catalogue)
188 188 {
189 189 // Remove it from both repository and repository_work
190 190 catalogue->setRepository(impl->toWorkRepository(catalogue->getRepository()));
191 191 impl->m_CatalogueDao.removeCatalogue(*catalogue);
192 192 catalogue->setRepository(impl->toSyncRepository(catalogue->getRepository()));
193 193 impl->m_CatalogueDao.removeCatalogue(*catalogue);
194 194 }
195 195
196 196 void CatalogueController::saveCatalogue(std::shared_ptr<DBCatalogue> catalogue)
197 197 {
198 198 impl->m_CatalogueDao.moveCatalogue(*catalogue,
199 199 impl->toSyncRepository(catalogue->getRepository()), true);
200 200 }
201 201
202 202 void CatalogueController::saveAll()
203 203 {
204 204 for (auto repository : impl->m_RepositoryList) {
205 205 // Save Event
206 206 auto events = this->retrieveEvents(repository);
207 207 for (auto event : events) {
208 208 this->saveEvent(event);
209 209 }
210 210
211 211 // Save Catalogue
212 212 auto catalogues = this->retrieveCatalogues(repository);
213 213 for (auto catalogue : catalogues) {
214 214 this->saveCatalogue(catalogue);
215 215 }
216 216 }
217 217 }
218 218
219 219 void CatalogueController::initialize()
220 220 {
221 221 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init")
222 222 << QThread::currentThread();
223 223 impl->m_WorkingMutex.lock();
224 224 impl->m_CatalogueDao.initialize();
225 225 auto defaultRepositoryLocation
226 226 = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
227 227
228 228 QDir defaultRepositoryLocationDir;
229 229 if (defaultRepositoryLocationDir.mkpath(defaultRepositoryLocation)) {
230 230 defaultRepositoryLocationDir.cd(defaultRepositoryLocation);
231 231 auto defaultRepository = defaultRepositoryLocationDir.absoluteFilePath(REPOSITORY_DEFAULT);
232 232 qCInfo(LOG_CatalogueController()) << tr("Persistant data loading from: ")
233 233 << defaultRepository;
234 234 this->addDB(defaultRepository);
235 235 }
236 236 else {
237 237 qCWarning(LOG_CatalogueController())
238 238 << tr("Cannot load the persistent default repository from ")
239 239 << defaultRepositoryLocation;
240 240 }
241 241
242 242 qCDebug(LOG_CatalogueController()) << tr("CatalogueController init END");
243 243 }
244 244
245 245 void CatalogueController::finalize()
246 246 {
247 247 impl->m_WorkingMutex.unlock();
248 248 }
249 249
250 250 void CatalogueController::waitForFinish()
251 251 {
252 252 QMutexLocker locker{&impl->m_WorkingMutex};
253 253 }
254 254
255 255 void CatalogueController::CatalogueControllerPrivate::copyDBtoDB(const QString &dbFrom,
256 256 const QString &dbTo)
257 257 {
258 auto catalogues = m_Q->retrieveCatalogues(dbFrom);
259 auto events = m_Q->retrieveEvents(dbFrom);
260
258 auto cataloguesShared = std::list<std::shared_ptr<DBCatalogue> >{};
259 auto catalogues = m_CatalogueDao.getCatalogues(dbFrom);
261 260 for (auto catalogue : catalogues) {
262 m_CatalogueDao.copyCatalogue(*catalogue, dbTo, true);
261 cataloguesShared.push_back(std::make_shared<DBCatalogue>(catalogue));
263 262 }
264 263
264 auto eventsShared = std::list<std::shared_ptr<DBEvent> >{};
265 auto events = m_CatalogueDao.getEvents(dbFrom);
265 266 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) {
266 275 m_CatalogueDao.copyEvent(*event, dbTo, true);
267 276 }
268 277 }
269 278
270 279 QString CatalogueController::CatalogueControllerPrivate::toWorkRepository(QString repository)
271 280 {
272 281 auto syncRepository = toSyncRepository(repository);
273 282
274 283 return QString("%1_%2").arg(syncRepository, REPOSITORY_WORK_SUFFIX);
275 284 }
276 285
277 286 QString CatalogueController::CatalogueControllerPrivate::toSyncRepository(QString repository)
278 287 {
279 288 auto syncRepository = repository;
280 289 if (repository.endsWith(REPOSITORY_WORK_SUFFIX)) {
281 290 syncRepository.remove(REPOSITORY_WORK_SUFFIX);
282 291 }
283 292 else if (repository.endsWith(REPOSITORY_TRASH_SUFFIX)) {
284 293 syncRepository.remove(REPOSITORY_TRASH_SUFFIX);
285 294 }
286 295 return syncRepository;
287 296 }
@@ -1,46 +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 #include <QLoggingCategory>
7 #include <unordered_set>
6 8
7 9 class DBEvent;
8 10 class DBEventProduct;
9 11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_CatalogueEventsModel)
13
10 14 class CatalogueEventsModel : public QAbstractItemModel {
15 Q_OBJECT
16
17 signals:
18 void modelSorted();
19
11 20 public:
12 21 CatalogueEventsModel(QObject *parent = nullptr);
13 22
23 enum class Column { Name, TStart, TEnd, Tags, Product, Validation, NbColumn };
24
14 25 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events);
15 26 void addEvent(const std::shared_ptr<DBEvent> &event);
16 27 void removeEvent(const std::shared_ptr<DBEvent> &event);
28 QVector<std::shared_ptr<DBEvent> > events() const;
17 29
18 30 enum class ItemType { Root, Event, EventProduct };
19 31 ItemType itemTypeOf(const QModelIndex &index) const;
20 32 std::shared_ptr<DBEvent> getEvent(const QModelIndex &index) const;
21 33 std::shared_ptr<DBEvent> getParentEvent(const QModelIndex &index) const;
22 34 std::shared_ptr<DBEventProduct> getEventProduct(const QModelIndex &index) const;
23 35
36 /// Refresh the data for the specified event
24 37 void refreshEvent(const std::shared_ptr<DBEvent> &event);
25 38
39 /// Returns a QModelIndex which represent the specified event
40 QModelIndex indexOf(const std::shared_ptr<DBEvent> &event) const;
41
42 /// Marks a change flag on the specified event to allow sorting on the validation column
43 void setEventHasChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
44
45 /// Returns true if the specified event has unsaved changes
46 bool eventsHasChanges(const std::shared_ptr<DBEvent> &event) const;
47
26 48 // Model
27 49 QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
28 50 QModelIndex parent(const QModelIndex &index) const;
29 51 int rowCount(const QModelIndex &parent = QModelIndex()) const override;
30 52 int columnCount(const QModelIndex &parent = QModelIndex()) const override;
31 53 Qt::ItemFlags flags(const QModelIndex &index) const override;
32 54 QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
33 55 QVariant headerData(int section, Qt::Orientation orientation,
34 56 int role = Qt::DisplayRole) const override;
35 57 void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override;
36 58
37 59 Qt::DropActions supportedDragActions() const override;
38 60 QStringList mimeTypes() const override;
39 61 QMimeData *mimeData(const QModelIndexList &indexes) const override;
40 62
41 63 private:
42 64 class CatalogueEventsModelPrivate;
43 65 spimpl::unique_impl_ptr<CatalogueEventsModelPrivate> impl;
44 66 };
45 67
46 68 #endif // SCIQLOP_CATALOGUEEVENTSMODEL_H
@@ -1,47 +1,48
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 35 void setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges);
36 36
37 37 public slots:
38 38 void populateWithCatalogues(const QVector<std::shared_ptr<DBCatalogue> > &catalogues);
39 void populateWithAllEvents();
39 40
40 41 private:
41 42 Ui::CatalogueEventsWidget *ui;
42 43
43 44 class CatalogueEventsWidgetPrivate;
44 45 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
45 46 };
46 47
47 48 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
@@ -1,33 +1,36
1 1 #ifndef SCIQLOP_CATALOGUETREEWIDGETITEM_H
2 2 #define SCIQLOP_CATALOGUETREEWIDGETITEM_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QTreeWidgetItem>
6 6
7 7 class DBCatalogue;
8 8
9 9
10 10 class CatalogueTreeWidgetItem : public QTreeWidgetItem {
11 11 public:
12 12 CatalogueTreeWidgetItem(std::shared_ptr<DBCatalogue> catalogue,
13 13 int type = QTreeWidgetItem::Type);
14 14
15 15 QVariant data(int column, int role) const override;
16 16 void setData(int column, int role, const QVariant &value) override;
17 17
18 18 /// Returns the catalogue represented by the item
19 19 std::shared_ptr<DBCatalogue> catalogue() const;
20 20
21 21 /// Displays or hides the save and cancel buttons indicating that the catalogue has unsaved
22 22 /// changes
23 23 void setHasChanges(bool value);
24 24
25 /// Returns true if the widget indicating the event has unsaved changes is displayed
26 bool hasChanges();
27
25 28 /// Refreshes the data displayed by the item from the catalogue
26 29 void refresh();
27 30
28 31 private:
29 32 class CatalogueTreeWidgetItemPrivate;
30 33 spimpl::unique_impl_ptr<CatalogueTreeWidgetItemPrivate> impl;
31 34 };
32 35
33 36 #endif // SCIQLOP_CATALOGUETREEWIDGETITEM_H
@@ -1,137 +1,143
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 'include/Catalogue/CatalogueInspectorWidget.h'
28 'include/Catalogue/CatalogueInspectorWidget.h',
29 'include/Catalogue/CatalogueEventsModel.h',
30 'include/Catalogue/CreateEventDialog.ui'
29 31 ]
30 32
31 33 gui_ui_files = [
32 34 'ui/DataSource/DataSourceWidget.ui',
33 35 'ui/Settings/SqpSettingsDialog.ui',
34 36 'ui/Settings/SqpSettingsGeneralWidget.ui',
35 37 'ui/SidePane/SqpSidePane.ui',
36 38 'ui/TimeWidget/TimeWidget.ui',
37 39 'ui/Variable/VariableInspectorWidget.ui',
38 40 'ui/Variable/RenameVariableDialog.ui',
39 41 'ui/Variable/VariableMenuHeaderWidget.ui',
40 42 'ui/Visualization/VisualizationGraphWidget.ui',
41 43 'ui/Visualization/VisualizationTabWidget.ui',
42 44 'ui/Visualization/VisualizationWidget.ui',
43 45 'ui/Visualization/VisualizationZoneWidget.ui',
44 46 'ui/Visualization/ColorScaleEditor.ui',
45 47 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui',
46 48 'ui/Catalogue/CatalogueExplorer.ui',
47 49 'ui/Catalogue/CatalogueEventsWidget.ui',
48 50 'ui/Catalogue/CatalogueSideBarWidget.ui',
49 'ui/Catalogue/CatalogueInspectorWidget.ui'
51 'ui/Catalogue/CatalogueInspectorWidget.ui',
52 'ui/Catalogue/CreateEventDialog.ui'
50 53 ]
51 54
52 55 gui_qresources = ['resources/sqpguiresources.qrc']
53 56
54 57 rcc_gen = generator(rcc,
55 58 output : 'qrc_@BASENAME@.cpp',
56 59 arguments : [
57 60 '--output',
58 61 '@OUTPUT@',
59 62 '@INPUT@',
60 63 '@EXTRA_ARGS@'])
61 64
62 65 rcc_files = rcc_gen.process(gui_qresources, extra_args : ['-name', 'sqpguiresources'])
63 66
64 67 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
65 68 ui_files : gui_ui_files)
66 69
67 70 gui_sources = [
68 71 'src/SqpApplication.cpp',
69 72 'src/DragAndDrop/DragDropGuiController.cpp',
70 73 'src/DragAndDrop/DragDropScroller.cpp',
71 74 'src/DragAndDrop/DragDropTabSwitcher.cpp',
72 75 'src/Common/ColorUtils.cpp',
73 76 'src/Common/VisualizationDef.cpp',
74 77 'src/DataSource/DataSourceTreeWidgetItem.cpp',
75 78 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
76 79 'src/DataSource/DataSourceWidget.cpp',
77 80 'src/DataSource/DataSourceTreeWidget.cpp',
78 81 'src/Settings/SqpSettingsDialog.cpp',
79 82 'src/Settings/SqpSettingsGeneralWidget.cpp',
80 83 'src/SidePane/SqpSidePane.cpp',
81 84 'src/TimeWidget/TimeWidget.cpp',
82 85 'src/Variable/VariableInspectorWidget.cpp',
83 86 'src/Variable/VariableInspectorTableView.cpp',
84 87 'src/Variable/VariableMenuHeaderWidget.cpp',
85 88 'src/Variable/RenameVariableDialog.cpp',
86 89 'src/Visualization/VisualizationGraphHelper.cpp',
87 90 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
88 91 'src/Visualization/VisualizationGraphWidget.cpp',
89 92 'src/Visualization/VisualizationTabWidget.cpp',
90 93 'src/Visualization/VisualizationWidget.cpp',
91 94 'src/Visualization/VisualizationZoneWidget.cpp',
92 95 'src/Visualization/qcustomplot.cpp',
93 96 'src/Visualization/QCustomPlotSynchronizer.cpp',
94 97 'src/Visualization/operations/FindVariableOperation.cpp',
95 98 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
96 99 'src/Visualization/operations/MenuBuilder.cpp',
97 100 'src/Visualization/operations/RemoveVariableOperation.cpp',
98 101 'src/Visualization/operations/RescaleAxeOperation.cpp',
99 102 'src/Visualization/VisualizationDragDropContainer.cpp',
100 103 'src/Visualization/VisualizationDragWidget.cpp',
101 104 'src/Visualization/AxisRenderingUtils.cpp',
102 105 'src/Visualization/PlottablesRenderingUtils.cpp',
103 106 'src/Visualization/MacScrollBarStyle.cpp',
104 107 'src/Visualization/VisualizationCursorItem.cpp',
105 108 'src/Visualization/ColorScaleEditor.cpp',
106 109 'src/Visualization/SqpColorScale.cpp',
107 110 'src/Visualization/QCPColorMapIterator.cpp',
108 111 'src/Visualization/VisualizationSelectionZoneItem.cpp',
109 112 'src/Visualization/VisualizationSelectionZoneManager.cpp',
110 113 'src/Actions/SelectionZoneAction.cpp',
111 114 'src/Actions/ActionsGuiController.cpp',
112 115 'src/Visualization/VisualizationActionManager.cpp',
113 116 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp',
114 117 'src/Catalogue/CatalogueExplorer.cpp',
115 118 'src/Catalogue/CatalogueEventsWidget.cpp',
116 119 'src/Catalogue/CatalogueSideBarWidget.cpp',
117 120 'src/Catalogue/CatalogueInspectorWidget.cpp',
118 121 'src/Catalogue/CatalogueTreeWidgetItem.cpp',
119 'src/Catalogue/CatalogueEventsModel.cpp'
122 'src/Catalogue/CatalogueEventsModel.cpp',
123 'src/Catalogue/CatalogueExplorerHelper.cpp',
124 'src/Catalogue/CatalogueActionManager.cpp',
125 'src/Catalogue/CreateEventDialog.cpp'
120 126 ]
121 127
122 128 gui_inc = include_directories(['include'])
123 129
124 130 sciqlop_gui_lib = library('sciqlopgui',
125 131 gui_sources,
126 132 gui_moc_files,
127 133 rcc_files,
128 134 include_directories : [gui_inc],
129 135 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep],
130 136 install : true
131 137 )
132 138
133 139 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
134 140 include_directories : gui_inc,
135 141 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core, catalogueapi_dep])
136 142
137 143
@@ -1,381 +1,442
1 1 #include "Catalogue/CatalogueEventsModel.h"
2 2
3 3 #include <Common/DateUtils.h>
4 4 #include <Common/MimeTypesDef.h>
5 5 #include <DBEvent.h>
6 6 #include <DBEventProduct.h>
7 7 #include <DBTag.h>
8 8 #include <Data/SqpRange.h>
9 9 #include <SqpApplication.h>
10 10 #include <Time/TimeController.h>
11 11
12 12 #include <list>
13 13 #include <unordered_map>
14 14
15 15 #include <QHash>
16 16 #include <QMimeData>
17 17
18 Q_LOGGING_CATEGORY(LOG_CatalogueEventsModel, "CatalogueEventsModel")
19
18 20 const auto EVENT_ITEM_TYPE = 1;
19 21 const auto EVENT_PRODUCT_ITEM_TYPE = 2;
20 22
21 23 struct CatalogueEventsModel::CatalogueEventsModelPrivate {
22 24 QVector<std::shared_ptr<DBEvent> > m_Events;
23 25 std::unordered_map<DBEvent *, QVector<std::shared_ptr<DBEventProduct> > > m_EventProducts;
26 std::unordered_set<std::shared_ptr<DBEvent> > m_EventsWithChanges;
24 27
25 enum class Column { Name, TStart, TEnd, Tags, Product, NbColumn };
26 28 QStringList columnNames()
27 29 {
28 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"), tr("Tags"), tr("Product")};
30 return QStringList{tr("Event"), tr("TStart"), tr("TEnd"),
31 tr("Tags"), tr("Product"), tr("")};
32 }
33
34 QVariant sortData(int col, const std::shared_ptr<DBEvent> &event) const
35 {
36 if (col == (int)CatalogueEventsModel::Column::Validation) {
37 return m_EventsWithChanges.find(event) != m_EventsWithChanges.cend() ? true
38 : QVariant();
39 }
40
41 return eventData(col, event);
29 42 }
30 43
31 44 QVariant eventData(int col, const std::shared_ptr<DBEvent> &event) const
32 45 {
33 46 switch (static_cast<Column>(col)) {
34 case Column::Name:
47 case CatalogueEventsModel::Column::Name:
35 48 return event->getName();
36 case Column::TStart:
37 return DateUtils::dateTime(event->getTStart());
38 case Column::TEnd:
39 return DateUtils::dateTime(event->getTEnd());
40 case Column::Product: {
41 auto eventProductsIt = m_EventProducts.find(event.get());
42 if (eventProductsIt != m_EventProducts.cend()) {
43 return QString::number(m_EventProducts.at(event.get()).count()) + " product(s)";
44 }
45 else {
46 return "0 product";
47 }
48 }
49 case Column::Tags: {
49 case CatalogueEventsModel::Column::TStart:
50 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTStart())
51 : QVariant{};
52 case CatalogueEventsModel::Column::TEnd:
53 return nbEventProducts(event) > 0 ? DateUtils::dateTime(event->getTEnd())
54 : QVariant{};
55 case CatalogueEventsModel::Column::Product:
56 return QString::number(nbEventProducts(event)) + " product(s)";
57 case CatalogueEventsModel::Column::Tags: {
50 58 QString tagList;
51 59 auto tags = event->getTags();
52 60 for (auto tag : tags) {
53 61 tagList += tag.getName();
54 62 tagList += ' ';
55 63 }
56 64
57 65 return tagList;
58 66 }
67 case CatalogueEventsModel::Column::Validation:
68 return QVariant();
59 69 default:
60 70 break;
61 71 }
62 72
63 73 Q_ASSERT(false);
64 74 return QStringLiteral("Unknown Data");
65 75 }
66 76
67 77 void parseEventProduct(const std::shared_ptr<DBEvent> &event)
68 78 {
69 79 for (auto product : event->getEventProducts()) {
70 80 m_EventProducts[event.get()].append(std::make_shared<DBEventProduct>(product));
71 81 }
72 82 }
73 83
84 int nbEventProducts(const std::shared_ptr<DBEvent> &event) const
85 {
86 auto eventProductsIt = m_EventProducts.find(event.get());
87 if (eventProductsIt != m_EventProducts.cend()) {
88 return m_EventProducts.at(event.get()).count();
89 }
90 else {
91 return 0;
92 }
93 }
94
74 95 QVariant eventProductData(int col, const std::shared_ptr<DBEventProduct> &eventProduct) const
75 96 {
76 97 switch (static_cast<Column>(col)) {
77 case Column::Name:
98 case CatalogueEventsModel::Column::Name:
78 99 return eventProduct->getProductId();
79 case Column::TStart:
100 case CatalogueEventsModel::Column::TStart:
80 101 return DateUtils::dateTime(eventProduct->getTStart());
81 case Column::TEnd:
102 case CatalogueEventsModel::Column::TEnd:
82 103 return DateUtils::dateTime(eventProduct->getTEnd());
83 case Column::Product:
104 case CatalogueEventsModel::Column::Product:
84 105 return eventProduct->getProductId();
85 case Column::Tags: {
106 case CatalogueEventsModel::Column::Tags:
86 107 return QString();
87 }
108 case CatalogueEventsModel::Column::Validation:
109 return QVariant();
88 110 default:
89 111 break;
90 112 }
91 113
92 114 Q_ASSERT(false);
93 115 return QStringLiteral("Unknown Data");
94 116 }
95 117 };
96 118
97 119 CatalogueEventsModel::CatalogueEventsModel(QObject *parent)
98 120 : QAbstractItemModel(parent), impl{spimpl::make_unique_impl<CatalogueEventsModelPrivate>()}
99 121 {
100 122 }
101 123
102 124 void CatalogueEventsModel::setEvents(const QVector<std::shared_ptr<DBEvent> > &events)
103 125 {
104 126 beginResetModel();
105 127
106 128 impl->m_Events = events;
107 129 impl->m_EventProducts.clear();
130 impl->m_EventsWithChanges.clear();
108 131 for (auto event : events) {
109 132 impl->parseEventProduct(event);
110 133 }
111 134
112 135 endResetModel();
113 136 }
114 137
115 138 std::shared_ptr<DBEvent> CatalogueEventsModel::getEvent(const QModelIndex &index) const
116 139 {
117 140 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::Event) {
118 141 return impl->m_Events.value(index.row());
119 142 }
120 143 else {
121 144 return nullptr;
122 145 }
123 146 }
124 147
125 148 std::shared_ptr<DBEvent> CatalogueEventsModel::getParentEvent(const QModelIndex &index) const
126 149 {
127 150 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
128 151 return getEvent(index.parent());
129 152 }
130 153 else {
131 154 return nullptr;
132 155 }
133 156 }
134 157
135 158 std::shared_ptr<DBEventProduct>
136 159 CatalogueEventsModel::getEventProduct(const QModelIndex &index) const
137 160 {
138 161 if (itemTypeOf(index) == CatalogueEventsModel::ItemType::EventProduct) {
139 162 auto event = static_cast<DBEvent *>(index.internalPointer());
140 163 return impl->m_EventProducts.at(event).value(index.row());
141 164 }
142 165 else {
143 166 return nullptr;
144 167 }
145 168 }
146 169
147 170 void CatalogueEventsModel::addEvent(const std::shared_ptr<DBEvent> &event)
148 171 {
149 172 beginInsertRows(QModelIndex(), impl->m_Events.count() - 1, impl->m_Events.count() - 1);
150 173 impl->m_Events.append(event);
151 174 impl->parseEventProduct(event);
152 175 endInsertRows();
153 176 }
154 177
155 178 void CatalogueEventsModel::removeEvent(const std::shared_ptr<DBEvent> &event)
156 179 {
157 180 auto index = impl->m_Events.indexOf(event);
158 181 if (index >= 0) {
159 182 beginRemoveRows(QModelIndex(), index, index);
160 183 impl->m_Events.removeAt(index);
161 184 impl->m_EventProducts.erase(event.get());
185 impl->m_EventsWithChanges.erase(event);
162 186 endRemoveRows();
163 187 }
164 188 }
165 189
190 QVector<std::shared_ptr<DBEvent> > CatalogueEventsModel::events() const
191 {
192 return impl->m_Events;
193 }
194
166 195 void CatalogueEventsModel::refreshEvent(const std::shared_ptr<DBEvent> &event)
167 196 {
168 auto i = impl->m_Events.indexOf(event);
169 if (i >= 0) {
170 auto eventIndex = index(i, 0);
197 auto eventIndex = indexOf(event);
198 if (eventIndex.isValid()) {
199
200 // Refreshes the event line
171 201 auto colCount = columnCount();
172 emit dataChanged(eventIndex, index(i, colCount));
202 emit dataChanged(eventIndex, index(eventIndex.row(), colCount));
173 203
204 // Also refreshes its children event products
174 205 auto childCount = rowCount(eventIndex);
175 206 emit dataChanged(index(0, 0, eventIndex), index(childCount, colCount, eventIndex));
176 207 }
208 else {
209 qCWarning(LOG_CatalogueEventsModel()) << "refreshEvent: event not found.";
210 }
211 }
212
213 QModelIndex CatalogueEventsModel::indexOf(const std::shared_ptr<DBEvent> &event) const
214 {
215 auto row = impl->m_Events.indexOf(event);
216 if (row >= 0) {
217 return index(row, 0);
218 }
219
220 return QModelIndex();
221 }
222
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();
177 237 }
178 238
179 239 QModelIndex CatalogueEventsModel::index(int row, int column, const QModelIndex &parent) const
180 240 {
181 241 if (!hasIndex(row, column, parent)) {
182 242 return QModelIndex();
183 243 }
184 244
185 245 switch (itemTypeOf(parent)) {
186 246 case CatalogueEventsModel::ItemType::Root:
187 247 return createIndex(row, column);
188 248 case CatalogueEventsModel::ItemType::Event: {
189 249 auto event = getEvent(parent);
190 250 return createIndex(row, column, event.get());
191 251 }
192 252 case CatalogueEventsModel::ItemType::EventProduct:
193 253 break;
194 254 default:
195 255 break;
196 256 }
197 257
198 258 return QModelIndex();
199 259 }
200 260
201 261 QModelIndex CatalogueEventsModel::parent(const QModelIndex &index) const
202 262 {
203 263 switch (itemTypeOf(index)) {
204 264 case CatalogueEventsModel::ItemType::EventProduct: {
205 265 auto parentEvent = static_cast<DBEvent *>(index.internalPointer());
206 266 auto it
207 267 = std::find_if(impl->m_Events.cbegin(), impl->m_Events.cend(),
208 268 [parentEvent](auto event) { return event.get() == parentEvent; });
209 269
210 270 if (it != impl->m_Events.cend()) {
211 271 return createIndex(it - impl->m_Events.cbegin(), 0);
212 272 }
213 273 else {
214 274 return QModelIndex();
215 275 }
216 276 }
217 277 case CatalogueEventsModel::ItemType::Root:
218 278 break;
219 279 case CatalogueEventsModel::ItemType::Event:
220 280 break;
221 281 default:
222 282 break;
223 283 }
224 284
225 285 return QModelIndex();
226 286 }
227 287
228 288 int CatalogueEventsModel::rowCount(const QModelIndex &parent) const
229 289 {
230 290 if (parent.column() > 0) {
231 291 return 0;
232 292 }
233 293
234 294 switch (itemTypeOf(parent)) {
235 295 case CatalogueEventsModel::ItemType::Root:
236 296 return impl->m_Events.count();
237 297 case CatalogueEventsModel::ItemType::Event: {
238 298 auto event = getEvent(parent);
239 299 return impl->m_EventProducts[event.get()].count();
240 300 }
241 301 case CatalogueEventsModel::ItemType::EventProduct:
242 302 break;
243 303 default:
244 304 break;
245 305 }
246 306
247 307 return 0;
248 308 }
249 309
250 310 int CatalogueEventsModel::columnCount(const QModelIndex &parent) const
251 311 {
252 return static_cast<int>(CatalogueEventsModelPrivate::Column::NbColumn);
312 return static_cast<int>(CatalogueEventsModel::Column::NbColumn);
253 313 }
254 314
255 315 Qt::ItemFlags CatalogueEventsModel::flags(const QModelIndex &index) const
256 316 {
257 317 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled;
258 318 }
259 319
260 320 QVariant CatalogueEventsModel::data(const QModelIndex &index, int role) const
261 321 {
262 322 if (index.isValid()) {
263 323
264 324 auto type = itemTypeOf(index);
265 325 if (type == CatalogueEventsModel::ItemType::Event) {
266 326 auto event = getEvent(index);
267 327 switch (role) {
268 328 case Qt::DisplayRole:
269 329 return impl->eventData(index.column(), event);
270 330 break;
271 331 }
272 332 }
273 333 else if (type == CatalogueEventsModel::ItemType::EventProduct) {
274 334 auto product = getEventProduct(index);
275 335 switch (role) {
276 336 case Qt::DisplayRole:
277 337 return impl->eventProductData(index.column(), product);
278 338 break;
279 339 }
280 340 }
281 341 }
282 342
283 343 return QVariant{};
284 344 }
285 345
286 346 QVariant CatalogueEventsModel::headerData(int section, Qt::Orientation orientation, int role) const
287 347 {
288 348 if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
289 349 return impl->columnNames().value(section);
290 350 }
291 351
292 352 return QVariant();
293 353 }
294 354
295 355 void CatalogueEventsModel::sort(int column, Qt::SortOrder order)
296 356 {
297 357 std::sort(impl->m_Events.begin(), impl->m_Events.end(),
298 358 [this, column, order](auto e1, auto e2) {
299 auto data1 = impl->eventData(column, e1);
300 auto data2 = impl->eventData(column, e2);
359 auto data1 = impl->sortData(column, e1);
360 auto data2 = impl->sortData(column, e2);
301 361
302 362 auto result = data1.toString() < data2.toString();
303 363
304 364 return order == Qt::AscendingOrder ? result : !result;
305 365 });
306 366
307 367 emit dataChanged(QModelIndex(), QModelIndex());
368 emit modelSorted();
308 369 }
309 370
310 371 Qt::DropActions CatalogueEventsModel::supportedDragActions() const
311 372 {
312 373 return Qt::CopyAction | Qt::MoveAction;
313 374 }
314 375
315 376 QStringList CatalogueEventsModel::mimeTypes() const
316 377 {
317 378 return {MIME_TYPE_EVENT_LIST, MIME_TYPE_TIME_RANGE};
318 379 }
319 380
320 381 QMimeData *CatalogueEventsModel::mimeData(const QModelIndexList &indexes) const
321 382 {
322 383 auto mimeData = new QMimeData;
323 384
324 385 bool isFirst = true;
325 386
326 387 QVector<std::shared_ptr<DBEvent> > eventList;
327 388 QVector<std::shared_ptr<DBEventProduct> > eventProductList;
328 389
329 390 SqpRange firstTimeRange;
330 391 for (const auto &index : indexes) {
331 392 if (index.column() == 0) { // only the first column
332 393
333 394 auto type = itemTypeOf(index);
334 395 if (type == ItemType::Event) {
335 396 auto event = getEvent(index);
336 397 eventList << event;
337 398
338 399 if (isFirst) {
339 400 isFirst = false;
340 401 firstTimeRange.m_TStart = event->getTStart();
341 402 firstTimeRange.m_TEnd = event->getTEnd();
342 403 }
343 404 }
344 405 else if (type == ItemType::EventProduct) {
345 406 auto product = getEventProduct(index);
346 407 eventProductList << product;
347 408
348 409 if (isFirst) {
349 410 isFirst = false;
350 411 firstTimeRange.m_TStart = product->getTStart();
351 412 firstTimeRange.m_TEnd = product->getTEnd();
352 413 }
353 414 }
354 415 }
355 416 }
356 417
357 418 auto eventsEncodedData
358 419 = QByteArray{}; // sqpApp->catalogueController().->mimeDataForEvents(eventList); //TODO
359 420 mimeData->setData(MIME_TYPE_EVENT_LIST, eventsEncodedData);
360 421
361 422 if (eventList.count() + eventProductList.count() == 1) {
362 423 // No time range MIME data if multiple events are dragged
363 424 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
364 425 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
365 426 }
366 427
367 428 return mimeData;
368 429 }
369 430
370 431 CatalogueEventsModel::ItemType CatalogueEventsModel::itemTypeOf(const QModelIndex &index) const
371 432 {
372 433 if (!index.isValid()) {
373 434 return ItemType::Root;
374 435 }
375 436 else if (index.internalPointer() == nullptr) {
376 437 return ItemType::Event;
377 438 }
378 439 else {
379 440 return ItemType::EventProduct;
380 441 }
381 442 }
@@ -1,316 +1,360
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 #include <Catalogue/CatalogueExplorerHelper.h>
6 7 #include <CatalogueDao.h>
7 8 #include <DBCatalogue.h>
8 9 #include <SqpApplication.h>
9 10 #include <Visualization/VisualizationTabWidget.h>
10 11 #include <Visualization/VisualizationWidget.h>
11 12 #include <Visualization/VisualizationZoneWidget.h>
12 13
13 14 #include <QDialog>
14 15 #include <QDialogButtonBox>
15 16 #include <QListWidget>
16 17
17 18 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
18 19
19 /// Format of the dates appearing in the label of a cursor
20 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss");
20 /// Fixed size of the validation column
21 const auto VALIDATION_COLUMN_SIZE = 35;
21 22
22 23 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
23 24
24 25 CatalogueEventsModel *m_Model = nullptr;
25 26 QStringList m_ZonesForTimeMode;
26 27 QString m_ZoneForGraphMode;
27 28
28 29 VisualizationWidget *m_VisualizationWidget = nullptr;
29 30
30 31 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, QTreeView *treeView)
31 32 {
32 33 treeView->setSortingEnabled(false);
33 34 m_Model->setEvents(events);
34 35 treeView->setSortingEnabled(true);
35 36 }
36 37
37 38 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
38 39 {
39 40 treeView->setSortingEnabled(false);
40 41 m_Model->addEvent(event);
41 42 treeView->setSortingEnabled(true);
42 43 }
43 44
44 45 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
45 46 {
46 47 treeView->setSortingEnabled(false);
47 48 m_Model->removeEvent(event);
48 49 treeView->setSortingEnabled(true);
49 50 }
50 51
51 52 QStringList getAvailableVisualizationZoneList() const
52 53 {
53 54 if (m_VisualizationWidget) {
54 55 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
55 56 return tab->availableZoneWidgets();
56 57 }
57 58 }
58 59
59 60 return QStringList{};
60 61 }
61 62
62 63 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
63 64 bool allowMultiSelection, const QPoint &location)
64 65 {
65 66 auto availableZones = getAvailableVisualizationZoneList();
66 67 if (availableZones.isEmpty()) {
67 68 return QStringList{};
68 69 }
69 70
70 71 QDialog d(parent, Qt::Tool);
71 72 d.setWindowTitle("Choose a zone");
72 73 auto layout = new QVBoxLayout{&d};
73 74 layout->setContentsMargins(0, 0, 0, 0);
74 75 auto listWidget = new QListWidget{&d};
75 76 layout->addWidget(listWidget);
76 77
77 78 QSet<QListWidgetItem *> checkedItems;
78 79 for (auto zone : availableZones) {
79 80 auto item = new QListWidgetItem{zone};
80 81 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
81 82 if (selectedZones.contains(zone)) {
82 83 item->setCheckState(Qt::Checked);
83 84 checkedItems << item;
84 85 }
85 86 else {
86 87 item->setCheckState(Qt::Unchecked);
87 88 }
88 89
89 90 listWidget->addItem(item);
90 91 }
91 92
92 93 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
93 94 layout->addWidget(buttonBox);
94 95
95 96 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
96 97 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
97 98
98 99 QObject::connect(listWidget, &QListWidget::itemChanged,
99 100 [&checkedItems, allowMultiSelection, listWidget](auto item) {
100 101 if (item->checkState() == Qt::Checked) {
101 102 if (!allowMultiSelection) {
102 103 for (auto checkedItem : checkedItems) {
103 104 listWidget->blockSignals(true);
104 105 checkedItem->setCheckState(Qt::Unchecked);
105 106 listWidget->blockSignals(false);
106 107 }
107 108
108 109 checkedItems.clear();
109 110 }
110 111 checkedItems << item;
111 112 }
112 113 else {
113 114 checkedItems.remove(item);
114 115 }
115 116 });
116 117
117 118 QStringList result;
118 119
119 120 d.setMinimumWidth(120);
120 121 d.resize(d.minimumSizeHint());
121 122 d.move(location);
122 123 if (d.exec() == QDialog::Accepted) {
123 124 for (auto item : checkedItems) {
124 125 result += item->text();
125 126 }
126 127 }
127 128 else {
128 129 result = selectedZones;
129 130 }
130 131
131 132 return result;
132 133 }
133 134
134 135 void updateForTimeMode(QTreeView *treeView)
135 136 {
136 137 auto selectedRows = treeView->selectionModel()->selectedRows();
137 138
138 139 if (selectedRows.count() == 1) {
139 140 auto event = m_Model->getEvent(selectedRows.first());
140 141 if (event) {
141 142 if (m_VisualizationWidget) {
142 143 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
143 144
144 145 for (auto zoneName : m_ZonesForTimeMode) {
145 146 if (auto zone = tab->getZoneWithName(zoneName)) {
146 147 SqpRange eventRange;
147 148 eventRange.m_TStart = event->getTStart();
148 149 eventRange.m_TEnd = event->getTEnd();
149 150 zone->setZoneRange(eventRange);
150 151 }
151 152 }
152 153 }
153 154 else {
154 155 qCWarning(LOG_CatalogueEventsWidget())
155 156 << "updateTimeZone: no tab found in the visualization";
156 157 }
157 158 }
158 159 else {
159 160 qCWarning(LOG_CatalogueEventsWidget())
160 161 << "updateTimeZone: visualization widget not found";
161 162 }
162 163 }
163 164 }
164 165 else {
165 166 qCWarning(LOG_CatalogueEventsWidget())
166 167 << "updateTimeZone: not compatible with multiple events selected";
167 168 }
168 169 }
169 170
170 171 void updateForGraphMode(QTreeView *treeView)
171 172 {
172 173 auto selectedRows = treeView->selectionModel()->selectedRows();
173 174
174 175 if (selectedRows.count() == 1) {
175 176 auto event = m_Model->getEvent(selectedRows.first());
176 177 if (m_VisualizationWidget) {
177 178 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
178 179 if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) {
179 180 // TODO
180 181 }
181 182 }
182 183 else {
183 184 qCWarning(LOG_CatalogueEventsWidget())
184 185 << "updateGraphMode: no tab found in the visualization";
185 186 }
186 187 }
187 188 else {
188 189 qCWarning(LOG_CatalogueEventsWidget())
189 190 << "updateGraphMode: visualization widget not found";
190 191 }
191 192 }
192 193 else {
193 194 qCWarning(LOG_CatalogueEventsWidget())
194 195 << "updateGraphMode: not compatible with multiple events selected";
195 196 }
196 197 }
197 198 };
198 199
199 200 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
200 201 : QWidget(parent),
201 202 ui(new Ui::CatalogueEventsWidget),
202 203 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
203 204 {
204 205 ui->setupUi(this);
205 206
206 207 impl->m_Model = new CatalogueEventsModel{this};
207 208 ui->treeView->setModel(impl->m_Model);
208 209
209 210 ui->treeView->setSortingEnabled(true);
210 211 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
211 212 ui->treeView->setDragEnabled(true);
212 213
213 214 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
214 215 if (checked) {
215 216 ui->btnChart->setChecked(false);
216 217 impl->m_ZonesForTimeMode
217 218 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
218 219 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
219 220
220 221 impl->updateForTimeMode(ui->treeView);
221 222 }
222 223 });
223 224
224 225 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
225 226 if (checked) {
226 227 ui->btnTime->setChecked(false);
227 228 impl->m_ZoneForGraphMode
228 229 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
229 230 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
230 231 .value(0);
231 232
232 233 impl->updateForGraphMode(ui->treeView);
233 234 }
234 235 });
235 236
236 237 auto emitSelection = [this]() {
237 238 QVector<std::shared_ptr<DBEvent> > events;
238 239 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
239 240
240 241 for (auto rowIndex : ui->treeView->selectionModel()->selectedRows()) {
241 242
242 243 auto itemType = impl->m_Model->itemTypeOf(rowIndex);
243 244 if (itemType == CatalogueEventsModel::ItemType::Event) {
244 245 events << impl->m_Model->getEvent(rowIndex);
245 246 }
246 247 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
247 248 eventProducts << qMakePair(impl->m_Model->getParentEvent(rowIndex),
248 249 impl->m_Model->getEventProduct(rowIndex));
249 250 }
250 251 }
251 252
252 253 if (!events.isEmpty() && eventProducts.isEmpty()) {
253 254 emit this->eventsSelected(events);
254 255 }
255 256 else if (events.isEmpty() && !eventProducts.isEmpty()) {
256 257 emit this->eventProductsSelected(eventProducts);
257 258 }
258 259 else {
259 260 emit this->selectionCleared();
260 261 }
261 262 };
262 263
263 264 connect(ui->treeView, &QTreeView::clicked, emitSelection);
264 265 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, emitSelection);
265 266
266 267 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
267 268 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
268 269 ui->btnChart->setEnabled(isNotMultiSelection);
269 270 ui->btnTime->setEnabled(isNotMultiSelection);
270 271
271 272 if (isNotMultiSelection && ui->btnTime->isChecked()) {
272 273 impl->updateForTimeMode(ui->treeView);
273 274 }
274 275 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
275 276 impl->updateForGraphMode(ui->treeView);
276 277 }
277 278 });
278 279
279 280 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
280 ui->treeView->header()->setSectionResizeMode(0, QHeaderView::Stretch);
281 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
282 QHeaderView::Stretch);
283 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
284 QHeaderView::Fixed);
285 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
286 VALIDATION_COLUMN_SIZE);
281 287 ui->treeView->header()->setSortIndicatorShown(true);
288
289 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
290 auto allEvents = impl->m_Model->events();
291 for (auto event : allEvents) {
292 setEventChanges(event, impl->m_Model->eventsHasChanges(event));
293 }
294 });
282 295 }
283 296
284 297 CatalogueEventsWidget::~CatalogueEventsWidget()
285 298 {
286 299 delete ui;
287 300 }
288 301
289 302 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
290 303 {
291 304 impl->m_VisualizationWidget = visualization;
292 305 }
293 306
294 307 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
295 308 {
296 309 impl->m_Model->refreshEvent(event);
310
311 auto eventIndex = impl->m_Model->indexOf(event);
312 auto validationIndex
313 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
314
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);
321 }
322 }
323 else {
324 // Note: the widget is destroyed
325 ui->treeView->setIndexWidget(validationIndex, nullptr);
326 }
327
328 impl->m_Model->setEventHasChanges(event, hasChanges);
297 329 }
298 330
299 331 void CatalogueEventsWidget::populateWithCatalogues(
300 332 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
301 333 {
302 334 QSet<QUuid> eventIds;
303 335 QVector<std::shared_ptr<DBEvent> > events;
304 336
305 337 for (auto catalogue : catalogues) {
306 338 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
307 339 for (auto event : catalogueEvents) {
308 340 if (!eventIds.contains(event->getUniqId())) {
309 341 events << event;
310 342 eventIds.insert(event->getUniqId());
311 343 }
312 344 }
313 345 }
314 346
315 347 impl->setEvents(events, ui->treeView);
316 348 }
349
350 void CatalogueEventsWidget::populateWithAllEvents()
351 {
352 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
353
354 QVector<std::shared_ptr<DBEvent> > events;
355 for (auto event : allEvents) {
356 events << event;
357 }
358
359 impl->setEvents(events, ui->treeView);
360 }
@@ -1,83 +1,95
1 1 #include "Catalogue/CatalogueExplorer.h"
2 2 #include "ui_CatalogueExplorer.h"
3 3
4 #include <Catalogue/CatalogueActionManager.h>
5 #include <Catalogue/CatalogueController.h>
6 #include <SqpApplication.h>
4 7 #include <Visualization/VisualizationWidget.h>
5 8
6 9 #include <DBCatalogue.h>
7 10 #include <DBEvent.h>
8 11
9 12 struct CatalogueExplorer::CatalogueExplorerPrivate {
13 CatalogueActionManager m_ActionManager;
10 14 };
11 15
12 16 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
13 17 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
14 18 ui(new Ui::CatalogueExplorer),
15 19 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>()}
16 20 {
17 21 ui->setupUi(this);
18 22
23 impl->m_ActionManager.installSelectionZoneActions();
24
19 25 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
20 26 if (catalogues.count() == 1) {
21 27 ui->inspector->setCatalogue(catalogues.first());
22 28 }
23 29 else {
24 30 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
25 31 }
26 32
27 33 ui->events->populateWithCatalogues(catalogues);
28 34 });
29 35
30 36 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
31 37 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
32 38 });
33 39
34 40 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected,
35 41 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
36 42
37 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected,
38 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
43 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected, [this]() {
44 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
45 ui->events->populateWithAllEvents();
46 });
39 47
40 48 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared,
41 49 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
42 50
43 51 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
44 52 if (events.count() == 1) {
45 53 ui->inspector->setEvent(events.first());
46 54 }
47 55 else {
48 56 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
49 57 }
50 58 });
51 59
52 60 connect(ui->events, &CatalogueEventsWidget::eventProductsSelected, [this](auto eventProducts) {
53 61 if (eventProducts.count() == 1) {
54 62 ui->inspector->setEventProduct(eventProducts.first().first,
55 63 eventProducts.first().second);
56 64 }
57 65 else {
58 66 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
59 67 }
60 68 });
61 69
62 70 connect(ui->events, &CatalogueEventsWidget::selectionCleared,
63 71 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
64 72
65 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated,
66 [this](auto catalogue) { ui->catalogues->setCatalogueChanges(catalogue, true); });
73 connect(ui->inspector, &CatalogueInspectorWidget::catalogueUpdated, [this](auto catalogue) {
74 sqpApp->catalogueController().updateCatalogue(catalogue);
75 ui->catalogues->setCatalogueChanges(catalogue, true);
76 });
67 77
68 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated,
69 [this](auto event) { ui->events->setEventChanges(event, true); });
78 connect(ui->inspector, &CatalogueInspectorWidget::eventUpdated, [this](auto event) {
79 sqpApp->catalogueController().updateEvent(event);
80 ui->events->setEventChanges(event, true);
81 });
70 82
71 83 connect(ui->inspector, &CatalogueInspectorWidget::eventProductUpdated,
72 84 [this](auto event, auto eventProduct) { ui->events->setEventChanges(event, true); });
73 85 }
74 86
75 87 CatalogueExplorer::~CatalogueExplorer()
76 88 {
77 89 delete ui;
78 90 }
79 91
80 92 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
81 93 {
82 94 ui->events->setVisualizationWidget(visualization);
83 95 }
@@ -1,247 +1,250
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 6 #include <Catalogue/CatalogueTreeWidgetItem.h>
7 7 #include <CatalogueDao.h>
8 8 #include <ComparaisonPredicate.h>
9 9 #include <DBCatalogue.h>
10 10
11 11 #include <QMenu>
12 12
13 13 Q_LOGGING_CATEGORY(LOG_CatalogueSideBarWidget, "CatalogueSideBarWidget")
14 14
15 15
16 16 constexpr auto ALL_EVENT_ITEM_TYPE = QTreeWidgetItem::UserType;
17 17 constexpr auto TRASH_ITEM_TYPE = QTreeWidgetItem::UserType + 1;
18 18 constexpr auto CATALOGUE_ITEM_TYPE = QTreeWidgetItem::UserType + 2;
19 19 constexpr auto DATABASE_ITEM_TYPE = QTreeWidgetItem::UserType + 3;
20 20
21 21
22 22 struct CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate {
23 23
24 24 void configureTreeWidget(QTreeWidget *treeWidget);
25 25 QTreeWidgetItem *addDatabaseItem(const QString &name, QTreeWidget *treeWidget);
26 26 QTreeWidgetItem *getDatabaseItem(const QString &name, QTreeWidget *treeWidget);
27 27 void addCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
28 28 QTreeWidgetItem *parentDatabaseItem);
29 29
30 30 CatalogueTreeWidgetItem *getCatalogueItem(const std::shared_ptr<DBCatalogue> &catalogue,
31 31 QTreeWidget *treeWidget) const;
32 32 };
33 33
34 34 CatalogueSideBarWidget::CatalogueSideBarWidget(QWidget *parent)
35 35 : QWidget(parent),
36 36 ui(new Ui::CatalogueSideBarWidget),
37 37 impl{spimpl::make_unique_impl<CatalogueSideBarWidgetPrivate>()}
38 38 {
39 39 ui->setupUi(this);
40 40 impl->configureTreeWidget(ui->treeWidget);
41 41
42 42 ui->treeWidget->setColumnCount(2);
43 43 ui->treeWidget->header()->setStretchLastSection(false);
44 44 ui->treeWidget->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
45 45 ui->treeWidget->header()->setSectionResizeMode(0, QHeaderView::Stretch);
46 46
47 47 auto emitSelection = [this]() {
48 48
49 49 auto selectedItems = ui->treeWidget->selectedItems();
50 50 if (selectedItems.isEmpty()) {
51 51 emit this->selectionCleared();
52 52 }
53 53 else {
54 54 QVector<std::shared_ptr<DBCatalogue> > catalogues;
55 55 QStringList databases;
56 56 int selectionType = selectedItems.first()->type();
57 57
58 58 for (auto item : ui->treeWidget->selectedItems()) {
59 59 if (item->type() == selectionType) {
60 60 switch (selectionType) {
61 61 case CATALOGUE_ITEM_TYPE:
62 62 catalogues.append(
63 63 static_cast<CatalogueTreeWidgetItem *>(item)->catalogue());
64 64 break;
65 65 case DATABASE_ITEM_TYPE:
66 66 selectionType = DATABASE_ITEM_TYPE;
67 67 databases.append(item->text(0));
68 68 case ALL_EVENT_ITEM_TYPE: // fallthrough
69 69 case TRASH_ITEM_TYPE: // fallthrough
70 70 default:
71 71 break;
72 72 }
73 73 }
74 74 else {
75 75 // Incoherent multi selection
76 76 selectionType = -1;
77 77 break;
78 78 }
79 79 }
80 80
81 81 switch (selectionType) {
82 82 case CATALOGUE_ITEM_TYPE:
83 83 emit this->catalogueSelected(catalogues);
84 84 break;
85 85 case DATABASE_ITEM_TYPE:
86 86 emit this->databaseSelected(databases);
87 87 break;
88 88 case ALL_EVENT_ITEM_TYPE:
89 89 emit this->allEventsSelected();
90 90 break;
91 91 case TRASH_ITEM_TYPE:
92 92 emit this->trashSelected();
93 93 break;
94 94 default:
95 95 emit this->selectionCleared();
96 96 break;
97 97 }
98 98 }
99 99
100 100
101 101 };
102 102
103 103 connect(ui->treeWidget, &QTreeWidget::itemClicked, emitSelection);
104 104 connect(ui->treeWidget, &QTreeWidget::currentItemChanged, emitSelection);
105 105 connect(ui->treeWidget, &QTreeWidget::itemChanged,
106 106 [emitSelection, this](auto item, auto column) {
107 107 auto selectedItems = ui->treeWidget->selectedItems();
108 108 qDebug() << "ITEM CHANGED" << column;
109 109 if (selectedItems.contains(item) && column == 0) {
110 110 emitSelection();
111 111 }
112 112 });
113 113
114 114 ui->treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
115 115 connect(ui->treeWidget, &QTreeWidget::customContextMenuRequested, this,
116 116 &CatalogueSideBarWidget::onContextMenuRequested);
117 117 }
118 118
119 119 CatalogueSideBarWidget::~CatalogueSideBarWidget()
120 120 {
121 121 delete ui;
122 122 }
123 123
124 124 void CatalogueSideBarWidget::setCatalogueChanges(const std::shared_ptr<DBCatalogue> &catalogue,
125 125 bool hasChanges)
126 126 {
127 127 if (auto catalogueItem = impl->getCatalogueItem(catalogue, ui->treeWidget)) {
128 128 catalogueItem->setHasChanges(hasChanges);
129 129 catalogueItem->refresh();
130 130 }
131 131 }
132 132
133 133 void CatalogueSideBarWidget::onContextMenuRequested(const QPoint &pos)
134 134 {
135 135 QMenu menu{this};
136 136
137 137 auto currentItem = ui->treeWidget->currentItem();
138 138 switch (currentItem->type()) {
139 139 case CATALOGUE_ITEM_TYPE:
140 140 menu.addAction("Rename",
141 141 [this, currentItem]() { ui->treeWidget->editItem(currentItem); });
142 142 break;
143 143 case DATABASE_ITEM_TYPE:
144 144 break;
145 145 case ALL_EVENT_ITEM_TYPE:
146 146 break;
147 147 case TRASH_ITEM_TYPE:
148 148 menu.addAction("Empty Trash", []() {
149 149 // TODO
150 150 });
151 151 break;
152 152 default:
153 153 break;
154 154 }
155 155
156 156 if (!menu.isEmpty()) {
157 157 menu.exec(ui->treeWidget->mapToGlobal(pos));
158 158 }
159 159 }
160 160
161 161 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::configureTreeWidget(
162 162 QTreeWidget *treeWidget)
163 163 {
164 164 auto allEventsItem = new QTreeWidgetItem{{"All Events"}, ALL_EVENT_ITEM_TYPE};
165 165 allEventsItem->setIcon(0, QIcon(":/icones/allEvents.png"));
166 166 treeWidget->addTopLevelItem(allEventsItem);
167 167
168 168 auto trashItem = new QTreeWidgetItem{{"Trash"}, TRASH_ITEM_TYPE};
169 169 trashItem->setIcon(0, QIcon(":/icones/trash.png"));
170 170 treeWidget->addTopLevelItem(trashItem);
171 171
172 172 auto separator = new QFrame{treeWidget};
173 173 separator->setFrameShape(QFrame::HLine);
174 174 auto separatorItem = new QTreeWidgetItem{};
175 175 separatorItem->setFlags(Qt::NoItemFlags);
176 176 treeWidget->addTopLevelItem(separatorItem);
177 177 treeWidget->setItemWidget(separatorItem, 0, separator);
178 178
179 auto db = addDatabaseItem("Default", treeWidget);
179 auto repositories = sqpApp->catalogueController().getRepositories();
180 for (auto dbname : repositories) {
181 auto db = addDatabaseItem(dbname, treeWidget);
180 182
181 auto catalogues = sqpApp->catalogueController().retrieveCatalogues("Default");
182 for (auto catalogue : catalogues) {
183 addCatalogueItem(catalogue, db);
183 auto catalogues = sqpApp->catalogueController().retrieveCatalogues(dbname);
184 for (auto catalogue : catalogues) {
185 addCatalogueItem(catalogue, db);
186 }
184 187 }
185 188
186 189 treeWidget->expandAll();
187 190 }
188 191
189 192 QTreeWidgetItem *
190 193 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addDatabaseItem(const QString &name,
191 194 QTreeWidget *treeWidget)
192 195 {
193 196 auto databaseItem = new QTreeWidgetItem{{name}, DATABASE_ITEM_TYPE};
194 197 databaseItem->setIcon(0, QIcon{":/icones/database.png"});
195 198 treeWidget->addTopLevelItem(databaseItem);
196 199
197 200 return databaseItem;
198 201 }
199 202
200 203 QTreeWidgetItem *
201 204 CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getDatabaseItem(const QString &name,
202 205 QTreeWidget *treeWidget)
203 206 {
204 207 for (auto i = 0; i < treeWidget->topLevelItemCount(); ++i) {
205 208 auto item = treeWidget->topLevelItem(i);
206 209 if (item->type() == DATABASE_ITEM_TYPE && item->text(0) == name) {
207 210 return item;
208 211 }
209 212 }
210 213
211 214 return nullptr;
212 215 }
213 216
214 217 void CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::addCatalogueItem(
215 218 const std::shared_ptr<DBCatalogue> &catalogue, QTreeWidgetItem *parentDatabaseItem)
216 219 {
217 220 auto catalogueItem = new CatalogueTreeWidgetItem{catalogue, CATALOGUE_ITEM_TYPE};
218 221 catalogueItem->setIcon(0, QIcon{":/icones/catalogue.png"});
219 222 parentDatabaseItem->addChild(catalogueItem);
220 223 }
221 224
222 225 CatalogueTreeWidgetItem *CatalogueSideBarWidget::CatalogueSideBarWidgetPrivate::getCatalogueItem(
223 226 const std::shared_ptr<DBCatalogue> &catalogue, QTreeWidget *treeWidget) const
224 227 {
225 228 for (auto i = 0; i < treeWidget->topLevelItemCount(); ++i) {
226 229 auto item = treeWidget->topLevelItem(i);
227 230 if (item->type() == DATABASE_ITEM_TYPE) {
228 231 for (auto j = 0; j < item->childCount(); ++j) {
229 232 auto childItem = item->child(j);
230 233 if (childItem->type() == CATALOGUE_ITEM_TYPE) {
231 234 auto catalogueItem = static_cast<CatalogueTreeWidgetItem *>(childItem);
232 235 if (catalogueItem->catalogue() == catalogue) {
233 236 return catalogueItem;
234 237 }
235 238 }
236 239 else {
237 240 qCWarning(LOG_CatalogueSideBarWidget()) << "getCatalogueItem: Invalid tree "
238 241 "structure. A database item should "
239 242 "only contain catalogues.";
240 243 Q_ASSERT(false);
241 244 }
242 245 }
243 246 }
244 247 }
245 248
246 249 return nullptr;
247 250 }
@@ -1,103 +1,91
1 1 #include "Catalogue/CatalogueTreeWidgetItem.h"
2 #include <Catalogue/CatalogueExplorerHelper.h>
3
4 #include <Catalogue/CatalogueController.h>
5 #include <SqpApplication.h>
2 6
3 7 #include <memory>
4 8
5 9 #include <DBCatalogue.h>
6 #include <QBoxLayout>
7 #include <QToolButton>
8
9 const auto VALIDATION_BUTTON_ICON_SIZE = 12;
10 10
11 11 /// Column in the tree widget where the apply and cancel buttons must appear
12 12 const auto APPLY_CANCEL_BUTTONS_COLUMN = 1;
13 13
14 14 struct CatalogueTreeWidgetItem::CatalogueTreeWidgetItemPrivate {
15 15
16 16 std::shared_ptr<DBCatalogue> m_Catalogue;
17 17
18 18 CatalogueTreeWidgetItemPrivate(std::shared_ptr<DBCatalogue> catalogue) : m_Catalogue(catalogue)
19 19 {
20 20 }
21 21 };
22 22
23 23
24 24 CatalogueTreeWidgetItem::CatalogueTreeWidgetItem(std::shared_ptr<DBCatalogue> catalogue, int type)
25 25 : QTreeWidgetItem(type),
26 26 impl{spimpl::make_unique_impl<CatalogueTreeWidgetItemPrivate>(catalogue)}
27 27 {
28 28 setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
29 29 }
30 30
31 31 QVariant CatalogueTreeWidgetItem::data(int column, int role) const
32 32 {
33 33 if (column == 0) {
34 34 switch (role) {
35 35 case Qt::EditRole: // fallthrough
36 36 case Qt::DisplayRole:
37 37 return impl->m_Catalogue->getName();
38 38 default:
39 39 break;
40 40 }
41 41 }
42 42
43 43 return QTreeWidgetItem::data(column, role);
44 44 }
45 45
46 46 void CatalogueTreeWidgetItem::setData(int column, int role, const QVariant &value)
47 47 {
48 48 if (role == Qt::EditRole && column == 0) {
49 49 auto newName = value.toString();
50 50 if (newName != impl->m_Catalogue->getName()) {
51 51 setText(0, newName);
52 52 impl->m_Catalogue->setName(newName);
53 sqpApp->catalogueController().updateCatalogue(impl->m_Catalogue);
53 54 setHasChanges(true);
54 55 }
55 56 }
56 57 else {
57 58 QTreeWidgetItem::setData(column, role, value);
58 59 }
59 60 }
60 61
61 62 std::shared_ptr<DBCatalogue> CatalogueTreeWidgetItem::catalogue() const
62 63 {
63 64 return impl->m_Catalogue;
64 65 }
65 66
66 67 void CatalogueTreeWidgetItem::setHasChanges(bool value)
67 68 {
68 69 if (value) {
69 if (treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) == nullptr) {
70 auto widet = new QWidget{treeWidget()};
71
72 auto layout = new QHBoxLayout{widet};
73 layout->setContentsMargins(0, 0, 0, 0);
74 layout->setSpacing(0);
75
76 auto btnValid = new QToolButton{widet};
77 btnValid->setIcon(QIcon{":/icones/save"});
78 btnValid->setIconSize(QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
79 btnValid->setAutoRaise(true);
80 QObject::connect(btnValid, &QToolButton::clicked, [this]() { setHasChanges(false); });
81 layout->addWidget(btnValid);
82
83 auto btnDiscard = new QToolButton{widet};
84 btnDiscard->setIcon(QIcon{":/icones/discard"});
85 btnDiscard->setIconSize(
86 QSize{VALIDATION_BUTTON_ICON_SIZE, VALIDATION_BUTTON_ICON_SIZE});
87 btnDiscard->setAutoRaise(true);
88 QObject::connect(btnDiscard, &QToolButton::clicked, [this]() { setHasChanges(false); });
89 layout->addWidget(btnDiscard);
90
91 treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, {widet});
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);
92 75 }
93 76 }
94 77 else {
95 78 // Note: the widget is destroyed
96 79 treeWidget()->setItemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN, nullptr);
97 80 }
98 81 }
99 82
83 bool CatalogueTreeWidgetItem::hasChanges()
84 {
85 return treeWidget()->itemWidget(this, APPLY_CANCEL_BUTTONS_COLUMN) != nullptr;
86 }
87
100 88 void CatalogueTreeWidgetItem::refresh()
101 89 {
102 90 emitDataChanged();
103 91 }
General Comments 4
Under Review
author

Pull request updated. Auto status change to "Under Review"

Changed commits:
  * 1 added
  * 0 removed

Changed files:
  * M app/src/Main.cpp
  * M core/include/Catalogue/CatalogueController.h
  * M core/src/Catalogue/CatalogueController.cpp
  * M core/src/Plugin/PluginManager.cpp
  * M core/tests/Data/TestDataSeriesUtils.cpp
  * M gui/include/Catalogue/CatalogueEventsModel.h
  * M gui/include/Catalogue/CatalogueEventsWidget.h
  * M gui/include/Catalogue/CatalogueTreeWidgetItem.h
  * M gui/meson.build
  * M gui/src/Catalogue/CatalogueEventsModel.cpp
  * M gui/src/Catalogue/CatalogueEventsWidget.cpp
  * M gui/src/Catalogue/CatalogueExplorer.cpp
  * M gui/src/Catalogue/CatalogueSideBarWidget.cpp
  * M gui/src/Catalogue/CatalogueTreeWidgetItem.cpp
  * M gui/src/Visualization/VisualizationActionManager.cpp
  * M gui/src/Visualization/VisualizationGraphWidget.cpp
  * M gui/src/Visualization/VisualizationSelectionZoneItem.cpp
  * M plugins/amda/tests/TestAmdaResultParser.cpp
  * R cmake/FindCatalogueAPI.cmake
  * R core/include/Common/MimeTypesDef.h
  * R core/include/Data/DataSeriesUtils.h
  * R core/include/Data/OptionalAxis.h
  * R core/include/Data/SpectrogramSeries.h
  * R core/include/Data/Unit.h
  * R core/include/DataSource/DataSourceItemMergeHelper.h
  * R core/include/Variable/VariableCacheStrategyFactory.h
  * R core/include/Variable/VariableSingleThresholdCacheStrategy.h
  * R core/src/Common/MimeTypesDef.cpp
  * R core/src/Data/DataSeriesUtils.cpp
  * R core/src/Data/OptionalAxis.cpp
  * R core/src/Data/SpectrogramSeries.cpp
  * R core/src/DataSource/DataSourceItemMergeHelper.cpp
  * R core/tests-resources/TestDataSeriesUtils/TestThresholds.txt
  * R core/tests/Data/DataSeriesBuilders.cpp
  * R core/tests/Data/DataSeriesBuilders.h
  * R core/tests/Data/DataSeriesTestsUtils.cpp
  * R core/tests/Data/DataSeriesTestsUtils.h
  * R core/tests/Data/TestOptionalAxis.cpp
  * R core/tests/Data/TestScalarSeries.cpp
  * R core/tests/Data/TestSpectrogramSeries.cpp
  * R core/tests/Data/TestVectorSeries.cpp
  * R core/tests/DataSource/DataSourceItemBuilder.cpp
  * R core/tests/DataSource/DataSourceItemBuilder.h
  * R core/tests/DataSource/TestDataSourceItem.cpp
  * R core/tests/Variable/TestVariableSync.cpp
  * R extern/CatalogueAPI.cmake
  * R gui/include/Actions/ActionsGuiController.h
  * R gui/include/Actions/SelectionZoneAction.h
  * R gui/include/Catalogue/CatalogueExplorer.h
  * R gui/include/Catalogue/CatalogueInspectorWidget.h
  * R gui/include/Catalogue/CatalogueSideBarWidget.h
  * R gui/include/Common/VisualizationDef.h
  * R gui/include/DataSource/DataSourceTreeWidget.h
  * R gui/include/DragAndDrop/DragDropGuiController.h
  * R gui/include/DragAndDrop/DragDropScroller.h
  * R gui/include/DragAndDrop/DragDropTabSwitcher.h
  * R gui/include/Variable/VariableInspectorTableView.h
  * R gui/include/Visualization/AxisRenderingUtils.h
  * R gui/include/Visualization/ColorScaleEditor.h
  * R gui/include/Visualization/MacScrollBarStyle.h
  * R gui/include/Visualization/PlottablesRenderingUtils.h
  * R gui/include/Visualization/QCPColorMapIterator.h
  * R gui/include/Visualization/SqpColorScale.h
  * R gui/include/Visualization/VisualizationActionManager.h
  * R gui/include/Visualization/VisualizationCursorItem.h
  * R gui/include/Visualization/VisualizationDragDropContainer.h
  * R gui/include/Visualization/VisualizationDragWidget.h
  * R gui/include/Visualization/VisualizationMultiZoneSelectionDialog.h
  * R gui/include/Visualization/VisualizationSelectionZoneItem.h
  * R gui/include/Visualization/VisualizationSelectionZoneManager.h
  * R gui/resources/icones/add.png
  * R gui/resources/icones/allEvents.png
  * R gui/resources/icones/catalogue.png
  * R gui/resources/icones/chart.png
  * R gui/resources/icones/cursor.png
  * R gui/resources/icones/database.png
  * R gui/resources/icones/discard.png
  * R gui/resources/icones/drag.png
  * R gui/resources/icones/pointer.png
  * R gui/resources/icones/rectangle.png
  * R gui/resources/icones/remove.png
  * R gui/resources/icones/save.png
  * R gui/resources/icones/time.png
  * R gui/resources/icones/trash.png
  * R gui/resources/icones/zoom.png
  * R gui/src/Actions/ActionsGuiController.cpp
  * R gui/src/Actions/SelectionZoneAction.cpp
  * R gui/src/Catalogue/CatalogueInspectorWidget.cpp
  * R gui/src/Common/VisualizationDef.cpp
  * R gui/src/DataSource/DataSourceTreeWidget.cpp
  * R gui/src/DragAndDrop/DragDropGuiController.cpp
  * R gui/src/DragAndDrop/DragDropScroller.cpp
  * R gui/src/DragAndDrop/DragDropTabSwitcher.cpp
  * R gui/src/Variable/VariableInspectorTableView.cpp
  * R gui/src/Visualization/AxisRenderingUtils.cpp
  * R gui/src/Visualization/ColorScaleEditor.cpp
  * R gui/src/Visualization/MacScrollBarStyle.cpp
  * R gui/src/Visualization/PlottablesRenderingUtils.cpp
  * R gui/src/Visualization/QCPColorMapIterator.cpp
  * R gui/src/Visualization/SqpColorScale.cpp
  * R gui/src/Visualization/VisualizationCursorItem.cpp
  * R gui/src/Visualization/VisualizationDragDropContainer.cpp
  * R gui/src/Visualization/VisualizationDragWidget.cpp
  * R gui/src/Visualization/VisualizationMultiZoneSelectionDialog.cpp
  * R gui/src/Visualization/VisualizationSelectionZoneManager.cpp
  * R gui/ui/Catalogue/CatalogueEventsWidget.ui
  * R gui/ui/Catalogue/CatalogueExplorer.ui
  * R gui/ui/Catalogue/CatalogueInspectorWidget.ui
  * R gui/ui/Catalogue/CatalogueSideBarWidget.ui
  * R gui/ui/Visualization/ColorScaleEditor.ui
  * R gui/ui/Visualization/VisualizationMultiZoneSelectionDialog.ui
  * R plugins/amda/include/AmdaResultParserDefs.h
  * R plugins/amda/include/AmdaResultParserHelper.h
  * R plugins/amda/include/AmdaServer.h
  * R plugins/amda/resources/samples/AmdaSampleV3.json
  * R plugins/amda/src/AmdaResultParserDefs.cpp
  * R plugins/amda/src/AmdaResultParserHelper.cpp
  * R plugins/amda/src/AmdaServer.cpp
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/FileNotFound.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/NaNValue.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/NaNX.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/NoUnit.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/TooManyValues.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/ValidScalar1.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/ValidVector1.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/WrongDate.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/WrongUnit.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/amdaV2/WrongValue.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/InvalidSpectrogramWrongBands.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogram1.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogram2.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogram3.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramDataHoles.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramDataHoles2.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramFillValues.txt
  * R plugins/amda/tests-resources/TestAmdaResultParser/spectro/ValidSpectrogramNaNValues.txt
  * R plugins/amda/vera-exclusions/exclusions.txt
  * R plugins/mockplugin/include/MockDefs.h
  * R plugins/mockplugin/src/MockDefs.cpp
  * R subprojects/CatalogueAPI.wrap
  * R subprojects/QxOrm.wrap
  * R .gitignore
  * R CMakeLists.txt
  * R app/src/MainWindow.cpp
  * R app/ui/MainWindow.ui
  * R cmake/sciqlop_applications.cmake
  * R cmake/sciqlop_package_qt.cmake
  * R core/CMakeLists.txt
  * R core/cmake/Findsciqlop-core.cmake
  * R core/include/Common/SortUtils.h
  * R core/include/Data/ArrayData.h
  * R core/include/Data/DataSeries.h
  * R core/include/Data/DataSeriesIterator.h
  * R core/include/Data/IDataSeries.h
  * R core/include/Data/VariableRequest.h
  * R core/include/DataSource/DataSourceController.h
  * R core/include/DataSource/DataSourceItem.h
  * R core/include/DataSource/DataSourceItemAction.h
  * R core/include/Plugin/PluginManager.h
  * R core/include/Time/TimeController.h
  * R core/include/Variable/Variable.h
  * R core/include/Variable/VariableCacheStrategy.h
  * R core/include/Variable/VariableController.h
  * R core/include/Variable/VariableModel.h
  * R core/meson.build
  * R core/src/Data/DataSeriesIterator.cpp
  * R core/src/Data/VectorSeries.cpp
  * R core/src/DataSource/DataSourceController.cpp
  * R core/src/DataSource/DataSourceItem.cpp
  * R core/src/DataSource/DataSourceItemAction.cpp
  * R core/src/Time/TimeController.cpp
  * R core/src/Variable/Variable.cpp
  * R core/src/Variable/VariableAcquisitionWorker.cpp
  * R core/src/Variable/VariableController.cpp
  * R core/src/Variable/VariableModel.cpp
  * R core/tests/Data/TestTwoDimArrayData.cpp
  * R core/tests/Variable/TestVariable.cpp
  * R core/tests/meson.build
  * R gui/CMakeLists.txt
  * R gui/cmake/Findsciqlop-gui.cmake
  * R gui/include/DataSource/DataSourceWidget.h
  * R gui/include/SqpApplication.h
  * R gui/include/TimeWidget/TimeWidget.h
  * R gui/include/Visualization/VisualizationGraphHelper.h
  * R gui/include/Visualization/VisualizationGraphRenderingDelegate.h
  * R gui/include/Visualization/VisualizationGraphWidget.h
  * R gui/include/Visualization/VisualizationTabWidget.h
  * R gui/include/Visualization/VisualizationWidget.h
  * R gui/include/Visualization/VisualizationZoneWidget.h
  * R gui/resources/sqpguiresources.qrc
  * R gui/src/DataSource/DataSourceTreeWidgetItem.cpp
  * R gui/src/DataSource/DataSourceWidget.cpp
  * R gui/src/SqpApplication.cpp
  * R gui/src/TimeWidget/TimeWidget.cpp
  * R gui/src/Variable/VariableInspectorWidget.cpp
  * R gui/src/Visualization/VisualizationGraphHelper.cpp
  * R gui/src/Visualization/VisualizationGraphRenderingDelegate.cpp
  * R gui/src/Visualization/VisualizationTabWidget.cpp
  * R gui/src/Visualization/VisualizationWidget.cpp
  * R gui/src/Visualization/VisualizationZoneWidget.cpp
  * R gui/src/Visualization/operations/GenerateVariableMenuOperation.cpp
  * R gui/src/Visualization/operations/RescaleAxeOperation.cpp
  * R gui/ui/DataSource/DataSourceWidget.ui
  * R gui/ui/TimeWidget/TimeWidget.ui
  * R gui/ui/Variable/VariableInspectorWidget.ui
  * R gui/ui/Visualization/VisualizationTabWidget.ui
  * R gui/ui/Visualization/VisualizationZoneWidget.ui
  * R gui/vera-exclusions/exclusions.txt
  * R meson.build
  * R plugins/amda/CMakeLists.txt
  * R plugins/amda/cmake/Findsciqlop-amda.cmake
  * R plugins/amda/include/AmdaDefs.h
  * R plugins/amda/include/AmdaPlugin.h
  * R plugins/amda/include/AmdaProvider.h
  * R plugins/amda/include/AmdaResultParser.h
  * R plugins/amda/meson.build
  * R plugins/amda/resources/amdaresources.qrc
  * R plugins/amda/src/AmdaDefs.cpp
  * R plugins/amda/src/AmdaPlugin.cpp
  * R plugins/amda/src/AmdaProvider.cpp
  * R plugins/amda/src/AmdaResultParser.cpp
  * R plugins/amda/tests/TestAmdaAcquisition.cpp
  * R plugins/mockplugin/cmake/Findsciqlop-mockplugin.cmake
  * R plugins/mockplugin/include/CosinusProvider.h
  * R plugins/mockplugin/meson.build
  * R plugins/mockplugin/src/CosinusProvider.cpp
  * R plugins/mockplugin/src/MockPlugin.cpp
  * R plugins/mockplugin/tests/TestCosinusAcquisition.cpp
  * R core/src/Variable/VariableCacheStrategy.cpp
  * R core/tests/Data/TestDataSeries.cpp
Approved

Status change > Approved

You need to be logged in to leave comments. Login now