##// END OF EJS Templates
MR for linux compilation
perrinel -
r848:89fbdd3d4a7b
parent child
Show More
@@ -1,230 +1,230
1 #include "DragDropHelper.h"
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragWidget.h"
3 #include "Visualization/VisualizationDragWidget.h"
4
4
5 #include <QDir>
5 #include <QDir>
6 #include <QDragEnterEvent>
6 #include <QDragEnterEvent>
7 #include <QDragMoveEvent>
7 #include <QDragMoveEvent>
8 #include <QScrollArea>
8 #include <QScrollArea>
9 #include <QScrollBar>
9 #include <QScrollBar>
10 #include <QTimer>
10 #include <QTimer>
11 #include <QVBoxLayout>
11 #include <QVBoxLayout>
12
12
13 const QString DragDropHelper::MIME_TYPE_GRAPH = "scqlop/graph";
13 const QString DragDropHelper::MIME_TYPE_GRAPH = "scqlop/graph";
14 const QString DragDropHelper::MIME_TYPE_ZONE = "scqlop/zone";
14 const QString DragDropHelper::MIME_TYPE_ZONE = "scqlop/zone";
15
15
16 const int SCROLL_SPEED = 5;
16 const int SCROLL_SPEED = 5;
17 const int SCROLL_ZONE_SIZE = 50;
17 const int SCROLL_ZONE_SIZE = 50;
18
18
19 struct DragDropScroller::DragDropScrollerPrivate {
19 struct DragDropScroller::DragDropScrollerPrivate {
20
20
21 QList<QScrollArea *> m_ScrollAreas;
21 QList<QScrollArea *> m_ScrollAreas;
22 QScrollArea *m_CurrentScrollArea = nullptr;
22 QScrollArea *m_CurrentScrollArea = nullptr;
23 std::unique_ptr<QTimer> m_Timer = nullptr;
23 std::unique_ptr<QTimer> m_Timer = nullptr;
24
24
25
25
26 enum class ScrollDirection { up, down, unknown };
26 enum class ScrollDirection { up, down, unknown };
27 ScrollDirection m_Direction = ScrollDirection::unknown;
27 ScrollDirection m_Direction = ScrollDirection::unknown;
28
28
29 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
29 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
30 {
30 {
31 m_Timer->setInterval(0);
31 m_Timer->setInterval(0);
32 }
32 }
33 };
33 };
34
34
35 DragDropScroller::DragDropScroller(QObject *parent)
35 DragDropScroller::DragDropScroller(QObject *parent)
36 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
36 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
37 {
37 {
38 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
38 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
39 }
39 }
40
40
41 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
41 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
42 {
42 {
43 impl->m_ScrollAreas << scrollArea;
43 impl->m_ScrollAreas << scrollArea;
44 scrollArea->viewport()->setAcceptDrops(true);
44 scrollArea->viewport()->setAcceptDrops(true);
45 }
45 }
46
46
47 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
47 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
48 {
48 {
49 impl->m_ScrollAreas.removeAll(scrollArea);
49 impl->m_ScrollAreas.removeAll(scrollArea);
50 scrollArea->viewport()->setAcceptDrops(false);
50 scrollArea->viewport()->setAcceptDrops(false);
51 }
51 }
52
52
53 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
53 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
54 {
54 {
55 if (event->type() == QEvent::DragMove) {
55 if (event->type() == QEvent::DragMove) {
56 auto w = static_cast<QWidget *>(obj);
56 auto w = static_cast<QWidget *>(obj);
57
57
58 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
58 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
59 auto moveEvent = static_cast<QDragMoveEvent *>(event);
59 auto moveEvent = static_cast<QDragMoveEvent *>(event);
60
60
61 auto pos = moveEvent->pos();
61 auto pos = moveEvent->pos();
62 if (impl->m_CurrentScrollArea->viewport() != w) {
62 if (impl->m_CurrentScrollArea->viewport() != w) {
63 auto globalPos = w->mapToGlobal(moveEvent->pos());
63 auto globalPos = w->mapToGlobal(moveEvent->pos());
64 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
64 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
65 }
65 }
66
66
67 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
67 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
68 - SCROLL_ZONE_SIZE;
68 - SCROLL_ZONE_SIZE;
69 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
69 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
70
70
71 if (!isInTopZone && !isInBottomZone) {
71 if (!isInTopZone && !isInBottomZone) {
72 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
72 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
73 impl->m_Timer->stop();
73 impl->m_Timer->stop();
74 }
74 }
75 else if (!impl->m_Timer->isActive()) {
75 else if (!impl->m_Timer->isActive()) {
76 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
76 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
77 : DragDropScrollerPrivate::ScrollDirection::down;
77 : DragDropScrollerPrivate::ScrollDirection::down;
78 impl->m_Timer->start();
78 impl->m_Timer->start();
79 }
79 }
80 }
80 }
81 }
81 }
82 else if (event->type() == QEvent::DragEnter) {
82 else if (event->type() == QEvent::DragEnter) {
83 auto w = static_cast<QWidget *>(obj);
83 auto w = static_cast<QWidget *>(obj);
84
84
85 for (auto scrollArea : impl->m_ScrollAreas) {
85 for (auto scrollArea : impl->m_ScrollAreas) {
86 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
86 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
87 auto enterEvent = static_cast<QDragEnterEvent *>(event);
87 auto enterEvent = static_cast<QDragEnterEvent *>(event);
88 enterEvent->acceptProposedAction();
88 enterEvent->acceptProposedAction();
89 enterEvent->setDropAction(Qt::IgnoreAction);
89 enterEvent->setDropAction(Qt::IgnoreAction);
90 impl->m_CurrentScrollArea = scrollArea;
90 impl->m_CurrentScrollArea = scrollArea;
91 break;
91 break;
92 }
92 }
93 }
93 }
94 }
94 }
95 else if (event->type() == QEvent::DragLeave) {
95 else if (event->type() == QEvent::DragLeave) {
96 auto w = static_cast<QWidget *>(obj);
97 if (impl->m_CurrentScrollArea) {
96 if (impl->m_CurrentScrollArea) {
98 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
97 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
99 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
98 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
100 impl->m_CurrentScrollArea = nullptr;
99 impl->m_CurrentScrollArea = nullptr;
101 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
100 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
102 impl->m_Timer->stop();
101 impl->m_Timer->stop();
103 }
102 }
104 }
103 }
105 }
104 }
106 else if (event->type() == QEvent::Drop) {
105 else if (event->type() == QEvent::Drop) {
107 auto w = static_cast<QWidget *>(obj);
108 if (impl->m_CurrentScrollArea) {
106 if (impl->m_CurrentScrollArea) {
109 impl->m_CurrentScrollArea = nullptr;
107 impl->m_CurrentScrollArea = nullptr;
110 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
108 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
111 impl->m_Timer->stop();
109 impl->m_Timer->stop();
112 }
110 }
113 }
111 }
114
112
115 return false;
113 return false;
116 }
114 }
117
115
118 void DragDropScroller::onTimer()
116 void DragDropScroller::onTimer()
119 {
117 {
120 if (impl->m_CurrentScrollArea) {
118 if (impl->m_CurrentScrollArea) {
121 auto mvt = 0;
119 auto mvt = 0;
122 switch (impl->m_Direction) {
120 switch (impl->m_Direction) {
123 case DragDropScrollerPrivate::ScrollDirection::up:
121 case DragDropScrollerPrivate::ScrollDirection::up:
124 mvt = SCROLL_SPEED;
122 mvt = SCROLL_SPEED;
125 break;
123 break;
126 case DragDropScrollerPrivate::ScrollDirection::down:
124 case DragDropScrollerPrivate::ScrollDirection::down:
127 mvt = -SCROLL_SPEED;
125 mvt = -SCROLL_SPEED;
128 break;
126 break;
129 default:
127 default:
130 break;
128 break;
131 }
129 }
132
130
133 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
131 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
134 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
132 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
135 }
133 }
136 }
134 }
137
135
138 struct DragDropHelper::DragDropHelperPrivate {
136 struct DragDropHelper::DragDropHelperPrivate {
139
137
140 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
138 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
141 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
139 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
142 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
140 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
143 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
141 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
144 // QTemporaryFile to have a name which is not generated.
142 // QTemporaryFile to have a name which is not generated.
145
143
146 explicit DragDropHelperPrivate()
144 explicit DragDropHelperPrivate()
147 : m_PlaceHolder{std::make_unique<QWidget>()},
145 : m_PlaceHolder{std::make_unique<QWidget>()},
148 m_DragDropScroller{std::make_unique<DragDropScroller>()}
146 m_DragDropScroller{std::make_unique<DragDropScroller>()}
149 {
147 {
150 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
148 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
151 sqpApp->installEventFilter(m_DragDropScroller.get());
149 sqpApp->installEventFilter(m_DragDropScroller.get());
152
150
153
151
154 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
152 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
155 }
153 }
156
154
157 void preparePlaceHolder() const
155 void preparePlaceHolder() const
158 {
156 {
159 if (m_CurrentDragWidget) {
157 if (m_CurrentDragWidget) {
160 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
158 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
161 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
159 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
162 }
160 }
163 else {
161 else {
164 m_PlaceHolder->setMinimumSize(200, 200);
162 m_PlaceHolder->setMinimumSize(200, 200);
165 }
163 }
166 }
164 }
167 };
165 };
168
166
169
167
170 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()} {}
168 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
169 {
170 }
171
171
172 DragDropHelper::~DragDropHelper()
172 DragDropHelper::~DragDropHelper()
173 {
173 {
174 QFile::remove(impl->m_ImageTempUrl);
174 QFile::remove(impl->m_ImageTempUrl);
175 }
175 }
176
176
177 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
177 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
178 {
178 {
179 impl->m_CurrentDragWidget = dragWidget;
179 impl->m_CurrentDragWidget = dragWidget;
180 }
180 }
181
181
182 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
182 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
183 {
183 {
184 return impl->m_CurrentDragWidget;
184 return impl->m_CurrentDragWidget;
185 }
185 }
186
186
187
187
188 QWidget &DragDropHelper::placeHolder() const
188 QWidget &DragDropHelper::placeHolder() const
189 {
189 {
190 return *impl->m_PlaceHolder;
190 return *impl->m_PlaceHolder;
191 }
191 }
192
192
193 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
193 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
194 {
194 {
195 removePlaceHolder();
195 removePlaceHolder();
196 impl->preparePlaceHolder();
196 impl->preparePlaceHolder();
197 layout->insertWidget(index, impl->m_PlaceHolder.get());
197 layout->insertWidget(index, impl->m_PlaceHolder.get());
198 impl->m_PlaceHolder->show();
198 impl->m_PlaceHolder->show();
199 }
199 }
200
200
201 void DragDropHelper::removePlaceHolder()
201 void DragDropHelper::removePlaceHolder()
202 {
202 {
203 auto parentWidget = impl->m_PlaceHolder->parentWidget();
203 auto parentWidget = impl->m_PlaceHolder->parentWidget();
204 if (parentWidget) {
204 if (parentWidget) {
205 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
205 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
206 impl->m_PlaceHolder->setParent(nullptr);
206 impl->m_PlaceHolder->setParent(nullptr);
207 impl->m_PlaceHolder->hide();
207 impl->m_PlaceHolder->hide();
208 }
208 }
209 }
209 }
210
210
211 bool DragDropHelper::isPlaceHolderSet() const
211 bool DragDropHelper::isPlaceHolderSet() const
212 {
212 {
213 return impl->m_PlaceHolder->parentWidget();
213 return impl->m_PlaceHolder->parentWidget();
214 }
214 }
215
215
216 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
216 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
217 {
217 {
218 impl->m_DragDropScroller->addScrollArea(scrollArea);
218 impl->m_DragDropScroller->addScrollArea(scrollArea);
219 }
219 }
220
220
221 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
221 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
222 {
222 {
223 impl->m_DragDropScroller->removeScrollArea(scrollArea);
223 impl->m_DragDropScroller->removeScrollArea(scrollArea);
224 }
224 }
225
225
226 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
226 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
227 {
227 {
228 image.save(impl->m_ImageTempUrl);
228 image.save(impl->m_ImageTempUrl);
229 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
229 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
230 }
230 }
@@ -1,155 +1,159
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 <DragDropHelper.h>
5 #include <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 <Visualization/VisualizationController.h>
11 #include <Visualization/VisualizationController.h>
12
12
13 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
13 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
14
14
15 class SqpApplication::SqpApplicationPrivate {
15 class SqpApplication::SqpApplicationPrivate {
16 public:
16 public:
17 SqpApplicationPrivate()
17 SqpApplicationPrivate()
18 : m_DataSourceController{std::make_unique<DataSourceController>()},
18 : m_DataSourceController{std::make_unique<DataSourceController>()},
19 m_NetworkController{std::make_unique<NetworkController>()},
19 m_NetworkController{std::make_unique<NetworkController>()},
20 m_TimeController{std::make_unique<TimeController>()},
20 m_TimeController{std::make_unique<TimeController>()},
21 m_VariableController{std::make_unique<VariableController>()},
21 m_VariableController{std::make_unique<VariableController>()},
22 m_VisualizationController{std::make_unique<VisualizationController>()},
22 m_VisualizationController{std::make_unique<VisualizationController>()},
23 m_DragDropHelper{std::make_unique<DragDropHelper>()}
23 m_DragDropHelper{std::make_unique<DragDropHelper>()}
24 {
24 {
25 // /////////////////////////////// //
25 // /////////////////////////////// //
26 // Connections between controllers //
26 // Connections between controllers //
27 // /////////////////////////////// //
27 // /////////////////////////////// //
28
28
29 // VariableController <-> DataSourceController
29 // VariableController <-> DataSourceController
30 connect(m_DataSourceController.get(),
30 connect(m_DataSourceController.get(),
31 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
31 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
32 std::shared_ptr<IDataProvider>)),
32 std::shared_ptr<IDataProvider>)),
33 m_VariableController.get(),
33 m_VariableController.get(),
34 SLOT(createVariable(const QString &, const QVariantHash &,
34 SLOT(createVariable(const QString &, const QVariantHash &,
35 std::shared_ptr<IDataProvider>)));
35 std::shared_ptr<IDataProvider>)));
36
36
37 // VariableController <-> VisualizationController
37 // VariableController <-> VisualizationController
38 connect(m_VariableController.get(),
38 connect(m_VariableController.get(),
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
39 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
40 m_VisualizationController.get(),
40 m_VisualizationController.get(),
41 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
41 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
42
42
43 connect(m_VariableController.get(),
43 connect(m_VariableController.get(),
44 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
44 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
45 m_VisualizationController.get(),
45 m_VisualizationController.get(),
46 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
46 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
47
47
48
48
49 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
49 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
50 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
50 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
51 m_NetworkController->moveToThread(&m_NetworkControllerThread);
51 m_NetworkController->moveToThread(&m_NetworkControllerThread);
52 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
52 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
53 m_VariableController->moveToThread(&m_VariableControllerThread);
53 m_VariableController->moveToThread(&m_VariableControllerThread);
54 m_VariableControllerThread.setObjectName("VariableControllerThread");
54 m_VariableControllerThread.setObjectName("VariableControllerThread");
55 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
55 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
56 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
56 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
57
57
58
58
59 // Additionnal init
59 // Additionnal init
60 m_VariableController->setTimeController(m_TimeController.get());
60 m_VariableController->setTimeController(m_TimeController.get());
61 }
61 }
62
62
63 virtual ~SqpApplicationPrivate()
63 virtual ~SqpApplicationPrivate()
64 {
64 {
65 m_DataSourceControllerThread.quit();
65 m_DataSourceControllerThread.quit();
66 m_DataSourceControllerThread.wait();
66 m_DataSourceControllerThread.wait();
67
67
68 m_NetworkControllerThread.quit();
68 m_NetworkControllerThread.quit();
69 m_NetworkControllerThread.wait();
69 m_NetworkControllerThread.wait();
70
70
71 m_VariableControllerThread.quit();
71 m_VariableControllerThread.quit();
72 m_VariableControllerThread.wait();
72 m_VariableControllerThread.wait();
73
73
74 m_VisualizationControllerThread.quit();
74 m_VisualizationControllerThread.quit();
75 m_VisualizationControllerThread.wait();
75 m_VisualizationControllerThread.wait();
76 }
76 }
77
77
78 std::unique_ptr<DataSourceController> m_DataSourceController;
78 std::unique_ptr<DataSourceController> m_DataSourceController;
79 std::unique_ptr<VariableController> m_VariableController;
79 std::unique_ptr<VariableController> m_VariableController;
80 std::unique_ptr<TimeController> m_TimeController;
80 std::unique_ptr<TimeController> m_TimeController;
81 std::unique_ptr<NetworkController> m_NetworkController;
81 std::unique_ptr<NetworkController> m_NetworkController;
82 std::unique_ptr<VisualizationController> m_VisualizationController;
82 std::unique_ptr<VisualizationController> m_VisualizationController;
83 QThread m_DataSourceControllerThread;
83 QThread m_DataSourceControllerThread;
84 QThread m_NetworkControllerThread;
84 QThread m_NetworkControllerThread;
85 QThread m_VariableControllerThread;
85 QThread m_VariableControllerThread;
86 QThread m_VisualizationControllerThread;
86 QThread m_VisualizationControllerThread;
87
87
88 std::unique_ptr<DragDropHelper> m_DragDropHelper;
88 std::unique_ptr<DragDropHelper> m_DragDropHelper;
89 };
89 };
90
90
91
91
92 SqpApplication::SqpApplication(int &argc, char **argv)
92 SqpApplication::SqpApplication(int &argc, char **argv)
93 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
93 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
94 {
94 {
95 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
95 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
96
96
97 connect(&impl->m_DataSourceControllerThread, &QThread::started,
97 connect(&impl->m_DataSourceControllerThread, &QThread::started,
98 impl->m_DataSourceController.get(), &DataSourceController::initialize);
98 impl->m_DataSourceController.get(), &DataSourceController::initialize);
99 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
99 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
100 impl->m_DataSourceController.get(), &DataSourceController::finalize);
100 impl->m_DataSourceController.get(), &DataSourceController::finalize);
101
101
102 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
102 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
103 &NetworkController::initialize);
103 &NetworkController::initialize);
104 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
104 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
105 &NetworkController::finalize);
105 &NetworkController::finalize);
106
106
107 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
107 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
108 &VariableController::initialize);
108 &VariableController::initialize);
109 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
109 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
110 &VariableController::finalize);
110 &VariableController::finalize);
111
111
112 connect(&impl->m_VisualizationControllerThread, &QThread::started,
112 connect(&impl->m_VisualizationControllerThread, &QThread::started,
113 impl->m_VisualizationController.get(), &VisualizationController::initialize);
113 impl->m_VisualizationController.get(), &VisualizationController::initialize);
114 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
114 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
115 impl->m_VisualizationController.get(), &VisualizationController::finalize);
115 impl->m_VisualizationController.get(), &VisualizationController::finalize);
116
116
117 impl->m_DataSourceControllerThread.start();
117 impl->m_DataSourceControllerThread.start();
118 impl->m_NetworkControllerThread.start();
118 impl->m_NetworkControllerThread.start();
119 impl->m_VariableControllerThread.start();
119 impl->m_VariableControllerThread.start();
120 impl->m_VisualizationControllerThread.start();
120 impl->m_VisualizationControllerThread.start();
121 }
121 }
122
122
123 SqpApplication::~SqpApplication() {}
123 SqpApplication::~SqpApplication()
124 {
125 }
124
126
125 void SqpApplication::initialize() {}
127 void SqpApplication::initialize()
128 {
129 }
126
130
127 DataSourceController &SqpApplication::dataSourceController() noexcept
131 DataSourceController &SqpApplication::dataSourceController() noexcept
128 {
132 {
129 return *impl->m_DataSourceController;
133 return *impl->m_DataSourceController;
130 }
134 }
131
135
132 NetworkController &SqpApplication::networkController() noexcept
136 NetworkController &SqpApplication::networkController() noexcept
133 {
137 {
134 return *impl->m_NetworkController;
138 return *impl->m_NetworkController;
135 }
139 }
136
140
137 TimeController &SqpApplication::timeController() noexcept
141 TimeController &SqpApplication::timeController() noexcept
138 {
142 {
139 return *impl->m_TimeController;
143 return *impl->m_TimeController;
140 }
144 }
141
145
142 VariableController &SqpApplication::variableController() noexcept
146 VariableController &SqpApplication::variableController() noexcept
143 {
147 {
144 return *impl->m_VariableController;
148 return *impl->m_VariableController;
145 }
149 }
146
150
147 VisualizationController &SqpApplication::visualizationController() noexcept
151 VisualizationController &SqpApplication::visualizationController() noexcept
148 {
152 {
149 return *impl->m_VisualizationController;
153 return *impl->m_VisualizationController;
150 }
154 }
151
155
152 DragDropHelper &SqpApplication::dragDropHelper() noexcept
156 DragDropHelper &SqpApplication::dragDropHelper() noexcept
153 {
157 {
154 return *impl->m_DragDropHelper;
158 return *impl->m_DragDropHelper;
155 }
159 }
@@ -1,301 +1,302
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
2 #include "DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include <QDrag>
6 #include <QDrag>
7 #include <QDragEnterEvent>
7 #include <QDragEnterEvent>
8 #include <QVBoxLayout>
8 #include <QVBoxLayout>
9
9
10 #include <cmath>
10 #include <memory>
11 #include <memory>
11
12
12 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
13 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
13
14
14 QVBoxLayout *m_Layout;
15 QVBoxLayout *m_Layout;
15 QStringList m_AcceptedMimeTypes;
16 QStringList m_AcceptedMimeTypes;
16 QStringList m_MergeAllowedMimeTypes;
17 QStringList m_MergeAllowedMimeTypes;
17
18
18 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
19 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
19 {
20 {
20 m_Layout = new QVBoxLayout(widget);
21 m_Layout = new QVBoxLayout(widget);
21 m_Layout->setContentsMargins(0, 0, 0, 0);
22 m_Layout->setContentsMargins(0, 0, 0, 0);
22 }
23 }
23
24
24 bool acceptMimeData(const QMimeData *data) const
25 bool acceptMimeData(const QMimeData *data) const
25 {
26 {
26 for (const auto &type : m_AcceptedMimeTypes) {
27 for (const auto &type : m_AcceptedMimeTypes) {
27 if (data->hasFormat(type)) {
28 if (data->hasFormat(type)) {
28 return true;
29 return true;
29 }
30 }
30 }
31 }
31
32
32 return false;
33 return false;
33 }
34 }
34
35
35 bool allowMergeMimeData(const QMimeData *data) const
36 bool allowMergeMimeData(const QMimeData *data) const
36 {
37 {
37 for (const auto &type : m_MergeAllowedMimeTypes) {
38 for (const auto &type : m_MergeAllowedMimeTypes) {
38 if (data->hasFormat(type)) {
39 if (data->hasFormat(type)) {
39 return true;
40 return true;
40 }
41 }
41 }
42 }
42
43
43 return false;
44 return false;
44 }
45 }
45
46
46 bool hasPlaceHolder() const
47 bool hasPlaceHolder() const
47 {
48 {
48 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
49 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
49 }
50 }
50
51
51 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
52 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
52 {
53 {
53 VisualizationDragWidget *dragWidget = nullptr;
54 VisualizationDragWidget *dragWidget = nullptr;
54
55
55 for (auto child : parent->children()) {
56 for (auto child : parent->children()) {
56 auto widget = qobject_cast<VisualizationDragWidget *>(child);
57 auto widget = qobject_cast<VisualizationDragWidget *>(child);
57 if (widget && widget->isVisible()) {
58 if (widget && widget->isVisible()) {
58 if (widget->frameGeometry().contains(pos)) {
59 if (widget->frameGeometry().contains(pos)) {
59 dragWidget = widget;
60 dragWidget = widget;
60 break;
61 break;
61 }
62 }
62 }
63 }
63 }
64 }
64
65
65 return dragWidget;
66 return dragWidget;
66 }
67 }
67
68
68 bool cursorIsInContainer(QWidget *container) const
69 bool cursorIsInContainer(QWidget *container) const
69 {
70 {
70 auto adustNum = 18; // to be safe, in case of scrollbar on the side
71 auto adustNum = 18; // to be safe, in case of scrollbar on the side
71 auto containerRect = QRect(QPoint(), container->contentsRect().size())
72 auto containerRect = QRect(QPoint(), container->contentsRect().size())
72 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
73 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
73 qDebug() << containerRect << container->mapFromGlobal(QCursor::pos());
74 qDebug() << containerRect << container->mapFromGlobal(QCursor::pos());
74 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
75 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
75 }
76 }
76 };
77 };
77
78
78 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
79 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
79 : QWidget{parent},
80 : QWidget{parent},
80 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
81 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
81 {
82 {
82 setAcceptDrops(true);
83 setAcceptDrops(true);
83 }
84 }
84
85
85 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
86 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
86 {
87 {
87 impl->m_Layout->addWidget(dragWidget);
88 impl->m_Layout->addWidget(dragWidget);
88 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
89 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
89 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
90 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
90 &VisualizationDragDropContainer::startDrag);
91 &VisualizationDragDropContainer::startDrag);
91 }
92 }
92
93
93 void VisualizationDragDropContainer::insertDragWidget(int index,
94 void VisualizationDragDropContainer::insertDragWidget(int index,
94 VisualizationDragWidget *dragWidget)
95 VisualizationDragWidget *dragWidget)
95 {
96 {
96 impl->m_Layout->insertWidget(index, dragWidget);
97 impl->m_Layout->insertWidget(index, dragWidget);
97 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
98 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
98 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
99 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
99 &VisualizationDragDropContainer::startDrag);
100 &VisualizationDragDropContainer::startDrag);
100 }
101 }
101
102
102 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
103 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
103 {
104 {
104 impl->m_AcceptedMimeTypes = mimeTypes;
105 impl->m_AcceptedMimeTypes = mimeTypes;
105 }
106 }
106
107
107 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
108 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
108 {
109 {
109 impl->m_MergeAllowedMimeTypes = mimeTypes;
110 impl->m_MergeAllowedMimeTypes = mimeTypes;
110 }
111 }
111
112
112 int VisualizationDragDropContainer::countDragWidget() const
113 int VisualizationDragDropContainer::countDragWidget() const
113 {
114 {
114 auto nbGraph = 0;
115 auto nbGraph = 0;
115 for (auto child : children()) {
116 for (auto child : children()) {
116 auto widget = qobject_cast<VisualizationDragWidget *>(child);
117 auto widget = qobject_cast<VisualizationDragWidget *>(child);
117 if (widget) {
118 if (widget) {
118 nbGraph += 1;
119 nbGraph += 1;
119 }
120 }
120 }
121 }
121
122
122 return nbGraph;
123 return nbGraph;
123 }
124 }
124
125
125 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
126 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
126 const QPoint &dragPosition)
127 const QPoint &dragPosition)
127 {
128 {
128 auto &helper = sqpApp->dragDropHelper();
129 auto &helper = sqpApp->dragDropHelper();
129
130
130 // Note: The management of the drag object is done by Qt
131 // Note: The management of the drag object is done by Qt
131 auto *drag = new QDrag{dragWidget};
132 auto *drag = new QDrag{dragWidget};
132 drag->setHotSpot(dragPosition);
133 drag->setHotSpot(dragPosition);
133
134
134 auto mimeData = dragWidget->mimeData();
135 auto mimeData = dragWidget->mimeData();
135 drag->setMimeData(mimeData);
136 drag->setMimeData(mimeData);
136
137
137 auto pixmap = QPixmap(dragWidget->size());
138 auto pixmap = QPixmap(dragWidget->size());
138 dragWidget->render(&pixmap);
139 dragWidget->render(&pixmap);
139 drag->setPixmap(pixmap);
140 drag->setPixmap(pixmap);
140
141
141 auto image = pixmap.toImage();
142 auto image = pixmap.toImage();
142 mimeData->setImageData(image);
143 mimeData->setImageData(image);
143 mimeData->setUrls({helper.imageTemporaryUrl(image)});
144 mimeData->setUrls({helper.imageTemporaryUrl(image)});
144
145
145 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
146 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
146 helper.setCurrentDragWidget(dragWidget);
147 helper.setCurrentDragWidget(dragWidget);
147
148
148 if (impl->cursorIsInContainer(this)) {
149 if (impl->cursorIsInContainer(this)) {
149 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
150 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
150 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
151 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
151 dragWidget->setVisible(false);
152 dragWidget->setVisible(false);
152 }
153 }
153 }
154 }
154
155
155 // Note: The exec() is blocking on windows but not on linux and macOS
156 // Note: The exec() is blocking on windows but not on linux and macOS
156 drag->exec(Qt::MoveAction | Qt::CopyAction);
157 drag->exec(Qt::MoveAction | Qt::CopyAction);
157 }
158 }
158
159
159 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
160 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
160 {
161 {
161 if (impl->acceptMimeData(event->mimeData())) {
162 if (impl->acceptMimeData(event->mimeData())) {
162 event->acceptProposedAction();
163 event->acceptProposedAction();
163
164
164 auto &helper = sqpApp->dragDropHelper();
165 auto &helper = sqpApp->dragDropHelper();
165
166
166 if (!impl->hasPlaceHolder()) {
167 if (!impl->hasPlaceHolder()) {
167 auto dragWidget = helper.getCurrentDragWidget();
168 auto dragWidget = helper.getCurrentDragWidget();
168 auto parentWidget
169 auto parentWidget
169 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
170 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
170 if (parentWidget) {
171 if (parentWidget) {
171 dragWidget->setVisible(false);
172 dragWidget->setVisible(false);
172 }
173 }
173
174
174 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
175 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
175
176
176 if (dragWidgetHovered) {
177 if (dragWidgetHovered) {
177 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
178 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
178 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
179 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
179 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
180 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
180 hoveredWidgetIndex
181 hoveredWidgetIndex
181 += 1; // Correction of the index if the drop occurs in the same container
182 += 1; // Correction of the index if the drop occurs in the same container
182 }
183 }
183
184
184 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
185 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
185 }
186 }
186 else {
187 else {
187 helper.insertPlaceHolder(impl->m_Layout, 0);
188 helper.insertPlaceHolder(impl->m_Layout, 0);
188 }
189 }
189 }
190 }
190 }
191 }
191 else
192 else
192 event->ignore();
193 event->ignore();
193
194
194 QWidget::dragEnterEvent(event);
195 QWidget::dragEnterEvent(event);
195 }
196 }
196
197
197 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
198 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
198 {
199 {
199 Q_UNUSED(event);
200 Q_UNUSED(event);
200
201
201 auto &helper = sqpApp->dragDropHelper();
202 auto &helper = sqpApp->dragDropHelper();
202
203
203 if (!impl->cursorIsInContainer(this)) {
204 if (!impl->cursorIsInContainer(this)) {
204 helper.removePlaceHolder();
205 helper.removePlaceHolder();
205
206
206 bool isInternal = true;
207 bool isInternal = true;
207 if (isInternal) {
208 if (isInternal) {
208 // Only if the drag is strated from the visualization
209 // Only if the drag is strated from the visualization
209 // Show the drag widget at its original place
210 // Show the drag widget at its original place
210 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
211 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
211 // drop zone (It is not possible to catch a drop event outside of the application)
212 // drop zone (It is not possible to catch a drop event outside of the application)
212
213
213 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
214 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
214 if (dragWidget) {
215 if (dragWidget) {
215 dragWidget->setVisible(true);
216 dragWidget->setVisible(true);
216 }
217 }
217 }
218 }
218 }
219 }
219
220
220 QWidget::dragLeaveEvent(event);
221 QWidget::dragLeaveEvent(event);
221 }
222 }
222
223
223 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
224 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
224 {
225 {
225 if (impl->acceptMimeData(event->mimeData())) {
226 if (impl->acceptMimeData(event->mimeData())) {
226 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
227 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
227 if (dragWidgetHovered) {
228 if (dragWidgetHovered) {
228 auto canMerge = impl->allowMergeMimeData(event->mimeData());
229 auto canMerge = impl->allowMergeMimeData(event->mimeData());
229
230
230 auto nbDragWidget = countDragWidget();
231 auto nbDragWidget = countDragWidget();
231 if (nbDragWidget > 0) {
232 if (nbDragWidget > 0) {
232 auto graphHeight = size().height() / nbDragWidget;
233 auto graphHeight = size().height() / nbDragWidget;
233 auto dropIndex = floor(event->pos().y() / graphHeight);
234 auto dropIndex = floor(event->pos().y() / graphHeight);
234 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
235 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
235
236
236 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
237 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
237 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
238 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
238
239
239 auto &helper = sqpApp->dragDropHelper();
240 auto &helper = sqpApp->dragDropHelper();
240 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
241 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
241
242
242 if (isOnTop || isOnBottom) {
243 if (isOnTop || isOnBottom) {
243 if (isOnBottom) {
244 if (isOnBottom) {
244 dropIndex += 1;
245 dropIndex += 1;
245 }
246 }
246
247
247 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
248 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
248 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
249 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
249 dropIndex += 1; // Correction of the index if the drop occurs in the same
250 dropIndex += 1; // Correction of the index if the drop occurs in the same
250 // container
251 // container
251 }
252 }
252
253
253 if (dropIndex != placeHolderIndex) {
254 if (dropIndex != placeHolderIndex) {
254 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
255 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
255 }
256 }
256 }
257 }
257 else if (canMerge) {
258 else if (canMerge) {
258 // drop on the middle -> merge
259 // drop on the middle -> merge
259 if (impl->hasPlaceHolder()) {
260 if (impl->hasPlaceHolder()) {
260 helper.removePlaceHolder();
261 helper.removePlaceHolder();
261 }
262 }
262 }
263 }
263 }
264 }
264 }
265 }
265 }
266 }
266 else
267 else
267 event->ignore();
268 event->ignore();
268
269
269 QWidget::dragMoveEvent(event);
270 QWidget::dragMoveEvent(event);
270 }
271 }
271
272
272 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
273 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
273 {
274 {
274 if (impl->acceptMimeData(event->mimeData())) {
275 if (impl->acceptMimeData(event->mimeData())) {
275 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
276 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
276 if (impl->hasPlaceHolder() && dragWidget) {
277 if (impl->hasPlaceHolder() && dragWidget) {
277 auto &helper = sqpApp->dragDropHelper();
278 auto &helper = sqpApp->dragDropHelper();
278
279
279 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
280 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
280
281
281 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
282 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
282 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
283 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
283 droppedIndex
284 droppedIndex
284 -= 1; // Correction of the index if the drop occurs in the same container
285 -= 1; // Correction of the index if the drop occurs in the same container
285 }
286 }
286
287
287 dragWidget->setVisible(true);
288 dragWidget->setVisible(true);
288 dragWidget->setStyleSheet("");
289 dragWidget->setStyleSheet("");
289
290
290 event->acceptProposedAction();
291 event->acceptProposedAction();
291
292
292 helper.removePlaceHolder();
293 helper.removePlaceHolder();
293
294
294 emit dropOccured(droppedIndex, event->mimeData());
295 emit dropOccured(droppedIndex, event->mimeData());
295 }
296 }
296 }
297 }
297 else
298 else
298 event->ignore();
299 event->ignore();
299
300
300 QWidget::dropEvent(event);
301 QWidget::dropEvent(event);
301 }
302 }
@@ -1,385 +1,384
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationDefs.h"
3 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationGraphHelper.h"
4 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
5 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Data/ArrayData.h>
9 #include <Data/ArrayData.h>
10 #include <Data/IDataSeries.h>
10 #include <Data/IDataSeries.h>
11 #include <DragDropHelper.h>
11 #include <DragDropHelper.h>
12 #include <Settings/SqpSettingsDefs.h>
12 #include <Settings/SqpSettingsDefs.h>
13 #include <SqpApplication.h>
13 #include <SqpApplication.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 <unordered_map>
17 #include <unordered_map>
18
18
19 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
19 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
20
20
21 namespace {
21 namespace {
22
22
23 /// Key pressed to enable zoom on horizontal axis
23 /// Key pressed to enable zoom on horizontal axis
24 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
24 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
25
25
26 /// Key pressed to enable zoom on vertical axis
26 /// Key pressed to enable zoom on vertical axis
27 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
27 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
28
28
29 } // namespace
29 } // namespace
30
30
31 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
31 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
32
32
33 explicit VisualizationGraphWidgetPrivate(const QString &name)
33 explicit VisualizationGraphWidgetPrivate(const QString &name)
34 : m_Name{name},
34 : m_Name{name},
35 m_DoAcquisition{true},
35 m_DoAcquisition{true},
36 m_IsCalibration{false},
36 m_IsCalibration{false},
37 m_RenderingDelegate{nullptr}
37 m_RenderingDelegate{nullptr}
38 {
38 {
39 }
39 }
40
40
41 QString m_Name;
41 QString m_Name;
42 // 1 variable -> n qcpplot
42 // 1 variable -> n qcpplot
43 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
43 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
44 bool m_DoAcquisition;
44 bool m_DoAcquisition;
45 bool m_IsCalibration;
45 bool m_IsCalibration;
46 QCPItemTracer *m_TextTracer;
46 QCPItemTracer *m_TextTracer;
47 /// Delegate used to attach rendering features to the plot
47 /// Delegate used to attach rendering features to the plot
48 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
48 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
49 };
49 };
50
50
51 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
51 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
52 : VisualizationDragWidget{parent},
52 : VisualizationDragWidget{parent},
53 ui{new Ui::VisualizationGraphWidget},
53 ui{new Ui::VisualizationGraphWidget},
54 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
54 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
55 {
55 {
56 ui->setupUi(this);
56 ui->setupUi(this);
57
57
58 // 'Close' options : widget is deleted when closed
58 // 'Close' options : widget is deleted when closed
59 setAttribute(Qt::WA_DeleteOnClose);
59 setAttribute(Qt::WA_DeleteOnClose);
60
60
61 // Set qcpplot properties :
61 // Set qcpplot properties :
62 // - Drag (on x-axis) and zoom are enabled
62 // - Drag (on x-axis) and zoom are enabled
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
63 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
64 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
65 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
66
66
67 // The delegate must be initialized after the ui as it uses the plot
67 // The delegate must be initialized after the ui as it uses the plot
68 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
68 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
69
69
70 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
70 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
71 connect(ui->widget, &QCustomPlot::mouseRelease, this,
71 connect(ui->widget, &QCustomPlot::mouseRelease, this,
72 &VisualizationGraphWidget::onMouseRelease);
72 &VisualizationGraphWidget::onMouseRelease);
73 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
73 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
74 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
74 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
75 connect(
75 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
76 ui->widget->xAxis,
76 &QCPAxis::rangeChanged),
77 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
77 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79
78
80 // Activates menu when right clicking on the graph
79 // Activates menu when right clicking on the graph
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
80 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
81 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 &VisualizationGraphWidget::onGraphMenuRequested);
82 &VisualizationGraphWidget::onGraphMenuRequested);
84
83
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
84 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 &VariableController::onRequestDataLoading);
85 &VariableController::onRequestDataLoading);
87
86
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
87 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
88 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 }
89 }
91
90
92
91
93 VisualizationGraphWidget::~VisualizationGraphWidget()
92 VisualizationGraphWidget::~VisualizationGraphWidget()
94 {
93 {
95 delete ui;
94 delete ui;
96 }
95 }
97
96
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
97 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 {
98 {
100 auto parent = parentWidget();
99 auto parent = parentWidget();
101 do {
100 do {
102 parent = parent->parentWidget();
101 parent = parent->parentWidget();
103 } while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent));
102 } while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent));
104
103
105 return qobject_cast<VisualizationZoneWidget *>(parent);
104 return qobject_cast<VisualizationZoneWidget *>(parent);
106 }
105 }
107
106
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
107 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 {
108 {
110 impl->m_DoAcquisition = enable;
109 impl->m_DoAcquisition = enable;
111 }
110 }
112
111
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
112 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 {
113 {
115 // Uses delegate to create the qcpplot components according to the variable
114 // Uses delegate to create the qcpplot components according to the variable
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
115 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
116 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
118
117
119 // Set axes properties according to the units of the data series
118 // Set axes properties according to the units of the data series
120 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
119 /// @todo : for the moment, no control is performed on the axes: the units and the tickers
121 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
120 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
122 auto xAxisUnit = Unit{};
121 auto xAxisUnit = Unit{};
123 auto valuesUnit = Unit{};
122 auto valuesUnit = Unit{};
124
123
125 if (auto dataSeries = variable->dataSeries()) {
124 if (auto dataSeries = variable->dataSeries()) {
126 dataSeries->lockRead();
125 dataSeries->lockRead();
127 xAxisUnit = dataSeries->xAxisUnit();
126 xAxisUnit = dataSeries->xAxisUnit();
128 valuesUnit = dataSeries->valuesUnit();
127 valuesUnit = dataSeries->valuesUnit();
129 dataSeries->unlock();
128 dataSeries->unlock();
130 }
129 }
131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
130 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
132
131
133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
132 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
134
133
135 this->enableAcquisition(false);
134 this->enableAcquisition(false);
136 this->setGraphRange(range);
135 this->setGraphRange(range);
137 this->enableAcquisition(true);
136 this->enableAcquisition(true);
138
137
139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
138 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
140
139
141 emit variableAdded(variable);
140 emit variableAdded(variable);
142 }
141 }
143
142
144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
143 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
145 {
144 {
146 // Each component associated to the variable :
145 // Each component associated to the variable :
147 // - is removed from qcpplot (which deletes it)
146 // - is removed from qcpplot (which deletes it)
148 // - is no longer referenced in the map
147 // - is no longer referenced in the map
149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
148 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
149 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
151 emit variableAboutToBeRemoved(variable);
150 emit variableAboutToBeRemoved(variable);
152
151
153 auto &plottablesMap = variableIt->second;
152 auto &plottablesMap = variableIt->second;
154
153
155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
154 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
156 plottableIt != plottableEnd;) {
155 plottableIt != plottableEnd;) {
157 ui->widget->removePlottable(plottableIt->second);
156 ui->widget->removePlottable(plottableIt->second);
158 plottableIt = plottablesMap.erase(plottableIt);
157 plottableIt = plottablesMap.erase(plottableIt);
159 }
158 }
160
159
161 impl->m_VariableToPlotMultiMap.erase(variableIt);
160 impl->m_VariableToPlotMultiMap.erase(variableIt);
162 }
161 }
163
162
164 // Updates graph
163 // Updates graph
165 ui->widget->replot();
164 ui->widget->replot();
166 }
165 }
167
166
168 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
167 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
169 {
168 {
170 auto variables = QList<std::shared_ptr<Variable> >{};
169 auto variables = QList<std::shared_ptr<Variable> >{};
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
170 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
172 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
171 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
173 variables << it->first;
172 variables << it->first;
174 }
173 }
175
174
176 return variables;
175 return variables;
177 }
176 }
178
177
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
178 void VisualizationGraphWidget::setYRange(const SqpRange &range)
180 {
179 {
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
180 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
182 }
181 }
183
182
184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
183 SqpRange VisualizationGraphWidget::graphRange() const noexcept
185 {
184 {
186 auto graphRange = ui->widget->xAxis->range();
185 auto graphRange = ui->widget->xAxis->range();
187 return SqpRange{graphRange.lower, graphRange.upper};
186 return SqpRange{graphRange.lower, graphRange.upper};
188 }
187 }
189
188
190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
189 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
191 {
190 {
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
191 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
192 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
194 ui->widget->replot();
193 ui->widget->replot();
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
194 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
196 }
195 }
197
196
198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
197 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
199 {
198 {
200 if (visitor) {
199 if (visitor) {
201 visitor->visit(this);
200 visitor->visit(this);
202 }
201 }
203 else {
202 else {
204 qCCritical(LOG_VisualizationGraphWidget())
203 qCCritical(LOG_VisualizationGraphWidget())
205 << tr("Can't visit widget : the visitor is null");
204 << tr("Can't visit widget : the visitor is null");
206 }
205 }
207 }
206 }
208
207
209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
208 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
210 {
209 {
211 /// @todo : for the moment, a graph can always accomodate a variable
210 /// @todo : for the moment, a graph can always accomodate a variable
212 Q_UNUSED(variable);
211 Q_UNUSED(variable);
213 return true;
212 return true;
214 }
213 }
215
214
216 bool VisualizationGraphWidget::contains(const Variable &variable) const
215 bool VisualizationGraphWidget::contains(const Variable &variable) const
217 {
216 {
218 // Finds the variable among the keys of the map
217 // Finds the variable among the keys of the map
219 auto variablePtr = &variable;
218 auto variablePtr = &variable;
220 auto findVariable
219 auto findVariable
221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
220 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
222
221
223 auto end = impl->m_VariableToPlotMultiMap.cend();
222 auto end = impl->m_VariableToPlotMultiMap.cend();
224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
223 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
225 return it != end;
224 return it != end;
226 }
225 }
227
226
228 QString VisualizationGraphWidget::name() const
227 QString VisualizationGraphWidget::name() const
229 {
228 {
230 return impl->m_Name;
229 return impl->m_Name;
231 }
230 }
232
231
233 QMimeData *VisualizationGraphWidget::mimeData() const
232 QMimeData *VisualizationGraphWidget::mimeData() const
234 {
233 {
235 auto *mimeData = new QMimeData;
234 auto *mimeData = new QMimeData;
236 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
235 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
237
236
238 return mimeData;
237 return mimeData;
239 }
238 }
240
239
241 bool VisualizationGraphWidget::isDragAllowed() const
240 bool VisualizationGraphWidget::isDragAllowed() const
242 {
241 {
243 return true;
242 return true;
244 }
243 }
245
244
246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
245 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
247 {
246 {
248 Q_UNUSED(event);
247 Q_UNUSED(event);
249
248
250 // Prevents that all variables will be removed from graph when it will be closed
249 // Prevents that all variables will be removed from graph when it will be closed
251 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
250 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
252 emit variableAboutToBeRemoved(variableEntry.first);
251 emit variableAboutToBeRemoved(variableEntry.first);
253 }
252 }
254 }
253 }
255
254
256 void VisualizationGraphWidget::enterEvent(QEvent *event)
255 void VisualizationGraphWidget::enterEvent(QEvent *event)
257 {
256 {
258 Q_UNUSED(event);
257 Q_UNUSED(event);
259 impl->m_RenderingDelegate->showGraphOverlay(true);
258 impl->m_RenderingDelegate->showGraphOverlay(true);
260 }
259 }
261
260
262 void VisualizationGraphWidget::leaveEvent(QEvent *event)
261 void VisualizationGraphWidget::leaveEvent(QEvent *event)
263 {
262 {
264 Q_UNUSED(event);
263 Q_UNUSED(event);
265 impl->m_RenderingDelegate->showGraphOverlay(false);
264 impl->m_RenderingDelegate->showGraphOverlay(false);
266 }
265 }
267
266
268 QCustomPlot &VisualizationGraphWidget::plot() noexcept
267 QCustomPlot &VisualizationGraphWidget::plot() noexcept
269 {
268 {
270 return *ui->widget;
269 return *ui->widget;
271 }
270 }
272
271
273 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
272 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
274 {
273 {
275 QMenu graphMenu{};
274 QMenu graphMenu{};
276
275
277 // Iterates on variables (unique keys)
276 // Iterates on variables (unique keys)
278 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
277 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
279 end = impl->m_VariableToPlotMultiMap.cend();
278 end = impl->m_VariableToPlotMultiMap.cend();
280 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
279 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
281 // 'Remove variable' action
280 // 'Remove variable' action
282 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
281 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
283 [ this, var = it->first ]() { removeVariable(var); });
282 [ this, var = it->first ]() { removeVariable(var); });
284 }
283 }
285
284
286 if (!graphMenu.isEmpty()) {
285 if (!graphMenu.isEmpty()) {
287 graphMenu.exec(QCursor::pos());
286 graphMenu.exec(QCursor::pos());
288 }
287 }
289 }
288 }
290
289
291 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
290 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
292 {
291 {
293 qCDebug(LOG_VisualizationGraphWidget())
292 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
294 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
293 << QThread::currentThread()->objectName() << "DoAcqui"
295 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
294 << impl->m_DoAcquisition;
296
295
297 auto graphRange = SqpRange{t1.lower, t1.upper};
296 auto graphRange = SqpRange{t1.lower, t1.upper};
298 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
297 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
299
298
300 if (impl->m_DoAcquisition) {
299 if (impl->m_DoAcquisition) {
301 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
300 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
302
301
303 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
302 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
304 end = impl->m_VariableToPlotMultiMap.end();
303 end = impl->m_VariableToPlotMultiMap.end();
305 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
304 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
306 variableUnderGraphVector.push_back(it->first);
305 variableUnderGraphVector.push_back(it->first);
307 }
306 }
308 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
307 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
309 !impl->m_IsCalibration);
308 !impl->m_IsCalibration);
310
309
311 if (!impl->m_IsCalibration) {
310 if (!impl->m_IsCalibration) {
312 qCDebug(LOG_VisualizationGraphWidget())
311 qCDebug(LOG_VisualizationGraphWidget())
313 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
312 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
314 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
313 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
315 emit synchronize(graphRange, oldGraphRange);
314 emit synchronize(graphRange, oldGraphRange);
316 }
315 }
317 }
316 }
318 }
317 }
319
318
320 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
319 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
321 {
320 {
322 // Handles plot rendering when mouse is moving
321 // Handles plot rendering when mouse is moving
323 impl->m_RenderingDelegate->onMouseMove(event);
322 impl->m_RenderingDelegate->onMouseMove(event);
324
323
325 VisualizationDragWidget::mouseMoveEvent(event);
324 VisualizationDragWidget::mouseMoveEvent(event);
326 }
325 }
327
326
328 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
327 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
329 {
328 {
330 auto zoomOrientations = QFlags<Qt::Orientation>{};
329 auto zoomOrientations = QFlags<Qt::Orientation>{};
331
330
332 // Lambda that enables a zoom orientation if the key modifier related to this orientation
331 // Lambda that enables a zoom orientation if the key modifier related to this orientation
333 // has
332 // has
334 // been pressed
333 // been pressed
335 auto enableOrientation
334 auto enableOrientation
336 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
335 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
337 auto orientationEnabled = event->modifiers().testFlag(modifier);
336 auto orientationEnabled = event->modifiers().testFlag(modifier);
338 zoomOrientations.setFlag(orientation, orientationEnabled);
337 zoomOrientations.setFlag(orientation, orientationEnabled);
339 };
338 };
340 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
339 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
341 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
340 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
342
341
343 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
342 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
344 }
343 }
345
344
346 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
345 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
347 {
346 {
348 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
347 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
349
348
350 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
349 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
351
350
352 VisualizationDragWidget::mousePressEvent(event);
351 VisualizationDragWidget::mousePressEvent(event);
353 }
352 }
354
353
355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
354 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
356 {
355 {
357 impl->m_IsCalibration = false;
356 impl->m_IsCalibration = false;
358 }
357 }
359
358
360 void VisualizationGraphWidget::onDataCacheVariableUpdated()
359 void VisualizationGraphWidget::onDataCacheVariableUpdated()
361 {
360 {
362 auto graphRange = ui->widget->xAxis->range();
361 auto graphRange = ui->widget->xAxis->range();
363 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
362 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
364
363
365 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
364 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
366 auto variable = variableEntry.first;
365 auto variable = variableEntry.first;
367 qCDebug(LOG_VisualizationGraphWidget())
366 qCDebug(LOG_VisualizationGraphWidget())
368 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
367 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
369 qCDebug(LOG_VisualizationGraphWidget())
368 qCDebug(LOG_VisualizationGraphWidget())
370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
369 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
371 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
370 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
372 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
371 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
373 variable->range());
372 variable->range());
374 }
373 }
375 }
374 }
376 }
375 }
377
376
378 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
377 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
379 const SqpRange &range)
378 const SqpRange &range)
380 {
379 {
381 auto it = impl->m_VariableToPlotMultiMap.find(variable);
380 auto it = impl->m_VariableToPlotMultiMap.find(variable);
382 if (it != impl->m_VariableToPlotMultiMap.end()) {
381 if (it != impl->m_VariableToPlotMultiMap.end()) {
383 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
382 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
384 }
383 }
385 }
384 }
@@ -1,410 +1,410
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 "ui_VisualizationZoneWidget.h"
6 #include "ui_VisualizationZoneWidget.h"
7
7
8 #include <Data/SqpRange.h>
8 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11
11
12 #include <DragDropHelper.h>
12 #include <DragDropHelper.h>
13 #include <QUuid>
13 #include <QUuid>
14 #include <SqpApplication.h>
14 #include <SqpApplication.h>
15 #include <cmath>
15 #include <cmath>
16
16
17 #include <QLayout>
17 #include <QLayout>
18
18
19 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
19 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
20
20
21 namespace {
21 namespace {
22
22
23 /// Minimum height for graph added in zones (in pixels)
23 /// Minimum height for graph added in zones (in pixels)
24 const auto GRAPH_MINIMUM_HEIGHT = 300;
24 const auto GRAPH_MINIMUM_HEIGHT = 300;
25
25
26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
27 /// the zone
27 /// the zone
28 QString defaultGraphName(const QLayout &layout)
28 QString defaultGraphName(const QLayout &layout)
29 {
29 {
30 auto count = 0;
30 auto count = 0;
31 for (auto i = 0; i < layout.count(); ++i) {
31 for (auto i = 0; i < layout.count(); ++i) {
32 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
32 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
33 count++;
33 count++;
34 }
34 }
35 }
35 }
36
36
37 return QObject::tr("Graph %1").arg(count + 1);
37 return QObject::tr("Graph %1").arg(count + 1);
38 }
38 }
39
39
40 /**
40 /**
41 * Applies a function to all graphs of the zone represented by its layout
41 * Applies a function to all graphs of the zone represented by its layout
42 * @param layout the layout that contains graphs
42 * @param layout the layout that contains graphs
43 * @param fun the function to apply to each graph
43 * @param fun the function to apply to each graph
44 */
44 */
45 template <typename Fun>
45 template <typename Fun>
46 void processGraphs(QLayout &layout, Fun fun)
46 void processGraphs(QLayout &layout, Fun fun)
47 {
47 {
48 for (auto i = 0; i < layout.count(); ++i) {
48 for (auto i = 0; i < layout.count(); ++i) {
49 if (auto item = layout.itemAt(i)) {
49 if (auto item = layout.itemAt(i)) {
50 if (auto visualizationGraphWidget
50 if (auto visualizationGraphWidget
51 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
51 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
52 fun(*visualizationGraphWidget);
52 fun(*visualizationGraphWidget);
53 }
53 }
54 }
54 }
55 }
55 }
56 }
56 }
57
57
58 } // namespace
58 } // namespace
59
59
60 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
60 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
61
61
62 explicit VisualizationZoneWidgetPrivate()
62 explicit VisualizationZoneWidgetPrivate()
63 : m_SynchronisationGroupId{QUuid::createUuid()},
63 : m_SynchronisationGroupId{QUuid::createUuid()},
64 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
64 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
65 {
65 {
66 }
66 }
67 QUuid m_SynchronisationGroupId;
67 QUuid m_SynchronisationGroupId;
68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
69 };
69 };
70
70
71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
72 : VisualizationDragWidget{parent},
72 : VisualizationDragWidget{parent},
73 ui{new Ui::VisualizationZoneWidget},
73 ui{new Ui::VisualizationZoneWidget},
74 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
74 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
75 {
75 {
76 ui->setupUi(this);
76 ui->setupUi(this);
77
77
78 ui->zoneNameLabel->setText(name);
78 ui->zoneNameLabel->setText(name);
79
79
80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
82 &VisualizationZoneWidget::dropMimeData);
82 &VisualizationZoneWidget::dropMimeData);
83
83
84 // 'Close' options : widget is deleted when closed
84 // 'Close' options : widget is deleted when closed
85 setAttribute(Qt::WA_DeleteOnClose);
85 setAttribute(Qt::WA_DeleteOnClose);
86 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
86 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
87 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
87 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
88
88
89 // Synchronisation id
89 // Synchronisation id
90 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
90 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
91 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
91 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
92 }
92 }
93
93
94 VisualizationZoneWidget::~VisualizationZoneWidget()
94 VisualizationZoneWidget::~VisualizationZoneWidget()
95 {
95 {
96 delete ui;
96 delete ui;
97 }
97 }
98
98
99 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
99 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
100 {
100 {
101 // Synchronize new graph with others in the zone
101 // Synchronize new graph with others in the zone
102 impl->m_Synchronizer->addGraph(*graphWidget);
102 impl->m_Synchronizer->addGraph(*graphWidget);
103
103
104 ui->dragDropContainer->addDragWidget(graphWidget);
104 ui->dragDropContainer->addDragWidget(graphWidget);
105 }
105 }
106
106
107 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
107 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
108 {
108 {
109 // Synchronize new graph with others in the zone
109 // Synchronize new graph with others in the zone
110 impl->m_Synchronizer->addGraph(*graphWidget);
110 impl->m_Synchronizer->addGraph(*graphWidget);
111
111
112 ui->dragDropContainer->insertDragWidget(index, graphWidget);
112 ui->dragDropContainer->insertDragWidget(index, graphWidget);
113 }
113 }
114
114
115 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
115 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
116 {
116 {
117 return createGraph(variable, -1);
117 return createGraph(variable, -1);
118 }
118 }
119
119
120 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
120 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
121 int index)
121 int index)
122 {
122 {
123 auto graphWidget
123 auto graphWidget
124 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
124 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
125
125
126
126
127 // Set graph properties
127 // Set graph properties
128 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
128 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
129 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
129 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
130
130
131
131
132 // Lambda to synchronize zone widget
132 // Lambda to synchronize zone widget
133 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
133 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
134 const SqpRange &oldGraphRange) {
134 const SqpRange &oldGraphRange) {
135
135
136 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
136 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
137 auto frameLayout = ui->dragDropContainer->layout();
137 auto frameLayout = ui->dragDropContainer->layout();
138 for (auto i = 0; i < frameLayout->count(); ++i) {
138 for (auto i = 0; i < frameLayout->count(); ++i) {
139 auto graphChild
139 auto graphChild
140 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
140 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
141 if (graphChild && (graphChild != graphWidget)) {
141 if (graphChild && (graphChild != graphWidget)) {
142
142
143 auto graphChildRange = graphChild->graphRange();
143 auto graphChildRange = graphChild->graphRange();
144 switch (zoomType) {
144 switch (zoomType) {
145 case AcquisitionZoomType::ZoomIn: {
145 case AcquisitionZoomType::ZoomIn: {
146 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
146 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
147 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
147 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
148 graphChildRange.m_TStart += deltaLeft;
148 graphChildRange.m_TStart += deltaLeft;
149 graphChildRange.m_TEnd -= deltaRight;
149 graphChildRange.m_TEnd -= deltaRight;
150 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
150 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
151 qCDebug(LOG_VisualizationZoneWidget())
151 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
152 << tr("TORM: deltaLeft") << deltaLeft;
152 << deltaLeft;
153 qCDebug(LOG_VisualizationZoneWidget())
153 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
154 << tr("TORM: deltaRight") << deltaRight;
154 << deltaRight;
155 qCDebug(LOG_VisualizationZoneWidget())
155 qCDebug(LOG_VisualizationZoneWidget())
156 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
156 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
157
157
158 break;
158 break;
159 }
159 }
160
160
161 case AcquisitionZoomType::ZoomOut: {
161 case AcquisitionZoomType::ZoomOut: {
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
163 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
163 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
164 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
164 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
165 qCDebug(LOG_VisualizationZoneWidget())
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
166 << tr("TORM: deltaLeft") << deltaLeft;
166 << deltaLeft;
167 qCDebug(LOG_VisualizationZoneWidget())
167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
168 << tr("TORM: deltaRight") << deltaRight;
168 << deltaRight;
169 qCDebug(LOG_VisualizationZoneWidget())
169 qCDebug(LOG_VisualizationZoneWidget())
170 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
170 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
171 graphChildRange.m_TStart -= deltaLeft;
171 graphChildRange.m_TStart -= deltaLeft;
172 graphChildRange.m_TEnd += deltaRight;
172 graphChildRange.m_TEnd += deltaRight;
173 break;
173 break;
174 }
174 }
175 case AcquisitionZoomType::PanRight: {
175 case AcquisitionZoomType::PanRight: {
176 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
176 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
177 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
177 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
178 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
178 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
179 graphChildRange.m_TStart += deltaLeft;
179 graphChildRange.m_TStart += deltaLeft;
180 graphChildRange.m_TEnd += deltaRight;
180 graphChildRange.m_TEnd += deltaRight;
181 qCDebug(LOG_VisualizationZoneWidget())
181 qCDebug(LOG_VisualizationZoneWidget())
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 break;
183 break;
184 }
184 }
185 case AcquisitionZoomType::PanLeft: {
185 case AcquisitionZoomType::PanLeft: {
186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
186 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
187 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
187 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
188 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
188 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
189 graphChildRange.m_TStart -= deltaLeft;
189 graphChildRange.m_TStart -= deltaLeft;
190 graphChildRange.m_TEnd -= deltaRight;
190 graphChildRange.m_TEnd -= deltaRight;
191 break;
191 break;
192 }
192 }
193 case AcquisitionZoomType::Unknown: {
193 case AcquisitionZoomType::Unknown: {
194 qCDebug(LOG_VisualizationZoneWidget())
194 qCDebug(LOG_VisualizationZoneWidget())
195 << tr("Impossible to synchronize: zoom type unknown");
195 << tr("Impossible to synchronize: zoom type unknown");
196 break;
196 break;
197 }
197 }
198 default:
198 default:
199 qCCritical(LOG_VisualizationZoneWidget())
199 qCCritical(LOG_VisualizationZoneWidget())
200 << tr("Impossible to synchronize: zoom type not take into account");
200 << tr("Impossible to synchronize: zoom type not take into account");
201 // No action
201 // No action
202 break;
202 break;
203 }
203 }
204 graphChild->enableAcquisition(false);
204 graphChild->enableAcquisition(false);
205 qCDebug(LOG_VisualizationZoneWidget())
205 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
206 << tr("TORM: Range before: ") << graphChild->graphRange();
206 << graphChild->graphRange();
207 qCDebug(LOG_VisualizationZoneWidget())
207 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
208 << tr("TORM: Range after : ") << graphChildRange;
208 << graphChildRange;
209 qCDebug(LOG_VisualizationZoneWidget())
209 qCDebug(LOG_VisualizationZoneWidget())
210 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
210 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
211 graphChild->setGraphRange(graphChildRange);
211 graphChild->setGraphRange(graphChildRange);
212 graphChild->enableAcquisition(true);
212 graphChild->enableAcquisition(true);
213 }
213 }
214 }
214 }
215 };
215 };
216
216
217 // connection for synchronization
217 // connection for synchronization
218 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
218 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
219 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
219 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
220 &VisualizationZoneWidget::onVariableAdded);
220 &VisualizationZoneWidget::onVariableAdded);
221 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
221 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
222 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
222 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
223
223
224 auto range = SqpRange{};
224 auto range = SqpRange{};
225
225
226 // Apply visitor to graph children
226 // Apply visitor to graph children
227 auto layout = ui->dragDropContainer->layout();
227 auto layout = ui->dragDropContainer->layout();
228 if (layout->count() > 0) {
228 if (layout->count() > 0) {
229 // Case of a new graph in a existant zone
229 // Case of a new graph in a existant zone
230 if (auto visualizationGraphWidget
230 if (auto visualizationGraphWidget
231 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
231 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
232 range = visualizationGraphWidget->graphRange();
232 range = visualizationGraphWidget->graphRange();
233 }
233 }
234 }
234 }
235 else {
235 else {
236 // Case of a new graph as the first of the zone
236 // Case of a new graph as the first of the zone
237 range = variable->range();
237 range = variable->range();
238 }
238 }
239
239
240 this->insertGraph(index, graphWidget);
240 this->insertGraph(index, graphWidget);
241
241
242 graphWidget->addVariable(variable, range);
242 graphWidget->addVariable(variable, range);
243
243
244 // get y using variable range
244 // get y using variable range
245 if (auto dataSeries = variable->dataSeries()) {
245 if (auto dataSeries = variable->dataSeries()) {
246 dataSeries->lockRead();
246 dataSeries->lockRead();
247 auto valuesBounds
247 auto valuesBounds
248 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
248 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
249 auto end = dataSeries->cend();
249 auto end = dataSeries->cend();
250 if (valuesBounds.first != end && valuesBounds.second != end) {
250 if (valuesBounds.first != end && valuesBounds.second != end) {
251 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
251 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
252
252
253 auto minValue = rangeValue(valuesBounds.first->minValue());
253 auto minValue = rangeValue(valuesBounds.first->minValue());
254 auto maxValue = rangeValue(valuesBounds.second->maxValue());
254 auto maxValue = rangeValue(valuesBounds.second->maxValue());
255
255
256 graphWidget->setYRange(SqpRange{minValue, maxValue});
256 graphWidget->setYRange(SqpRange{minValue, maxValue});
257 }
257 }
258 dataSeries->unlock();
258 dataSeries->unlock();
259 }
259 }
260
260
261 return graphWidget;
261 return graphWidget;
262 }
262 }
263
263
264 VisualizationGraphWidget *
264 VisualizationGraphWidget *
265 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
265 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
266 {
266 {
267 if (variables.isEmpty()) {
267 if (variables.isEmpty()) {
268 return nullptr;
268 return nullptr;
269 }
269 }
270
270
271 auto graphWidget = createGraph(variables.first(), index);
271 auto graphWidget = createGraph(variables.first(), index);
272 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
272 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
273 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
273 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
274 }
274 }
275
275
276 return graphWidget;
276 return graphWidget;
277 }
277 }
278
278
279 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
279 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
280 {
280 {
281 if (visitor) {
281 if (visitor) {
282 visitor->visitEnter(this);
282 visitor->visitEnter(this);
283
283
284 // Apply visitor to graph children: widgets different from graphs are not visited (no
284 // Apply visitor to graph children: widgets different from graphs are not visited (no
285 // action)
285 // action)
286 processGraphs(
286 processGraphs(
287 *ui->dragDropContainer->layout(),
287 *ui->dragDropContainer->layout(),
288 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
288 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
289
289
290 visitor->visitLeave(this);
290 visitor->visitLeave(this);
291 }
291 }
292 else {
292 else {
293 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
293 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
294 }
294 }
295 }
295 }
296
296
297 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
297 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
298 {
298 {
299 // A tab can always accomodate a variable
299 // A tab can always accomodate a variable
300 Q_UNUSED(variable);
300 Q_UNUSED(variable);
301 return true;
301 return true;
302 }
302 }
303
303
304 bool VisualizationZoneWidget::contains(const Variable &variable) const
304 bool VisualizationZoneWidget::contains(const Variable &variable) const
305 {
305 {
306 Q_UNUSED(variable);
306 Q_UNUSED(variable);
307 return false;
307 return false;
308 }
308 }
309
309
310 QString VisualizationZoneWidget::name() const
310 QString VisualizationZoneWidget::name() const
311 {
311 {
312 return ui->zoneNameLabel->text();
312 return ui->zoneNameLabel->text();
313 }
313 }
314
314
315 QMimeData *VisualizationZoneWidget::mimeData() const
315 QMimeData *VisualizationZoneWidget::mimeData() const
316 {
316 {
317 auto *mimeData = new QMimeData;
317 auto *mimeData = new QMimeData;
318 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
318 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
319
319
320 return mimeData;
320 return mimeData;
321 }
321 }
322
322
323 bool VisualizationZoneWidget::isDragAllowed() const
323 bool VisualizationZoneWidget::isDragAllowed() const
324 {
324 {
325 return true;
325 return true;
326 }
326 }
327
327
328 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
328 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
329 {
329 {
330 // Closes graphs in the zone
330 // Closes graphs in the zone
331 processGraphs(*ui->dragDropContainer->layout(),
331 processGraphs(*ui->dragDropContainer->layout(),
332 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
332 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
333
333
334 // Delete synchronization group from variable controller
334 // Delete synchronization group from variable controller
335 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
335 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
336 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
336 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
337
337
338 QWidget::closeEvent(event);
338 QWidget::closeEvent(event);
339 }
339 }
340
340
341 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
341 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
342 {
342 {
343 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
343 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
344 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
344 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
345 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
345 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
346 }
346 }
347
347
348 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
348 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
349 {
349 {
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
350 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
351 Q_ARG(std::shared_ptr<Variable>, variable),
351 Q_ARG(std::shared_ptr<Variable>, variable),
352 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
352 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
353 }
353 }
354
354
355 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
355 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
356 {
356 {
357 auto &helper = sqpApp->dragDropHelper();
357 auto &helper = sqpApp->dragDropHelper();
358 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
358 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
359 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
359 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
360 auto parentDragDropContainer
360 auto parentDragDropContainer
361 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
361 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
362 Q_ASSERT(parentDragDropContainer);
362 Q_ASSERT(parentDragDropContainer);
363
363
364 const auto &variables = graphWidget->variables();
364 const auto &variables = graphWidget->variables();
365
365
366 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
366 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
367 // The drop didn't occur in the same zone
367 // The drop didn't occur in the same zone
368
368
369 // Abort the requests for the variables (if any)
369 // Abort the requests for the variables (if any)
370 // Commented, because it's not sure if it's needed or not
370 // Commented, because it's not sure if it's needed or not
371 // for (const auto& var : variables)
371 // for (const auto& var : variables)
372 //{
372 //{
373 // sqpApp->variableController().onAbortProgressRequested(var);
373 // sqpApp->variableController().onAbortProgressRequested(var);
374 //}
374 //}
375
375
376 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
376 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
377 auto nbGraph = parentDragDropContainer->countDragWidget();
377 auto nbGraph = parentDragDropContainer->countDragWidget();
378 if (nbGraph == 1) {
378 if (nbGraph == 1) {
379 // This is the only graph in the previous zone, close the zone
379 // This is the only graph in the previous zone, close the zone
380 previousParentZoneWidget->close();
380 previousParentZoneWidget->close();
381 }
381 }
382 else {
382 else {
383 // Close the graph
383 // Close the graph
384 graphWidget->close();
384 graphWidget->close();
385 }
385 }
386
386
387 // Creates the new graph in the zone
387 // Creates the new graph in the zone
388 createGraph(variables, index);
388 createGraph(variables, index);
389 }
389 }
390 else {
390 else {
391 // The drop occurred in the same zone or the graph is empty
391 // The drop occurred in the same zone or the graph is empty
392 // Simple move of the graph, no variable operation associated
392 // Simple move of the graph, no variable operation associated
393 parentDragDropContainer->layout()->removeWidget(graphWidget);
393 parentDragDropContainer->layout()->removeWidget(graphWidget);
394
394
395 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
395 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
396 // The graph is empty and dropped in a different zone.
396 // The graph is empty and dropped in a different zone.
397 // Take the range of the first graph in the zone (if existing).
397 // Take the range of the first graph in the zone (if existing).
398 auto layout = ui->dragDropContainer->layout();
398 auto layout = ui->dragDropContainer->layout();
399 if (layout->count() > 0) {
399 if (layout->count() > 0) {
400 if (auto visualizationGraphWidget
400 if (auto visualizationGraphWidget
401 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
401 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
402 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
402 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
403 }
403 }
404 }
404 }
405 }
405 }
406
406
407 ui->dragDropContainer->insertDragWidget(index, graphWidget);
407 ui->dragDropContainer->insertDragWidget(index, graphWidget);
408 }
408 }
409 }
409 }
410 }
410 }
General Comments 6
Approved

Status change > Approved

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