##// END OF EJS Templates
Retrieves zone names from the visualization
trabillard -
r1136:6897882500e5
parent child
Show More
@@ -1,364 +1,366
1 1 /*------------------------------------------------------------------------------
2 2 -- This file is a part of the SciQLop Software
3 3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
4 4 --
5 5 -- This program is free software; you can redistribute it and/or modify
6 6 -- it under the terms of the GNU General Public License as published by
7 7 -- the Free Software Foundation; either version 2 of the License, or
8 8 -- (at your option) any later version.
9 9 --
10 10 -- This program is distributed in the hope that it will be useful,
11 11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 13 -- GNU General Public License for more details.
14 14 --
15 15 -- You should have received a copy of the GNU General Public License
16 16 -- along with this program; if not, write to the Free Software
17 17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 18 -------------------------------------------------------------------------------*/
19 19 /*-- Author : Alexis Jeandet
20 20 -- Mail : alexis.jeandet@member.fsf.org
21 21 ----------------------------------------------------------------------------*/
22 22 #include "MainWindow.h"
23 23 #include "ui_MainWindow.h"
24 24
25 25 #include <Catalogue/CatalogueExplorer.h>
26 26 #include <DataSource/DataSourceController.h>
27 27 #include <DataSource/DataSourceWidget.h>
28 28 #include <Settings/SqpSettingsDialog.h>
29 29 #include <Settings/SqpSettingsGeneralWidget.h>
30 30 #include <SidePane/SqpSidePane.h>
31 31 #include <SqpApplication.h>
32 32 #include <Time/TimeController.h>
33 33 #include <TimeWidget/TimeWidget.h>
34 34 #include <Variable/Variable.h>
35 35 #include <Variable/VariableController.h>
36 36 #include <Visualization/VisualizationController.h>
37 37
38 38 #include <QAction>
39 39 #include <QDate>
40 40 #include <QDir>
41 41 #include <QFileDialog>
42 42 #include <QToolBar>
43 43 #include <QToolButton>
44 44 #include <memory.h>
45 45
46 46 #include "iostream"
47 47
48 48 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
49 49
50 50 namespace {
51 51 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
52 52 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
53 53 const auto VIEWPLITTERINDEX = 2;
54 54 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
55 55 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
56 56 }
57 57
58 58 class MainWindow::MainWindowPrivate {
59 59 public:
60 60 explicit MainWindowPrivate(MainWindow *mainWindow)
61 61 : m_LastOpenLeftInspectorSize{},
62 62 m_LastOpenRightInspectorSize{},
63 63 m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}},
64 64 m_SettingsDialog{new SqpSettingsDialog{mainWindow}},
65 65 m_CatalogExplorer{new CatalogueExplorer{mainWindow}}
66 66 {
67 67 }
68 68
69 69 QSize m_LastOpenLeftInspectorSize;
70 70 QSize m_LastOpenRightInspectorSize;
71 71 /// General settings widget. MainWindow has the ownership
72 72 SqpSettingsGeneralWidget *m_GeneralSettingsWidget;
73 73 /// Settings dialog. MainWindow has the ownership
74 74 SqpSettingsDialog *m_SettingsDialog;
75 75 /// Catalogue dialog. MainWindow has the ownership
76 76 CatalogueExplorer *m_CatalogExplorer;
77 77 };
78 78
79 79 MainWindow::MainWindow(QWidget *parent)
80 80 : QMainWindow{parent},
81 81 m_Ui{new Ui::MainWindow},
82 82 impl{spimpl::make_unique_impl<MainWindowPrivate>(this)}
83 83 {
84 84 m_Ui->setupUi(this);
85 85
86 86 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
87 87 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
88 88
89 impl->m_CatalogExplorer->setVisualizationWidget(m_Ui->view);
90
89 91
90 92 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
91 93 auto openLeftInspectorAction = new QAction{QIcon{
92 94 ":/icones/previous.png",
93 95 },
94 96 tr("Show/hide the left inspector"), this};
95 97
96 98
97 99 auto spacerLeftTop = new QWidget{};
98 100 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
99 101
100 102 auto spacerLeftBottom = new QWidget{};
101 103 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
102 104
103 105 leftSidePane->addWidget(spacerLeftTop);
104 106 leftSidePane->addAction(openLeftInspectorAction);
105 107 leftSidePane->addWidget(spacerLeftBottom);
106 108
107 109
108 110 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
109 111 auto openRightInspectorAction = new QAction{QIcon{
110 112 ":/icones/next.png",
111 113 },
112 114 tr("Show/hide the right inspector"), this};
113 115
114 116 auto spacerRightTop = new QWidget{};
115 117 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
116 118
117 119 auto spacerRightBottom = new QWidget{};
118 120 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
119 121
120 122 rightSidePane->addWidget(spacerRightTop);
121 123 rightSidePane->addAction(openRightInspectorAction);
122 124 rightSidePane->addWidget(spacerRightBottom);
123 125
124 126 openLeftInspectorAction->setCheckable(true);
125 127 openRightInspectorAction->setCheckable(true);
126 128
127 129 auto openInspector = [this](bool checked, bool right, auto action) {
128 130
129 131 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
130 132
131 133 auto &lastInspectorSize
132 134 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
133 135
134 136 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
135 137 : m_Ui->leftMainInspectorWidget->size();
136 138
137 139 // Update of the last opened geometry
138 140 if (checked) {
139 141 lastInspectorSize = nextInspectorSize;
140 142 }
141 143
142 144 auto startSize = lastInspectorSize;
143 145 auto endSize = startSize;
144 146 endSize.setWidth(0);
145 147
146 148 auto splitterInspectorIndex
147 149 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
148 150
149 151 auto currentSizes = m_Ui->splitter->sizes();
150 152 if (checked) {
151 153 // adjust sizes individually here, e.g.
152 154 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
153 155 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
154 156 m_Ui->splitter->setSizes(currentSizes);
155 157 }
156 158 else {
157 159 // adjust sizes individually here, e.g.
158 160 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
159 161 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
160 162 m_Ui->splitter->setSizes(currentSizes);
161 163 }
162 164
163 165 };
164 166
165 167
166 168 connect(openLeftInspectorAction, &QAction::triggered,
167 169 [openInspector, openLeftInspectorAction](bool checked) {
168 170 openInspector(checked, false, openLeftInspectorAction);
169 171 });
170 172 connect(openRightInspectorAction, &QAction::triggered,
171 173 [openInspector, openRightInspectorAction](bool checked) {
172 174 openInspector(checked, true, openRightInspectorAction);
173 175 });
174 176
175 177 // //////////////// //
176 178 // Menu and Toolbar //
177 179 // //////////////// //
178 180 this->menuBar()->addAction(tr("File"));
179 181 auto toolsMenu = this->menuBar()->addMenu(tr("Tools"));
180 182 toolsMenu->addAction(tr("Settings..."), [this]() {
181 183 // Loads settings
182 184 impl->m_SettingsDialog->loadSettings();
183 185
184 186 // Open settings dialog and save settings if the dialog is accepted
185 187 if (impl->m_SettingsDialog->exec() == QDialog::Accepted) {
186 188 impl->m_SettingsDialog->saveSettings();
187 189 }
188 190
189 191 });
190 192
191 193 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
192 194
193 195 auto timeWidget = new TimeWidget{};
194 196 mainToolBar->addWidget(timeWidget);
195 197
196 198 // Interaction modes
197 199 auto actionPointerMode = new QAction{QIcon(":/icones/pointer.png"), "Move", this};
198 200 actionPointerMode->setCheckable(true);
199 201 actionPointerMode->setChecked(sqpApp->plotsInteractionMode()
200 202 == SqpApplication::PlotsInteractionMode::None);
201 203 connect(actionPointerMode, &QAction::triggered,
202 204 []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); });
203 205
204 206 auto actionZoomMode = new QAction{QIcon(":/icones/zoom.png"), "Zoom", this};
205 207 actionZoomMode->setCheckable(true);
206 208 actionZoomMode->setChecked(sqpApp->plotsInteractionMode()
207 209 == SqpApplication::PlotsInteractionMode::ZoomBox);
208 210 connect(actionZoomMode, &QAction::triggered, []() {
209 211 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox);
210 212 });
211 213
212 214 auto actionOrganisationMode = new QAction{QIcon(":/icones/drag.png"), "Organize", this};
213 215 actionOrganisationMode->setCheckable(true);
214 216 actionOrganisationMode->setChecked(sqpApp->plotsInteractionMode()
215 217 == SqpApplication::PlotsInteractionMode::DragAndDrop);
216 218 connect(actionOrganisationMode, &QAction::triggered, []() {
217 219 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop);
218 220 });
219 221
220 222 auto actionZonesMode = new QAction{QIcon(":/icones/rectangle.png"), "Zones", this};
221 223 actionZonesMode->setCheckable(true);
222 224 actionZonesMode->setChecked(sqpApp->plotsInteractionMode()
223 225 == SqpApplication::PlotsInteractionMode::SelectionZones);
224 226 connect(actionZonesMode, &QAction::triggered, []() {
225 227 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones);
226 228 });
227 229
228 230 auto modeActionGroup = new QActionGroup{this};
229 231 modeActionGroup->addAction(actionZoomMode);
230 232 modeActionGroup->addAction(actionZonesMode);
231 233 modeActionGroup->addAction(actionOrganisationMode);
232 234 modeActionGroup->addAction(actionPointerMode);
233 235 modeActionGroup->setExclusive(true);
234 236
235 237 mainToolBar->addSeparator();
236 238 mainToolBar->addAction(actionPointerMode);
237 239 mainToolBar->addAction(actionZoomMode);
238 240 mainToolBar->addAction(actionOrganisationMode);
239 241 mainToolBar->addAction(actionZonesMode);
240 242 mainToolBar->addSeparator();
241 243
242 244 // Cursors
243 245 auto btnCursor = new QToolButton{this};
244 246 btnCursor->setIcon(QIcon(":/icones/cursor.png"));
245 247 btnCursor->setText("Cursor");
246 248 btnCursor->setToolTip("Cursor");
247 249 btnCursor->setPopupMode(QToolButton::InstantPopup);
248 250 auto cursorMenu = new QMenu("CursorMenu", this);
249 251 btnCursor->setMenu(cursorMenu);
250 252
251 253 auto noCursorAction = cursorMenu->addAction("No Cursor");
252 254 noCursorAction->setCheckable(true);
253 255 noCursorAction->setChecked(sqpApp->plotsCursorMode()
254 256 == SqpApplication::PlotsCursorMode::NoCursor);
255 257 connect(noCursorAction, &QAction::triggered,
256 258 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); });
257 259
258 260 cursorMenu->addSeparator();
259 261 auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor");
260 262 verticalCursorAction->setCheckable(true);
261 263 verticalCursorAction->setChecked(sqpApp->plotsCursorMode()
262 264 == SqpApplication::PlotsCursorMode::Vertical);
263 265 connect(verticalCursorAction, &QAction::triggered,
264 266 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); });
265 267
266 268 auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor");
267 269 temporalCursorAction->setCheckable(true);
268 270 temporalCursorAction->setChecked(sqpApp->plotsCursorMode()
269 271 == SqpApplication::PlotsCursorMode::Temporal);
270 272 connect(temporalCursorAction, &QAction::triggered,
271 273 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); });
272 274
273 275 auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor");
274 276 horizontalCursorAction->setCheckable(true);
275 277 horizontalCursorAction->setChecked(sqpApp->plotsCursorMode()
276 278 == SqpApplication::PlotsCursorMode::Horizontal);
277 279 connect(horizontalCursorAction, &QAction::triggered,
278 280 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); });
279 281
280 282 auto crossCursorAction = cursorMenu->addAction("Cross Cursor");
281 283 crossCursorAction->setCheckable(true);
282 284 crossCursorAction->setChecked(sqpApp->plotsCursorMode()
283 285 == SqpApplication::PlotsCursorMode::Cross);
284 286 connect(crossCursorAction, &QAction::triggered,
285 287 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); });
286 288
287 289 mainToolBar->addWidget(btnCursor);
288 290
289 291 auto cursorModeActionGroup = new QActionGroup{this};
290 292 cursorModeActionGroup->setExclusive(true);
291 293 cursorModeActionGroup->addAction(noCursorAction);
292 294 cursorModeActionGroup->addAction(verticalCursorAction);
293 295 cursorModeActionGroup->addAction(temporalCursorAction);
294 296 cursorModeActionGroup->addAction(horizontalCursorAction);
295 297 cursorModeActionGroup->addAction(crossCursorAction);
296 298
297 299 // Catalog
298 300 mainToolBar->addSeparator();
299 301 mainToolBar->addAction(QIcon(":/icones/catalogue.png"), "Catalogues",
300 302 [this]() { impl->m_CatalogExplorer->show(); });
301 303
302 304 // //////// //
303 305 // Settings //
304 306 // //////// //
305 307
306 308 // Registers "general settings" widget to the settings dialog
307 309 impl->m_SettingsDialog->registerWidget(QStringLiteral("General"),
308 310 impl->m_GeneralSettingsWidget);
309 311
310 312 // /////////// //
311 313 // Connections //
312 314 // /////////// //
313 315
314 316 // Controllers / controllers connections
315 317 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpRange)), &sqpApp->variableController(),
316 318 SLOT(onDateTimeOnSelection(SqpRange)));
317 319
318 320 // Widgets / controllers connections
319 321
320 322 // DataSource
321 323 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
322 324 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
323 325
324 326 // Time
325 327 connect(timeWidget, SIGNAL(timeUpdated(SqpRange)), &sqpApp->timeController(),
326 328 SLOT(onTimeToUpdate(SqpRange)));
327 329
328 330 // Visualization
329 331 connect(&sqpApp->visualizationController(),
330 332 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
331 333 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
332 334
333 335 connect(&sqpApp->visualizationController(),
334 336 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), m_Ui->view,
335 337 SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
336 338
337 339 // Widgets / widgets connections
338 340
339 341 // For the following connections, we use DirectConnection to allow each widget that can
340 342 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
341 343 // The order of connections is also important, since it determines the order in which each
342 344 // widget will attach its menu
343 345 connect(
344 346 m_Ui->variableInspectorWidget,
345 347 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
346 348 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
347 349 Qt::DirectConnection);
348 350 }
349 351
350 352 MainWindow::~MainWindow()
351 353 {
352 354 }
353 355
354 356 void MainWindow::changeEvent(QEvent *e)
355 357 {
356 358 QMainWindow::changeEvent(e);
357 359 switch (e->type()) {
358 360 case QEvent::LanguageChange:
359 361 m_Ui->retranslateUi(this);
360 362 break;
361 363 default:
362 364 break;
363 365 }
364 366 }
@@ -1,34 +1,37
1 1 #ifndef SCIQLOP_CATALOGUEEVENTSWIDGET_H
2 2 #define SCIQLOP_CATALOGUEEVENTSWIDGET_H
3 3
4 4 #include <Common/spimpl.h>
5 5 #include <QWidget>
6 6
7 7 class DBCatalogue;
8 8 class DBEvent;
9 class VisualizationWidget;
9 10
10 11 namespace Ui {
11 12 class CatalogueEventsWidget;
12 13 }
13 14
14 15 class CatalogueEventsWidget : public QWidget {
15 16 Q_OBJECT
16 17
17 18 signals:
18 19 void eventsSelected(const QVector<DBEvent> &event);
19 20
20 21 public:
21 22 explicit CatalogueEventsWidget(QWidget *parent = 0);
22 23 virtual ~CatalogueEventsWidget();
23 24
25 void setVisualizationWidget(VisualizationWidget *visualization);
26
24 27 public slots:
25 28 void populateWithCatalogues(const QVector<DBCatalogue> &catalogues);
26 29
27 30 private:
28 31 Ui::CatalogueEventsWidget *ui;
29 32
30 33 class CatalogueEventsWidgetPrivate;
31 34 spimpl::unique_impl_ptr<CatalogueEventsWidgetPrivate> impl;
32 35 };
33 36
34 37 #endif // SCIQLOP_CATALOGUEEVENTSWIDGET_H
@@ -1,21 +1,29
1 1 #ifndef SCIQLOP_CATALOGUEEXPLORER_H
2 2 #define SCIQLOP_CATALOGUEEXPLORER_H
3 3
4 #include <Common/spimpl.h>
4 5 #include <QDialog>
5 6
6 7 namespace Ui {
7 8 class CatalogueExplorer;
8 9 }
9 10
11 class VisualizationWidget;
12
10 13 class CatalogueExplorer : public QDialog {
11 14 Q_OBJECT
12 15
13 16 public:
14 17 explicit CatalogueExplorer(QWidget *parent = 0);
15 18 virtual ~CatalogueExplorer();
16 19
20 void setVisualizationWidget(VisualizationWidget *visualization);
21
17 22 private:
18 23 Ui::CatalogueExplorer *ui;
24
25 class CatalogueExplorerPrivate;
26 spimpl::unique_impl_ptr<CatalogueExplorerPrivate> impl;
19 27 };
20 28
21 29 #endif // SCIQLOP_CATALOGUEEXPLORER_H
@@ -1,80 +1,84
1 1 #ifndef SCIQLOP_VISUALIZATIONTABWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONTABWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5
6 6 #include <Common/spimpl.h>
7 7
8 8 #include <QLoggingCategory>
9 9 #include <QMimeData>
10 10 #include <QWidget>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationTabWidget)
13 13
14 14 class Variable;
15 15 class VisualizationZoneWidget;
16 16
17 17 namespace Ui {
18 18 class VisualizationTabWidget;
19 19 } // namespace Ui
20 20
21 21 class VisualizationTabWidget : public QWidget, public IVisualizationWidget {
22 22 Q_OBJECT
23 23
24 24 public:
25 25 explicit VisualizationTabWidget(const QString &name = {}, QWidget *parent = 0);
26 26 virtual ~VisualizationTabWidget();
27 27
28 /// Add a zone widget
28 /// Adds a zone widget
29 29 void addZone(VisualizationZoneWidget *zoneWidget);
30 30
31 /// Inserts a zone widget at the specified position
31 32 void insertZone(int index, VisualizationZoneWidget *zoneWidget);
32 33
34 /// Returns the list of zone widget names in the order they are displayed
35 QStringList availableZoneWidgets() const;
36
33 37 /**
34 38 * Creates a zone using a variable. The variable will be displayed in a new graph of the new
35 39 * zone. The zone is added at the end.
36 40 * @param variable the variable for which to create the zone
37 41 * @return the pointer to the created zone
38 42 */
39 43 VisualizationZoneWidget *createZone(std::shared_ptr<Variable> variable);
40 44
41 45 /**
42 46 * Creates a zone using a list of variables. The variables will be displayed in a new graph of
43 47 * the new zone. The zone is inserted at the specified index.
44 48 * @param variables the variables for which to create the zone
45 49 * @param index The index where the zone should be inserted in the layout
46 50 * @return the pointer to the created zone
47 51 */
48 52 VisualizationZoneWidget *createZone(const QList<std::shared_ptr<Variable> > &variables,
49 53 int index);
50 54
51 55 /**
52 56 * Creates a zone which is empty (no variables). The zone is inserted at the specified index.
53 57 * @param index The index where the zone should be inserted in the layout
54 58 * @return the pointer to the created zone
55 59 */
56 60 VisualizationZoneWidget *createEmptyZone(int index);
57 61
58 62 // IVisualizationWidget interface
59 63 void accept(IVisualizationWidgetVisitor *visitor) override;
60 64 bool canDrop(const Variable &variable) const override;
61 65 bool contains(const Variable &variable) const override;
62 66 QString name() const override;
63 67
64 68 protected:
65 69 void closeEvent(QCloseEvent *event) override;
66 70
67 71 private:
68 72 /// @return the layout of tab in which zones are added
69 73 QLayout &tabLayout() const noexcept;
70 74
71 75 Ui::VisualizationTabWidget *ui;
72 76
73 77 class VisualizationTabWidgetPrivate;
74 78 spimpl::unique_impl_ptr<VisualizationTabWidgetPrivate> impl;
75 79
76 80 private slots:
77 81 void dropMimeData(int index, const QMimeData *mimeData);
78 82 };
79 83
80 84 #endif // SCIQLOP_VISUALIZATIONTABWIDGET_H
@@ -1,63 +1,65
1 1 #ifndef SCIQLOP_VISUALIZATIONWIDGET_H
2 2 #define SCIQLOP_VISUALIZATIONWIDGET_H
3 3
4 4 #include "Visualization/IVisualizationWidget.h"
5 5 #include <Data/SqpRange.h>
6 6
7 7 #include <QLoggingCategory>
8 8 #include <QWidget>
9 9
10 10 #include <Common/spimpl.h>
11 11
12 12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationWidget)
13 13
14 14 class QMenu;
15 15 class Variable;
16 16 class VisualizationTabWidget;
17 17 class VisualizationSelectionZoneManager;
18 18
19 19 namespace Ui {
20 20 class VisualizationWidget;
21 21 } // namespace Ui
22 22
23 23 class VisualizationWidget : public QWidget, public IVisualizationWidget {
24 24 Q_OBJECT
25 25
26 26 public:
27 27 explicit VisualizationWidget(QWidget *parent = 0);
28 28 virtual ~VisualizationWidget();
29 29
30 30 /// Returns the class which manage the selection of selection zone across the visualization
31 31 VisualizationSelectionZoneManager &selectionZoneManager() const;
32 32
33 VisualizationTabWidget *currentTabWidget() const;
34
33 35 // IVisualizationWidget interface
34 36 void accept(IVisualizationWidgetVisitor *visitor) override;
35 37 bool canDrop(const Variable &variable) const override;
36 38 bool contains(const Variable &variable) const override;
37 39 QString name() const override;
38 40
39 41 public slots:
40 42 /**
41 43 * Attaches to a menu the menu relative to the visualization of variables
42 44 * @param menu the parent menu of the generated menu
43 45 * @param variables the variables for which to generate the menu
44 46 */
45 47 void attachVariableMenu(QMenu *menu,
46 48 const QVector<std::shared_ptr<Variable> > &variables) noexcept;
47 49
48 50 /// Slot called when a variable is about to be deleted from SciQlop
49 51 void onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept;
50 52
51 53 void onRangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range) noexcept;
52 54
53 55 protected:
54 56 void closeEvent(QCloseEvent *event) override;
55 57
56 58 private:
57 59 Ui::VisualizationWidget *ui;
58 60
59 61 class VisualizationWidgetPrivate;
60 62 spimpl::unique_impl_ptr<VisualizationWidgetPrivate> impl;
61 63 };
62 64
63 65 #endif // VISUALIZATIONWIDGET_H
@@ -1,193 +1,218
1 1 #include "Catalogue/CatalogueEventsWidget.h"
2 2 #include "ui_CatalogueEventsWidget.h"
3 3
4 4 #include <Catalogue/CatalogueController.h>
5 5 #include <Catalogue/CatalogueEventsTableModel.h>
6 6 #include <CatalogueDao.h>
7 7 #include <DBCatalogue.h>
8 8 #include <SqpApplication.h>
9 #include <Visualization/VisualizationTabWidget.h>
10 #include <Visualization/VisualizationWidget.h>
9 11
10 12 #include <QDialog>
11 13 #include <QDialogButtonBox>
12 14 #include <QListWidget>
13 15
14 16
15 17 /// Format of the dates appearing in the label of a cursor
16 18 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss");
17 19
18 20 struct CatalogueEventsWidget::CatalogueEventsWidgetPrivate {
19 21
20 22 CatalogueEventsTableModel *m_Model = nullptr;
21 23 QString m_ZoneForTimeMode;
22 24 QString m_ZoneForGraphMode;
23 25
26 VisualizationWidget *m_VisualizationWidget = nullptr;
27
24 28 void setEvents(const QVector<DBEvent> &events, QTableView *tableView)
25 29 {
26 30 tableView->setSortingEnabled(false);
27 31 m_Model->setEvents(events);
28 32 tableView->setSortingEnabled(true);
29 33 }
30 34
31 35 void addEvent(const DBEvent &event, QTableView *tableView)
32 36 {
33 37 tableView->setSortingEnabled(false);
34 38 m_Model->addEvent(event);
35 39 tableView->setSortingEnabled(true);
36 40 }
37 41
38 42 void removeEvent(const DBEvent &event, QTableView *tableView)
39 43 {
40 44 tableView->setSortingEnabled(false);
41 45 m_Model->removeEvent(event);
42 46 tableView->setSortingEnabled(true);
43 47 }
44 48
45 QStringList selectZone(QWidget *parent, const QStringList &availableZones,
46 const QStringList &selectedZones, bool allowMultiSelection,
47 const QPoint &location)
49 QStringList getAvailableVisualizationZoneList() const
50 {
51 if (m_VisualizationWidget) {
52 if (auto tab = m_VisualizationWidget->currentTabWidget()) {
53 return tab->availableZoneWidgets();
54 }
55 }
56
57 return QStringList{};
58 }
59
60 QStringList selectZone(QWidget *parent, const QStringList &selectedZones,
61 bool allowMultiSelection, const QPoint &location)
48 62 {
63 auto availableZones = getAvailableVisualizationZoneList();
64 if (availableZones.isEmpty()) {
65 return QStringList{};
66 }
67
49 68 QDialog d(parent, Qt::Tool);
50 69 d.setWindowTitle("Choose a zone");
51 70 auto layout = new QVBoxLayout{&d};
52 71 layout->setContentsMargins(0, 0, 0, 0);
53 72 auto listWidget = new QListWidget{&d};
54 73 layout->addWidget(listWidget);
55 74
56 75 QSet<QListWidgetItem *> checkedItems;
57 76 for (auto zone : availableZones) {
58 77 auto item = new QListWidgetItem{zone};
59 78 item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsUserCheckable);
60 79 if (selectedZones.contains(zone)) {
61 80 item->setCheckState(Qt::Checked);
62 81 checkedItems << item;
63 82 }
64 83 else {
65 84 item->setCheckState(Qt::Unchecked);
66 85 }
67 86
68 87 listWidget->addItem(item);
69 88 }
70 89
71 90 auto buttonBox = new QDialogButtonBox{QDialogButtonBox::Ok, &d};
72 91 layout->addWidget(buttonBox);
73 92
74 93 QObject::connect(buttonBox, &QDialogButtonBox::accepted, &d, &QDialog::accept);
75 94 QObject::connect(buttonBox, &QDialogButtonBox::rejected, &d, &QDialog::reject);
76 95
77 96 QObject::connect(listWidget, &QListWidget::itemChanged,
78 97 [&checkedItems, allowMultiSelection, listWidget](auto item) {
79 98 if (item->checkState() == Qt::Checked) {
80 99 if (!allowMultiSelection) {
81 100 for (auto checkedItem : checkedItems) {
82 101 listWidget->blockSignals(true);
83 102 checkedItem->setCheckState(Qt::Unchecked);
84 103 listWidget->blockSignals(false);
85 104 }
86 105
87 106 checkedItems.clear();
88 107 }
89 108 checkedItems << item;
90 109 }
91 110 else {
92 111 checkedItems.remove(item);
93 112 }
94 113 });
95 114
96 115 QStringList result;
97 116
98 117 d.setMinimumWidth(120);
99 118 d.resize(d.minimumSizeHint());
100 119 d.move(location);
101 120 if (d.exec() == QDialog::Accepted) {
102 121 for (auto item : checkedItems) {
103 122 result += item->text();
104 123 }
105 124 }
125 else {
126 result = selectedZones;
127 }
106 128
107 129 return result;
108 130 }
109 131 };
110 132
111 133 CatalogueEventsWidget::CatalogueEventsWidget(QWidget *parent)
112 134 : QWidget(parent),
113 135 ui(new Ui::CatalogueEventsWidget),
114 136 impl{spimpl::make_unique_impl<CatalogueEventsWidgetPrivate>()}
115 137 {
116 138 ui->setupUi(this);
117 139
118 140 impl->m_Model = new CatalogueEventsTableModel{this};
119 141 ui->tableView->setModel(impl->m_Model);
120 142
121 143 ui->tableView->setSortingEnabled(true);
122 144 ui->tableView->setDragDropMode(QAbstractItemView::DragDrop);
123 145 ui->tableView->setDragEnabled(true);
124 146
125 147 connect(ui->btnTime, &QToolButton::clicked, [this](auto checked) {
126 148 if (checked) {
127 149 ui->btnChart->setChecked(false);
128 150 impl->m_ZoneForTimeMode
129 = impl->selectZone(this, {"Zone 1", "Zone 2", "Zone 3", "Zone 4"},
130 {impl->m_ZoneForTimeMode}, false,
151 = impl->selectZone(this, {impl->m_ZoneForTimeMode}, false,
131 152 this->mapToGlobal(ui->btnTime->frameGeometry().center()))
132 153 .value(0);
133 154 }
134 155 });
135 156
136 157 connect(ui->btnChart, &QToolButton::clicked, [this](auto checked) {
137 158 if (checked) {
138 159 ui->btnTime->setChecked(false);
139 160 impl->m_ZoneForGraphMode
140 = impl->selectZone(this, {"Zone 1", "Zone 2", "Zone 3", "Zone 4"},
141 {impl->m_ZoneForGraphMode}, false,
161 = impl->selectZone(this, {impl->m_ZoneForGraphMode}, false,
142 162 this->mapToGlobal(ui->btnChart->frameGeometry().center()))
143 163 .value(0);
144 164 }
145 165 });
146 166
147 167 auto emitSelection = [this]() {
148 168 QVector<DBEvent> events;
149 169 for (auto rowIndex : ui->tableView->selectionModel()->selectedRows()) {
150 170 events << impl->m_Model->getEvent(rowIndex.row());
151 171 }
152 172
153 173 emit this->eventsSelected(events);
154 174 };
155 175
156 176 connect(ui->tableView, &QTableView::clicked, emitSelection);
157 177 connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged, emitSelection);
158 178
159 179 connect(ui->tableView->selectionModel(), &QItemSelectionModel::selectionChanged, [this]() {
160 180 auto isNotMultiSelection = ui->tableView->selectionModel()->selectedRows().count() <= 1;
161 181 ui->btnChart->setEnabled(isNotMultiSelection);
162 182 ui->btnTime->setEnabled(isNotMultiSelection);
163 183 });
164 184
165 185 ui->tableView->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents);
166 186 ui->tableView->horizontalHeader()->setSectionResizeMode(0, QHeaderView::Stretch);
167 187 ui->tableView->horizontalHeader()->setSortIndicatorShown(true);
168 188 }
169 189
170 190 CatalogueEventsWidget::~CatalogueEventsWidget()
171 191 {
172 192 delete ui;
173 193 }
174 194
195 void CatalogueEventsWidget::setVisualizationWidget(VisualizationWidget *visualization)
196 {
197 impl->m_VisualizationWidget = visualization;
198 }
199
175 200 void CatalogueEventsWidget::populateWithCatalogues(const QVector<DBCatalogue> &catalogues)
176 201 {
177 202 auto &dao = sqpApp->catalogueController().getDao();
178 203
179 204 QSet<QUuid> eventIds;
180 205 QVector<DBEvent> events;
181 206
182 207 for (auto catalogue : catalogues) {
183 208 auto catalogueEvents = dao.getCatalogueEvents(catalogue);
184 209 for (auto event : catalogueEvents) {
185 210 if (!eventIds.contains(event.getUniqId())) {
186 211 events << event;
187 212 eventIds.insert(event.getUniqId());
188 213 }
189 214 }
190 215 }
191 216
192 217 impl->setEvents(events, ui->tableView);
193 218 }
@@ -1,50 +1,61
1 1 #include "Catalogue/CatalogueExplorer.h"
2 2 #include "ui_CatalogueExplorer.h"
3 3
4 #include <Visualization/VisualizationWidget.h>
5
4 6 #include <DBCatalogue.h>
5 7 #include <DBEvent.h>
6 8
9 struct CatalogueExplorer::CatalogueExplorerPrivate {
10 };
11
7 12 CatalogueExplorer::CatalogueExplorer(QWidget *parent)
8 13 : QDialog(parent, Qt::Dialog | Qt::WindowMinMaxButtonsHint | Qt::WindowCloseButtonHint),
9 ui(new Ui::CatalogueExplorer)
14 ui(new Ui::CatalogueExplorer),
15 impl{spimpl::make_unique_impl<CatalogueExplorerPrivate>()}
10 16 {
11 17 ui->setupUi(this);
12 18
13 19 connect(ui->catalogues, &CatalogueSideBarWidget::catalogueSelected, [this](auto catalogues) {
14 20 if (catalogues.count() == 1) {
15 21 ui->inspector->setCatalogue(catalogues.first());
16 22 }
17 23 else {
18 24 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
19 25 }
20 26
21 27 ui->events->populateWithCatalogues(catalogues);
22 28 });
23 29
24 30 connect(ui->catalogues, &CatalogueSideBarWidget::databaseSelected, [this](auto databases) {
25 31 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
26 32 });
27 33
28 34 connect(ui->catalogues, &CatalogueSideBarWidget::trashSelected,
29 35 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
30 36
31 37 connect(ui->catalogues, &CatalogueSideBarWidget::allEventsSelected,
32 38 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
33 39
34 40 connect(ui->catalogues, &CatalogueSideBarWidget::selectionCleared,
35 41 [this]() { ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty); });
36 42
37 43 connect(ui->events, &CatalogueEventsWidget::eventsSelected, [this](auto events) {
38 44 if (events.count() == 1) {
39 45 ui->inspector->setEvent(events.first());
40 46 }
41 47 else {
42 48 ui->inspector->showPage(CatalogueInspectorWidget::Page::Empty);
43 49 }
44 50 });
45 51 }
46 52
47 53 CatalogueExplorer::~CatalogueExplorer()
48 54 {
49 55 delete ui;
50 56 }
57
58 void CatalogueExplorer::setVisualizationWidget(VisualizationWidget *visualization)
59 {
60 ui->events->setVisualizationWidget(visualization);
61 }
@@ -1,329 +1,338
1 1 #include "Visualization/VisualizationTabWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "ui_VisualizationTabWidget.h"
4 4
5 5 #include "Visualization/VisualizationGraphWidget.h"
6 6 #include "Visualization/VisualizationZoneWidget.h"
7 7
8 8 #include "Visualization/MacScrollBarStyle.h"
9 9
10 10 #include "Variable/VariableController.h"
11 11
12 12 #include "Common/MimeTypesDef.h"
13 13
14 14 #include "DragAndDrop/DragDropGuiController.h"
15 15 #include "SqpApplication.h"
16 16
17 17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18 18
19 19 namespace {
20 20
21 21 /// Generates a default name for a new zone, according to the number of zones already displayed in
22 22 /// the tab
23 23 QString defaultZoneName(const QLayout &layout)
24 24 {
25 25 auto count = 0;
26 26 for (auto i = 0; i < layout.count(); ++i) {
27 27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
28 28 count++;
29 29 }
30 30 }
31 31
32 32 return QObject::tr("Zone %1").arg(count + 1);
33 33 }
34 34
35 35 /**
36 36 * Applies a function to all zones of the tab represented by its layout
37 37 * @param layout the layout that contains zones
38 38 * @param fun the function to apply to each zone
39 39 */
40 40 template <typename Fun>
41 41 void processZones(QLayout &layout, Fun fun)
42 42 {
43 43 for (auto i = 0; i < layout.count(); ++i) {
44 44 if (auto item = layout.itemAt(i)) {
45 45 if (auto visualizationZoneWidget
46 46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
47 47 fun(*visualizationZoneWidget);
48 48 }
49 49 }
50 50 }
51 51 }
52 52
53 53 } // namespace
54 54
55 55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
56 56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
57 57
58 58 QString m_Name;
59 59
60 60 #ifdef Q_OS_MAC
61 61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 62 #endif
63 63
64 64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
65 65 void dropZone(int index, VisualizationTabWidget *tabWidget);
66 66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
67 67 VisualizationTabWidget *tabWidget);
68 68 };
69 69
70 70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
71 71 : QWidget{parent},
72 72 ui{new Ui::VisualizationTabWidget},
73 73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
74 74 {
75 75 ui->setupUi(this);
76 76
77 77 #ifdef Q_OS_MAC
78 78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 79 #endif
80 80
81 81 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
82 82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
83 83 ui->dragDropContainer->layout()->setSpacing(0);
84 84 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
85 85 VisualizationDragDropContainer::DropBehavior::Inserted);
86 86 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
87 87 VisualizationDragDropContainer::DropBehavior::Inserted);
88 88 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
89 89 VisualizationDragDropContainer::DropBehavior::Inserted);
90 90
91 91 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
92 92 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
93 93 ui->dragDropContainer);
94 94 });
95 95
96 96 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
97 97 &VisualizationTabWidget::dropMimeData);
98 98
99 99 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
100 100
101 101 // Widget is deleted when closed
102 102 setAttribute(Qt::WA_DeleteOnClose);
103 103 }
104 104
105 105 VisualizationTabWidget::~VisualizationTabWidget()
106 106 {
107 107 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
108 108 delete ui;
109 109 }
110 110
111 111 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
112 112 {
113 113 ui->dragDropContainer->addDragWidget(zoneWidget);
114 114 }
115 115
116 116 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
117 117 {
118 118 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
119 119 }
120 120
121 QStringList VisualizationTabWidget::availableZoneWidgets() const
122 {
123 QStringList zones;
124 processZones(tabLayout(),
125 [&zones](VisualizationZoneWidget &zoneWidget) { zones << zoneWidget.name(); });
126
127 return zones;
128 }
129
121 130 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
122 131 {
123 132 return createZone({variable}, -1);
124 133 }
125 134
126 135 VisualizationZoneWidget *
127 136 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
128 137 {
129 138 auto zoneWidget = createEmptyZone(index);
130 139
131 140 // Creates a new graph into the zone
132 141 zoneWidget->createGraph(variables, index);
133 142
134 143 return zoneWidget;
135 144 }
136 145
137 146 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
138 147 {
139 148 auto zoneWidget
140 149 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
141 150 this->insertZone(index, zoneWidget);
142 151
143 152 return zoneWidget;
144 153 }
145 154
146 155 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
147 156 {
148 157 if (visitor) {
149 158 visitor->visitEnter(this);
150 159
151 160 // Apply visitor to zone children: widgets different from zones are not visited (no action)
152 161 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
153 162 zoneWidget.accept(visitor);
154 163 });
155 164
156 165 visitor->visitLeave(this);
157 166 }
158 167 else {
159 168 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
160 169 }
161 170 }
162 171
163 172 bool VisualizationTabWidget::canDrop(const Variable &variable) const
164 173 {
165 174 // A tab can always accomodate a variable
166 175 Q_UNUSED(variable);
167 176 return true;
168 177 }
169 178
170 179 bool VisualizationTabWidget::contains(const Variable &variable) const
171 180 {
172 181 Q_UNUSED(variable);
173 182 return false;
174 183 }
175 184
176 185 QString VisualizationTabWidget::name() const
177 186 {
178 187 return impl->m_Name;
179 188 }
180 189
181 190 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
182 191 {
183 192 // Closes zones in the tab
184 193 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
185 194
186 195 QWidget::closeEvent(event);
187 196 }
188 197
189 198 QLayout &VisualizationTabWidget::tabLayout() const noexcept
190 199 {
191 200 return *ui->dragDropContainer->layout();
192 201 }
193 202
194 203 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
195 204 {
196 205 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
197 206 impl->dropGraph(index, this);
198 207 }
199 208 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
200 209 impl->dropZone(index, this);
201 210 }
202 211 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
203 212 auto variables = sqpApp->variableController().variablesForMimeData(
204 213 mimeData->data(MIME_TYPE_VARIABLE_LIST));
205 214 impl->dropVariables(variables, index, this);
206 215 }
207 216 else {
208 217 qCWarning(LOG_VisualizationZoneWidget())
209 218 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
210 219 }
211 220 }
212 221
213 222 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
214 223 int index, VisualizationTabWidget *tabWidget)
215 224 {
216 225 auto &helper = sqpApp->dragDropGuiController();
217 226
218 227 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
219 228 if (!graphWidget) {
220 229 qCWarning(LOG_VisualizationZoneWidget())
221 230 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
222 231 "found or invalid.");
223 232 Q_ASSERT(false);
224 233 return;
225 234 }
226 235
227 236 auto parentDragDropContainer
228 237 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
229 238 if (!parentDragDropContainer) {
230 239 qCWarning(LOG_VisualizationZoneWidget())
231 240 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
232 241 "the dropped graph is not found.");
233 242 Q_ASSERT(false);
234 243 return;
235 244 }
236 245
237 246 auto nbGraph = parentDragDropContainer->countDragWidget();
238 247
239 248 const auto &variables = graphWidget->variables();
240 249
241 250 if (!variables.isEmpty()) {
242 251 // Abort the requests for the variables (if any)
243 252 // Commented, because it's not sure if it's needed or not
244 253 // for (const auto& var : variables)
245 254 //{
246 255 // sqpApp->variableController().onAbortProgressRequested(var);
247 256 //}
248 257
249 258 if (nbGraph == 1) {
250 259 // This is the only graph in the previous zone, close the zone
251 260 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
252 261 }
253 262 else {
254 263 // Close the graph
255 264 helper.delayedCloseWidget(graphWidget);
256 265 }
257 266
258 267 auto zoneWidget = tabWidget->createZone(variables, index);
259 268 auto firstGraph = zoneWidget->firstGraph();
260 269 if (firstGraph) {
261 270 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
262 271 }
263 272 else {
264 273 qCWarning(LOG_VisualizationZoneWidget())
265 274 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
266 275 Q_ASSERT(false);
267 276 }
268 277 }
269 278 else {
270 279 // The graph is empty, create an empty zone and move the graph inside
271 280
272 281 auto parentZoneWidget = graphWidget->parentZoneWidget();
273 282
274 283 parentDragDropContainer->layout()->removeWidget(graphWidget);
275 284
276 285 auto zoneWidget = tabWidget->createEmptyZone(index);
277 286 zoneWidget->addGraph(graphWidget);
278 287
279 288 // Close the old zone if it was the only graph inside
280 289 if (nbGraph == 1) {
281 290 helper.delayedCloseWidget(parentZoneWidget);
282 291 }
283 292 }
284 293 }
285 294
286 295 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
287 296 int index, VisualizationTabWidget *tabWidget)
288 297 {
289 298 auto &helper = sqpApp->dragDropGuiController();
290 299
291 300 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
292 301 if (!zoneWidget) {
293 302 qCWarning(LOG_VisualizationZoneWidget())
294 303 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
295 304 "found or invalid.");
296 305 Q_ASSERT(false);
297 306 return;
298 307 }
299 308
300 309 auto parentDragDropContainer
301 310 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
302 311 if (!parentDragDropContainer) {
303 312 qCWarning(LOG_VisualizationZoneWidget())
304 313 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
305 314 "the dropped zone is not found.");
306 315 Q_ASSERT(false);
307 316 return;
308 317 }
309 318
310 319 // Simple move of the zone, no variable operation associated
311 320 parentDragDropContainer->layout()->removeWidget(zoneWidget);
312 321 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
313 322 }
314 323
315 324 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
316 325 const QList<std::shared_ptr<Variable> > &variables, int index,
317 326 VisualizationTabWidget *tabWidget)
318 327 {
319 328 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
320 329 // compatible variable here
321 330 if (variables.count() > 1) {
322 331 qCWarning(LOG_VisualizationZoneWidget())
323 332 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
324 333 "aborted.");
325 334 return;
326 335 }
327 336
328 337 tabWidget->createZone(variables, index);
329 338 }
@@ -1,215 +1,224
1 1 #include "Visualization/VisualizationWidget.h"
2 2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 3 #include "Visualization/VisualizationActionManager.h"
4 4 #include "Visualization/VisualizationGraphWidget.h"
5 5 #include "Visualization/VisualizationSelectionZoneItem.h"
6 6 #include "Visualization/VisualizationSelectionZoneManager.h"
7 7 #include "Visualization/VisualizationTabWidget.h"
8 8 #include "Visualization/VisualizationZoneWidget.h"
9 9 #include "Visualization/operations/FindVariableOperation.h"
10 10 #include "Visualization/operations/GenerateVariableMenuOperation.h"
11 11 #include "Visualization/operations/RemoveVariableOperation.h"
12 12 #include "Visualization/operations/RescaleAxeOperation.h"
13 13 #include "Visualization/qcustomplot.h"
14 14
15 15 #include "ui_VisualizationWidget.h"
16 16
17 17 #include "DragAndDrop/DragDropGuiController.h"
18 18 #include "SqpApplication.h"
19 19
20 20 #include <QToolButton>
21 21
22 22 #include <memory>
23 23
24 24 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
25 25
26 26 struct VisualizationWidget::VisualizationWidgetPrivate {
27 27 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
28 28 VisualizationActionManager m_ActionManager;
29 29
30 30 VisualizationWidgetPrivate()
31 31 : m_ZoneSelectionManager(std::make_unique<VisualizationSelectionZoneManager>())
32 32 {
33 33 }
34 34 };
35 35
36 36 VisualizationWidget::VisualizationWidget(QWidget *parent)
37 37 : QWidget{parent},
38 38 ui{new Ui::VisualizationWidget},
39 39 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
40 40 {
41 41 ui->setupUi(this);
42 42
43 43 auto addTabViewButton = new QToolButton{ui->tabWidget};
44 44 addTabViewButton->setText(tr("Add View"));
45 45 addTabViewButton->setCursor(Qt::ArrowCursor);
46 46 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
47 47
48 48 auto enableMinimumCornerWidgetSize = [this](bool enable) {
49 49
50 50 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
51 51 auto width = enable ? tabViewCornerWidget->width() : 0;
52 52 auto height = enable ? tabViewCornerWidget->height() : 0;
53 53 tabViewCornerWidget->setMinimumHeight(height);
54 54 tabViewCornerWidget->setMinimumWidth(width);
55 55 ui->tabWidget->setMinimumHeight(height);
56 56 ui->tabWidget->setMinimumWidth(width);
57 57 };
58 58
59 59 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
60 60 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
61 61 ui->tabWidget};
62 62 auto index = ui->tabWidget->addTab(widget, widget->name());
63 63 if (ui->tabWidget->count() > 0) {
64 64 enableMinimumCornerWidgetSize(false);
65 65 }
66 66 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
67 67 };
68 68
69 69 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
70 70 if (ui->tabWidget->count() == 1) {
71 71 enableMinimumCornerWidgetSize(true);
72 72 }
73 73
74 74 // Removes widget from tab and closes it
75 75 auto widget = ui->tabWidget->widget(index);
76 76 ui->tabWidget->removeTab(index);
77 77 if (widget) {
78 78 widget->close();
79 79 }
80 80
81 81 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
82 82
83 83 };
84 84
85 85 ui->tabWidget->setTabsClosable(true);
86 86
87 87 connect(addTabViewButton, &QToolButton::clicked, addTabView);
88 88 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
89 89
90 90 sqpApp->dragDropGuiController().addDragDropTabBar(ui->tabWidget->tabBar());
91 91
92 92 // Actions
93 93 impl->m_ActionManager.installSelectionZoneActions();
94 94
95 95 auto removeZoneAction = new QAction("Remove selected zone(s)");
96 96 removeZoneAction->setShortcut(QKeySequence::Delete);
97 97 connect(removeZoneAction, &QAction::triggered, [this]() {
98 98 auto selection = impl->m_ZoneSelectionManager->selectedItems();
99 99 for (auto selectionZone : selection) {
100 100 if (auto graph = selectionZone->parentGraphWidget()) {
101 101 graph->removeSelectionZone(selectionZone);
102 102 }
103 103 }
104 104 });
105 105 addAction(removeZoneAction);
106 106
107 107 // Adds default tab
108 108 addTabView();
109 109 }
110 110
111 111 VisualizationWidget::~VisualizationWidget()
112 112 {
113 113 sqpApp->dragDropGuiController().removeDragDropTabBar(ui->tabWidget->tabBar());
114 114 delete ui;
115 115 }
116 116
117 117 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
118 118 {
119 119 return *impl->m_ZoneSelectionManager.get();
120 120 }
121 121
122 VisualizationTabWidget *VisualizationWidget::currentTabWidget() const
123 {
124 if (auto tab = qobject_cast<VisualizationTabWidget *>(ui->tabWidget->currentWidget())) {
125 return tab;
126 }
127
128 return nullptr;
129 }
130
122 131 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
123 132 {
124 133 if (visitor) {
125 134 visitor->visitEnter(this);
126 135
127 136 // Apply visitor for tab children
128 137 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
129 138 // Widgets different from tabs are not visited (no action)
130 139 if (auto visualizationTabWidget
131 140 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
132 141 visualizationTabWidget->accept(visitor);
133 142 }
134 143 }
135 144
136 145 visitor->visitLeave(this);
137 146 }
138 147 else {
139 148 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
140 149 }
141 150 }
142 151
143 152 bool VisualizationWidget::canDrop(const Variable &variable) const
144 153 {
145 154 // The main widget can never accomodate a variable
146 155 Q_UNUSED(variable);
147 156 return false;
148 157 }
149 158
150 159 bool VisualizationWidget::contains(const Variable &variable) const
151 160 {
152 161 Q_UNUSED(variable);
153 162 return false;
154 163 }
155 164
156 165 QString VisualizationWidget::name() const
157 166 {
158 167 return QStringLiteral("MainView");
159 168 }
160 169
161 170 void VisualizationWidget::attachVariableMenu(
162 171 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
163 172 {
164 173 // Menu is generated only if there is a single variable
165 174 if (variables.size() == 1) {
166 175 if (auto variable = variables.first()) {
167 176 // Gets the containers of the variable
168 177 FindVariableOperation findVariableOperation{variable};
169 178 accept(&findVariableOperation);
170 179 auto variableContainers = findVariableOperation.result();
171 180
172 181 // Generates the actions that make it possible to visualize the variable
173 182 GenerateVariableMenuOperation generateVariableMenuOperation{
174 183 menu, variable, std::move(variableContainers)};
175 184 accept(&generateVariableMenuOperation);
176 185 }
177 186 else {
178 187 qCCritical(LOG_VisualizationWidget()) << tr(
179 188 "Can't generate the menu relative to the visualization: the variable is null");
180 189 }
181 190 }
182 191 else {
183 192 qCDebug(LOG_VisualizationWidget())
184 193 << tr("No generation of the menu related to the visualization: several variables are "
185 194 "selected");
186 195 }
187 196 }
188 197
189 198 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
190 199 {
191 200 // Calls the operation of removing all references to the variable in the visualization
192 201 auto removeVariableOperation = RemoveVariableOperation{variable};
193 202 accept(&removeVariableOperation);
194 203 }
195 204
196 205 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
197 206 const SqpRange &range) noexcept
198 207 {
199 208 // Calls the operation of rescaling all graph that contrains variable in the visualization
200 209 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
201 210 accept(&rescaleVariableOperation);
202 211 }
203 212
204 213 void VisualizationWidget::closeEvent(QCloseEvent *event)
205 214 {
206 215 // Closes tabs in the widget
207 216 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
208 217 if (auto visualizationTabWidget
209 218 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
210 219 visualizationTabWidget->close();
211 220 }
212 221 }
213 222
214 223 QWidget::closeEvent(event);
215 224 }
General Comments 0
You need to be logged in to leave comments. Login now