##// END OF EJS Templates
Merge branch 'feature/InteractionModesAndCursors' into develop
trabillard -
r1010:cf3e9de4d0c6 merge
parent child
Show More
@@ -0,0 +1,26
1 #ifndef SCIQLOP_VISUALIZATIONCURSORITEM_H
2 #define SCIQLOP_VISUALIZATIONCURSORITEM_H
3
4 #include <Common/spimpl.h>
5 #include <SqpApplication.h>
6
7 class QCustomPlot;
8
9 class VisualizationCursorItem {
10 public:
11 VisualizationCursorItem(QCustomPlot *plot);
12
13 void setVisible(bool value);
14 bool isVisible() const;
15
16 void setPosition(double value);
17 void setAbsolutePosition(double value);
18 void setOrientation(Qt::Orientation orientation);
19 void setLabelText(const QString &text);
20
21 private:
22 class VisualizationCursorItemPrivate;
23 spimpl::unique_impl_ptr<VisualizationCursorItemPrivate> impl;
24 };
25
26 #endif // SCIQLOP_VISUALIZATIONCURSORITEM_H
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
1 NO CONTENT: new file 100644, binary diff hidden
NO CONTENT: new file 100644, binary diff hidden
@@ -0,0 +1,163
1 #include <Common/DateUtils.h>
2 #include <Visualization/VisualizationCursorItem.h>
3 #include <Visualization/qcustomplot.h>
4
5 /// Width of the cursor in pixel
6 const auto CURSOR_WIDTH = 3;
7
8 /// Color of the cursor in the graph
9 const auto CURSOR_COLOR = QColor{68, 114, 196};
10
11 /// Line style of the cursor in the graph
12 auto CURSOR_PEN_STYLE = Qt::DotLine;
13
14 struct VisualizationCursorItem::VisualizationCursorItemPrivate {
15
16 QCustomPlot *m_Plot = nullptr;
17
18 QCPItemStraightLine *m_LineItem = nullptr;
19 QCPItemText *m_LabelItem = nullptr;
20
21 Qt::Orientation m_Orientation;
22 double m_Position = 0.0;
23 bool m_IsAbsolutePosition = false;
24 QString m_LabelText;
25
26 explicit VisualizationCursorItemPrivate(QCustomPlot *plot)
27 : m_Plot(plot), m_Orientation(Qt::Vertical)
28 {
29 }
30
31 void updateOrientation()
32 {
33 if (m_LineItem) {
34 switch (m_Orientation) {
35 case Qt::Vertical:
36 m_LineItem->point1->setTypeX(m_IsAbsolutePosition
37 ? QCPItemPosition::ptAbsolute
38 : QCPItemPosition::ptPlotCoords);
39 m_LineItem->point1->setTypeY(QCPItemPosition::ptAxisRectRatio);
40 m_LineItem->point2->setTypeX(m_IsAbsolutePosition
41 ? QCPItemPosition::ptAbsolute
42 : QCPItemPosition::ptPlotCoords);
43 m_LineItem->point2->setTypeY(QCPItemPosition::ptAxisRectRatio);
44 m_LabelItem->setPositionAlignment(Qt::AlignLeft | Qt::AlignTop);
45 break;
46 case Qt::Horizontal:
47 m_LineItem->point1->setTypeX(QCPItemPosition::ptAxisRectRatio);
48 m_LineItem->point1->setTypeY(m_IsAbsolutePosition
49 ? QCPItemPosition::ptAbsolute
50 : QCPItemPosition::ptPlotCoords);
51 m_LineItem->point2->setTypeX(QCPItemPosition::ptAxisRectRatio);
52 m_LineItem->point2->setTypeY(m_IsAbsolutePosition
53 ? QCPItemPosition::ptAbsolute
54 : QCPItemPosition::ptPlotCoords);
55 m_LabelItem->setPositionAlignment(Qt::AlignRight | Qt::AlignBottom);
56 }
57 }
58 }
59
60 void updateCursorPosition()
61 {
62 if (m_LineItem) {
63 switch (m_Orientation) {
64 case Qt::Vertical:
65 m_LineItem->point1->setCoords(m_Position, 0);
66 m_LineItem->point2->setCoords(m_Position, 1);
67 m_LabelItem->position->setCoords(5, 5);
68 break;
69 case Qt::Horizontal:
70 m_LineItem->point1->setCoords(1, m_Position);
71 m_LineItem->point2->setCoords(0, m_Position);
72 m_LabelItem->position->setCoords(-5, -5);
73 }
74 }
75 }
76
77 void updateLabelText()
78 {
79 if (m_LabelItem) {
80 m_LabelItem->setText(m_LabelText);
81 }
82 }
83 };
84
85 VisualizationCursorItem::VisualizationCursorItem(QCustomPlot *plot)
86 : impl{spimpl::make_unique_impl<VisualizationCursorItemPrivate>(plot)}
87 {
88 }
89
90 void VisualizationCursorItem::setVisible(bool value)
91 {
92 if (value != isVisible()) {
93
94 if (value) {
95 Q_ASSERT(!impl->m_LineItem && !impl->m_Plot);
96
97 impl->m_LineItem = new QCPItemStraightLine{impl->m_Plot};
98 auto pen = QPen{CURSOR_PEN_STYLE};
99 pen.setColor(CURSOR_COLOR);
100 pen.setWidth(CURSOR_WIDTH);
101 impl->m_LineItem->setPen(pen);
102 impl->m_LineItem->setSelectable(false);
103
104 impl->m_LabelItem = new QCPItemText{impl->m_Plot};
105 impl->m_LabelItem->setColor(CURSOR_COLOR);
106 impl->m_LabelItem->setSelectable(false);
107 impl->m_LabelItem->position->setParentAnchor(impl->m_LineItem->point1);
108 impl->m_LabelItem->position->setTypeX(QCPItemPosition::ptAbsolute);
109 impl->m_LabelItem->position->setTypeY(QCPItemPosition::ptAbsolute);
110
111 auto font = impl->m_LabelItem->font();
112 font.setPointSize(10);
113 font.setBold(true);
114 impl->m_LabelItem->setFont(font);
115
116 impl->updateOrientation();
117 impl->updateLabelText();
118 impl->updateCursorPosition();
119 }
120 else {
121 Q_ASSERT(impl->m_LineItem && impl->m_Plot);
122
123 // Note: the items are destroyed by QCustomPlot in removeItem
124 impl->m_Plot->removeItem(impl->m_LineItem);
125 impl->m_LineItem = nullptr;
126 impl->m_Plot->removeItem(impl->m_LabelItem);
127 impl->m_LabelItem = nullptr;
128 }
129 }
130 }
131
132 bool VisualizationCursorItem::isVisible() const
133 {
134 return impl->m_LineItem != nullptr;
135 }
136
137 void VisualizationCursorItem::setPosition(double value)
138 {
139 impl->m_Position = value;
140 impl->m_IsAbsolutePosition = false;
141 impl->updateLabelText();
142 impl->updateCursorPosition();
143 }
144
145 void VisualizationCursorItem::setAbsolutePosition(double value)
146 {
147 setPosition(value);
148 impl->m_IsAbsolutePosition = true;
149 }
150
151 void VisualizationCursorItem::setOrientation(Qt::Orientation orientation)
152 {
153 impl->m_Orientation = orientation;
154 impl->updateLabelText();
155 impl->updateOrientation();
156 impl->updateCursorPosition();
157 }
158
159 void VisualizationCursorItem::setLabelText(const QString &text)
160 {
161 impl->m_LabelText = text;
162 impl->updateLabelText();
163 }
@@ -1,254 +1,353
1 /*------------------------------------------------------------------------------
1 /*------------------------------------------------------------------------------
2 -- This file is a part of the SciQLop Software
2 -- This file is a part of the SciQLop Software
3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
3 -- Copyright (C) 2017, Plasma Physics Laboratory - CNRS
4 --
4 --
5 -- This program is free software; you can redistribute it and/or modify
5 -- This program is free software; you can redistribute it and/or modify
6 -- it under the terms of the GNU General Public License as published by
6 -- it under the terms of the GNU General Public License as published by
7 -- the Free Software Foundation; either version 2 of the License, or
7 -- the Free Software Foundation; either version 2 of the License, or
8 -- (at your option) any later version.
8 -- (at your option) any later version.
9 --
9 --
10 -- This program is distributed in the hope that it will be useful,
10 -- This program is distributed in the hope that it will be useful,
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
11 -- but WITHOUT ANY WARRANTY; without even the implied warranty of
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 -- GNU General Public License for more details.
13 -- GNU General Public License for more details.
14 --
14 --
15 -- You should have received a copy of the GNU General Public License
15 -- You should have received a copy of the GNU General Public License
16 -- along with this program; if not, write to the Free Software
16 -- along with this program; if not, write to the Free Software
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 -- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 -------------------------------------------------------------------------------*/
18 -------------------------------------------------------------------------------*/
19 /*-- Author : Alexis Jeandet
19 /*-- Author : Alexis Jeandet
20 -- Mail : alexis.jeandet@member.fsf.org
20 -- Mail : alexis.jeandet@member.fsf.org
21 ----------------------------------------------------------------------------*/
21 ----------------------------------------------------------------------------*/
22 #include "MainWindow.h"
22 #include "MainWindow.h"
23 #include "ui_MainWindow.h"
23 #include "ui_MainWindow.h"
24
24
25 #include <DataSource/DataSourceController.h>
25 #include <DataSource/DataSourceController.h>
26 #include <DataSource/DataSourceWidget.h>
26 #include <DataSource/DataSourceWidget.h>
27 #include <Settings/SqpSettingsDialog.h>
27 #include <Settings/SqpSettingsDialog.h>
28 #include <Settings/SqpSettingsGeneralWidget.h>
28 #include <Settings/SqpSettingsGeneralWidget.h>
29 #include <SidePane/SqpSidePane.h>
29 #include <SidePane/SqpSidePane.h>
30 #include <SqpApplication.h>
30 #include <SqpApplication.h>
31 #include <Time/TimeController.h>
31 #include <Time/TimeController.h>
32 #include <TimeWidget/TimeWidget.h>
32 #include <TimeWidget/TimeWidget.h>
33 #include <Variable/Variable.h>
33 #include <Variable/Variable.h>
34 #include <Variable/VariableController.h>
34 #include <Variable/VariableController.h>
35 #include <Visualization/VisualizationController.h>
35 #include <Visualization/VisualizationController.h>
36
36
37 #include <QAction>
37 #include <QAction>
38 #include <QDate>
38 #include <QDate>
39 #include <QDir>
39 #include <QDir>
40 #include <QFileDialog>
40 #include <QFileDialog>
41 #include <QToolBar>
41 #include <QToolBar>
42 #include <QToolButton>
42 #include <QToolButton>
43 #include <memory.h>
43 #include <memory.h>
44
44
45 #include "iostream"
45 #include "iostream"
46
46
47 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
47 Q_LOGGING_CATEGORY(LOG_MainWindow, "MainWindow")
48
48
49 namespace {
49 namespace {
50 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
50 const auto LEFTMAININSPECTORWIDGETSPLITTERINDEX = 0;
51 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
51 const auto LEFTINSPECTORSIDEPANESPLITTERINDEX = 1;
52 const auto VIEWPLITTERINDEX = 2;
52 const auto VIEWPLITTERINDEX = 2;
53 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
53 const auto RIGHTINSPECTORSIDEPANESPLITTERINDEX = 3;
54 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
54 const auto RIGHTMAININSPECTORWIDGETSPLITTERINDEX = 4;
55 }
55 }
56
56
57 class MainWindow::MainWindowPrivate {
57 class MainWindow::MainWindowPrivate {
58 public:
58 public:
59 explicit MainWindowPrivate(MainWindow *mainWindow)
59 explicit MainWindowPrivate(MainWindow *mainWindow)
60 : m_LastOpenLeftInspectorSize{},
60 : m_LastOpenLeftInspectorSize{},
61 m_LastOpenRightInspectorSize{},
61 m_LastOpenRightInspectorSize{},
62 m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}},
62 m_GeneralSettingsWidget{new SqpSettingsGeneralWidget{mainWindow}},
63 m_SettingsDialog{new SqpSettingsDialog{mainWindow}}
63 m_SettingsDialog{new SqpSettingsDialog{mainWindow}}
64 {
64 {
65 }
65 }
66
66
67 QSize m_LastOpenLeftInspectorSize;
67 QSize m_LastOpenLeftInspectorSize;
68 QSize m_LastOpenRightInspectorSize;
68 QSize m_LastOpenRightInspectorSize;
69 /// General settings widget. MainWindow has the ownership
69 /// General settings widget. MainWindow has the ownership
70 SqpSettingsGeneralWidget *m_GeneralSettingsWidget;
70 SqpSettingsGeneralWidget *m_GeneralSettingsWidget;
71 /// Settings dialog. MainWindow has the ownership
71 /// Settings dialog. MainWindow has the ownership
72 SqpSettingsDialog *m_SettingsDialog;
72 SqpSettingsDialog *m_SettingsDialog;
73 };
73 };
74
74
75 MainWindow::MainWindow(QWidget *parent)
75 MainWindow::MainWindow(QWidget *parent)
76 : QMainWindow{parent},
76 : QMainWindow{parent},
77 m_Ui{new Ui::MainWindow},
77 m_Ui{new Ui::MainWindow},
78 impl{spimpl::make_unique_impl<MainWindowPrivate>(this)}
78 impl{spimpl::make_unique_impl<MainWindowPrivate>(this)}
79 {
79 {
80 m_Ui->setupUi(this);
80 m_Ui->setupUi(this);
81
81
82 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
82 m_Ui->splitter->setCollapsible(LEFTINSPECTORSIDEPANESPLITTERINDEX, false);
83 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
83 m_Ui->splitter->setCollapsible(RIGHTINSPECTORSIDEPANESPLITTERINDEX, false);
84
84
85
85
86 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
86 auto leftSidePane = m_Ui->leftInspectorSidePane->sidePane();
87 auto openLeftInspectorAction = new QAction{QIcon{
87 auto openLeftInspectorAction = new QAction{QIcon{
88 ":/icones/previous.png",
88 ":/icones/previous.png",
89 },
89 },
90 tr("Show/hide the left inspector"), this};
90 tr("Show/hide the left inspector"), this};
91
91
92
92
93 auto spacerLeftTop = new QWidget{};
93 auto spacerLeftTop = new QWidget{};
94 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
94 spacerLeftTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
95
95
96 auto spacerLeftBottom = new QWidget{};
96 auto spacerLeftBottom = new QWidget{};
97 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
97 spacerLeftBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
98
98
99 leftSidePane->addWidget(spacerLeftTop);
99 leftSidePane->addWidget(spacerLeftTop);
100 leftSidePane->addAction(openLeftInspectorAction);
100 leftSidePane->addAction(openLeftInspectorAction);
101 leftSidePane->addWidget(spacerLeftBottom);
101 leftSidePane->addWidget(spacerLeftBottom);
102
102
103
103
104 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
104 auto rightSidePane = m_Ui->rightInspectorSidePane->sidePane();
105 auto openRightInspectorAction = new QAction{QIcon{
105 auto openRightInspectorAction = new QAction{QIcon{
106 ":/icones/next.png",
106 ":/icones/next.png",
107 },
107 },
108 tr("Show/hide the right inspector"), this};
108 tr("Show/hide the right inspector"), this};
109
109
110 auto spacerRightTop = new QWidget{};
110 auto spacerRightTop = new QWidget{};
111 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
111 spacerRightTop->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
112
112
113 auto spacerRightBottom = new QWidget{};
113 auto spacerRightBottom = new QWidget{};
114 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
114 spacerRightBottom->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
115
115
116 rightSidePane->addWidget(spacerRightTop);
116 rightSidePane->addWidget(spacerRightTop);
117 rightSidePane->addAction(openRightInspectorAction);
117 rightSidePane->addAction(openRightInspectorAction);
118 rightSidePane->addWidget(spacerRightBottom);
118 rightSidePane->addWidget(spacerRightBottom);
119
119
120 openLeftInspectorAction->setCheckable(true);
120 openLeftInspectorAction->setCheckable(true);
121 openRightInspectorAction->setCheckable(true);
121 openRightInspectorAction->setCheckable(true);
122
122
123 auto openInspector = [this](bool checked, bool right, auto action) {
123 auto openInspector = [this](bool checked, bool right, auto action) {
124
124
125 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
125 action->setIcon(QIcon{(checked xor right) ? ":/icones/next.png" : ":/icones/previous.png"});
126
126
127 auto &lastInspectorSize
127 auto &lastInspectorSize
128 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
128 = right ? impl->m_LastOpenRightInspectorSize : impl->m_LastOpenLeftInspectorSize;
129
129
130 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
130 auto nextInspectorSize = right ? m_Ui->rightMainInspectorWidget->size()
131 : m_Ui->leftMainInspectorWidget->size();
131 : m_Ui->leftMainInspectorWidget->size();
132
132
133 // Update of the last opened geometry
133 // Update of the last opened geometry
134 if (checked) {
134 if (checked) {
135 lastInspectorSize = nextInspectorSize;
135 lastInspectorSize = nextInspectorSize;
136 }
136 }
137
137
138 auto startSize = lastInspectorSize;
138 auto startSize = lastInspectorSize;
139 auto endSize = startSize;
139 auto endSize = startSize;
140 endSize.setWidth(0);
140 endSize.setWidth(0);
141
141
142 auto splitterInspectorIndex
142 auto splitterInspectorIndex
143 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
143 = right ? RIGHTMAININSPECTORWIDGETSPLITTERINDEX : LEFTMAININSPECTORWIDGETSPLITTERINDEX;
144
144
145 auto currentSizes = m_Ui->splitter->sizes();
145 auto currentSizes = m_Ui->splitter->sizes();
146 if (checked) {
146 if (checked) {
147 // adjust sizes individually here, e.g.
147 // adjust sizes individually here, e.g.
148 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
148 currentSizes[splitterInspectorIndex] -= lastInspectorSize.width();
149 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
149 currentSizes[VIEWPLITTERINDEX] += lastInspectorSize.width();
150 m_Ui->splitter->setSizes(currentSizes);
150 m_Ui->splitter->setSizes(currentSizes);
151 }
151 }
152 else {
152 else {
153 // adjust sizes individually here, e.g.
153 // adjust sizes individually here, e.g.
154 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
154 currentSizes[splitterInspectorIndex] += lastInspectorSize.width();
155 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
155 currentSizes[VIEWPLITTERINDEX] -= lastInspectorSize.width();
156 m_Ui->splitter->setSizes(currentSizes);
156 m_Ui->splitter->setSizes(currentSizes);
157 }
157 }
158
158
159 };
159 };
160
160
161
161
162 connect(openLeftInspectorAction, &QAction::triggered,
162 connect(openLeftInspectorAction, &QAction::triggered,
163 [openInspector, openLeftInspectorAction](bool checked) {
163 [openInspector, openLeftInspectorAction](bool checked) {
164 openInspector(checked, false, openLeftInspectorAction);
164 openInspector(checked, false, openLeftInspectorAction);
165 });
165 });
166 connect(openRightInspectorAction, &QAction::triggered,
166 connect(openRightInspectorAction, &QAction::triggered,
167 [openInspector, openRightInspectorAction](bool checked) {
167 [openInspector, openRightInspectorAction](bool checked) {
168 openInspector(checked, true, openRightInspectorAction);
168 openInspector(checked, true, openRightInspectorAction);
169 });
169 });
170
170
171 // //// //
171 // //////////////// //
172 // Menu //
172 // Menu and Toolbar //
173 // //// //
173 // //////////////// //
174 this->menuBar()->addAction(tr("File"));
174 this->menuBar()->addAction(tr("File"));
175 auto toolsMenu = this->menuBar()->addMenu(tr("Tools"));
175 auto toolsMenu = this->menuBar()->addMenu(tr("Tools"));
176 toolsMenu->addAction(tr("Settings..."), [this]() {
176 toolsMenu->addAction(tr("Settings..."), [this]() {
177 // Loads settings
177 // Loads settings
178 impl->m_SettingsDialog->loadSettings();
178 impl->m_SettingsDialog->loadSettings();
179
179
180 // Open settings dialog and save settings if the dialog is accepted
180 // Open settings dialog and save settings if the dialog is accepted
181 if (impl->m_SettingsDialog->exec() == QDialog::Accepted) {
181 if (impl->m_SettingsDialog->exec() == QDialog::Accepted) {
182 impl->m_SettingsDialog->saveSettings();
182 impl->m_SettingsDialog->saveSettings();
183 }
183 }
184
184
185 });
185 });
186
186
187 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
187 auto mainToolBar = this->addToolBar(QStringLiteral("MainToolBar"));
188
188
189 auto timeWidget = new TimeWidget{};
189 auto timeWidget = new TimeWidget{};
190 mainToolBar->addWidget(timeWidget);
190 mainToolBar->addWidget(timeWidget);
191
191
192 auto actionPointerMode = new QAction{QIcon(":/icones/pointer.png"), "Pointer", this};
193 actionPointerMode->setCheckable(true);
194 actionPointerMode->setChecked(sqpApp->plotsInteractionMode()
195 == SqpApplication::PlotsInteractionMode::None);
196 connect(actionPointerMode, &QAction::triggered,
197 []() { sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::None); });
198
199 auto actionZoomMode = new QAction{QIcon(":/icones/zoom.png"), "Zoom", this};
200 actionZoomMode->setCheckable(true);
201 actionZoomMode->setChecked(sqpApp->plotsInteractionMode()
202 == SqpApplication::PlotsInteractionMode::ZoomBox);
203 connect(actionZoomMode, &QAction::triggered, []() {
204 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::ZoomBox);
205 });
206
207 auto actionOrganisationMode = new QAction{QIcon(":/icones/drag.png"), "Organize", this};
208 actionOrganisationMode->setCheckable(true);
209 actionOrganisationMode->setChecked(sqpApp->plotsInteractionMode()
210 == SqpApplication::PlotsInteractionMode::DragAndDrop);
211 connect(actionOrganisationMode, &QAction::triggered, []() {
212 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::DragAndDrop);
213 });
214
215 auto actionZonesMode = new QAction{QIcon(":/icones/rectangle.png"), "Zones", this};
216 actionZonesMode->setCheckable(true);
217 actionZonesMode->setChecked(sqpApp->plotsInteractionMode()
218 == SqpApplication::PlotsInteractionMode::SelectionZones);
219 connect(actionZonesMode, &QAction::triggered, []() {
220 sqpApp->setPlotsInteractionMode(SqpApplication::PlotsInteractionMode::SelectionZones);
221 });
222
223 auto modeActionGroup = new QActionGroup{this};
224 modeActionGroup->addAction(actionZoomMode);
225 modeActionGroup->addAction(actionZonesMode);
226 modeActionGroup->addAction(actionOrganisationMode);
227 modeActionGroup->addAction(actionPointerMode);
228 modeActionGroup->setExclusive(true);
229
230 mainToolBar->addSeparator();
231 mainToolBar->addAction(actionPointerMode);
232 mainToolBar->addAction(actionZoomMode);
233 mainToolBar->addAction(actionOrganisationMode);
234 mainToolBar->addAction(actionZonesMode);
235 mainToolBar->addSeparator();
236
237 auto btnCursor = new QToolButton{this};
238 btnCursor->setIcon(QIcon(":/icones/cursor.png"));
239 btnCursor->setText("Cursor");
240 btnCursor->setToolTip("Cursor");
241 btnCursor->setPopupMode(QToolButton::InstantPopup);
242 auto cursorMenu = new QMenu("CursorMenu", this);
243 btnCursor->setMenu(cursorMenu);
244
245 auto noCursorAction = cursorMenu->addAction("No Cursor");
246 noCursorAction->setCheckable(true);
247 noCursorAction->setChecked(sqpApp->plotsCursorMode()
248 == SqpApplication::PlotsCursorMode::NoCursor);
249 connect(noCursorAction, &QAction::triggered,
250 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::NoCursor); });
251
252 cursorMenu->addSeparator();
253 auto verticalCursorAction = cursorMenu->addAction("Vertical Cursor");
254 verticalCursorAction->setCheckable(true);
255 verticalCursorAction->setChecked(sqpApp->plotsCursorMode()
256 == SqpApplication::PlotsCursorMode::Vertical);
257 connect(verticalCursorAction, &QAction::triggered,
258 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Vertical); });
259
260 auto temporalCursorAction = cursorMenu->addAction("Temporal Cursor");
261 temporalCursorAction->setCheckable(true);
262 temporalCursorAction->setChecked(sqpApp->plotsCursorMode()
263 == SqpApplication::PlotsCursorMode::Temporal);
264 connect(temporalCursorAction, &QAction::triggered,
265 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Temporal); });
266
267 auto horizontalCursorAction = cursorMenu->addAction("Horizontal Cursor");
268 horizontalCursorAction->setCheckable(true);
269 horizontalCursorAction->setChecked(sqpApp->plotsCursorMode()
270 == SqpApplication::PlotsCursorMode::Horizontal);
271 connect(horizontalCursorAction, &QAction::triggered,
272 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Horizontal); });
273
274 auto crossCursorAction = cursorMenu->addAction("Cross Cursor");
275 crossCursorAction->setCheckable(true);
276 crossCursorAction->setChecked(sqpApp->plotsCursorMode()
277 == SqpApplication::PlotsCursorMode::Cross);
278 connect(crossCursorAction, &QAction::triggered,
279 []() { sqpApp->setPlotsCursorMode(SqpApplication::PlotsCursorMode::Cross); });
280
281 mainToolBar->addWidget(btnCursor);
282
283 auto cursorModeActionGroup = new QActionGroup{this};
284 cursorModeActionGroup->setExclusive(true);
285 cursorModeActionGroup->addAction(noCursorAction);
286 cursorModeActionGroup->addAction(verticalCursorAction);
287 cursorModeActionGroup->addAction(temporalCursorAction);
288 cursorModeActionGroup->addAction(horizontalCursorAction);
289 cursorModeActionGroup->addAction(crossCursorAction);
290
192 // //////// //
291 // //////// //
193 // Settings //
292 // Settings //
194 // //////// //
293 // //////// //
195
294
196 // Registers "general settings" widget to the settings dialog
295 // Registers "general settings" widget to the settings dialog
197 impl->m_SettingsDialog->registerWidget(QStringLiteral("General"),
296 impl->m_SettingsDialog->registerWidget(QStringLiteral("General"),
198 impl->m_GeneralSettingsWidget);
297 impl->m_GeneralSettingsWidget);
199
298
200 // /////////// //
299 // /////////// //
201 // Connections //
300 // Connections //
202 // /////////// //
301 // /////////// //
203
302
204 // Controllers / controllers connections
303 // Controllers / controllers connections
205 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpRange)), &sqpApp->variableController(),
304 connect(&sqpApp->timeController(), SIGNAL(timeUpdated(SqpRange)), &sqpApp->variableController(),
206 SLOT(onDateTimeOnSelection(SqpRange)));
305 SLOT(onDateTimeOnSelection(SqpRange)));
207
306
208 // Widgets / controllers connections
307 // Widgets / controllers connections
209
308
210 // DataSource
309 // DataSource
211 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
310 connect(&sqpApp->dataSourceController(), SIGNAL(dataSourceItemSet(DataSourceItem *)),
212 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
311 m_Ui->dataSourceWidget, SLOT(addDataSource(DataSourceItem *)));
213
312
214 // Time
313 // Time
215 connect(timeWidget, SIGNAL(timeUpdated(SqpRange)), &sqpApp->timeController(),
314 connect(timeWidget, SIGNAL(timeUpdated(SqpRange)), &sqpApp->timeController(),
216 SLOT(onTimeToUpdate(SqpRange)));
315 SLOT(onTimeToUpdate(SqpRange)));
217
316
218 // Visualization
317 // Visualization
219 connect(&sqpApp->visualizationController(),
318 connect(&sqpApp->visualizationController(),
220 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
319 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), m_Ui->view,
221 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
320 SLOT(onVariableAboutToBeDeleted(std::shared_ptr<Variable>)));
222
321
223 connect(&sqpApp->visualizationController(),
322 connect(&sqpApp->visualizationController(),
224 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), m_Ui->view,
323 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)), m_Ui->view,
225 SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
324 SLOT(onRangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
226
325
227 // Widgets / widgets connections
326 // Widgets / widgets connections
228
327
229 // For the following connections, we use DirectConnection to allow each widget that can
328 // For the following connections, we use DirectConnection to allow each widget that can
230 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
329 // potentially attach a menu to the variable's menu to do so before this menu is displayed.
231 // The order of connections is also important, since it determines the order in which each
330 // The order of connections is also important, since it determines the order in which each
232 // widget will attach its menu
331 // widget will attach its menu
233 connect(
332 connect(
234 m_Ui->variableInspectorWidget,
333 m_Ui->variableInspectorWidget,
235 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
334 SIGNAL(tableMenuAboutToBeDisplayed(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
236 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
335 m_Ui->view, SLOT(attachVariableMenu(QMenu *, const QVector<std::shared_ptr<Variable> > &)),
237 Qt::DirectConnection);
336 Qt::DirectConnection);
238 }
337 }
239
338
240 MainWindow::~MainWindow()
339 MainWindow::~MainWindow()
241 {
340 {
242 }
341 }
243
342
244 void MainWindow::changeEvent(QEvent *e)
343 void MainWindow::changeEvent(QEvent *e)
245 {
344 {
246 QMainWindow::changeEvent(e);
345 QMainWindow::changeEvent(e);
247 switch (e->type()) {
346 switch (e->type()) {
248 case QEvent::LanguageChange:
347 case QEvent::LanguageChange:
249 m_Ui->retranslateUi(this);
348 m_Ui->retranslateUi(this);
250 break;
349 break;
251 default:
350 default:
252 break;
351 break;
253 }
352 }
254 }
353 }
@@ -1,7 +1,8
1 #ifndef SCIQLOP_VISUALIZATIONDEF_H
1 #ifndef SCIQLOP_VISUALIZATIONDEF_H
2 #define SCIQLOP_VISUALIZATIONDEF_H
2 #define SCIQLOP_VISUALIZATIONDEF_H
3
3
4 /// Minimum height for graph added in zones (in pixels)
4 /// Minimum height for graph added in zones (in pixels)
5 extern const int GRAPH_MINIMUM_HEIGHT;
5 extern const int GRAPH_MINIMUM_HEIGHT;
6
6
7
7 #endif // SCIQLOP_VISUALIZATIONDEF_H
8 #endif // SCIQLOP_VISUALIZATIONDEF_H
@@ -1,57 +1,67
1 #ifndef SCIQLOP_SQPAPPLICATION_H
1 #ifndef SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
3
3
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5
5
6 #include <QApplication>
6 #include <QApplication>
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8
8
9 #include <Common/spimpl.h>
9 #include <Common/spimpl.h>
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
12
12
13 #if defined(sqpApp)
13 #if defined(sqpApp)
14 #undef sqpApp
14 #undef sqpApp
15 #endif
15 #endif
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
17
17
18 class DataSourceController;
18 class DataSourceController;
19 class NetworkController;
19 class NetworkController;
20 class TimeController;
20 class TimeController;
21 class VariableController;
21 class VariableController;
22 class VisualizationController;
22 class VisualizationController;
23 class DragDropHelper;
23 class DragDropHelper;
24
24
25 /**
25 /**
26 * @brief The SqpApplication class aims to make the link between SciQlop
26 * @brief The SqpApplication class aims to make the link between SciQlop
27 * and its plugins. This is the intermediate class that SciQlop has to use
27 * and its plugins. This is the intermediate class that SciQlop has to use
28 * in the way to connect a data source. Please first use load method to initialize
28 * in the way to connect a data source. Please first use load method to initialize
29 * a plugin specified by its metadata name (JSON plugin source) then others specifics
29 * a plugin specified by its metadata name (JSON plugin source) then others specifics
30 * method will be able to access it.
30 * method will be able to access it.
31 * You can load a data source driver plugin then create a data source.
31 * You can load a data source driver plugin then create a data source.
32 */
32 */
33
33
34 class SqpApplication : public QApplication {
34 class SqpApplication : public QApplication {
35 Q_OBJECT
35 Q_OBJECT
36 public:
36 public:
37 explicit SqpApplication(int &argc, char **argv);
37 explicit SqpApplication(int &argc, char **argv);
38 virtual ~SqpApplication();
38 virtual ~SqpApplication();
39 void initialize();
39 void initialize();
40
40
41 /// Accessors for the differents sciqlop controllers
41 /// Accessors for the differents sciqlop controllers
42 DataSourceController &dataSourceController() noexcept;
42 DataSourceController &dataSourceController() noexcept;
43 NetworkController &networkController() noexcept;
43 NetworkController &networkController() noexcept;
44 TimeController &timeController() noexcept;
44 TimeController &timeController() noexcept;
45 VariableController &variableController() noexcept;
45 VariableController &variableController() noexcept;
46 VisualizationController &visualizationController() noexcept;
46 VisualizationController &visualizationController() noexcept;
47
47
48 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
48 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
49 /// doesn't live in a thread and access gui
49 /// doesn't live in a thread and access gui
50 DragDropHelper &dragDropHelper() noexcept;
50 DragDropHelper &dragDropHelper() noexcept;
51
51
52 enum class PlotsInteractionMode { None, ZoomBox, DragAndDrop, SelectionZones };
53
54 enum class PlotsCursorMode { NoCursor, Vertical, Temporal, Horizontal, Cross };
55
56 PlotsInteractionMode plotsInteractionMode() const;
57 void setPlotsInteractionMode(PlotsInteractionMode mode);
58
59 PlotsCursorMode plotsCursorMode() const;
60 void setPlotsCursorMode(PlotsCursorMode mode);
61
52 private:
62 private:
53 class SqpApplicationPrivate;
63 class SqpApplicationPrivate;
54 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
64 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
55 };
65 };
56
66
57 #endif // SCIQLOP_SQPAPPLICATION_H
67 #endif // SCIQLOP_SQPAPPLICATION_H
@@ -1,109 +1,121
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
15
15
16 class QCPRange;
16 class QCPRange;
17 class QCustomPlot;
17 class QCustomPlot;
18 class SqpRange;
18 class SqpRange;
19 class Variable;
19 class Variable;
20 class VisualizationZoneWidget;
20 class VisualizationZoneWidget;
21
21
22 namespace Ui {
22 namespace Ui {
23 class VisualizationGraphWidget;
23 class VisualizationGraphWidget;
24 } // namespace Ui
24 } // namespace Ui
25
25
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
27 Q_OBJECT
27 Q_OBJECT
28
28
29 friend class QCustomPlotSynchronizer;
29 friend class QCustomPlotSynchronizer;
30 friend class VisualizationGraphRenderingDelegate;
30 friend class VisualizationGraphRenderingDelegate;
31
31
32 public:
32 public:
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
34 virtual ~VisualizationGraphWidget();
34 virtual ~VisualizationGraphWidget();
35
35
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
37
37
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
39 void enableAcquisition(bool enable);
39 void enableAcquisition(bool enable);
40
40
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
42
42
43 /// Removes a variable from the graph
43 /// Removes a variable from the graph
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /// Returns the list of all variables used in the graph
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable> > variables() const;
47 QList<std::shared_ptr<Variable> > variables() const;
48
48
49 /// Sets the y-axis range based on the data of a variable
49 /// Sets the y-axis range based on the data of a variable
50 void setYRange(std::shared_ptr<Variable> variable);
50 void setYRange(std::shared_ptr<Variable> variable);
51 SqpRange graphRange() const noexcept;
51 SqpRange graphRange() const noexcept;
52 void setGraphRange(const SqpRange &range);
52 void setGraphRange(const SqpRange &range);
53
53
54 // IVisualizationWidget interface
54 // IVisualizationWidget interface
55 void accept(IVisualizationWidgetVisitor *visitor) override;
55 void accept(IVisualizationWidgetVisitor *visitor) override;
56 bool canDrop(const Variable &variable) const override;
56 bool canDrop(const Variable &variable) const override;
57 bool contains(const Variable &variable) const override;
57 bool contains(const Variable &variable) const override;
58 QString name() const override;
58 QString name() const override;
59
59
60 // VisualisationDragWidget
60 // VisualisationDragWidget
61 QMimeData *mimeData() const override;
61 QMimeData *mimeData() const override;
62 bool isDragAllowed() const override;
62 bool isDragAllowed() const override;
63 void highlightForMerge(bool highlighted) override;
63 void highlightForMerge(bool highlighted) override;
64
64
65 // Cursors
66 /// Adds or moves the vertical cursor at the specified value on the x-axis
67 void addVerticalCursor(double time);
68 /// Adds or moves the vertical cursor at the specified value on the x-axis
69 void addVerticalCursorAtViewportPosition(double position);
70 void removeVerticalCursor();
71 /// Adds or moves the vertical cursor at the specified value on the y-axis
72 void addHorizontalCursor(double value);
73 /// Adds or moves the vertical cursor at the specified value on the y-axis
74 void addHorizontalCursorAtViewportPosition(double position);
75 void removeHorizontalCursor();
76
65 signals:
77 signals:
66 void synchronize(const SqpRange &range, const SqpRange &oldRange);
78 void synchronize(const SqpRange &range, const SqpRange &oldRange);
67 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
79 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
68 bool synchronise);
80 bool synchronise);
69
81
70 /// Signal emitted when the variable is about to be removed from the graph
82 /// Signal emitted when the variable is about to be removed from the graph
71 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
83 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
72 /// Signal emitted when the variable has been added to the graph
84 /// Signal emitted when the variable has been added to the graph
73 void variableAdded(std::shared_ptr<Variable> var);
85 void variableAdded(std::shared_ptr<Variable> var);
74
86
75 protected:
87 protected:
76 void closeEvent(QCloseEvent *event) override;
88 void closeEvent(QCloseEvent *event) override;
77 void enterEvent(QEvent *event) override;
89 void enterEvent(QEvent *event) override;
78 void leaveEvent(QEvent *event) override;
90 void leaveEvent(QEvent *event) override;
79
91
80 QCustomPlot &plot() noexcept;
92 QCustomPlot &plot() noexcept;
81
93
82 private:
94 private:
83 Ui::VisualizationGraphWidget *ui;
95 Ui::VisualizationGraphWidget *ui;
84
96
85 class VisualizationGraphWidgetPrivate;
97 class VisualizationGraphWidgetPrivate;
86 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
98 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
87
99
88 private slots:
100 private slots:
89 /// Slot called when right clicking on the graph (displays a menu)
101 /// Slot called when right clicking on the graph (displays a menu)
90 void onGraphMenuRequested(const QPoint &pos) noexcept;
102 void onGraphMenuRequested(const QPoint &pos) noexcept;
91
103
92 /// Rescale the X axe to range parameter
104 /// Rescale the X axe to range parameter
93 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
105 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
94
106
95 /// Slot called when a mouse move was made
107 /// Slot called when a mouse move was made
96 void onMouseMove(QMouseEvent *event) noexcept;
108 void onMouseMove(QMouseEvent *event) noexcept;
97 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
109 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
98 void onMouseWheel(QWheelEvent *event) noexcept;
110 void onMouseWheel(QWheelEvent *event) noexcept;
99 /// Slot called when a mouse press was made, to activate the calibration of a graph
111 /// Slot called when a mouse press was made, to activate the calibration of a graph
100 void onMousePress(QMouseEvent *event) noexcept;
112 void onMousePress(QMouseEvent *event) noexcept;
101 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
113 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
102 void onMouseRelease(QMouseEvent *event) noexcept;
114 void onMouseRelease(QMouseEvent *event) noexcept;
103
115
104 void onDataCacheVariableUpdated();
116 void onDataCacheVariableUpdated();
105
117
106 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
118 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
107 };
119 };
108
120
109 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
121 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,91 +1,95
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
15
15
16 namespace Ui {
16 namespace Ui {
17 class VisualizationZoneWidget;
17 class VisualizationZoneWidget;
18 } // namespace Ui
18 } // namespace Ui
19
19
20 class Variable;
20 class Variable;
21 class VisualizationGraphWidget;
21 class VisualizationGraphWidget;
22
22
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
24 Q_OBJECT
24 Q_OBJECT
25
25
26 public:
26 public:
27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
28 virtual ~VisualizationZoneWidget();
28 virtual ~VisualizationZoneWidget();
29
29
30 /// Adds a graph widget
30 /// Adds a graph widget
31 void addGraph(VisualizationGraphWidget *graphWidget);
31 void addGraph(VisualizationGraphWidget *graphWidget);
32
32
33 /// Inserts a graph widget
33 /// Inserts a graph widget
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
35
35
36 /**
36 /**
37 * Creates a graph using a variable. The variable will be displayed in the new graph.
37 * Creates a graph using a variable. The variable will be displayed in the new graph.
38 * The graph is added at the end.
38 * The graph is added at the end.
39 * @param variable the variable for which to create the graph
39 * @param variable the variable for which to create the graph
40 * @return the pointer to the created graph
40 * @return the pointer to the created graph
41 */
41 */
42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
43
43
44 /**
44 /**
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
46 * The graph is inserted at the specified index.
46 * The graph is inserted at the specified index.
47 * @param variable the variable for which to create the graph
47 * @param variable the variable for which to create the graph
48 * @param index The index where the graph should be inserted in the layout
48 * @param index The index where the graph should be inserted in the layout
49 * @return the pointer to the created graph
49 * @return the pointer to the created graph
50 */
50 */
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
52
52
53 /**
53 /**
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
55 * The graph is inserted at the specified index.
55 * The graph is inserted at the specified index.
56 * @param variables List of variables to be added to the graph
56 * @param variables List of variables to be added to the graph
57 * @param index The index where the graph should be inserted in the layout
57 * @param index The index where the graph should be inserted in the layout
58 * @return the pointer to the created graph
58 * @return the pointer to the created graph
59 */
59 */
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
61 int index);
61 int index);
62
62
63 // IVisualizationWidget interface
63 // IVisualizationWidget interface
64 void accept(IVisualizationWidgetVisitor *visitor) override;
64 void accept(IVisualizationWidgetVisitor *visitor) override;
65 bool canDrop(const Variable &variable) const override;
65 bool canDrop(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
67 QString name() const override;
67 QString name() const override;
68
68
69 // VisualisationDragWidget
69 // VisualisationDragWidget
70 QMimeData *mimeData() const override;
70 QMimeData *mimeData() const override;
71 bool isDragAllowed() const override;
71 bool isDragAllowed() const override;
72
72
73 void notifyMouseMoveInGraph(const QPointF &graphPosition, const QPointF &plotPosition,
74 VisualizationGraphWidget *graphWidget);
75 void notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget);
76
73 protected:
77 protected:
74 void closeEvent(QCloseEvent *event) override;
78 void closeEvent(QCloseEvent *event) override;
75
79
76 private:
80 private:
77 Ui::VisualizationZoneWidget *ui;
81 Ui::VisualizationZoneWidget *ui;
78
82
79 class VisualizationZoneWidgetPrivate;
83 class VisualizationZoneWidgetPrivate;
80 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
84 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
81
85
82 private slots:
86 private slots:
83 void onVariableAdded(std::shared_ptr<Variable> variable);
87 void onVariableAdded(std::shared_ptr<Variable> variable);
84 /// Slot called when a variable is about to be removed from a graph contained in the zone
88 /// Slot called when a variable is about to be removed from a graph contained in the zone
85 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
89 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
86
90
87 void dropMimeData(int index, const QMimeData *mimeData);
91 void dropMimeData(int index, const QMimeData *mimeData);
88 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
92 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
89 };
93 };
90
94
91 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
95 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,95 +1,96
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/Settings/SqpSettingsDialog.h',
4 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/SidePane/SqpSidePane.h',
6 'include/SidePane/SqpSidePane.h',
7 'include/SqpApplication.h',
7 'include/SqpApplication.h',
8 'include/DragAndDrop/DragDropScroller.h',
8 'include/DragAndDrop/DragDropScroller.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
10 'include/TimeWidget/TimeWidget.h',
10 'include/TimeWidget/TimeWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
12 'include/Variable/RenameVariableDialog.h',
12 'include/Variable/RenameVariableDialog.h',
13 'include/Visualization/qcustomplot.h',
13 'include/Visualization/qcustomplot.h',
14 'include/Visualization/VisualizationGraphWidget.h',
14 'include/Visualization/VisualizationGraphWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
16 'include/Visualization/VisualizationWidget.h',
16 'include/Visualization/VisualizationWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
19 'include/Visualization/VisualizationDragWidget.h'
19 'include/Visualization/VisualizationDragWidget.h'
20 ]
20 ]
21
21
22 gui_ui_files = [
22 gui_ui_files = [
23 'ui/DataSource/DataSourceWidget.ui',
23 'ui/DataSource/DataSourceWidget.ui',
24 'ui/Settings/SqpSettingsDialog.ui',
24 'ui/Settings/SqpSettingsDialog.ui',
25 'ui/Settings/SqpSettingsGeneralWidget.ui',
25 'ui/Settings/SqpSettingsGeneralWidget.ui',
26 'ui/SidePane/SqpSidePane.ui',
26 'ui/SidePane/SqpSidePane.ui',
27 'ui/TimeWidget/TimeWidget.ui',
27 'ui/TimeWidget/TimeWidget.ui',
28 'ui/Variable/VariableInspectorWidget.ui',
28 'ui/Variable/VariableInspectorWidget.ui',
29 'ui/Variable/RenameVariableDialog.ui',
29 'ui/Variable/RenameVariableDialog.ui',
30 'ui/Variable/VariableMenuHeaderWidget.ui',
30 'ui/Variable/VariableMenuHeaderWidget.ui',
31 'ui/Visualization/VisualizationGraphWidget.ui',
31 'ui/Visualization/VisualizationGraphWidget.ui',
32 'ui/Visualization/VisualizationTabWidget.ui',
32 'ui/Visualization/VisualizationTabWidget.ui',
33 'ui/Visualization/VisualizationWidget.ui',
33 'ui/Visualization/VisualizationWidget.ui',
34 'ui/Visualization/VisualizationZoneWidget.ui'
34 'ui/Visualization/VisualizationZoneWidget.ui'
35 ]
35 ]
36
36
37 gui_qresources = ['resources/sqpguiresources.qrc']
37 gui_qresources = ['resources/sqpguiresources.qrc']
38
38
39 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
39 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
40 ui_files : gui_ui_files,
40 ui_files : gui_ui_files,
41 qresources : gui_qresources)
41 qresources : gui_qresources)
42
42
43 gui_sources = [
43 gui_sources = [
44 'src/SqpApplication.cpp',
44 'src/SqpApplication.cpp',
45 'src/DragAndDrop/DragDropHelper.cpp',
45 'src/DragAndDrop/DragDropHelper.cpp',
46 'src/DragAndDrop/DragDropScroller.cpp',
46 'src/DragAndDrop/DragDropScroller.cpp',
47 'src/DragAndDrop/DragDropTabSwitcher.cpp',
47 'src/DragAndDrop/DragDropTabSwitcher.cpp',
48 'src/Common/ColorUtils.cpp',
48 'src/Common/ColorUtils.cpp',
49 'src/Common/VisualizationDef.cpp',
49 'src/Common/VisualizationDef.cpp',
50 'src/DataSource/DataSourceTreeWidgetItem.cpp',
50 'src/DataSource/DataSourceTreeWidgetItem.cpp',
51 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
51 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
52 'src/DataSource/DataSourceWidget.cpp',
52 'src/DataSource/DataSourceWidget.cpp',
53 'src/DataSource/DataSourceTreeWidget.cpp',
53 'src/DataSource/DataSourceTreeWidget.cpp',
54 'src/Settings/SqpSettingsDialog.cpp',
54 'src/Settings/SqpSettingsDialog.cpp',
55 'src/Settings/SqpSettingsGeneralWidget.cpp',
55 'src/Settings/SqpSettingsGeneralWidget.cpp',
56 'src/SidePane/SqpSidePane.cpp',
56 'src/SidePane/SqpSidePane.cpp',
57 'src/TimeWidget/TimeWidget.cpp',
57 'src/TimeWidget/TimeWidget.cpp',
58 'src/Variable/VariableInspectorWidget.cpp',
58 'src/Variable/VariableInspectorWidget.cpp',
59 'src/Variable/VariableInspectorTableView.cpp',
59 'src/Variable/VariableInspectorTableView.cpp',
60 'src/Variable/VariableMenuHeaderWidget.cpp',
60 'src/Variable/VariableMenuHeaderWidget.cpp',
61 'src/Variable/RenameVariableDialog.cpp',
61 'src/Variable/RenameVariableDialog.cpp',
62 'src/Visualization/VisualizationGraphHelper.cpp',
62 'src/Visualization/VisualizationGraphHelper.cpp',
63 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
63 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
64 'src/Visualization/VisualizationGraphWidget.cpp',
64 'src/Visualization/VisualizationGraphWidget.cpp',
65 'src/Visualization/VisualizationTabWidget.cpp',
65 'src/Visualization/VisualizationTabWidget.cpp',
66 'src/Visualization/VisualizationWidget.cpp',
66 'src/Visualization/VisualizationWidget.cpp',
67 'src/Visualization/VisualizationZoneWidget.cpp',
67 'src/Visualization/VisualizationZoneWidget.cpp',
68 'src/Visualization/qcustomplot.cpp',
68 'src/Visualization/qcustomplot.cpp',
69 'src/Visualization/QCustomPlotSynchronizer.cpp',
69 'src/Visualization/QCustomPlotSynchronizer.cpp',
70 'src/Visualization/operations/FindVariableOperation.cpp',
70 'src/Visualization/operations/FindVariableOperation.cpp',
71 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
71 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
72 'src/Visualization/operations/MenuBuilder.cpp',
72 'src/Visualization/operations/MenuBuilder.cpp',
73 'src/Visualization/operations/RemoveVariableOperation.cpp',
73 'src/Visualization/operations/RemoveVariableOperation.cpp',
74 'src/Visualization/operations/RescaleAxeOperation.cpp',
74 'src/Visualization/operations/RescaleAxeOperation.cpp',
75 'src/Visualization/VisualizationDragDropContainer.cpp',
75 'src/Visualization/VisualizationDragDropContainer.cpp',
76 'src/Visualization/VisualizationDragWidget.cpp',
76 'src/Visualization/VisualizationDragWidget.cpp',
77 'src/Visualization/AxisRenderingUtils.cpp',
77 'src/Visualization/AxisRenderingUtils.cpp',
78 'src/Visualization/PlottablesRenderingUtils.cpp',
78 'src/Visualization/PlottablesRenderingUtils.cpp',
79 'src/Visualization/MacScrollBarStyle.cpp'
79 'src/Visualization/MacScrollBarStyle.cpp',
80 'src/Visualization/VisualizationCursorItem.cpp'
80 ]
81 ]
81
82
82 gui_inc = include_directories(['include'])
83 gui_inc = include_directories(['include'])
83
84
84 sciqlop_gui_lib = library('sciqlopgui',
85 sciqlop_gui_lib = library('sciqlopgui',
85 gui_sources,
86 gui_sources,
86 gui_moc_files,
87 gui_moc_files,
87 include_directories : [gui_inc],
88 include_directories : [gui_inc],
88 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
89 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
89 install : true
90 install : true
90 )
91 )
91
92
92 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
93 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
93 include_directories : gui_inc,
94 include_directories : gui_inc,
94 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
95 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
95
96
1 NO CONTENT: modified file, binary diff hidden
NO CONTENT: modified file, binary diff hidden
@@ -1,17 +1,22
1 <RCC>
1 <RCC>
2 <qresource prefix="/">
2 <qresource prefix="/">
3 <file>icones/dataSourceComponent.png</file>
3 <file>icones/dataSourceComponent.png</file>
4 <file>icones/dataSourceNode.png</file>
4 <file>icones/dataSourceNode.png</file>
5 <file>icones/dataSourceProduct.png</file>
5 <file>icones/dataSourceProduct.png</file>
6 <file>icones/dataSourceRoot.png</file>
6 <file>icones/dataSourceRoot.png</file>
7 <file>icones/delete.png</file>
7 <file>icones/delete.png</file>
8 <file>icones/down.png</file>
8 <file>icones/down.png</file>
9 <file>icones/openInspector.png</file>
9 <file>icones/openInspector.png</file>
10 <file>icones/next.png</file>
10 <file>icones/next.png</file>
11 <file>icones/plot.png</file>
11 <file>icones/plot.png</file>
12 <file>icones/previous.png</file>
12 <file>icones/previous.png</file>
13 <file>icones/unplot.png</file>
13 <file>icones/unplot.png</file>
14 <file>icones/up.png</file>
14 <file>icones/up.png</file>
15 <file>icones/time.png</file>
15 <file>icones/time.png</file>
16 <file>icones/zoom.png</file>
17 <file>icones/rectangle.png</file>
18 <file>icones/drag.png</file>
19 <file>icones/cursor.png</file>
20 <file>icones/pointer.png</file>
16 </qresource>
21 </qresource>
17 </RCC>
22 </RCC>
@@ -1,163 +1,188
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Data/IDataProvider.h>
3 #include <Data/IDataProvider.h>
4 #include <DataSource/DataSourceController.h>
4 #include <DataSource/DataSourceController.h>
5 #include <DragAndDrop/DragDropHelper.h>
5 #include <DragAndDrop/DragDropHelper.h>
6 #include <Network/NetworkController.h>
6 #include <Network/NetworkController.h>
7 #include <QThread>
7 #include <QThread>
8 #include <Time/TimeController.h>
8 #include <Time/TimeController.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11 #include <Variable/VariableModel.h>
11 #include <Variable/VariableModel.h>
12 #include <Visualization/VisualizationController.h>
12 #include <Visualization/VisualizationController.h>
13
13
14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
15
15
16 class SqpApplication::SqpApplicationPrivate {
16 class SqpApplication::SqpApplicationPrivate {
17 public:
17 public:
18 SqpApplicationPrivate()
18 SqpApplicationPrivate()
19 : m_DataSourceController{std::make_unique<DataSourceController>()},
19 : m_DataSourceController{std::make_unique<DataSourceController>()},
20 m_VariableController{std::make_unique<VariableController>()},
20 m_VariableController{std::make_unique<VariableController>()},
21 m_TimeController{std::make_unique<TimeController>()},
21 m_TimeController{std::make_unique<TimeController>()},
22 m_NetworkController{std::make_unique<NetworkController>()},
22 m_NetworkController{std::make_unique<NetworkController>()},
23 m_VisualizationController{std::make_unique<VisualizationController>()},
23 m_VisualizationController{std::make_unique<VisualizationController>()},
24 m_DragDropHelper{std::make_unique<DragDropHelper>()}
24 m_DragDropHelper{std::make_unique<DragDropHelper>()},
25 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
26 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
25 {
27 {
26 // /////////////////////////////// //
28 // /////////////////////////////// //
27 // Connections between controllers //
29 // Connections between controllers //
28 // /////////////////////////////// //
30 // /////////////////////////////// //
29
31
30 // VariableController <-> DataSourceController
32 // VariableController <-> DataSourceController
31 connect(m_DataSourceController.get(),
33 connect(m_DataSourceController.get(),
32 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
34 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)),
35 std::shared_ptr<IDataProvider>)),
34 m_VariableController.get(),
36 m_VariableController.get(),
35 SLOT(createVariable(const QString &, const QVariantHash &,
37 SLOT(createVariable(const QString &, const QVariantHash &,
36 std::shared_ptr<IDataProvider>)));
38 std::shared_ptr<IDataProvider>)));
37
39
38 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
40 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
39 m_DataSourceController.get(), &DataSourceController::requestVariable);
41 m_DataSourceController.get(), &DataSourceController::requestVariable);
40
42
41 // VariableController <-> VisualizationController
43 // VariableController <-> VisualizationController
42 connect(m_VariableController.get(),
44 connect(m_VariableController.get(),
43 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
45 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
44 m_VisualizationController.get(),
46 m_VisualizationController.get(),
45 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
47 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
46
48
47 connect(m_VariableController.get(),
49 connect(m_VariableController.get(),
48 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
50 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
49 m_VisualizationController.get(),
51 m_VisualizationController.get(),
50 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
52 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
51
53
52
54
53 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
55 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
54 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
56 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
55 m_NetworkController->moveToThread(&m_NetworkControllerThread);
57 m_NetworkController->moveToThread(&m_NetworkControllerThread);
56 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
58 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
57 m_VariableController->moveToThread(&m_VariableControllerThread);
59 m_VariableController->moveToThread(&m_VariableControllerThread);
58 m_VariableControllerThread.setObjectName("VariableControllerThread");
60 m_VariableControllerThread.setObjectName("VariableControllerThread");
59 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
61 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
60 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
62 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
61
63
62
64
63 // Additionnal init
65 // Additionnal init
64 m_VariableController->setTimeController(m_TimeController.get());
66 m_VariableController->setTimeController(m_TimeController.get());
65 }
67 }
66
68
67 virtual ~SqpApplicationPrivate()
69 virtual ~SqpApplicationPrivate()
68 {
70 {
69 m_DataSourceControllerThread.quit();
71 m_DataSourceControllerThread.quit();
70 m_DataSourceControllerThread.wait();
72 m_DataSourceControllerThread.wait();
71
73
72 m_NetworkControllerThread.quit();
74 m_NetworkControllerThread.quit();
73 m_NetworkControllerThread.wait();
75 m_NetworkControllerThread.wait();
74
76
75 m_VariableControllerThread.quit();
77 m_VariableControllerThread.quit();
76 m_VariableControllerThread.wait();
78 m_VariableControllerThread.wait();
77
79
78 m_VisualizationControllerThread.quit();
80 m_VisualizationControllerThread.quit();
79 m_VisualizationControllerThread.wait();
81 m_VisualizationControllerThread.wait();
80 }
82 }
81
83
82 std::unique_ptr<DataSourceController> m_DataSourceController;
84 std::unique_ptr<DataSourceController> m_DataSourceController;
83 std::unique_ptr<VariableController> m_VariableController;
85 std::unique_ptr<VariableController> m_VariableController;
84 std::unique_ptr<TimeController> m_TimeController;
86 std::unique_ptr<TimeController> m_TimeController;
85 std::unique_ptr<NetworkController> m_NetworkController;
87 std::unique_ptr<NetworkController> m_NetworkController;
86 std::unique_ptr<VisualizationController> m_VisualizationController;
88 std::unique_ptr<VisualizationController> m_VisualizationController;
87 QThread m_DataSourceControllerThread;
89 QThread m_DataSourceControllerThread;
88 QThread m_NetworkControllerThread;
90 QThread m_NetworkControllerThread;
89 QThread m_VariableControllerThread;
91 QThread m_VariableControllerThread;
90 QThread m_VisualizationControllerThread;
92 QThread m_VisualizationControllerThread;
91
93
92 std::unique_ptr<DragDropHelper> m_DragDropHelper;
94 std::unique_ptr<DragDropHelper> m_DragDropHelper;
95
96 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
97 SqpApplication::PlotsCursorMode m_PlotCursorMode;
93 };
98 };
94
99
95
100
96 SqpApplication::SqpApplication(int &argc, char **argv)
101 SqpApplication::SqpApplication(int &argc, char **argv)
97 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
102 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
98 {
103 {
99 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
104 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
100
105
101 connect(&impl->m_DataSourceControllerThread, &QThread::started,
106 connect(&impl->m_DataSourceControllerThread, &QThread::started,
102 impl->m_DataSourceController.get(), &DataSourceController::initialize);
107 impl->m_DataSourceController.get(), &DataSourceController::initialize);
103 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
108 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
104 impl->m_DataSourceController.get(), &DataSourceController::finalize);
109 impl->m_DataSourceController.get(), &DataSourceController::finalize);
105
110
106 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
111 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
107 &NetworkController::initialize);
112 &NetworkController::initialize);
108 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
113 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
109 &NetworkController::finalize);
114 &NetworkController::finalize);
110
115
111 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
116 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
112 &VariableController::initialize);
117 &VariableController::initialize);
113 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
118 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
114 &VariableController::finalize);
119 &VariableController::finalize);
115
120
116 connect(&impl->m_VisualizationControllerThread, &QThread::started,
121 connect(&impl->m_VisualizationControllerThread, &QThread::started,
117 impl->m_VisualizationController.get(), &VisualizationController::initialize);
122 impl->m_VisualizationController.get(), &VisualizationController::initialize);
118 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
123 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
119 impl->m_VisualizationController.get(), &VisualizationController::finalize);
124 impl->m_VisualizationController.get(), &VisualizationController::finalize);
120
125
121 impl->m_DataSourceControllerThread.start();
126 impl->m_DataSourceControllerThread.start();
122 impl->m_NetworkControllerThread.start();
127 impl->m_NetworkControllerThread.start();
123 impl->m_VariableControllerThread.start();
128 impl->m_VariableControllerThread.start();
124 impl->m_VisualizationControllerThread.start();
129 impl->m_VisualizationControllerThread.start();
125 }
130 }
126
131
127 SqpApplication::~SqpApplication()
132 SqpApplication::~SqpApplication()
128 {
133 {
129 }
134 }
130
135
131 void SqpApplication::initialize()
136 void SqpApplication::initialize()
132 {
137 {
133 }
138 }
134
139
135 DataSourceController &SqpApplication::dataSourceController() noexcept
140 DataSourceController &SqpApplication::dataSourceController() noexcept
136 {
141 {
137 return *impl->m_DataSourceController;
142 return *impl->m_DataSourceController;
138 }
143 }
139
144
140 NetworkController &SqpApplication::networkController() noexcept
145 NetworkController &SqpApplication::networkController() noexcept
141 {
146 {
142 return *impl->m_NetworkController;
147 return *impl->m_NetworkController;
143 }
148 }
144
149
145 TimeController &SqpApplication::timeController() noexcept
150 TimeController &SqpApplication::timeController() noexcept
146 {
151 {
147 return *impl->m_TimeController;
152 return *impl->m_TimeController;
148 }
153 }
149
154
150 VariableController &SqpApplication::variableController() noexcept
155 VariableController &SqpApplication::variableController() noexcept
151 {
156 {
152 return *impl->m_VariableController;
157 return *impl->m_VariableController;
153 }
158 }
154
159
155 VisualizationController &SqpApplication::visualizationController() noexcept
160 VisualizationController &SqpApplication::visualizationController() noexcept
156 {
161 {
157 return *impl->m_VisualizationController;
162 return *impl->m_VisualizationController;
158 }
163 }
159
164
160 DragDropHelper &SqpApplication::dragDropHelper() noexcept
165 DragDropHelper &SqpApplication::dragDropHelper() noexcept
161 {
166 {
162 return *impl->m_DragDropHelper;
167 return *impl->m_DragDropHelper;
163 }
168 }
169
170 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
171 {
172 return impl->m_PlotInterractionMode;
173 }
174
175 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
176 {
177 impl->m_PlotInterractionMode = mode;
178 }
179
180 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
181 {
182 return impl->m_PlotCursorMode;
183 }
184
185 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
186 {
187 impl->m_PlotCursorMode = mode;
188 }
@@ -1,472 +1,473
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
18
18
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
20
20
21 QVBoxLayout *m_Layout;
21 QVBoxLayout *m_Layout;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
23 QString m_PlaceHolderText;
23 QString m_PlaceHolderText;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType;
25
25
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
27 = [](auto mimeData) { return true; };
27 = [](auto mimeData) { return true; };
28
28
29 int m_MinContainerHeight = 0;
29 int m_MinContainerHeight = 0;
30
30
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
31 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
32 : m_PlaceHolderType(DragDropHelper::PlaceHolderType::Graph)
32 {
33 {
33 m_Layout = new QVBoxLayout(widget);
34 m_Layout = new QVBoxLayout(widget);
34 m_Layout->setContentsMargins(0, 0, 0, 0);
35 m_Layout->setContentsMargins(0, 0, 0, 0);
35 }
36 }
36
37
37 bool acceptMimeData(const QMimeData *data) const
38 bool acceptMimeData(const QMimeData *data) const
38 {
39 {
39 auto accepted = false;
40 auto accepted = false;
40 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
41 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
41 ++it) {
42 ++it) {
42 const auto &type = it.key();
43 const auto &type = it.key();
43 const auto &behavior = it.value();
44 const auto &behavior = it.value();
44
45
45 if (data->hasFormat(type)) {
46 if (data->hasFormat(type)) {
46 if (behavior != DropBehavior::Forbidden) {
47 if (behavior != DropBehavior::Forbidden) {
47 accepted = true;
48 accepted = true;
48 }
49 }
49 else {
50 else {
50 accepted = false;
51 accepted = false;
51 break;
52 break;
52 }
53 }
53 }
54 }
54 }
55 }
55
56
56 if (accepted) {
57 if (accepted) {
57 accepted = m_AcceptMimeDataFun(data);
58 accepted = m_AcceptMimeDataFun(data);
58 }
59 }
59
60
60 return accepted;
61 return accepted;
61 }
62 }
62
63
63 bool allowMergeForMimeData(const QMimeData *data) const
64 bool allowMergeForMimeData(const QMimeData *data) const
64 {
65 {
65 auto result = false;
66 auto result = false;
66 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
67 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
67 ++it) {
68 ++it) {
68
69
69 if (data->hasFormat(it.key())
70 if (data->hasFormat(it.key())
70 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
71 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
71 || it.value()
72 || it.value()
72 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
73 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
73 result = true;
74 result = true;
74 }
75 }
75 else if (data->hasFormat(it.key())
76 else if (data->hasFormat(it.key())
76 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
77 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
77 // Merge is forbidden if the mime data contain an acceptable type which cannot be
78 // Merge is forbidden if the mime data contain an acceptable type which cannot be
78 // merged
79 // merged
79 result = false;
80 result = false;
80 break;
81 break;
81 }
82 }
82 }
83 }
83
84
84 return result;
85 return result;
85 }
86 }
86
87
87 bool allowInsertForMimeData(const QMimeData *data) const
88 bool allowInsertForMimeData(const QMimeData *data) const
88 {
89 {
89 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
90 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
90 ++it) {
91 ++it) {
91 if (data->hasFormat(it.key())
92 if (data->hasFormat(it.key())
92 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
93 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
93 || it.value()
94 || it.value()
94 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
95 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
95 return true;
96 return true;
96 }
97 }
97 }
98 }
98
99
99 return false;
100 return false;
100 }
101 }
101
102
102 bool hasPlaceHolder() const
103 bool hasPlaceHolder() const
103 {
104 {
104 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
105 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
105 }
106 }
106
107
107 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
108 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
108 {
109 {
109 VisualizationDragWidget *dragWidget = nullptr;
110 VisualizationDragWidget *dragWidget = nullptr;
110
111
111 for (auto child : parent->children()) {
112 for (auto child : parent->children()) {
112 auto widget = qobject_cast<VisualizationDragWidget *>(child);
113 auto widget = qobject_cast<VisualizationDragWidget *>(child);
113 if (widget && widget->isVisible()) {
114 if (widget && widget->isVisible()) {
114 if (widget->frameGeometry().contains(pos)) {
115 if (widget->frameGeometry().contains(pos)) {
115 dragWidget = widget;
116 dragWidget = widget;
116 break;
117 break;
117 }
118 }
118 }
119 }
119 }
120 }
120
121
121 return dragWidget;
122 return dragWidget;
122 }
123 }
123
124
124 bool cursorIsInContainer(QWidget *container) const
125 bool cursorIsInContainer(QWidget *container) const
125 {
126 {
126 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
127 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
127 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
128 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
128 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
129 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
129 }
130 }
130
131
131 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
132 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
132 {
133 {
133 auto nbGraph = 0;
134 auto nbGraph = 0;
134 for (auto child : parent->children()) {
135 for (auto child : parent->children()) {
135 if (qobject_cast<VisualizationDragWidget *>(child)) {
136 if (qobject_cast<VisualizationDragWidget *>(child)) {
136 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
137 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
137 nbGraph += 1;
138 nbGraph += 1;
138 }
139 }
139 }
140 }
140 }
141 }
141
142
142 return nbGraph;
143 return nbGraph;
143 }
144 }
144
145
145 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
146 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
146 const VisualizationDragDropContainer *container);
147 const VisualizationDragDropContainer *container);
147 };
148 };
148
149
149 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
150 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
150 : QFrame{parent},
151 : QFrame{parent},
151 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
152 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
152 {
153 {
153 setAcceptDrops(true);
154 setAcceptDrops(true);
154 }
155 }
155
156
156 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
157 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
157 {
158 {
158 impl->m_Layout->addWidget(dragWidget);
159 impl->m_Layout->addWidget(dragWidget);
159 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
160 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
160 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
161 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
161 &VisualizationDragDropContainer::startDrag);
162 &VisualizationDragDropContainer::startDrag);
162 }
163 }
163
164
164 void VisualizationDragDropContainer::insertDragWidget(int index,
165 void VisualizationDragDropContainer::insertDragWidget(int index,
165 VisualizationDragWidget *dragWidget)
166 VisualizationDragWidget *dragWidget)
166 {
167 {
167 impl->m_Layout->insertWidget(index, dragWidget);
168 impl->m_Layout->insertWidget(index, dragWidget);
168 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
169 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
169 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
170 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
170 &VisualizationDragDropContainer::startDrag);
171 &VisualizationDragDropContainer::startDrag);
171 }
172 }
172
173
173 void VisualizationDragDropContainer::setMimeType(
174 void VisualizationDragDropContainer::setMimeType(
174 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
175 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
175 {
176 {
176 impl->m_AcceptedMimeTypes[mimeType] = behavior;
177 impl->m_AcceptedMimeTypes[mimeType] = behavior;
177 }
178 }
178
179
179 int VisualizationDragDropContainer::countDragWidget() const
180 int VisualizationDragDropContainer::countDragWidget() const
180 {
181 {
181 return impl->countDragWidget(this);
182 return impl->countDragWidget(this);
182 }
183 }
183
184
184 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
185 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
185 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
186 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
186 {
187 {
187 impl->m_AcceptMimeDataFun = fun;
188 impl->m_AcceptMimeDataFun = fun;
188 }
189 }
189
190
190 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
191 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
191 const QString &placeHolderText)
192 const QString &placeHolderText)
192 {
193 {
193 impl->m_PlaceHolderType = type;
194 impl->m_PlaceHolderType = type;
194 impl->m_PlaceHolderText = placeHolderText;
195 impl->m_PlaceHolderText = placeHolderText;
195 }
196 }
196
197
197 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
198 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
198 const QPoint &dragPosition)
199 const QPoint &dragPosition)
199 {
200 {
200 auto &helper = sqpApp->dragDropHelper();
201 auto &helper = sqpApp->dragDropHelper();
201 helper.resetDragAndDrop();
202 helper.resetDragAndDrop();
202
203
203 // Note: The management of the drag object is done by Qt
204 // Note: The management of the drag object is done by Qt
204 auto drag = new QDrag{dragWidget};
205 auto drag = new QDrag{dragWidget};
205
206
206 auto mimeData = dragWidget->mimeData();
207 auto mimeData = dragWidget->mimeData();
207 drag->setMimeData(mimeData);
208 drag->setMimeData(mimeData);
208
209
209 auto pixmap = QPixmap(dragWidget->size());
210 auto pixmap = QPixmap(dragWidget->size());
210 dragWidget->render(&pixmap);
211 dragWidget->render(&pixmap);
211 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
212 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
212 Qt::KeepAspectRatio, Qt::SmoothTransformation));
213 Qt::KeepAspectRatio, Qt::SmoothTransformation));
213
214
214 auto image = pixmap.toImage();
215 auto image = pixmap.toImage();
215 mimeData->setImageData(image);
216 mimeData->setImageData(image);
216 mimeData->setUrls({helper.imageTemporaryUrl(image)});
217 mimeData->setUrls({helper.imageTemporaryUrl(image)});
217
218
218 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
219 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
219 helper.setCurrentDragWidget(dragWidget);
220 helper.setCurrentDragWidget(dragWidget);
220
221
221 if (impl->cursorIsInContainer(this)) {
222 if (impl->cursorIsInContainer(this)) {
222 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
223 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
223 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
224 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
224 impl->m_PlaceHolderText);
225 impl->m_PlaceHolderText);
225 dragWidget->setVisible(false);
226 dragWidget->setVisible(false);
226 }
227 }
227 else {
228 else {
228 // The drag starts directly outside the drop zone
229 // The drag starts directly outside the drop zone
229 // do not add the placeHolder
230 // do not add the placeHolder
230 }
231 }
231
232
232 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
233 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
233
234
234 helper.doCloseWidgets();
235 helper.doCloseWidgets();
235 }
236 }
236 else {
237 else {
237 qCWarning(LOG_VisualizationDragDropContainer())
238 qCWarning(LOG_VisualizationDragDropContainer())
238 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
239 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
239 "VisualizationDragWidget is not found in this container.");
240 "VisualizationDragWidget is not found in this container.");
240 }
241 }
241 }
242 }
242
243
243 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
244 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
244 {
245 {
245 if (impl->acceptMimeData(event->mimeData())) {
246 if (impl->acceptMimeData(event->mimeData())) {
246 event->acceptProposedAction();
247 event->acceptProposedAction();
247
248
248 auto &helper = sqpApp->dragDropHelper();
249 auto &helper = sqpApp->dragDropHelper();
249
250
250 if (!impl->hasPlaceHolder()) {
251 if (!impl->hasPlaceHolder()) {
251 auto dragWidget = helper.getCurrentDragWidget();
252 auto dragWidget = helper.getCurrentDragWidget();
252
253
253 if (dragWidget) {
254 if (dragWidget) {
254 // If the drag&drop is internal to the visualization, entering the container hide
255 // If the drag&drop is internal to the visualization, entering the container hide
255 // the dragWidget which was made visible by the dragLeaveEvent
256 // the dragWidget which was made visible by the dragLeaveEvent
256 auto parentWidget
257 auto parentWidget
257 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
258 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
258 if (parentWidget) {
259 if (parentWidget) {
259 dragWidget->setVisible(false);
260 dragWidget->setVisible(false);
260 }
261 }
261 }
262 }
262
263
263 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
264 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
264 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
265 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
265 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
266 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
266 }
267 }
267 else {
268 else {
268 // do nothing
269 // do nothing
269 }
270 }
270 }
271 }
271 else {
272 else {
272 event->ignore();
273 event->ignore();
273 }
274 }
274
275
275 QWidget::dragEnterEvent(event);
276 QWidget::dragEnterEvent(event);
276 }
277 }
277
278
278 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
279 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
279 {
280 {
280 Q_UNUSED(event);
281 Q_UNUSED(event);
281
282
282 auto &helper = sqpApp->dragDropHelper();
283 auto &helper = sqpApp->dragDropHelper();
283
284
284 if (!impl->cursorIsInContainer(this)) {
285 if (!impl->cursorIsInContainer(this)) {
285 helper.removePlaceHolder();
286 helper.removePlaceHolder();
286 helper.setHightlightedDragWidget(nullptr);
287 helper.setHightlightedDragWidget(nullptr);
287 impl->m_MinContainerHeight = 0;
288 impl->m_MinContainerHeight = 0;
288
289
289 auto dragWidget = helper.getCurrentDragWidget();
290 auto dragWidget = helper.getCurrentDragWidget();
290 if (dragWidget) {
291 if (dragWidget) {
291 // dragWidget has a value only if the drag is started from the visualization
292 // dragWidget has a value only if the drag is started from the visualization
292 // In that case, shows the drag widget at its original place
293 // In that case, shows the drag widget at its original place
293 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
294 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
294 // drop zone (It is not possible to catch a drop event outside of the application)
295 // drop zone (It is not possible to catch a drop event outside of the application)
295
296
296 if (dragWidget) {
297 if (dragWidget) {
297 dragWidget->setVisible(true);
298 dragWidget->setVisible(true);
298 }
299 }
299 }
300 }
300 }
301 }
301 else {
302 else {
302 // Leave event probably received for a child widget.
303 // Leave event probably received for a child widget.
303 // Do nothing.
304 // Do nothing.
304 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
305 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
305 }
306 }
306
307
307 QWidget::dragLeaveEvent(event);
308 QWidget::dragLeaveEvent(event);
308 }
309 }
309
310
310 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
311 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
311 {
312 {
312 if (impl->acceptMimeData(event->mimeData())) {
313 if (impl->acceptMimeData(event->mimeData())) {
313 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
314 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
314 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
315 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
315 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
316 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
316 }
317 }
317 else {
318 else {
318 event->ignore();
319 event->ignore();
319 }
320 }
320
321
321 QWidget::dragMoveEvent(event);
322 QWidget::dragMoveEvent(event);
322 }
323 }
323
324
324 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
325 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
325 {
326 {
326 auto &helper = sqpApp->dragDropHelper();
327 auto &helper = sqpApp->dragDropHelper();
327
328
328 if (impl->acceptMimeData(event->mimeData())) {
329 if (impl->acceptMimeData(event->mimeData())) {
329 auto dragWidget = helper.getCurrentDragWidget();
330 auto dragWidget = helper.getCurrentDragWidget();
330 if (impl->hasPlaceHolder()) {
331 if (impl->hasPlaceHolder()) {
331 // drop where the placeHolder is located
332 // drop where the placeHolder is located
332
333
333 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
334 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
334 if (canInsert) {
335 if (canInsert) {
335 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
336 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
336
337
337 if (dragWidget) {
338 if (dragWidget) {
338 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
339 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
339 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
340 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
340 // Correction of the index if the drop occurs in the same container
341 // Correction of the index if the drop occurs in the same container
341 // and if the drag is started from the visualization (in that case, the
342 // and if the drag is started from the visualization (in that case, the
342 // dragWidget is hidden)
343 // dragWidget is hidden)
343 droppedIndex -= 1;
344 droppedIndex -= 1;
344 }
345 }
345
346
346 dragWidget->setVisible(true);
347 dragWidget->setVisible(true);
347 }
348 }
348
349
349 event->acceptProposedAction();
350 event->acceptProposedAction();
350
351
351 helper.removePlaceHolder();
352 helper.removePlaceHolder();
352
353
353 emit dropOccuredInContainer(droppedIndex, event->mimeData());
354 emit dropOccuredInContainer(droppedIndex, event->mimeData());
354 }
355 }
355 else {
356 else {
356 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
357 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
357 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
358 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
358 "the insertion is forbidden.");
359 "the insertion is forbidden.");
359 Q_ASSERT(false);
360 Q_ASSERT(false);
360 }
361 }
361 }
362 }
362 else if (helper.getHightlightedDragWidget()) {
363 else if (helper.getHightlightedDragWidget()) {
363 // drop on the highlighted widget
364 // drop on the highlighted widget
364
365
365 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
366 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
366 if (canMerge) {
367 if (canMerge) {
367 event->acceptProposedAction();
368 event->acceptProposedAction();
368 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
369 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
369 }
370 }
370 else {
371 else {
371 qCWarning(LOG_VisualizationDragDropContainer())
372 qCWarning(LOG_VisualizationDragDropContainer())
372 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
373 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
373 "the merge is forbidden.");
374 "the merge is forbidden.");
374 Q_ASSERT(false);
375 Q_ASSERT(false);
375 }
376 }
376 }
377 }
377 }
378 }
378 else {
379 else {
379 event->ignore();
380 event->ignore();
380 }
381 }
381
382
382 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
383 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
383 impl->m_MinContainerHeight = 0;
384 impl->m_MinContainerHeight = 0;
384
385
385 QWidget::dropEvent(event);
386 QWidget::dropEvent(event);
386 }
387 }
387
388
388
389
389 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
390 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
390 const QPoint &pos, bool canInsert, bool canMerge,
391 const QPoint &pos, bool canInsert, bool canMerge,
391 const VisualizationDragDropContainer *container)
392 const VisualizationDragDropContainer *container)
392 {
393 {
393 auto &helper = sqpApp->dragDropHelper();
394 auto &helper = sqpApp->dragDropHelper();
394
395
395 auto absPos = container->mapToGlobal(pos);
396 auto absPos = container->mapToGlobal(pos);
396 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
397 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
397
398
398 if (countDragWidget(container, true) == 0) {
399 if (countDragWidget(container, true) == 0) {
399 // Drop on an empty container, just add the placeHolder at the top
400 // Drop on an empty container, just add the placeHolder at the top
400 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
401 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
401 }
402 }
402 else if (!isOnPlaceHolder) {
403 else if (!isOnPlaceHolder) {
403 auto nbDragWidget = countDragWidget(container);
404 auto nbDragWidget = countDragWidget(container);
404 if (nbDragWidget > 0) {
405 if (nbDragWidget > 0) {
405
406
406 if (m_MinContainerHeight == 0) {
407 if (m_MinContainerHeight == 0) {
407 m_MinContainerHeight = container->size().height();
408 m_MinContainerHeight = container->size().height();
408 }
409 }
409
410
410 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
411 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
411 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
412 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
412
413
413 auto posY = pos.y();
414 auto posY = pos.y();
414 auto dropIndex = floor(posY / graphHeight);
415 auto dropIndex = floor(posY / graphHeight);
415 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
416 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
416
417
417
418
418 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
419 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
419 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
420 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
420
421
421 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
422 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
422
423
423 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
424 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
424
425
425 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
426 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
426 if (isOnBottom) {
427 if (isOnBottom) {
427 dropIndex += 1;
428 dropIndex += 1;
428 }
429 }
429
430
430 if (helper.getCurrentDragWidget()) {
431 if (helper.getCurrentDragWidget()) {
431 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
432 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
432 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
433 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
433 // Correction of the index if the drop occurs in the same container
434 // Correction of the index if the drop occurs in the same container
434 // and if the drag is started from the visualization (in that case, the
435 // and if the drag is started from the visualization (in that case, the
435 // dragWidget is hidden)
436 // dragWidget is hidden)
436 dropIndex += 1;
437 dropIndex += 1;
437 }
438 }
438 }
439 }
439
440
440 if (dropIndex != placeHolderIndex) {
441 if (dropIndex != placeHolderIndex) {
441 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
442 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
442 m_PlaceHolderText);
443 m_PlaceHolderText);
443 }
444 }
444
445
445 helper.setHightlightedDragWidget(nullptr);
446 helper.setHightlightedDragWidget(nullptr);
446 }
447 }
447 else if (canMerge && dragWidgetHovered) {
448 else if (canMerge && dragWidgetHovered) {
448 // drop on the middle -> merge
449 // drop on the middle -> merge
449 if (hasPlaceHolder()) {
450 if (hasPlaceHolder()) {
450 helper.removePlaceHolder();
451 helper.removePlaceHolder();
451 }
452 }
452
453
453 helper.setHightlightedDragWidget(dragWidgetHovered);
454 helper.setHightlightedDragWidget(dragWidgetHovered);
454 }
455 }
455 else {
456 else {
456 qCWarning(LOG_VisualizationDragDropContainer())
457 qCWarning(LOG_VisualizationDragDropContainer())
457 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
458 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
458 "action.");
459 "action.");
459 }
460 }
460 }
461 }
461 else {
462 else {
462 qCWarning(LOG_VisualizationDragDropContainer())
463 qCWarning(LOG_VisualizationDragDropContainer())
463 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
464 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
464 "found in the "
465 "found in the "
465 "container");
466 "container");
466 }
467 }
467 }
468 }
468 else {
469 else {
469 // the mouse is hover the placeHolder
470 // the mouse is hover the placeHolder
470 // Do nothing
471 // Do nothing
471 }
472 }
472 }
473 }
@@ -1,53 +1,55
1 #include "Visualization/VisualizationDragWidget.h"
1 #include "Visualization/VisualizationDragWidget.h"
2 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "Visualization/VisualizationDragDropContainer.h"
3
3
4 #include <QApplication>
4 #include <QApplication>
5 #include <QMouseEvent>
5 #include <QMouseEvent>
6
6
7 #include <SqpApplication.h>
8
7 struct VisualizationDragWidget::VisualizationDragWidgetPrivate {
9 struct VisualizationDragWidget::VisualizationDragWidgetPrivate {
8
10
9 QPoint m_DragStartPosition;
11 QPoint m_DragStartPosition;
10 bool m_DragStartPositionValid = false;
12 bool m_DragStartPositionValid = false;
11
13
12 explicit VisualizationDragWidgetPrivate() {}
14 explicit VisualizationDragWidgetPrivate() {}
13 };
15 };
14
16
15 VisualizationDragWidget::VisualizationDragWidget(QWidget *parent)
17 VisualizationDragWidget::VisualizationDragWidget(QWidget *parent)
16 : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragWidgetPrivate>()}
18 : QWidget{parent}, impl{spimpl::make_unique_impl<VisualizationDragWidgetPrivate>()}
17 {
19 {
18 }
20 }
19
21
20 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
22 void VisualizationDragWidget::mousePressEvent(QMouseEvent *event)
21 {
23 {
22 if (event->button() == Qt::LeftButton) {
24 if (event->button() == Qt::LeftButton) {
23 impl->m_DragStartPosition = event->pos();
25 impl->m_DragStartPosition = event->pos();
24 }
26 }
25
27
26 impl->m_DragStartPositionValid = isDragAllowed();
28 impl->m_DragStartPositionValid = isDragAllowed();
27
29
28 QWidget::mousePressEvent(event);
30 QWidget::mousePressEvent(event);
29 }
31 }
30
32
31 void VisualizationDragWidget::mouseMoveEvent(QMouseEvent *event)
33 void VisualizationDragWidget::mouseMoveEvent(QMouseEvent *event)
32 {
34 {
33 if (!impl->m_DragStartPositionValid || !isDragAllowed()) {
35 if (!impl->m_DragStartPositionValid || !isDragAllowed()) {
34 return;
36 return;
35 }
37 }
36
38
37 if (!(event->buttons() & Qt::LeftButton)) {
39 if (!(event->buttons() & Qt::LeftButton)) {
38 return;
40 return;
39 }
41 }
40
42
41 if (!event->modifiers().testFlag(Qt::AltModifier)) {
43 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::DragAndDrop
42 return;
44 || event->modifiers().testFlag(Qt::AltModifier)) {
43 }
44
45
45 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
46 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
46 < QApplication::startDragDistance()) {
47 < QApplication::startDragDistance()) {
47 return;
48 return;
48 }
49 }
49
50
50 emit dragDetected(this, impl->m_DragStartPosition);
51 emit dragDetected(this, impl->m_DragStartPosition);
52 }
51
53
52 QWidget::mouseMoveEvent(event);
54 QWidget::mouseMoveEvent(event);
53 }
55 }
@@ -1,406 +1,597
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationCursorItem.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8 #include "ui_VisualizationGraphWidget.h"
8
9
9 #include <Common/MimeTypesDef.h>
10 #include <Common/MimeTypesDef.h>
10 #include <Data/ArrayData.h>
11 #include <Data/ArrayData.h>
11 #include <Data/IDataSeries.h>
12 #include <Data/IDataSeries.h>
12 #include <DragAndDrop/DragDropHelper.h>
13 #include <DragAndDrop/DragDropHelper.h>
13 #include <Settings/SqpSettingsDefs.h>
14 #include <Settings/SqpSettingsDefs.h>
14 #include <SqpApplication.h>
15 #include <SqpApplication.h>
15 #include <Time/TimeController.h>
16 #include <Time/TimeController.h>
16 #include <Variable/Variable.h>
17 #include <Variable/Variable.h>
17 #include <Variable/VariableController.h>
18 #include <Variable/VariableController.h>
18
19
19 #include <unordered_map>
20 #include <unordered_map>
20
21
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
22 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
22
23
23 namespace {
24 namespace {
24
25
25 /// Key pressed to enable zoom on horizontal axis
26 /// Key pressed to enable zoom on horizontal axis
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
27 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
27
28
28 /// Key pressed to enable zoom on vertical axis
29 /// Key pressed to enable zoom on vertical axis
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
30 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
31
32 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
33 const auto PAN_SPEED = 5;
34
35 /// Key pressed to enable a calibration pan
36 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
37
38 /// Minimum size for the zoom box, in percentage of the axis range
39 const auto ZOOM_BOX_MIN_SIZE = 0.8;
40
41 /// Format of the dates appearing in the label of a cursor
42 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
30
43
31 } // namespace
44 } // namespace
32
45
33 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
46 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
34
47
35 explicit VisualizationGraphWidgetPrivate(const QString &name)
48 explicit VisualizationGraphWidgetPrivate(const QString &name)
36 : m_Name{name},
49 : m_Name{name},
37 m_DoAcquisition{true},
50 m_DoAcquisition{true},
38 m_IsCalibration{false},
51 m_IsCalibration{false},
39 m_RenderingDelegate{nullptr}
52 m_RenderingDelegate{nullptr}
40 {
53 {
41 }
54 }
42
55
43 QString m_Name;
56 QString m_Name;
44 // 1 variable -> n qcpplot
57 // 1 variable -> n qcpplot
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
58 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
46 bool m_DoAcquisition;
59 bool m_DoAcquisition;
47 bool m_IsCalibration;
60 bool m_IsCalibration;
48 /// Delegate used to attach rendering features to the plot
61 /// Delegate used to attach rendering features to the plot
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
62 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
63
64 QCPItemRect *m_DrawingRect = nullptr;
65 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
66 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
67
68 void configureDrawingRect()
69 {
70 if (m_DrawingRect) {
71 QPen p;
72 p.setWidth(2);
73 m_DrawingRect->setPen(p);
74 }
75 }
76
77 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
78 {
79 removeDrawingRect(plot);
80
81 auto axisPos = posToAxisPos(pos, plot);
82
83 m_DrawingRect = new QCPItemRect{&plot};
84 configureDrawingRect();
85
86 m_DrawingRect->topLeft->setCoords(axisPos);
87 m_DrawingRect->bottomRight->setCoords(axisPos);
88 }
89
90 void removeDrawingRect(QCustomPlot &plot)
91 {
92 if (m_DrawingRect) {
93 plot.removeItem(m_DrawingRect); // the item is deleted by QCustomPlot
94 m_DrawingRect = nullptr;
95 plot.replot(QCustomPlot::rpQueuedReplot);
96 }
97 }
98
99 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
100 {
101 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
102 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
103 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
104 }
105
106 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
107 {
108 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
109 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
110
111 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
112 }
50 };
113 };
51
114
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
115 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 : VisualizationDragWidget{parent},
116 : VisualizationDragWidget{parent},
54 ui{new Ui::VisualizationGraphWidget},
117 ui{new Ui::VisualizationGraphWidget},
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
118 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 {
119 {
57 ui->setupUi(this);
120 ui->setupUi(this);
58
121
59 // 'Close' options : widget is deleted when closed
122 // 'Close' options : widget is deleted when closed
60 setAttribute(Qt::WA_DeleteOnClose);
123 setAttribute(Qt::WA_DeleteOnClose);
61
124
62 // Set qcpplot properties :
125 // Set qcpplot properties :
63 // - Drag (on x-axis) and zoom are enabled
126 // - Drag (on x-axis) and zoom are enabled
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
127 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
128 ui->widget->setInteractions(QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67
129
68 // The delegate must be initialized after the ui as it uses the plot
130 // The delegate must be initialized after the ui as it uses the plot
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
131 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70
132
133 // Init the cursors
134 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
135 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
136 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
137 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
138
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
139 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
140 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 &VisualizationGraphWidget::onMouseRelease);
141 &VisualizationGraphWidget::onMouseRelease);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
142 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
143 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
144 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 &QCPAxis::rangeChanged),
145 &QCPAxis::rangeChanged),
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
146 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79
147
80 // Activates menu when right clicking on the graph
148 // Activates menu when right clicking on the graph
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
149 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
150 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 &VisualizationGraphWidget::onGraphMenuRequested);
151 &VisualizationGraphWidget::onGraphMenuRequested);
84
152
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
153 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 &VariableController::onRequestDataLoading);
154 &VariableController::onRequestDataLoading);
87
155
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
156 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
157 &VisualizationGraphWidget::onUpdateVarDisplaying);
90
158
91 #ifdef Q_OS_MAC
159 #ifdef Q_OS_MAC
92 plot().setPlottingHint(QCP::phFastPolylines, true);
160 plot().setPlottingHint(QCP::phFastPolylines, true);
93 #endif
161 #endif
94 }
162 }
95
163
96
164
97 VisualizationGraphWidget::~VisualizationGraphWidget()
165 VisualizationGraphWidget::~VisualizationGraphWidget()
98 {
166 {
99 delete ui;
167 delete ui;
100 }
168 }
101
169
102 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
170 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
103 {
171 {
104 auto parent = parentWidget();
172 auto parent = parentWidget();
105 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
173 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
106 parent = parent->parentWidget();
174 parent = parent->parentWidget();
107 }
175 }
108
176
109 return qobject_cast<VisualizationZoneWidget *>(parent);
177 return qobject_cast<VisualizationZoneWidget *>(parent);
110 }
178 }
111
179
112 void VisualizationGraphWidget::enableAcquisition(bool enable)
180 void VisualizationGraphWidget::enableAcquisition(bool enable)
113 {
181 {
114 impl->m_DoAcquisition = enable;
182 impl->m_DoAcquisition = enable;
115 }
183 }
116
184
117 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
185 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
118 {
186 {
119 // Uses delegate to create the qcpplot components according to the variable
187 // Uses delegate to create the qcpplot components according to the variable
120 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
188 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
121
189
122 if (auto dataSeries = variable->dataSeries()) {
190 if (auto dataSeries = variable->dataSeries()) {
123 // Set axes properties according to the units of the data series
191 // Set axes properties according to the units of the data series
124 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
192 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
125
193
126 // Sets rendering properties for the new plottables
194 // Sets rendering properties for the new plottables
127 // Warning: this method must be called after setAxesProperties(), as it can access to some
195 // Warning: this method must be called after setAxesProperties(), as it can access to some
128 // axes properties that have to be initialized
196 // axes properties that have to be initialized
129 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
197 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
130 }
198 }
131
199
132 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
200 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
133
201
134 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
202 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
135
203
136 this->enableAcquisition(false);
204 this->enableAcquisition(false);
137 this->setGraphRange(range);
205 this->setGraphRange(range);
138 this->enableAcquisition(true);
206 this->enableAcquisition(true);
139
207
140 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
208 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
141
209
142 emit variableAdded(variable);
210 emit variableAdded(variable);
143 }
211 }
144
212
145 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
213 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
146 {
214 {
147 // Each component associated to the variable :
215 // Each component associated to the variable :
148 // - is removed from qcpplot (which deletes it)
216 // - is removed from qcpplot (which deletes it)
149 // - is no longer referenced in the map
217 // - is no longer referenced in the map
150 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
218 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
151 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
219 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
152 emit variableAboutToBeRemoved(variable);
220 emit variableAboutToBeRemoved(variable);
153
221
154 auto &plottablesMap = variableIt->second;
222 auto &plottablesMap = variableIt->second;
155
223
156 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
224 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
157 plottableIt != plottableEnd;) {
225 plottableIt != plottableEnd;) {
158 ui->widget->removePlottable(plottableIt->second);
226 ui->widget->removePlottable(plottableIt->second);
159 plottableIt = plottablesMap.erase(plottableIt);
227 plottableIt = plottablesMap.erase(plottableIt);
160 }
228 }
161
229
162 impl->m_VariableToPlotMultiMap.erase(variableIt);
230 impl->m_VariableToPlotMultiMap.erase(variableIt);
163 }
231 }
164
232
165 // Updates graph
233 // Updates graph
166 ui->widget->replot();
234 ui->widget->replot();
167 }
235 }
168
236
169 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
237 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
170 {
238 {
171 auto variables = QList<std::shared_ptr<Variable> >{};
239 auto variables = QList<std::shared_ptr<Variable> >{};
172 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
240 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
173 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
241 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
174 variables << it->first;
242 variables << it->first;
175 }
243 }
176
244
177 return variables;
245 return variables;
178 }
246 }
179
247
180 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
248 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
181 {
249 {
182 if (!variable) {
250 if (!variable) {
183 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
251 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
184 return;
252 return;
185 }
253 }
186
254
187 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
255 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
188 }
256 }
189
257
190 SqpRange VisualizationGraphWidget::graphRange() const noexcept
258 SqpRange VisualizationGraphWidget::graphRange() const noexcept
191 {
259 {
192 auto graphRange = ui->widget->xAxis->range();
260 auto graphRange = ui->widget->xAxis->range();
193 return SqpRange{graphRange.lower, graphRange.upper};
261 return SqpRange{graphRange.lower, graphRange.upper};
194 }
262 }
195
263
196 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
264 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
197 {
265 {
198 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
266 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
199 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
267 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
200 ui->widget->replot();
268 ui->widget->replot();
201 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
269 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
202 }
270 }
203
271
204 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
272 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
205 {
273 {
206 if (visitor) {
274 if (visitor) {
207 visitor->visit(this);
275 visitor->visit(this);
208 }
276 }
209 else {
277 else {
210 qCCritical(LOG_VisualizationGraphWidget())
278 qCCritical(LOG_VisualizationGraphWidget())
211 << tr("Can't visit widget : the visitor is null");
279 << tr("Can't visit widget : the visitor is null");
212 }
280 }
213 }
281 }
214
282
215 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
283 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
216 {
284 {
217 /// @todo : for the moment, a graph can always accomodate a variable
285 /// @todo : for the moment, a graph can always accomodate a variable
218 Q_UNUSED(variable);
286 Q_UNUSED(variable);
219 return true;
287 return true;
220 }
288 }
221
289
222 bool VisualizationGraphWidget::contains(const Variable &variable) const
290 bool VisualizationGraphWidget::contains(const Variable &variable) const
223 {
291 {
224 // Finds the variable among the keys of the map
292 // Finds the variable among the keys of the map
225 auto variablePtr = &variable;
293 auto variablePtr = &variable;
226 auto findVariable
294 auto findVariable
227 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
295 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
228
296
229 auto end = impl->m_VariableToPlotMultiMap.cend();
297 auto end = impl->m_VariableToPlotMultiMap.cend();
230 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
298 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
231 return it != end;
299 return it != end;
232 }
300 }
233
301
234 QString VisualizationGraphWidget::name() const
302 QString VisualizationGraphWidget::name() const
235 {
303 {
236 return impl->m_Name;
304 return impl->m_Name;
237 }
305 }
238
306
239 QMimeData *VisualizationGraphWidget::mimeData() const
307 QMimeData *VisualizationGraphWidget::mimeData() const
240 {
308 {
241 auto mimeData = new QMimeData;
309 auto mimeData = new QMimeData;
242 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
310 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
243
311
244 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
312 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
245 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
313 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
246
314
247 return mimeData;
315 return mimeData;
248 }
316 }
249
317
250 bool VisualizationGraphWidget::isDragAllowed() const
318 bool VisualizationGraphWidget::isDragAllowed() const
251 {
319 {
252 return true;
320 return true;
253 }
321 }
254
322
255 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
323 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
256 {
324 {
257 if (highlighted) {
325 if (highlighted) {
258 plot().setBackground(QBrush(QColor("#BBD5EE")));
326 plot().setBackground(QBrush(QColor("#BBD5EE")));
259 }
327 }
260 else {
328 else {
261 plot().setBackground(QBrush(Qt::white));
329 plot().setBackground(QBrush(Qt::white));
262 }
330 }
263
331
264 plot().update();
332 plot().update();
265 }
333 }
266
334
335 void VisualizationGraphWidget::addVerticalCursor(double time)
336 {
337 impl->m_VerticalCursor->setPosition(time);
338 impl->m_VerticalCursor->setVisible(true);
339
340 auto text
341 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
342 impl->m_VerticalCursor->setLabelText(text);
343 }
344
345 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
346 {
347 impl->m_VerticalCursor->setAbsolutePosition(position);
348 impl->m_VerticalCursor->setVisible(true);
349
350 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
351 auto text
352 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
353 impl->m_VerticalCursor->setLabelText(text);
354 }
355
356 void VisualizationGraphWidget::removeVerticalCursor()
357 {
358 impl->m_VerticalCursor->setVisible(false);
359 plot().replot(QCustomPlot::rpQueuedReplot);
360 }
361
362 void VisualizationGraphWidget::addHorizontalCursor(double value)
363 {
364 impl->m_HorizontalCursor->setPosition(value);
365 impl->m_HorizontalCursor->setVisible(true);
366 impl->m_HorizontalCursor->setLabelText(QString::number(value));
367 }
368
369 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
370 {
371 impl->m_HorizontalCursor->setAbsolutePosition(position);
372 impl->m_HorizontalCursor->setVisible(true);
373
374 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
375 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
376 }
377
378 void VisualizationGraphWidget::removeHorizontalCursor()
379 {
380 impl->m_HorizontalCursor->setVisible(false);
381 plot().replot(QCustomPlot::rpQueuedReplot);
382 }
383
267 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
384 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
268 {
385 {
269 Q_UNUSED(event);
386 Q_UNUSED(event);
270
387
271 // Prevents that all variables will be removed from graph when it will be closed
388 // Prevents that all variables will be removed from graph when it will be closed
272 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
389 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
273 emit variableAboutToBeRemoved(variableEntry.first);
390 emit variableAboutToBeRemoved(variableEntry.first);
274 }
391 }
275 }
392 }
276
393
277 void VisualizationGraphWidget::enterEvent(QEvent *event)
394 void VisualizationGraphWidget::enterEvent(QEvent *event)
278 {
395 {
279 Q_UNUSED(event);
396 Q_UNUSED(event);
280 impl->m_RenderingDelegate->showGraphOverlay(true);
397 impl->m_RenderingDelegate->showGraphOverlay(true);
281 }
398 }
282
399
283 void VisualizationGraphWidget::leaveEvent(QEvent *event)
400 void VisualizationGraphWidget::leaveEvent(QEvent *event)
284 {
401 {
285 Q_UNUSED(event);
402 Q_UNUSED(event);
286 impl->m_RenderingDelegate->showGraphOverlay(false);
403 impl->m_RenderingDelegate->showGraphOverlay(false);
404
405 if (auto parentZone = parentZoneWidget()) {
406 parentZone->notifyMouseLeaveGraph(this);
407 }
408 else {
409 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
410 }
287 }
411 }
288
412
289 QCustomPlot &VisualizationGraphWidget::plot() noexcept
413 QCustomPlot &VisualizationGraphWidget::plot() noexcept
290 {
414 {
291 return *ui->widget;
415 return *ui->widget;
292 }
416 }
293
417
294 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
418 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
295 {
419 {
296 QMenu graphMenu{};
420 QMenu graphMenu{};
297
421
298 // Iterates on variables (unique keys)
422 // Iterates on variables (unique keys)
299 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
423 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
300 end = impl->m_VariableToPlotMultiMap.cend();
424 end = impl->m_VariableToPlotMultiMap.cend();
301 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
425 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
302 // 'Remove variable' action
426 // 'Remove variable' action
303 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
427 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
304 [ this, var = it->first ]() { removeVariable(var); });
428 [ this, var = it->first ]() { removeVariable(var); });
305 }
429 }
306
430
307 if (!graphMenu.isEmpty()) {
431 if (!graphMenu.isEmpty()) {
308 graphMenu.exec(QCursor::pos());
432 graphMenu.exec(QCursor::pos());
309 }
433 }
310 }
434 }
311
435
312 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
436 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
313 {
437 {
314 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
438 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
315 << QThread::currentThread()->objectName() << "DoAcqui"
439 << QThread::currentThread()->objectName() << "DoAcqui"
316 << impl->m_DoAcquisition;
440 << impl->m_DoAcquisition;
317
441
318 auto graphRange = SqpRange{t1.lower, t1.upper};
442 auto graphRange = SqpRange{t1.lower, t1.upper};
319 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
443 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
320
444
321 if (impl->m_DoAcquisition) {
445 if (impl->m_DoAcquisition) {
322 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
446 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
323
447
324 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
448 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
325 end = impl->m_VariableToPlotMultiMap.end();
449 end = impl->m_VariableToPlotMultiMap.end();
326 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
450 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
327 variableUnderGraphVector.push_back(it->first);
451 variableUnderGraphVector.push_back(it->first);
328 }
452 }
329 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
453 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
330 !impl->m_IsCalibration);
454 !impl->m_IsCalibration);
331
455
332 if (!impl->m_IsCalibration) {
456 if (!impl->m_IsCalibration) {
333 qCDebug(LOG_VisualizationGraphWidget())
457 qCDebug(LOG_VisualizationGraphWidget())
334 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
458 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
335 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
459 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
336 emit synchronize(graphRange, oldGraphRange);
460 emit synchronize(graphRange, oldGraphRange);
337 }
461 }
338 }
462 }
463
464 auto pos = mapFromGlobal(QCursor::pos());
465 auto axisPos = impl->posToAxisPos(pos, plot());
466 if (auto parentZone = parentZoneWidget()) {
467 if (impl->pointIsInAxisRect(axisPos, plot())) {
468 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
469 }
470 else {
471 parentZone->notifyMouseLeaveGraph(this);
472 }
473 }
474 else {
475 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
476 }
339 }
477 }
340
478
341 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
479 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
342 {
480 {
343 // Handles plot rendering when mouse is moving
481 // Handles plot rendering when mouse is moving
344 impl->m_RenderingDelegate->onMouseMove(event);
482 impl->m_RenderingDelegate->onMouseMove(event);
345
483
484 auto axisPos = impl->posToAxisPos(event->pos(), plot());
485
486 if (impl->m_DrawingRect) {
487 impl->m_DrawingRect->bottomRight->setCoords(axisPos);
488 }
489
490 if (auto parentZone = parentZoneWidget()) {
491 if (impl->pointIsInAxisRect(axisPos, plot())) {
492 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
493 }
494 else {
495 parentZone->notifyMouseLeaveGraph(this);
496 }
497 }
498 else {
499 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
500 }
501
346 VisualizationDragWidget::mouseMoveEvent(event);
502 VisualizationDragWidget::mouseMoveEvent(event);
347 }
503 }
348
504
349 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
505 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
350 {
506 {
351 auto zoomOrientations = QFlags<Qt::Orientation>{};
507 auto value = event->angleDelta().x() + event->angleDelta().y();
508 if (value != 0) {
509
510 auto direction = value > 0 ? 1.0 : -1.0;
511 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
512 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
513 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
514
515 auto zoomOrientations = QFlags<Qt::Orientation>{};
516 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
517 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
518
519 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
352
520
353 // Lambda that enables a zoom orientation if the key modifier related to this orientation
521 if (!isZoomX && !isZoomY) {
354 // has
522 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
355 // been pressed
523 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
356 auto enableOrientation
357 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
358 auto orientationEnabled = event->modifiers().testFlag(modifier);
359 zoomOrientations.setFlag(orientation, orientationEnabled);
360 };
361 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
362 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
363
524
364 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
525 axis->setRange(axis->range() + diff);
526
527 if (plot().noAntialiasingOnDrag()) {
528 plot().setNotAntialiasedElements(QCP::aeAll);
529 }
530
531 plot().replot(QCustomPlot::rpQueuedReplot);
532 }
533 }
365 }
534 }
366
535
367 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
536 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
368 {
537 {
369 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
538 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
370
539 impl->startDrawingRect(event->pos(), plot());
371 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
540 }
372
541
373 VisualizationDragWidget::mousePressEvent(event);
542 VisualizationDragWidget::mousePressEvent(event);
374 }
543 }
375
544
376 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
545 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
377 {
546 {
547 if (impl->m_DrawingRect) {
548
549 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
550 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
551
552 auto newAxisXRange = QCPRange{impl->m_DrawingRect->topLeft->coords().x(),
553 impl->m_DrawingRect->bottomRight->coords().x()};
554
555 auto newAxisYRange = QCPRange{impl->m_DrawingRect->topLeft->coords().y(),
556 impl->m_DrawingRect->bottomRight->coords().y()};
557
558 impl->removeDrawingRect(plot());
559
560 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
561 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
562 axisX->setRange(newAxisXRange);
563 axisY->setRange(newAxisYRange);
564
565 plot().replot(QCustomPlot::rpQueuedReplot);
566 }
567 }
568
378 impl->m_IsCalibration = false;
569 impl->m_IsCalibration = false;
379 }
570 }
380
571
381 void VisualizationGraphWidget::onDataCacheVariableUpdated()
572 void VisualizationGraphWidget::onDataCacheVariableUpdated()
382 {
573 {
383 auto graphRange = ui->widget->xAxis->range();
574 auto graphRange = ui->widget->xAxis->range();
384 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
575 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
385
576
386 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
577 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
387 auto variable = variableEntry.first;
578 auto variable = variableEntry.first;
388 qCDebug(LOG_VisualizationGraphWidget())
579 qCDebug(LOG_VisualizationGraphWidget())
389 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
580 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
390 qCDebug(LOG_VisualizationGraphWidget())
581 qCDebug(LOG_VisualizationGraphWidget())
391 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
582 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
392 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
583 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
393 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
584 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
394 variable->range());
585 variable->range());
395 }
586 }
396 }
587 }
397 }
588 }
398
589
399 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
590 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
400 const SqpRange &range)
591 const SqpRange &range)
401 {
592 {
402 auto it = impl->m_VariableToPlotMultiMap.find(variable);
593 auto it = impl->m_VariableToPlotMultiMap.find(variable);
403 if (it != impl->m_VariableToPlotMultiMap.end()) {
594 if (it != impl->m_VariableToPlotMultiMap.end()) {
404 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
595 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
405 }
596 }
406 }
597 }
@@ -1,507 +1,560
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61 }
62
62
63 } // namespace
63 } // namespace
64
64
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
66
67 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
70 {
71 }
71 }
72 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
83 firstGraph = visualizationGraphWidget;
84 }
84 }
85 }
85 }
86
86
87 return firstGraph;
87 return firstGraph;
88 }
88 }
89
89
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
92 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
93 };
93 };
94
94
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
96 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
97 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
99 {
99 {
100 ui->setupUi(this);
100 ui->setupUi(this);
101
101
102 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
103
103
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
105 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
106 VisualizationDragDropContainer::DropBehavior::Inserted);
106 VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->setMimeType(
107 ui->dragDropContainer->setMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
109 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
110 VisualizationDragDropContainer::DropBehavior::Merged);
110 VisualizationDragDropContainer::DropBehavior::Merged);
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
111 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
112 VisualizationDragDropContainer::DropBehavior::Forbidden);
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
113 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
114 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
115 ui->dragDropContainer);
115 ui->dragDropContainer);
116 });
116 });
117
117
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
119 &VisualizationZoneWidget::dropMimeData);
119 &VisualizationZoneWidget::dropMimeData);
120 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
120 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
121 &VisualizationZoneWidget::dropMimeDataOnGraph);
121 &VisualizationZoneWidget::dropMimeDataOnGraph);
122
122
123 // 'Close' options : widget is deleted when closed
123 // 'Close' options : widget is deleted when closed
124 setAttribute(Qt::WA_DeleteOnClose);
124 setAttribute(Qt::WA_DeleteOnClose);
125 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
125 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
126 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
126 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
127
127
128 // Synchronisation id
128 // Synchronisation id
129 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
129 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
130 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
130 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
131 }
131 }
132
132
133 VisualizationZoneWidget::~VisualizationZoneWidget()
133 VisualizationZoneWidget::~VisualizationZoneWidget()
134 {
134 {
135 delete ui;
135 delete ui;
136 }
136 }
137
137
138 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
138 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
139 {
139 {
140 // Synchronize new graph with others in the zone
140 // Synchronize new graph with others in the zone
141 impl->m_Synchronizer->addGraph(*graphWidget);
141 impl->m_Synchronizer->addGraph(*graphWidget);
142
142
143 ui->dragDropContainer->addDragWidget(graphWidget);
143 ui->dragDropContainer->addDragWidget(graphWidget);
144 }
144 }
145
145
146 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
146 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
147 {
147 {
148 // Synchronize new graph with others in the zone
148 // Synchronize new graph with others in the zone
149 impl->m_Synchronizer->addGraph(*graphWidget);
149 impl->m_Synchronizer->addGraph(*graphWidget);
150
150
151 ui->dragDropContainer->insertDragWidget(index, graphWidget);
151 ui->dragDropContainer->insertDragWidget(index, graphWidget);
152 }
152 }
153
153
154 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
154 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
155 {
155 {
156 return createGraph(variable, -1);
156 return createGraph(variable, -1);
157 }
157 }
158
158
159 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
159 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
160 int index)
160 int index)
161 {
161 {
162 auto graphWidget
162 auto graphWidget
163 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
163 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
164
164
165
165
166 // Set graph properties
166 // Set graph properties
167 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
167 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
168 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
168 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
169
169
170
170
171 // Lambda to synchronize zone widget
171 // Lambda to synchronize zone widget
172 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
172 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
173 const SqpRange &oldGraphRange) {
173 const SqpRange &oldGraphRange) {
174
174
175 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
175 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
176 auto frameLayout = ui->dragDropContainer->layout();
176 auto frameLayout = ui->dragDropContainer->layout();
177 for (auto i = 0; i < frameLayout->count(); ++i) {
177 for (auto i = 0; i < frameLayout->count(); ++i) {
178 auto graphChild
178 auto graphChild
179 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
179 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
180 if (graphChild && (graphChild != graphWidget)) {
180 if (graphChild && (graphChild != graphWidget)) {
181
181
182 auto graphChildRange = graphChild->graphRange();
182 auto graphChildRange = graphChild->graphRange();
183 switch (zoomType) {
183 switch (zoomType) {
184 case AcquisitionZoomType::ZoomIn: {
184 case AcquisitionZoomType::ZoomIn: {
185 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
185 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
186 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
187 graphChildRange.m_TStart += deltaLeft;
187 graphChildRange.m_TStart += deltaLeft;
188 graphChildRange.m_TEnd -= deltaRight;
188 graphChildRange.m_TEnd -= deltaRight;
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
191 << deltaLeft;
191 << deltaLeft;
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
193 << deltaRight;
193 << deltaRight;
194 qCDebug(LOG_VisualizationZoneWidget())
194 qCDebug(LOG_VisualizationZoneWidget())
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
196
196
197 break;
197 break;
198 }
198 }
199
199
200 case AcquisitionZoomType::ZoomOut: {
200 case AcquisitionZoomType::ZoomOut: {
201 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
201 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
202 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
202 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
203 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
203 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
205 << deltaLeft;
205 << deltaLeft;
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
206 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
207 << deltaRight;
207 << deltaRight;
208 qCDebug(LOG_VisualizationZoneWidget())
208 qCDebug(LOG_VisualizationZoneWidget())
209 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
209 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
210 graphChildRange.m_TStart -= deltaLeft;
210 graphChildRange.m_TStart -= deltaLeft;
211 graphChildRange.m_TEnd += deltaRight;
211 graphChildRange.m_TEnd += deltaRight;
212 break;
212 break;
213 }
213 }
214 case AcquisitionZoomType::PanRight: {
214 case AcquisitionZoomType::PanRight: {
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
215 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
216 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
217 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
217 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
218 graphChildRange.m_TStart += deltaLeft;
218 graphChildRange.m_TStart += deltaLeft;
219 graphChildRange.m_TEnd += deltaRight;
219 graphChildRange.m_TEnd += deltaRight;
220 qCDebug(LOG_VisualizationZoneWidget())
220 qCDebug(LOG_VisualizationZoneWidget())
221 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
221 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
222 break;
222 break;
223 }
223 }
224 case AcquisitionZoomType::PanLeft: {
224 case AcquisitionZoomType::PanLeft: {
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
226 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
227 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
227 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
228 graphChildRange.m_TStart -= deltaLeft;
228 graphChildRange.m_TStart -= deltaLeft;
229 graphChildRange.m_TEnd -= deltaRight;
229 graphChildRange.m_TEnd -= deltaRight;
230 break;
230 break;
231 }
231 }
232 case AcquisitionZoomType::Unknown: {
232 case AcquisitionZoomType::Unknown: {
233 qCDebug(LOG_VisualizationZoneWidget())
233 qCDebug(LOG_VisualizationZoneWidget())
234 << tr("Impossible to synchronize: zoom type unknown");
234 << tr("Impossible to synchronize: zoom type unknown");
235 break;
235 break;
236 }
236 }
237 default:
237 default:
238 qCCritical(LOG_VisualizationZoneWidget())
238 qCCritical(LOG_VisualizationZoneWidget())
239 << tr("Impossible to synchronize: zoom type not take into account");
239 << tr("Impossible to synchronize: zoom type not take into account");
240 // No action
240 // No action
241 break;
241 break;
242 }
242 }
243 graphChild->enableAcquisition(false);
243 graphChild->enableAcquisition(false);
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
245 << graphChild->graphRange();
245 << graphChild->graphRange();
246 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
246 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
247 << graphChildRange;
247 << graphChildRange;
248 qCDebug(LOG_VisualizationZoneWidget())
248 qCDebug(LOG_VisualizationZoneWidget())
249 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
249 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
250 graphChild->setGraphRange(graphChildRange);
250 graphChild->setGraphRange(graphChildRange);
251 graphChild->enableAcquisition(true);
251 graphChild->enableAcquisition(true);
252 }
252 }
253 }
253 }
254 };
254 };
255
255
256 // connection for synchronization
256 // connection for synchronization
257 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
257 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
258 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
258 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
259 &VisualizationZoneWidget::onVariableAdded);
259 &VisualizationZoneWidget::onVariableAdded);
260 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
260 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
261 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
261 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
262
262
263 auto range = SqpRange{};
263 auto range = SqpRange{};
264 if (auto firstGraph = impl->firstGraph(this)) {
264 if (auto firstGraph = impl->firstGraph(this)) {
265 // Case of a new graph in a existant zone
265 // Case of a new graph in a existant zone
266 range = firstGraph->graphRange();
266 range = firstGraph->graphRange();
267 }
267 }
268 else {
268 else {
269 // Case of a new graph as the first of the zone
269 // Case of a new graph as the first of the zone
270 range = variable->range();
270 range = variable->range();
271 }
271 }
272
272
273 this->insertGraph(index, graphWidget);
273 this->insertGraph(index, graphWidget);
274
274
275 graphWidget->addVariable(variable, range);
275 graphWidget->addVariable(variable, range);
276 graphWidget->setYRange(variable);
276 graphWidget->setYRange(variable);
277
277
278 return graphWidget;
278 return graphWidget;
279 }
279 }
280
280
281 VisualizationGraphWidget *
281 VisualizationGraphWidget *
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
282 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
283 {
283 {
284 if (variables.isEmpty()) {
284 if (variables.isEmpty()) {
285 return nullptr;
285 return nullptr;
286 }
286 }
287
287
288 auto graphWidget = createGraph(variables.first(), index);
288 auto graphWidget = createGraph(variables.first(), index);
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
289 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
290 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
291 }
291 }
292
292
293 return graphWidget;
293 return graphWidget;
294 }
294 }
295
295
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
296 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
297 {
297 {
298 if (visitor) {
298 if (visitor) {
299 visitor->visitEnter(this);
299 visitor->visitEnter(this);
300
300
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
301 // Apply visitor to graph children: widgets different from graphs are not visited (no
302 // action)
302 // action)
303 processGraphs(
303 processGraphs(
304 *ui->dragDropContainer->layout(),
304 *ui->dragDropContainer->layout(),
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
305 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
306
306
307 visitor->visitLeave(this);
307 visitor->visitLeave(this);
308 }
308 }
309 else {
309 else {
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
310 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
311 }
311 }
312 }
312 }
313
313
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
314 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
315 {
315 {
316 // A tab can always accomodate a variable
316 // A tab can always accomodate a variable
317 Q_UNUSED(variable);
317 Q_UNUSED(variable);
318 return true;
318 return true;
319 }
319 }
320
320
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
321 bool VisualizationZoneWidget::contains(const Variable &variable) const
322 {
322 {
323 Q_UNUSED(variable);
323 Q_UNUSED(variable);
324 return false;
324 return false;
325 }
325 }
326
326
327 QString VisualizationZoneWidget::name() const
327 QString VisualizationZoneWidget::name() const
328 {
328 {
329 return ui->zoneNameLabel->text();
329 return ui->zoneNameLabel->text();
330 }
330 }
331
331
332 QMimeData *VisualizationZoneWidget::mimeData() const
332 QMimeData *VisualizationZoneWidget::mimeData() const
333 {
333 {
334 auto mimeData = new QMimeData;
334 auto mimeData = new QMimeData;
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
335 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
336
336
337 if (auto firstGraph = impl->firstGraph(this)) {
337 if (auto firstGraph = impl->firstGraph(this)) {
338 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
338 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
339 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
339 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
340 }
340 }
341
341
342 return mimeData;
342 return mimeData;
343 }
343 }
344
344
345 bool VisualizationZoneWidget::isDragAllowed() const
345 bool VisualizationZoneWidget::isDragAllowed() const
346 {
346 {
347 return true;
347 return true;
348 }
348 }
349
349
350 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
351 const QPointF &plotPosition,
352 VisualizationGraphWidget *graphWidget)
353 {
354 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
355 VisualizationGraphWidget &processedGraph) {
356
357 switch (sqpApp->plotsCursorMode()) {
358 case SqpApplication::PlotsCursorMode::Vertical:
359 processedGraph.removeHorizontalCursor();
360 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
361 break;
362 case SqpApplication::PlotsCursorMode::Temporal:
363 processedGraph.addVerticalCursor(plotPosition.x());
364 processedGraph.removeHorizontalCursor();
365 break;
366 case SqpApplication::PlotsCursorMode::Horizontal:
367 processedGraph.removeVerticalCursor();
368 if (&processedGraph == graphWidget) {
369 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
370 }
371 else {
372 processedGraph.removeHorizontalCursor();
373 }
374 break;
375 case SqpApplication::PlotsCursorMode::Cross:
376 if (&processedGraph == graphWidget) {
377 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
378 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
379 }
380 else {
381 processedGraph.removeHorizontalCursor();
382 processedGraph.removeVerticalCursor();
383 }
384 break;
385 case SqpApplication::PlotsCursorMode::NoCursor:
386 processedGraph.removeHorizontalCursor();
387 processedGraph.removeVerticalCursor();
388 break;
389 }
390
391
392 });
393 }
394
395 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
396 {
397 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
398 processedGraph.removeHorizontalCursor();
399 processedGraph.removeVerticalCursor();
400 });
401 }
402
350 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
403 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
351 {
404 {
352 // Closes graphs in the zone
405 // Closes graphs in the zone
353 processGraphs(*ui->dragDropContainer->layout(),
406 processGraphs(*ui->dragDropContainer->layout(),
354 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
407 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
355
408
356 // Delete synchronization group from variable controller
409 // Delete synchronization group from variable controller
357 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
410 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
358 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
411 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
359
412
360 QWidget::closeEvent(event);
413 QWidget::closeEvent(event);
361 }
414 }
362
415
363 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
416 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
364 {
417 {
365 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
418 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
366 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
419 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
367 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
420 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
368 }
421 }
369
422
370 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
423 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
371 {
424 {
372 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
425 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
373 Q_ARG(std::shared_ptr<Variable>, variable),
426 Q_ARG(std::shared_ptr<Variable>, variable),
374 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
427 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
375 }
428 }
376
429
377 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
430 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
378 {
431 {
379 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
432 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
380 impl->dropGraph(index, this);
433 impl->dropGraph(index, this);
381 }
434 }
382 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
435 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
383 auto variables = sqpApp->variableController().variablesForMimeData(
436 auto variables = sqpApp->variableController().variablesForMimeData(
384 mimeData->data(MIME_TYPE_VARIABLE_LIST));
437 mimeData->data(MIME_TYPE_VARIABLE_LIST));
385 impl->dropVariables(variables, index, this);
438 impl->dropVariables(variables, index, this);
386 }
439 }
387 else {
440 else {
388 qCWarning(LOG_VisualizationZoneWidget())
441 qCWarning(LOG_VisualizationZoneWidget())
389 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
442 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
390 }
443 }
391 }
444 }
392
445
393 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
446 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
394 const QMimeData *mimeData)
447 const QMimeData *mimeData)
395 {
448 {
396 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
449 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
397 if (!graphWidget) {
450 if (!graphWidget) {
398 qCWarning(LOG_VisualizationZoneWidget())
451 qCWarning(LOG_VisualizationZoneWidget())
399 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
452 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
400 "drop aborted");
453 "drop aborted");
401 Q_ASSERT(false);
454 Q_ASSERT(false);
402 return;
455 return;
403 }
456 }
404
457
405 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
458 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
406 auto variables = sqpApp->variableController().variablesForMimeData(
459 auto variables = sqpApp->variableController().variablesForMimeData(
407 mimeData->data(MIME_TYPE_VARIABLE_LIST));
460 mimeData->data(MIME_TYPE_VARIABLE_LIST));
408 for (const auto &var : variables) {
461 for (const auto &var : variables) {
409 graphWidget->addVariable(var, graphWidget->graphRange());
462 graphWidget->addVariable(var, graphWidget->graphRange());
410 }
463 }
411 }
464 }
412 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
465 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
413 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
466 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
414 graphWidget->setGraphRange(range);
467 graphWidget->setGraphRange(range);
415 }
468 }
416 else {
469 else {
417 qCWarning(LOG_VisualizationZoneWidget())
470 qCWarning(LOG_VisualizationZoneWidget())
418 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
471 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
419 }
472 }
420 }
473 }
421
474
422 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
475 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
423 int index, VisualizationZoneWidget *zoneWidget)
476 int index, VisualizationZoneWidget *zoneWidget)
424 {
477 {
425 auto &helper = sqpApp->dragDropHelper();
478 auto &helper = sqpApp->dragDropHelper();
426
479
427 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
480 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
428 if (!graphWidget) {
481 if (!graphWidget) {
429 qCWarning(LOG_VisualizationZoneWidget())
482 qCWarning(LOG_VisualizationZoneWidget())
430 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
483 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
431 "found or invalid.");
484 "found or invalid.");
432 Q_ASSERT(false);
485 Q_ASSERT(false);
433 return;
486 return;
434 }
487 }
435
488
436 auto parentDragDropContainer
489 auto parentDragDropContainer
437 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
490 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
438 if (!parentDragDropContainer) {
491 if (!parentDragDropContainer) {
439 qCWarning(LOG_VisualizationZoneWidget())
492 qCWarning(LOG_VisualizationZoneWidget())
440 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
493 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
441 "the dropped graph is not found.");
494 "the dropped graph is not found.");
442 Q_ASSERT(false);
495 Q_ASSERT(false);
443 return;
496 return;
444 }
497 }
445
498
446 const auto &variables = graphWidget->variables();
499 const auto &variables = graphWidget->variables();
447
500
448 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
501 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
449 // The drop didn't occur in the same zone
502 // The drop didn't occur in the same zone
450
503
451 // Abort the requests for the variables (if any)
504 // Abort the requests for the variables (if any)
452 // Commented, because it's not sure if it's needed or not
505 // Commented, because it's not sure if it's needed or not
453 // for (const auto& var : variables)
506 // for (const auto& var : variables)
454 //{
507 //{
455 // sqpApp->variableController().onAbortProgressRequested(var);
508 // sqpApp->variableController().onAbortProgressRequested(var);
456 //}
509 //}
457
510
458 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
511 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
459 auto nbGraph = parentDragDropContainer->countDragWidget();
512 auto nbGraph = parentDragDropContainer->countDragWidget();
460 if (nbGraph == 1) {
513 if (nbGraph == 1) {
461 // This is the only graph in the previous zone, close the zone
514 // This is the only graph in the previous zone, close the zone
462 helper.delayedCloseWidget(previousParentZoneWidget);
515 helper.delayedCloseWidget(previousParentZoneWidget);
463 }
516 }
464 else {
517 else {
465 // Close the graph
518 // Close the graph
466 helper.delayedCloseWidget(graphWidget);
519 helper.delayedCloseWidget(graphWidget);
467 }
520 }
468
521
469 // Creates the new graph in the zone
522 // Creates the new graph in the zone
470 zoneWidget->createGraph(variables, index);
523 zoneWidget->createGraph(variables, index);
471 }
524 }
472 else {
525 else {
473 // The drop occurred in the same zone or the graph is empty
526 // The drop occurred in the same zone or the graph is empty
474 // Simple move of the graph, no variable operation associated
527 // Simple move of the graph, no variable operation associated
475 parentDragDropContainer->layout()->removeWidget(graphWidget);
528 parentDragDropContainer->layout()->removeWidget(graphWidget);
476
529
477 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
530 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
478 // The graph is empty and dropped in a different zone.
531 // The graph is empty and dropped in a different zone.
479 // Take the range of the first graph in the zone (if existing).
532 // Take the range of the first graph in the zone (if existing).
480 auto layout = zoneWidget->ui->dragDropContainer->layout();
533 auto layout = zoneWidget->ui->dragDropContainer->layout();
481 if (layout->count() > 0) {
534 if (layout->count() > 0) {
482 if (auto visualizationGraphWidget
535 if (auto visualizationGraphWidget
483 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
536 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
484 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
537 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
485 }
538 }
486 }
539 }
487 }
540 }
488
541
489 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
542 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
490 }
543 }
491 }
544 }
492
545
493 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
546 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
494 const QList<std::shared_ptr<Variable> > &variables, int index,
547 const QList<std::shared_ptr<Variable> > &variables, int index,
495 VisualizationZoneWidget *zoneWidget)
548 VisualizationZoneWidget *zoneWidget)
496 {
549 {
497 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
550 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
498 // compatible variable here
551 // compatible variable here
499 if (variables.count() > 1) {
552 if (variables.count() > 1) {
500 qCWarning(LOG_VisualizationZoneWidget())
553 qCWarning(LOG_VisualizationZoneWidget())
501 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
554 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
502 "aborted.");
555 "aborted.");
503 return;
556 return;
504 }
557 }
505
558
506 zoneWidget->createGraph(variables, index);
559 zoneWidget->createGraph(variables, index);
507 }
560 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

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