##// END OF EJS Templates
spelling fix
trabillard -
r1339:1a2f30e2d800
parent child
Show More
@@ -1,405 +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 25 #include <Catalogue/CatalogueController.h>
26 26 #include <Catalogue/CatalogueExplorer.h>
27 27 #include <DataSource/DataSourceController.h>
28 28 #include <DataSource/DataSourceWidget.h>
29 29 #include <Settings/SqpSettingsDialog.h>
30 30 #include <Settings/SqpSettingsGeneralWidget.h>
31 31 #include <SidePane/SqpSidePane.h>
32 32 #include <SqpApplication.h>
33 33 #include <Time/TimeController.h>
34 34 #include <TimeWidget/TimeWidget.h>
35 35 #include <Variable/Variable.h>
36 36 #include <Variable/VariableController.h>
37 37 #include <Visualization/VisualizationController.h>
38 38
39 39 #include <QAction>
40 40 #include <QCloseEvent>
41 41 #include <QDate>
42 42 #include <QDir>
43 43 #include <QFileDialog>
44 44 #include <QMessageBox>
45 45 #include <QToolBar>
46 46 #include <QToolButton>
47 47 #include <memory.h>
48 48
49 49 #include "iostream"
50 50
51 51 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
52 52
53 53 namespace {
54 54 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
55 55 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
56 56 const auto VIEWPLITTERINDEX = 2;
57 57 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
58 58 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
59 59 }
60 60
61 61 class MainWindow::MainWindowPrivate {
62 62 public:
63 63 explicit MainWindowPrivate(MainWindow *mainWindow)
64 64 : m_LastOpenLeftInspectorSize{},
65 65 m_LastOpenRightInspectorSize{},
66 66 m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}},
67 67 m_SettingsDialog{new SqpSettingsDialog{mainWindow}},
68 68 m_CatalogExplorer{new CatalogueExplorer{mainWindow}}
69 69 {
70 70 }
71 71
72 72 QSize m_LastOpenLeftInspectorSize;
73 73 QSize m_LastOpenRightInspectorSize;
74 74 /// General settings widget. MainWindow has the ownership
75 75 SqpSettingsGeneralWidget *m_GeneralSettingsWidget;
76 76 /// Settings dialog. MainWindow has the ownership
77 77 SqpSettingsDialog *m_SettingsDialog;
78 78 /// Catalogue dialog. MainWindow has the ownership
79 79 CatalogueExplorer *m_CatalogExplorer;
80 80
81 81 bool checkDataToSave(QWidget *parentWidget);
82 82 };
83 83
84 84 MainWindow::MainWindow(QWidget *parent)
85 85 : QMainWindow{parent},
86 86 m_Ui{new Ui::MainWindow},
87 87 impl{spimpl::make_unique_impl<MainWindowPrivate>(this)}
88 88 {
89 89 m_Ui->setupUi(this);
90 90
91 91 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
92 92 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
93 93
94 94 impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view);
95 95
96 96
97 97 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
98 98 auto openLeftInspectorAction = new QAction{QIcon{
99 99 ":/icones/previous.png",
100 100 },
101 101 tr("Show/hide the left inspector"), this};
102 102
103 103
104 104 auto spacerLeftTop = new QWidget{};
105 105 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
106 106
107 107 auto spacerLeftBottom = new QWidget{};
108 108 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
109 109
110 110 leftSidePane->addWidget(spacerLeftTop);
111 111 leftSidePane->addAction(openLeftInspectorAction);
112 112 leftSidePane->addWidget(spacerLeftBottom);
113 113
114 114
115 115 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
116 116 auto openRightInspectorAction = new QAction{QIcon{
117 117 ":/icones/next.png",
118 118 },
119 119 tr("Show/hide the right inspector"), this};
120 120
121 121 auto spacerRightTop = new QWidget{};
122 122 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
123 123
124 124 auto spacerRightBottom = new QWidget{};
125 125 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
126 126
127 127 rightSidePane->addWidget(spacerRightTop);
128 128 rightSidePane->addAction(openRightInspectorAction);
129 129 rightSidePane->addWidget(spacerRightBottom);
130 130
131 131 openLeftInspectorAction->setCheckable(true);
132 132 openRightInspectorAction->setCheckable(true);
133 133
134 134 auto openInspector = [this](bool checked, bool right, auto action) {
135 135
136 136 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
137 137
138 138 auto &lastInspectorSize
139 139 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
140 140
141 141 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
142 142 : m_Ui->leftMainInspectorWidget->size();
143 143
144 144 // Update of the last opened geometry
145 145 if (checked) {
146 146 lastInspectorSize = nextInspectorSize;
147 147 }
148 148
149 149 auto startSize = lastInspectorSize;
150 150 auto endSize = startSize;
151 151 endSize.setWidth(0);
152 152
153 153 auto splitterInspectorIndex
154 154 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
155 155
156 156 auto currentSizes = m_Ui->splitter->sizes();
157 157 if (checked) {
158 158 // adjust sizes individually here, e.g.
159 159 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
160 160 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
161 161 m_Ui->splitter->setSizes(currentSizes);
162 162 }
163 163 else {
164 164 // adjust sizes individually here, e.g.
165 165 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
166 166 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
167 167 m_Ui->splitter->setSizes(currentSizes);
168 168 }
169 169
170 170 };
171 171
172 172
173 173 connect(openLeftInspectorAction, &QAction::triggered,
174 174 [openInspector, openLeftInspectorAction](bool checked) {
175 175 openInspector(checked, false, openLeftInspectorAction);
176 176 });
177 177 connect(openRightInspectorAction, &QAction::triggered,
178 178 [openInspector, openRightInspectorAction](bool checked) {
179 179 openInspector(checked, true, openRightInspectorAction);
180 180 });
181 181
182 182 // //////////////// //
183 183 // Menu and Toolbar //
184 184 // //////////////// //
185 185 this->menuBar()->addAction(tr("File"));
186 186 auto toolsMenu = this->menuBar()->addMenu(tr("Tools"));
187 187 toolsMenu->addAction(tr("Settings..."), [this]() {
188 188 // Loads settings
189 189 impl->m_SettingsDialog->loadSettings();
190 190
191 191 // Open settings dialog and save settings if the dialog is accepted
192 192 if (impl->m_SettingsDialog->exec() == QDialog::Accepted) {
193 193 impl->m_SettingsDialog->saveSettings();
194 194 }
195 195
196 196 });
197 197
198 198 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
199 199
200 200 auto timeWidget = new TimeWidget{};
201 201 mainToolBar->addWidget(timeWidget);
202 202
203 203 // Interaction modes
204 204 auto actionPointerMode = new QAction{QIcon(":/icones/pointer.png"), "Move", this};
205 205 actionPointerMode->setCheckable(true);
206 206 actionPointerMode->setChecked(sqpApp->plotsInteractionMode()
207 207 == SqpApplication::PlotsInteractionMode::None);
208 208 connect(actionPointerMode, &QAction::triggered,
209 209 []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); });
210 210
211 211 auto actionZoomMode = new QAction{QIcon(":/icones/zoom.png"), "Zoom", this};
212 212 actionZoomMode->setCheckable(true);
213 213 actionZoomMode->setChecked(sqpApp->plotsInteractionMode()
214 214 == SqpApplication::PlotsInteractionMode::ZoomBox);
215 215 connect(actionZoomMode, &QAction::triggered, []() {
216 216 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox);
217 217 });
218 218
219 219 auto actionOrganisationMode = new QAction{QIcon(":/icones/drag.png"), "Organize", this};
220 220 actionOrganisationMode->setCheckable(true);
221 221 actionOrganisationMode->setChecked(sqpApp->plotsInteractionMode()
222 222 == SqpApplication::PlotsInteractionMode::DragAndDrop);
223 223 connect(actionOrganisationMode, &QAction::triggered, []() {
224 224 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop);
225 225 });
226 226
227 227 auto actionZonesMode = new QAction{QIcon(":/icones/rectangle.png"), "Zones", this};
228 228 actionZonesMode->setCheckable(true);
229 229 actionZonesMode->setChecked(sqpApp->plotsInteractionMode()
230 230 == SqpApplication::PlotsInteractionMode::SelectionZones);
231 231 connect(actionZonesMode, &QAction::triggered, []() {
232 232 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones);
233 233 });
234 234
235 235 auto modeActionGroup = new QActionGroup{this};
236 236 modeActionGroup->addAction(actionZoomMode);
237 237 modeActionGroup->addAction(actionZonesMode);
238 238 modeActionGroup->addAction(actionOrganisationMode);
239 239 modeActionGroup->addAction(actionPointerMode);
240 240 modeActionGroup->setExclusive(true);
241 241
242 242 mainToolBar->addSeparator();
243 243 mainToolBar->addAction(actionPointerMode);
244 244 mainToolBar->addAction(actionZoomMode);
245 245 mainToolBar->addAction(actionOrganisationMode);
246 246 mainToolBar->addAction(actionZonesMode);
247 247 mainToolBar->addSeparator();
248 248
249 249 // Cursors
250 250 auto btnCursor = new QToolButton{this};
251 251 btnCursor->setIcon(QIcon(":/icones/cursor.png"));
252 252 btnCursor->setText("Cursor");
253 253 btnCursor->setToolTip("Cursor");
254 254 btnCursor->setPopupMode(QToolButton::InstantPopup);
255 255 auto cursorMenu = new QMenu("CursorMenu", this);
256 256 btnCursor->setMenu(cursorMenu);
257 257
258 258 auto noCursorAction = cursorMenu->addAction("No Cursor");
259 259 noCursorAction->setCheckable(true);
260 260 noCursorAction->setChecked(sqpApp->plotsCursorMode()
261 261 == SqpApplication::PlotsCursorMode::NoCursor);
262 262 connect(noCursorAction, &QAction::triggered,
263 263 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); });
264 264
265 265 cursorMenu->addSeparator();
266 266 auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor");
267 267 verticalCursorAction->setCheckable(true);
268 268 verticalCursorAction->setChecked(sqpApp->plotsCursorMode()
269 269 == SqpApplication::PlotsCursorMode::Vertical);
270 270 connect(verticalCursorAction, &QAction::triggered,
271 271 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); });
272 272
273 273 auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor");
274 274 temporalCursorAction->setCheckable(true);
275 275 temporalCursorAction->setChecked(sqpApp->plotsCursorMode()
276 276 == SqpApplication::PlotsCursorMode::Temporal);
277 277 connect(temporalCursorAction, &QAction::triggered,
278 278 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); });
279 279
280 280 auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor");
281 281 horizontalCursorAction->setCheckable(true);
282 282 horizontalCursorAction->setChecked(sqpApp->plotsCursorMode()
283 283 == SqpApplication::PlotsCursorMode::Horizontal);
284 284 connect(horizontalCursorAction, &QAction::triggered,
285 285 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); });
286 286
287 287 auto crossCursorAction = cursorMenu->addAction("Cross Cursor");
288 288 crossCursorAction->setCheckable(true);
289 289 crossCursorAction->setChecked(sqpApp->plotsCursorMode()
290 290 == SqpApplication::PlotsCursorMode::Cross);
291 291 connect(crossCursorAction, &QAction::triggered,
292 292 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); });
293 293
294 294 mainToolBar->addWidget(btnCursor);
295 295
296 296 auto cursorModeActionGroup = new QActionGroup{this};
297 297 cursorModeActionGroup->setExclusive(true);
298 298 cursorModeActionGroup->addAction(noCursorAction);
299 299 cursorModeActionGroup->addAction(verticalCursorAction);
300 300 cursorModeActionGroup->addAction(temporalCursorAction);
301 301 cursorModeActionGroup->addAction(horizontalCursorAction);
302 302 cursorModeActionGroup->addAction(crossCursorAction);
303 303
304 304 // Catalog
305 305 mainToolBar->addSeparator();
306 306 mainToolBar->addAction(QIcon(":/icones/catalogue.png"), "Catalogues",
307 307 [this]() { impl->m_CatalogExplorer->show(); });
308 308
309 309 // //////// //
310 310 // Settings //
311 311 // //////// //
312 312
313 313 // Registers "general settings" widget to the settings dialog
314 314 impl->m_SettingsDialog->registerWidget(QStringLiteral("General"),
315 315 impl->m_GeneralSettingsWidget);
316 316
317 317 // /////////// //
318 318 // Connections //
319 319 // /////////// //
320 320
321 321 // Controllers / controllers connections
322 322 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpRange)), &sqpApp->variableController(),
323 323 SLOT(onDateTimeOnSelection(SqpRange)));
324 324
325 325 // Widgets / controllers connections
326 326
327 327 // DataSource
328 328 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
329 329 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
330 330
331 331 // Time
332 332 connect(timeWidget, SIGNAL(timeUpdated(SqpRange)), &sqpApp->timeController(),
333 333 SLOT(onTimeToUpdate(SqpRange)));
334 334
335 335 // Visualization
336 336 connect(&sqpApp->visualizationController(),
337 337 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
338 338 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
339 339
340 340 connect(&sqpApp->visualizationController(),
341 341 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), m_Ui->view,
342 342 SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
343 343
344 344 // Widgets / widgets connections
345 345
346 346 // For the following connections, we use DirectConnection to allow each widget that can
347 347 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
348 348 // The order of connections is also important, since it determines the order in which each
349 349 // widget will attach its menu
350 350 connect(
351 351 m_Ui->variableInspectorWidget,
352 352 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
353 353 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
354 354 Qt::DirectConnection);
355 355 }
356 356
357 357 MainWindow::~MainWindow()
358 358 {
359 359 }
360 360
361 361 void MainWindow::changeEvent(QEvent *e)
362 362 {
363 363 QMainWindow::changeEvent(e);
364 364 switch (e->type()) {
365 365 case QEvent::LanguageChange:
366 366 m_Ui->retranslateUi(this);
367 367 break;
368 368 default:
369 369 break;
370 370 }
371 371 }
372 372
373 373 void MainWindow::closeEvent(QCloseEvent *event)
374 374 {
375 375 if (!impl->checkDataToSave(this)) {
376 376 event->ignore();
377 377 }
378 378 else {
379 379 event->accept();
380 380 }
381 381 }
382 382
383 383 bool MainWindow::MainWindowPrivate::checkDataToSave(QWidget *parentWidget)
384 384 {
385 385 auto hasChanges = sqpApp->catalogueController().hasChanges();
386 386 if (hasChanges) {
387 387 // There are some unsaved changes
388 388 switch (QMessageBox::question(
389 parentWidget, "Save changes",
390 tr("The catalogue controller unsaved changes.\nDo you want to save them ?"),
389 parentWidget, tr("Save changes"),
390 tr("The catalogue controller has unsaved changes.\nDo you want to save them ?"),
391 391 QMessageBox::SaveAll | QMessageBox::Discard | QMessageBox::Cancel,
392 392 QMessageBox::SaveAll)) {
393 393 case QMessageBox::SaveAll:
394 394 sqpApp->catalogueController().saveAll();
395 395 break;
396 396 case QMessageBox::Discard:
397 397 break;
398 398 case QMessageBox::Cancel:
399 399 default:
400 400 return false;
401 401 }
402 402 }
403 403
404 404 return true;
405 405 }
@@ -1,470 +1,470
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 17 #include <QMessageBox>
18 18
19 19 Q_LOGGING_CATEGORY(LOG_CatalogueEventsWidget, "CatalogueEventsWidget")
20 20
21 21 /// Fixed size of the validation column
22 22 const auto VALIDATION_COLUMN_SIZE = 35;
23 23
24 24 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
25 25
26 26 CatalogueEventsModel *m_Model = nullptr;
27 27 QStringList m_ZonesForTimeMode;
28 28 QString m_ZoneForGraphMode;
29 29 QVector<std::shared_ptr<DBCatalogue> > m_DisplayedCatalogues;
30 30 bool m_AllEventDisplayed = false;
31 31
32 32 VisualizationWidget *m_VisualizationWidget = nullptr;
33 33
34 34 void setEvents(const QVector<std::shared_ptr<DBEvent> > &events, CatalogueEventsWidget *widget)
35 35 {
36 36 widget->ui->treeView->setSortingEnabled(false);
37 37 m_Model->setEvents(events);
38 38 widget->ui->treeView->setSortingEnabled(true);
39 39
40 40 for (auto event : events) {
41 41 if (sqpApp->catalogueController().eventHasChanges(event)) {
42 42 auto index = m_Model->indexOf(event);
43 43 widget->setEventChanges(event, true);
44 44 }
45 45 }
46 46 }
47 47
48 48 void addEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
49 49 {
50 50 treeView->setSortingEnabled(false);
51 51 m_Model->addEvent(event);
52 52 treeView->setSortingEnabled(true);
53 53 }
54 54
55 55 void removeEvent(const std::shared_ptr<DBEvent> &event, QTreeView *treeView)
56 56 {
57 57 treeView->setSortingEnabled(false);
58 58 m_Model->removeEvent(event);
59 59 treeView->setSortingEnabled(true);
60 60 }
61 61
62 62 QStringList getAvailableVisualizationZoneList() const
63 63 {
64 64 if (m_VisualizationWidget) {
65 65 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
66 66 return tab->availableZoneWidgets();
67 67 }
68 68 }
69 69
70 70 return QStringList{};
71 71 }
72 72
73 73 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
74 74 bool allowMultiSelection, const QPoint &location)
75 75 {
76 76 auto availableZones = getAvailableVisualizationZoneList();
77 77 if (availableZones.isEmpty()) {
78 78 return QStringList{};
79 79 }
80 80
81 81 QDialog d(parent, Qt::Tool);
82 82 d.setWindowTitle("Choose a zone");
83 83 auto layout = new QVBoxLayout{&d};
84 84 layout->setContentsMargins(0, 0, 0, 0);
85 85 auto listWidget = new QListWidget{&d};
86 86 layout->addWidget(listWidget);
87 87
88 88 QSet<QListWidgetItem *> checkedItems;
89 89 for (auto zone : availableZones) {
90 90 auto item = new QListWidgetItem{zone};
91 91 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
92 92 if (selectedZones.contains(zone)) {
93 93 item->setCheckState(Qt::Checked);
94 94 checkedItems << item;
95 95 }
96 96 else {
97 97 item->setCheckState(Qt::Unchecked);
98 98 }
99 99
100 100 listWidget->addItem(item);
101 101 }
102 102
103 103 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
104 104 layout->addWidget(buttonBox);
105 105
106 106 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
107 107 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
108 108
109 109 QObject::connect(listWidget, &QListWidget::itemChanged,
110 110 [&checkedItems, allowMultiSelection, listWidget](auto item) {
111 111 if (item->checkState() == Qt::Checked) {
112 112 if (!allowMultiSelection) {
113 113 for (auto checkedItem : checkedItems) {
114 114 listWidget->blockSignals(true);
115 115 checkedItem->setCheckState(Qt::Unchecked);
116 116 listWidget->blockSignals(false);
117 117 }
118 118
119 119 checkedItems.clear();
120 120 }
121 121 checkedItems << item;
122 122 }
123 123 else {
124 124 checkedItems.remove(item);
125 125 }
126 126 });
127 127
128 128 QStringList result;
129 129
130 130 d.setMinimumWidth(120);
131 131 d.resize(d.minimumSizeHint());
132 132 d.move(location);
133 133 if (d.exec() == QDialog::Accepted) {
134 134 for (auto item : checkedItems) {
135 135 result += item->text();
136 136 }
137 137 }
138 138 else {
139 139 result = selectedZones;
140 140 }
141 141
142 142 return result;
143 143 }
144 144
145 145 void updateForTimeMode(QTreeView *treeView)
146 146 {
147 147 auto selectedRows = treeView->selectionModel()->selectedRows();
148 148
149 149 if (selectedRows.count() == 1) {
150 150 auto event = m_Model->getEvent(selectedRows.first());
151 151 if (event) {
152 152 if (m_VisualizationWidget) {
153 153 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
154 154
155 155 for (auto zoneName : m_ZonesForTimeMode) {
156 156 if (auto zone = tab->getZoneWithName(zoneName)) {
157 157 SqpRange eventRange;
158 158 eventRange.m_TStart = event->getTStart();
159 159 eventRange.m_TEnd = event->getTEnd();
160 160 zone->setZoneRange(eventRange);
161 161 }
162 162 }
163 163 }
164 164 else {
165 165 qCWarning(LOG_CatalogueEventsWidget())
166 166 << "updateTimeZone: no tab found in the visualization";
167 167 }
168 168 }
169 169 else {
170 170 qCWarning(LOG_CatalogueEventsWidget())
171 171 << "updateTimeZone: visualization widget not found";
172 172 }
173 173 }
174 174 }
175 175 else {
176 176 qCWarning(LOG_CatalogueEventsWidget())
177 177 << "updateTimeZone: not compatible with multiple events selected";
178 178 }
179 179 }
180 180
181 181 void updateForGraphMode(QTreeView *treeView)
182 182 {
183 183 auto selectedRows = treeView->selectionModel()->selectedRows();
184 184
185 185 if (selectedRows.count() == 1) {
186 186 auto event = m_Model->getEvent(selectedRows.first());
187 187 if (m_VisualizationWidget) {
188 188 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
189 189 if (auto zone = tab->getZoneWithName(m_ZoneForGraphMode)) {
190 190 // TODO
191 191 }
192 192 }
193 193 else {
194 194 qCWarning(LOG_CatalogueEventsWidget())
195 195 << "updateGraphMode: no tab found in the visualization";
196 196 }
197 197 }
198 198 else {
199 199 qCWarning(LOG_CatalogueEventsWidget())
200 200 << "updateGraphMode: visualization widget not found";
201 201 }
202 202 }
203 203 else {
204 204 qCWarning(LOG_CatalogueEventsWidget())
205 205 << "updateGraphMode: not compatible with multiple events selected";
206 206 }
207 207 }
208 208
209 209 void getSelectedItems(
210 210 QTreeView *treeView, QVector<std::shared_ptr<DBEvent> > &events,
211 211 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > &eventProducts)
212 212 {
213 213 for (auto rowIndex : treeView->selectionModel()->selectedRows()) {
214 214 auto itemType = m_Model->itemTypeOf(rowIndex);
215 215 if (itemType == CatalogueEventsModel::ItemType::Event) {
216 216 events << m_Model->getEvent(rowIndex);
217 217 }
218 218 else if (itemType == CatalogueEventsModel::ItemType::EventProduct) {
219 219 eventProducts << qMakePair(m_Model->getParentEvent(rowIndex),
220 220 m_Model->getEventProduct(rowIndex));
221 221 }
222 222 }
223 223 }
224 224 };
225 225
226 226 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
227 227 : QWidget(parent),
228 228 ui(new Ui::CatalogueEventsWidget),
229 229 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
230 230 {
231 231 ui->setupUi(this);
232 232
233 233 impl->m_Model = new CatalogueEventsModel{this};
234 234 ui->treeView->setModel(impl->m_Model);
235 235
236 236 ui->treeView->setSortingEnabled(true);
237 237 ui->treeView->setDragDropMode(QAbstractItemView::DragDrop);
238 238 ui->treeView->setDragEnabled(true);
239 239
240 240 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
241 241 if (checked) {
242 242 ui->btnChart->setChecked(false);
243 243 impl->m_ZonesForTimeMode
244 244 = impl->selectZone(this, impl->m_ZonesForTimeMode, true,
245 245 this->mapToGlobal(ui->btnTime->frameGeometry().center()));
246 246
247 247 impl->updateForTimeMode(ui->treeView);
248 248 }
249 249 });
250 250
251 251 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
252 252 if (checked) {
253 253 ui->btnTime->setChecked(false);
254 254 impl->m_ZoneForGraphMode
255 255 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
256 256 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
257 257 .value(0);
258 258
259 259 impl->updateForGraphMode(ui->treeView);
260 260 }
261 261 });
262 262
263 263 connect(ui->btnRemove, &QToolButton::clicked, [this]() {
264 264 QVector<std::shared_ptr<DBEvent> > events;
265 265 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
266 266 impl->getSelectedItems(ui->treeView, events, eventProducts);
267 267
268 268 if (!events.isEmpty() && eventProducts.isEmpty()) {
269 269
270 270 if (QMessageBox::warning(this, tr("Remove Event(s)"),
271 tr("The selected event(s) will be completly removed "
271 tr("The selected event(s) will be permanently removed "
272 272 "from the repository!\nAre you sure you want to continue?"),
273 273 QMessageBox::Yes | QMessageBox::No, QMessageBox::No)
274 274 == QMessageBox::Yes) {
275 275
276 276 for (auto event : events) {
277 277 sqpApp->catalogueController().removeEvent(event);
278 278 impl->removeEvent(event, ui->treeView);
279 279 }
280 280 }
281 281 }
282 282 });
283 283
284 284 connect(ui->treeView, &QTreeView::clicked, this, &CatalogueEventsWidget::emitSelection);
285 285 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, this,
286 286 &CatalogueEventsWidget::emitSelection);
287 287
288 288 ui->btnRemove->setEnabled(false); // Disabled by default when nothing is selected
289 289 connect(ui->treeView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
290 290 auto isNotMultiSelection = ui->treeView->selectionModel()->selectedRows().count() <= 1;
291 291 ui->btnChart->setEnabled(isNotMultiSelection);
292 292 ui->btnTime->setEnabled(isNotMultiSelection);
293 293
294 294 if (isNotMultiSelection && ui->btnTime->isChecked()) {
295 295 impl->updateForTimeMode(ui->treeView);
296 296 }
297 297 else if (isNotMultiSelection && ui->btnChart->isChecked()) {
298 298 impl->updateForGraphMode(ui->treeView);
299 299 }
300 300
301 301 QVector<std::shared_ptr<DBEvent> > events;
302 302 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
303 303 impl->getSelectedItems(ui->treeView, events, eventProducts);
304 304 ui->btnRemove->setEnabled(!events.isEmpty() && eventProducts.isEmpty());
305 305 });
306 306
307 307 ui->treeView->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
308 308 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Tags,
309 309 QHeaderView::Stretch);
310 310 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Validation,
311 311 QHeaderView::Fixed);
312 312 ui->treeView->header()->setSectionResizeMode((int)CatalogueEventsModel::Column::Name,
313 313 QHeaderView::Interactive);
314 314 ui->treeView->header()->resizeSection((int)CatalogueEventsModel::Column::Validation,
315 315 VALIDATION_COLUMN_SIZE);
316 316 ui->treeView->header()->setSortIndicatorShown(true);
317 317
318 318 connect(impl->m_Model, &CatalogueEventsModel::modelSorted, [this]() {
319 319 auto allEvents = impl->m_Model->events();
320 320 for (auto event : allEvents) {
321 321 setEventChanges(event, sqpApp->catalogueController().eventHasChanges(event));
322 322 }
323 323 });
324 324
325 325 populateWithAllEvents();
326 326 }
327 327
328 328 CatalogueEventsWidget::~CatalogueEventsWidget()
329 329 {
330 330 delete ui;
331 331 }
332 332
333 333 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
334 334 {
335 335 impl->m_VisualizationWidget = visualization;
336 336 }
337 337
338 338 void CatalogueEventsWidget::addEvent(const std::shared_ptr<DBEvent> &event)
339 339 {
340 340 impl->addEvent(event, ui->treeView);
341 341 }
342 342
343 343 void CatalogueEventsWidget::setEventChanges(const std::shared_ptr<DBEvent> &event, bool hasChanges)
344 344 {
345 345 impl->m_Model->refreshEvent(event);
346 346
347 347 auto eventIndex = impl->m_Model->indexOf(event);
348 348 auto validationIndex
349 349 = eventIndex.sibling(eventIndex.row(), (int)CatalogueEventsModel::Column::Validation);
350 350
351 351 if (validationIndex.isValid()) {
352 352 if (hasChanges) {
353 353 if (ui->treeView->indexWidget(validationIndex) == nullptr) {
354 354 auto widget = CatalogueExplorerHelper::buildValidationWidget(
355 355 ui->treeView,
356 356 [this, event]() {
357 357 sqpApp->catalogueController().saveEvent(event);
358 358 setEventChanges(event, false);
359 359 },
360 360 [this, event]() {
361 361 bool removed = false;
362 362 sqpApp->catalogueController().discardEvent(event, removed);
363 363 if (removed) {
364 364 impl->m_Model->removeEvent(event);
365 365 }
366 366 else {
367 367 setEventChanges(event, false);
368 368 impl->m_Model->refreshEvent(event, true);
369 369 }
370 370 emitSelection();
371 371 });
372 372 ui->treeView->setIndexWidget(validationIndex, widget);
373 373 }
374 374 }
375 375 else {
376 376 // Note: the widget is destroyed
377 377 ui->treeView->setIndexWidget(validationIndex, nullptr);
378 378 }
379 379 }
380 380 else {
381 381 qCWarning(LOG_CatalogueEventsWidget())
382 382 << "setEventChanges: the event is not displayed in the model.";
383 383 }
384 384 }
385 385
386 386 QVector<std::shared_ptr<DBCatalogue> > CatalogueEventsWidget::displayedCatalogues() const
387 387 {
388 388 return impl->m_DisplayedCatalogues;
389 389 }
390 390
391 391 bool CatalogueEventsWidget::isAllEventsDisplayed() const
392 392 {
393 393 return impl->m_AllEventDisplayed;
394 394 }
395 395
396 396 bool CatalogueEventsWidget::isEventDisplayed(const std::shared_ptr<DBEvent> &event) const
397 397 {
398 398 return impl->m_Model->indexOf(event).isValid();
399 399 }
400 400
401 401 void CatalogueEventsWidget::populateWithCatalogues(
402 402 const QVector<std::shared_ptr<DBCatalogue> > &catalogues)
403 403 {
404 404 impl->m_DisplayedCatalogues = catalogues;
405 405 impl->m_AllEventDisplayed = false;
406 406
407 407 QSet<QUuid> eventIds;
408 408 QVector<std::shared_ptr<DBEvent> > events;
409 409
410 410 for (auto catalogue : catalogues) {
411 411 auto catalogueEvents = sqpApp->catalogueController().retrieveEventsFromCatalogue(catalogue);
412 412 for (auto event : catalogueEvents) {
413 413 if (!eventIds.contains(event->getUniqId())) {
414 414 events << event;
415 415 eventIds.insert(event->getUniqId());
416 416 }
417 417 }
418 418 }
419 419
420 420 impl->setEvents(events, this);
421 421 }
422 422
423 423 void CatalogueEventsWidget::populateWithAllEvents()
424 424 {
425 425 impl->m_DisplayedCatalogues.clear();
426 426 impl->m_AllEventDisplayed = true;
427 427
428 428 auto allEvents = sqpApp->catalogueController().retrieveAllEvents();
429 429
430 430 QVector<std::shared_ptr<DBEvent> > events;
431 431 for (auto event : allEvents) {
432 432 events << event;
433 433 }
434 434
435 435 impl->setEvents(events, this);
436 436 }
437 437
438 438 void CatalogueEventsWidget::clear()
439 439 {
440 440 impl->m_DisplayedCatalogues.clear();
441 441 impl->m_AllEventDisplayed = false;
442 442 impl->setEvents({}, this);
443 443 }
444 444
445 445 void CatalogueEventsWidget::refresh()
446 446 {
447 447 if (isAllEventsDisplayed()) {
448 448 populateWithAllEvents();
449 449 }
450 450 else if (!impl->m_DisplayedCatalogues.isEmpty()) {
451 451 populateWithCatalogues(impl->m_DisplayedCatalogues);
452 452 }
453 453 }
454 454
455 455 void CatalogueEventsWidget::emitSelection()
456 456 {
457 457 QVector<std::shared_ptr<DBEvent> > events;
458 458 QVector<QPair<std::shared_ptr<DBEvent>, std::shared_ptr<DBEventProduct> > > eventProducts;
459 459 impl->getSelectedItems(ui->treeView, events, eventProducts);
460 460
461 461 if (!events.isEmpty() && eventProducts.isEmpty()) {
462 462 emit eventsSelected(events);
463 463 }
464 464 else if (events.isEmpty() && !eventProducts.isEmpty()) {
465 465 emit eventProductsSelected(eventProducts);
466 466 }
467 467 else {
468 468 emit selectionCleared();
469 469 }
470 470 }
General Comments 0
You need to be logged in to leave comments. Login now