##// END OF EJS Templates
Merge pull request 323 from SciQLop-fork develop...
leroux -
r889:756d7fefd6f4 merge
parent child
Show More
@@ -0,0 +1,32
1 #ifndef SCIQLOP_DRAGDROPSCROLLER_H
2 #define SCIQLOP_DRAGDROPSCROLLER_H
3
4 #include <Common/spimpl.h>
5 #include <QScrollArea>
6
7 /**
8 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
9 * @note A QScrollArea inside an other QScrollArea is not fully supported.
10 */
11 class DragDropScroller : public QObject {
12 Q_OBJECT
13
14 public:
15 DragDropScroller(QObject *parent = nullptr);
16
17 void addScrollArea(QScrollArea *scrollArea);
18 void removeScrollArea(QScrollArea *scrollArea);
19
20 protected:
21 bool eventFilter(QObject *obj, QEvent *event);
22
23 private:
24 class DragDropScrollerPrivate;
25 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
26
27 private slots:
28 void onTimer();
29 };
30
31
32 #endif // SCIQLOP_DRAGDROPSCROLLER_H
@@ -0,0 +1,29
1 #ifndef SCIQLOP_DRAGDROPTABSWITCHER_H
2 #define SCIQLOP_DRAGDROPTABSWITCHER_H
3
4 #include <Common/spimpl.h>
5
6 #include <QLoggingCategory>
7 #include <QTabBar>
8
9 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropTabSwitcher)
10
11 class DragDropTabSwitcher : public QObject {
12 Q_OBJECT
13
14 public:
15 DragDropTabSwitcher(QObject *parent = nullptr);
16
17 void addTabBar(QTabBar *tabBar);
18 void removeTabBar(QTabBar *tabBar);
19
20 protected:
21 bool eventFilter(QObject *obj, QEvent *event);
22
23 private:
24 class DragDropTabSwitcherPrivate;
25 spimpl::unique_impl_ptr<DragDropTabSwitcherPrivate> impl;
26 };
27
28
29 #endif // SCIQLOP_DRAGDROPTABSWITCHER_H
@@ -0,0 +1,14
1 #ifndef SCIQLOP_VARIABLEINSPECTORTABLEVIEW_H
2 #define SCIQLOP_VARIABLEINSPECTORTABLEVIEW_H
3
4 #include <QTableView>
5
6 class VariableInspectorTableView : public QTableView {
7 public:
8 VariableInspectorTableView(QWidget *parent = nullptr);
9
10 protected:
11 void startDrag(Qt::DropActions supportedActions);
12 };
13
14 #endif // SCIQLOP_VARIABLEINSPECTORTABLEVIEW_H
@@ -0,0 +1,275
1 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/DragDropScroller.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
4 #include "SqpApplication.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
6 #include "Visualization/VisualizationDragWidget.h"
7 #include "Visualization/VisualizationWidget.h"
8 #include "Visualization/operations/FindVariableOperation.h"
9
10 #include "Variable/Variable.h"
11 #include "Variable/VariableController.h"
12
13 #include "Common/MimeTypesDef.h"
14 #include "Common/VisualizationDef.h"
15
16 #include <QDir>
17 #include <QLabel>
18 #include <QUrl>
19 #include <QVBoxLayout>
20
21
22 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDropHelper")
23
24
25 struct DragDropHelper::DragDropHelperPrivate {
26
27 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
28 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
29 QLabel *m_PlaceHolderLabel;
30 QWidget *m_PlaceBackground;
31 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
32 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
33 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
34 // QTemporaryFile to have a name which is not generated.
35
36 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
37
38 QMetaObject::Connection m_DragWidgetDestroyedConnection;
39 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
40
41 explicit DragDropHelperPrivate()
42 : m_PlaceHolder{std::make_unique<QWidget>()},
43 m_DragDropScroller{std::make_unique<DragDropScroller>()},
44 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
45 {
46
47 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
48 layout->setSpacing(0);
49 layout->setContentsMargins(0, 0, 0, 0);
50
51 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
52 m_PlaceHolderLabel->setMinimumHeight(25);
53 layout->addWidget(m_PlaceHolderLabel);
54
55 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
56 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
57 layout->addWidget(m_PlaceBackground);
58
59 sqpApp->installEventFilter(m_DragDropScroller.get());
60 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
61
62 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
63 }
64
65 void preparePlaceHolder(DragDropHelper::PlaceHolderType type, const QString &topLabelText) const
66 {
67 if (m_CurrentDragWidget) {
68 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
69 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
70 }
71 else {
72 // Configuration of the placeHolder when there is no dragWidget
73 // (for instance with a drag from a variable)
74
75 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
76 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
77 }
78
79 switch (type) {
80 case DragDropHelper::PlaceHolderType::Graph:
81 m_PlaceBackground->setStyleSheet(
82 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
83 break;
84 case DragDropHelper::PlaceHolderType::Zone:
85 case DragDropHelper::PlaceHolderType::Default:
86 m_PlaceBackground->setStyleSheet(
87 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
88 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
89 break;
90 }
91
92 m_PlaceHolderLabel->setText(topLabelText);
93 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
94 }
95 };
96
97
98 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()} {}
99
100 DragDropHelper::~DragDropHelper()
101 {
102 QFile::remove(impl->m_ImageTempUrl);
103 }
104
105 void DragDropHelper::resetDragAndDrop()
106 {
107 setCurrentDragWidget(nullptr);
108 impl->m_HighlightedDragWidget = nullptr;
109 }
110
111 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
112 {
113 if (impl->m_CurrentDragWidget) {
114
115 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
116 }
117
118 if (dragWidget) {
119 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
120 impl->m_DragWidgetDestroyedConnection
121 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
122 [this]() { impl->m_CurrentDragWidget = nullptr; });
123 }
124
125 impl->m_CurrentDragWidget = dragWidget;
126 }
127
128 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
129 {
130 return impl->m_CurrentDragWidget;
131 }
132
133 QWidget &DragDropHelper::placeHolder() const
134 {
135 return *impl->m_PlaceHolder;
136 }
137
138 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
139 const QString &topLabelText)
140 {
141 removePlaceHolder();
142 impl->preparePlaceHolder(type, topLabelText);
143 layout->insertWidget(index, impl->m_PlaceHolder.get());
144 impl->m_PlaceHolder->show();
145 }
146
147 void DragDropHelper::removePlaceHolder()
148 {
149 auto parentWidget = impl->m_PlaceHolder->parentWidget();
150 if (parentWidget) {
151 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
152 impl->m_PlaceHolder->setParent(nullptr);
153 impl->m_PlaceHolder->hide();
154 }
155 }
156
157 bool DragDropHelper::isPlaceHolderSet() const
158 {
159 return impl->m_PlaceHolder->parentWidget();
160 }
161
162 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
163 {
164 impl->m_DragDropScroller->addScrollArea(scrollArea);
165 }
166
167 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
168 {
169 impl->m_DragDropScroller->removeScrollArea(scrollArea);
170 }
171
172 void DragDropHelper::addDragDropTabBar(QTabBar *tabBar)
173 {
174 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
175 }
176
177 void DragDropHelper::removeDragDropTabBar(QTabBar *tabBar)
178 {
179 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
180 }
181
182 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
183 {
184 image.save(impl->m_ImageTempUrl);
185 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
186 }
187
188 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
189 {
190 if (impl->m_HighlightedDragWidget) {
191 impl->m_HighlightedDragWidget->highlightForMerge(false);
192 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
193 }
194
195 if (dragWidget) {
196 dragWidget->highlightForMerge(true);
197
198 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
199 impl->m_DragWidgetDestroyedConnection
200 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
201 [this]() { impl->m_HighlightedDragWidget = nullptr; });
202 }
203
204 impl->m_HighlightedDragWidget = dragWidget;
205 }
206
207 VisualizationDragWidget *DragDropHelper::getHightlightedDragWidget() const
208 {
209 return impl->m_HighlightedDragWidget;
210 }
211
212 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
213 VisualizationDragDropContainer *dropContainer)
214 {
215 if (!mimeData || !dropContainer) {
216 qCWarning(LOG_DragDropHelper()) << QObject::tr(
217 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
218 Q_ASSERT(false);
219 return false;
220 }
221
222 auto result = false;
223
224 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
225 auto variables = sqpApp->variableController().variablesForMimeData(
226 mimeData->data(MIME_TYPE_VARIABLE_LIST));
227
228 if (variables.count() == 1) {
229
230 auto variable = variables.first();
231 if (variable->dataSeries() != nullptr) {
232
233 // Check that the variable is not already in a graph
234
235 auto parent = dropContainer->parentWidget();
236 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
237 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
238 }
239
240 if (parent) {
241 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
242
243 FindVariableOperation findVariableOperation{variable};
244 visualizationWidget->accept(&findVariableOperation);
245 auto variableContainers = findVariableOperation.result();
246 if (variableContainers.empty()) {
247 result = true;
248 }
249 else {
250 // result = false: the variable already exist in the visualisation
251 }
252 }
253 else {
254 qCWarning(LOG_DragDropHelper()) << QObject::tr(
255 "DragDropHelper::checkMimeDataForVisualization, the parent "
256 "VisualizationWidget cannot be found. Cannot check if the variable is "
257 "already used or not.");
258 }
259 }
260 else {
261 // result = false: the variable is not fully loaded
262 }
263 }
264 else {
265 // result = false: cannot drop multiple variables in the visualisation
266 }
267 }
268 else {
269 // Other MIME data
270 // no special rules, accepted by default
271 result = true;
272 }
273
274 return result;
275 }
@@ -0,0 +1,180
1 #include "DragAndDrop/DragDropTabSwitcher.h"
2
3 #include <QAbstractButton>
4 #include <QDragEnterEvent>
5 #include <QDragMoveEvent>
6 #include <QTimer>
7
8 #include "SqpApplication.h"
9
10 Q_LOGGING_CATEGORY(LOG_DragDropTabSwitcher, "DragDropTabSwitcher")
11
12 const int CHANGE_TAB_INTERVAL = 400; // time necessary over a tab to accept the switch
13 const int SCROLL_BUTTON_AUTO_CLICK_INTERVAL
14 = 500; // time between 2 auto clicks on a scroll button of the tab bar
15
16 struct DragDropTabSwitcher::DragDropTabSwitcherPrivate {
17
18 QList<QTabBar *> m_TabBarList;
19 QTabBar *m_CurrentTabBar = nullptr;
20
21 int m_HoveredTabIndex = -1;
22 std::unique_ptr<QTimer> m_TabSwitchTimer = nullptr;
23
24 QAbstractButton *m_HoveredScrollButton = nullptr;
25 std::unique_ptr<QTimer> m_ScrollButtonsTimer = nullptr;
26
27 explicit DragDropTabSwitcherPrivate()
28 : m_TabSwitchTimer{std::make_unique<QTimer>()},
29 m_ScrollButtonsTimer{std::make_unique<QTimer>()}
30 {
31 m_TabSwitchTimer->setSingleShot(true);
32 m_TabSwitchTimer->setInterval(CHANGE_TAB_INTERVAL);
33 QObject::connect(m_TabSwitchTimer.get(), &QTimer::timeout, [this]() {
34 if (m_CurrentTabBar) {
35 m_CurrentTabBar->setCurrentIndex(m_HoveredTabIndex);
36 }
37 else {
38 qCWarning(LOG_DragDropTabSwitcher()) << "DragDropTabSwitcherPrivate::timeout: "
39 "Cannot select a new tab: unknown current "
40 "tab bar.";
41 }
42 });
43
44 m_ScrollButtonsTimer->setInterval(SCROLL_BUTTON_AUTO_CLICK_INTERVAL);
45 QObject::connect(m_ScrollButtonsTimer.get(), &QTimer::timeout, [this]() {
46 if (m_HoveredScrollButton) {
47 m_HoveredScrollButton->animateClick();
48 }
49 else {
50 qCWarning(LOG_DragDropTabSwitcher())
51 << "DragDropTabSwitcherPrivate::timeoutScroll: "
52 "Unknown scroll button";
53 }
54 });
55 }
56
57 bool isScrollTabButton(QAbstractButton *button, QTabBar *tabBar)
58 {
59 auto isNextOrPreviousTabButton = true;
60
61 if (tabBar->isAncestorOf(button)) {
62 for (auto i = 0; i < tabBar->count(); ++i) {
63 if (tabBar->tabButton(i, QTabBar::RightSide) == button
64 || tabBar->tabButton(i, QTabBar::LeftSide) == button) {
65 isNextOrPreviousTabButton = false;
66 break;
67 }
68 }
69 }
70 else {
71 isNextOrPreviousTabButton = false;
72 }
73
74 return isNextOrPreviousTabButton;
75 }
76
77 QAbstractButton *tabScrollButtonAt(const QPoint &pos, QTabBar *tabBar)
78 {
79
80 auto globalPos = tabBar->mapToGlobal(pos);
81
82 auto widgetUnderMouse = sqpApp->widgetAt(globalPos);
83 if (auto btn = qobject_cast<QAbstractButton *>(widgetUnderMouse)) {
84
85 if (isScrollTabButton(btn, tabBar)) {
86 return btn;
87 }
88 }
89
90 return nullptr;
91 }
92 };
93
94 DragDropTabSwitcher::DragDropTabSwitcher(QObject *parent)
95 : QObject(parent), impl{spimpl::make_unique_impl<DragDropTabSwitcherPrivate>()}
96 {
97 }
98
99 void DragDropTabSwitcher::addTabBar(QTabBar *tabBar)
100 {
101 impl->m_TabBarList << tabBar;
102 tabBar->setAcceptDrops(true);
103 }
104
105 void DragDropTabSwitcher::removeTabBar(QTabBar *tabBar)
106 {
107 impl->m_TabBarList.removeAll(tabBar);
108 tabBar->setAcceptDrops(false);
109 }
110
111 bool DragDropTabSwitcher::eventFilter(QObject *obj, QEvent *event)
112 {
113 if (event->type() == QEvent::DragMove) {
114
115 if (impl->m_CurrentTabBar) {
116
117 QWidget *w = static_cast<QWidget *>(obj);
118 if (!impl->m_CurrentTabBar->isAncestorOf(w)) {
119 return false;
120 }
121
122 auto moveEvent = static_cast<QDragMoveEvent *>(event);
123
124 auto scrollButton = impl->tabScrollButtonAt(moveEvent->pos(), impl->m_CurrentTabBar);
125
126 if (!scrollButton) {
127
128 auto tabIndex = impl->m_CurrentTabBar->tabAt(moveEvent->pos());
129 if (tabIndex >= 0 && tabIndex != impl->m_CurrentTabBar->currentIndex()) {
130 // The mouse is over an unselected tab
131 if (!impl->m_TabSwitchTimer->isActive()
132 || tabIndex != impl->m_HoveredTabIndex) {
133 impl->m_HoveredTabIndex = tabIndex;
134 impl->m_TabSwitchTimer->start();
135 }
136 else {
137 // do nothing, timer already running
138 }
139 }
140 else {
141 impl->m_TabSwitchTimer->stop();
142 }
143
144 impl->m_ScrollButtonsTimer->stop();
145 }
146 else {
147 // The mouse is over a scroll button
148 // click it in a loop with a timer
149 if (!impl->m_ScrollButtonsTimer->isActive()
150 || impl->m_HoveredScrollButton != scrollButton) {
151 impl->m_HoveredScrollButton = scrollButton;
152 impl->m_ScrollButtonsTimer->start();
153 }
154 }
155 }
156 }
157 else if (event->type() == QEvent::DragEnter) {
158 QWidget *w = static_cast<QWidget *>(obj);
159
160 for (auto tabBar : impl->m_TabBarList) {
161 if (w == tabBar) {
162 auto enterEvent = static_cast<QDragEnterEvent *>(event);
163 enterEvent->acceptProposedAction();
164 enterEvent->setDropAction(Qt::IgnoreAction);
165 impl->m_CurrentTabBar = tabBar;
166 break;
167 }
168 }
169 }
170 else if (event->type() == QEvent::DragLeave || event->type() == QEvent::Drop) {
171 if (impl->m_CurrentTabBar) {
172 impl->m_HoveredTabIndex = -1;
173 impl->m_TabSwitchTimer->stop();
174 impl->m_CurrentTabBar = nullptr;
175 impl->m_ScrollButtonsTimer->stop();
176 }
177 }
178
179 return false;
180 }
@@ -0,0 +1,13
1 #include "Variable/VariableInspectorTableView.h"
2
3 #include "DragAndDrop/DragDropHelper.h"
4 #include "SqpApplication.h"
5
6 VariableInspectorTableView::VariableInspectorTableView(QWidget *parent) : QTableView(parent) {}
7
8 void VariableInspectorTableView::startDrag(Qt::DropActions supportedActions)
9 {
10 // Resets the drag&drop operations before it's starting
11 sqpApp->dragDropHelper().resetDragAndDrop();
12 QTableView::startDrag(supportedActions);
13 }
@@ -1,99 +1,102
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
1 #ifndef SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
2 #define SCIQLOP_DATASOURCECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QObject>
7 #include <QObject>
8 #include <QUuid>
8 #include <QUuid>
9
9
10 #include <Common/spimpl.h>
10 #include <Common/spimpl.h>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSourceController)
13
13
14 class DataSourceItem;
14 class DataSourceItem;
15 class IDataProvider;
15 class IDataProvider;
16
16
17 /**
17 /**
18 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
18 * @brief The DataSourceController class aims to make the link between SciQlop and its plugins. This
19 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
19 * is the intermediate class that SciQlop has to use in the way to connect a data source. Please
20 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
20 * first use register method to initialize a plugin specified by its metadata name (JSON plugin
21 * source) then others specifics method will be able to access it. You can load a data source driver
21 * source) then others specifics method will be able to access it. You can load a data source driver
22 * plugin then create a data source.
22 * plugin then create a data source.
23 */
23 */
24 class SCIQLOP_CORE_EXPORT DataSourceController : public QObject {
24 class SCIQLOP_CORE_EXPORT DataSourceController : public QObject {
25 Q_OBJECT
25 Q_OBJECT
26 public:
26 public:
27 explicit DataSourceController(QObject *parent = 0);
27 explicit DataSourceController(QObject *parent = 0);
28 virtual ~DataSourceController();
28 virtual ~DataSourceController();
29
29
30 /**
30 /**
31 * Registers a data source. The method delivers a unique id that can be used afterwards to
31 * Registers a data source. The method delivers a unique id that can be used afterwards to
32 * access to the data source properties (structure, connection parameters, data provider, etc.)
32 * access to the data source properties (structure, connection parameters, data provider, etc.)
33 * @param dataSourceName the name of the data source
33 * @param dataSourceName the name of the data source
34 * @return the unique id with which the data source has been registered
34 * @return the unique id with which the data source has been registered
35 */
35 */
36 QUuid registerDataSource(const QString &dataSourceName) noexcept;
36 QUuid registerDataSource(const QString &dataSourceName) noexcept;
37
37
38 /**
38 /**
39 * Sets the structure of a data source. The controller takes ownership of the structure.
39 * Sets the structure of a data source. The controller takes ownership of the structure.
40 * @param dataSourceUid the unique id with which the data source has been registered into the
40 * @param dataSourceUid the unique id with which the data source has been registered into the
41 * controller. If it is invalid, the method has no effect.
41 * controller. If it is invalid, the method has no effect.
42 * @param dataSourceItem the structure of the data source. It must be not null to be registered
42 * @param dataSourceItem the structure of the data source. It must be not null to be registered
43 * @sa registerDataSource()
43 * @sa registerDataSource()
44 */
44 */
45 void setDataSourceItem(const QUuid &dataSourceUid,
45 void setDataSourceItem(const QUuid &dataSourceUid,
46 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
46 std::unique_ptr<DataSourceItem> dataSourceItem) noexcept;
47
47
48 /**
48 /**
49 * Sets the data provider used to retrieve data from of a data source. The controller takes
49 * Sets the data provider used to retrieve data from of a data source. The controller takes
50 * ownership of the provider.
50 * ownership of the provider.
51 * @param dataSourceUid the unique id with which the data source has been registered into the
51 * @param dataSourceUid the unique id with which the data source has been registered into the
52 * controller. If it is invalid, the method has no effect.
52 * controller. If it is invalid, the method has no effect.
53 * @param dataProvider the provider of the data source
53 * @param dataProvider the provider of the data source
54 * @sa registerDataSource()
54 * @sa registerDataSource()
55 */
55 */
56 void setDataProvider(const QUuid &dataSourceUid,
56 void setDataProvider(const QUuid &dataSourceUid,
57 std::unique_ptr<IDataProvider> dataProvider) noexcept;
57 std::unique_ptr<IDataProvider> dataProvider) noexcept;
58
58
59 /**
59 /**
60 * Loads an item (product) as a variable in SciQlop
60 * Loads an item (product) as a variable in SciQlop
61 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
61 * @param dataSourceUid the unique id of the data source containing the item. It is used to get
62 * the data provider associated to the data source, and pass it to for the variable creation
62 * the data provider associated to the data source, and pass it to for the variable creation
63 * @param productItem the item to load
63 * @param productItem the item to load
64 */
64 */
65 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
65 void loadProductItem(const QUuid &dataSourceUid, const DataSourceItem &productItem) noexcept;
66
66
67 QByteArray mimeDataForProductsData(const QVariantList &productsData) const;
67 /// Returns the MIME data associated to a list of product meta data
68 QVariantList productsDataForMimeData(const QByteArray &mimeData) const;
68 static QByteArray mimeDataForProductsData(const QVariantList &productsData);
69
70 /// Returns the list of meta data contained in a MIME data
71 static QVariantList productsDataForMimeData(const QByteArray &mimeData);
69
72
70 public slots:
73 public slots:
71 /// Manage init/end of the controller
74 /// Manage init/end of the controller
72 void initialize();
75 void initialize();
73 void finalize();
76 void finalize();
74
77
75 void requestVariable(const QVariantHash &productData);
78 void requestVariable(const QVariantHash &productData);
76
79
77 signals:
80 signals:
78 /// Signal emitted when a structure has been set for a data source
81 /// Signal emitted when a structure has been set for a data source
79 void dataSourceItemSet(DataSourceItem *dataSourceItem);
82 void dataSourceItemSet(DataSourceItem *dataSourceItem);
80
83
81 /**
84 /**
82 * Signal emitted when a variable creation is asked for a product
85 * Signal emitted when a variable creation is asked for a product
83 * @param variableName the name of the variable
86 * @param variableName the name of the variable
84 * @param variableMetadata the metadata of the variable
87 * @param variableMetadata the metadata of the variable
85 * @param variableProvider the provider that will be used to retrieve the data of the variable
88 * @param variableProvider the provider that will be used to retrieve the data of the variable
86 * (can be null)
89 * (can be null)
87 */
90 */
88 void variableCreationRequested(const QString &variableName,
91 void variableCreationRequested(const QString &variableName,
89 const QVariantHash &variableMetadata,
92 const QVariantHash &variableMetadata,
90 std::shared_ptr<IDataProvider> variableProvider);
93 std::shared_ptr<IDataProvider> variableProvider);
91
94
92 private:
95 private:
93 void waitForFinish();
96 void waitForFinish();
94
97
95 class DataSourceControllerPrivate;
98 class DataSourceControllerPrivate;
96 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
99 spimpl::unique_impl_ptr<DataSourceControllerPrivate> impl;
97 };
100 };
98
101
99 #endif // SCIQLOP_DATASOURCECONTROLLER_H
102 #endif // SCIQLOP_DATASOURCECONTROLLER_H
@@ -1,42 +1,48
1 #ifndef SCIQLOP_TIMECONTROLLER_H
1 #ifndef SCIQLOP_TIMECONTROLLER_H
2 #define SCIQLOP_TIMECONTROLLER_H
2 #define SCIQLOP_TIMECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <QLoggingCategory>
8 #include <QLoggingCategory>
9 #include <QObject>
9 #include <QObject>
10
10
11 #include <Common/spimpl.h>
11 #include <Common/spimpl.h>
12
12
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_TimeController)
15
15
16 /**
16 /**
17 * @brief The TimeController class aims to handle the Time parameters notification in SciQlop.
17 * @brief The TimeController class aims to handle the Time parameters notification in SciQlop.
18 */
18 */
19 class SCIQLOP_CORE_EXPORT TimeController : public QObject {
19 class SCIQLOP_CORE_EXPORT TimeController : public QObject {
20 Q_OBJECT
20 Q_OBJECT
21 public:
21 public:
22 explicit TimeController(QObject *parent = 0);
22 explicit TimeController(QObject *parent = 0);
23
23
24 SqpRange dateTime() const noexcept;
24 SqpRange dateTime() const noexcept;
25
25
26 /// Returns the MIME data associated to a time range
27 static QByteArray mimeDataForTimeRange(const SqpRange &timeRange);
28
29 /// Returns the time range contained in a MIME data
30 static SqpRange timeRangeForMimeData(const QByteArray &mimeData);
31
26 signals:
32 signals:
27 /// Signal emitted to notify that time parameters has beed updated
33 /// Signal emitted to notify that time parameters has beed updated
28 void timeUpdated(SqpRange time);
34 void timeUpdated(SqpRange time);
29
35
30 public slots:
36 public slots:
31 /// Slot called when a new dateTime has been defined.
37 /// Slot called when a new dateTime has been defined.
32 void onTimeToUpdate(SqpRange dateTime);
38 void onTimeToUpdate(SqpRange dateTime);
33
39
34 /// Slot called when the dateTime has to be notified. Call timeUpdated signal
40 /// Slot called when the dateTime has to be notified. Call timeUpdated signal
35 void onTimeNotify();
41 void onTimeNotify();
36
42
37 private:
43 private:
38 class TimeControllerPrivate;
44 class TimeControllerPrivate;
39 spimpl::unique_impl_ptr<TimeControllerPrivate> impl;
45 spimpl::unique_impl_ptr<TimeControllerPrivate> impl;
40 };
46 };
41
47
42 #endif // SCIQLOP_TIMECONTROLLER_H
48 #endif // SCIQLOP_TIMECONTROLLER_H
@@ -1,132 +1,135
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
1 #ifndef SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
2 #define SCIQLOP_VARIABLECONTROLLER_H
3
3
4 #include "CoreGlobal.h"
4 #include "CoreGlobal.h"
5
5
6 #include <Data/AcquisitionDataPacket.h>
6 #include <Data/AcquisitionDataPacket.h>
7 #include <Data/SqpRange.h>
7 #include <Data/SqpRange.h>
8
8
9 #include <QLoggingCategory>
9 #include <QLoggingCategory>
10 #include <QObject>
10 #include <QObject>
11 #include <QUuid>
11 #include <QUuid>
12
12
13 #include <Common/spimpl.h>
13 #include <Common/spimpl.h>
14
14
15 class IDataProvider;
15 class IDataProvider;
16 class QItemSelectionModel;
16 class QItemSelectionModel;
17 class TimeController;
17 class TimeController;
18 class Variable;
18 class Variable;
19 class VariableModel;
19 class VariableModel;
20
20
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
21 Q_DECLARE_LOGGING_CATEGORY(LOG_VariableController)
22
22
23
23
24 /**
24 /**
25 * Possible types of zoom operation
25 * Possible types of zoom operation
26 */
26 */
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
27 enum class AcquisitionZoomType { ZoomOut, ZoomIn, PanRight, PanLeft, Unknown };
28
28
29
29
30 /**
30 /**
31 * @brief The VariableController class aims to handle the variables in SciQlop.
31 * @brief The VariableController class aims to handle the variables in SciQlop.
32 */
32 */
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
33 class SCIQLOP_CORE_EXPORT VariableController : public QObject {
34 Q_OBJECT
34 Q_OBJECT
35 public:
35 public:
36 explicit VariableController(QObject *parent = 0);
36 explicit VariableController(QObject *parent = 0);
37 virtual ~VariableController();
37 virtual ~VariableController();
38
38
39 VariableModel *variableModel() noexcept;
39 VariableModel *variableModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
40 QItemSelectionModel *variableSelectionModel() noexcept;
41
41
42 void setTimeController(TimeController *timeController) noexcept;
42 void setTimeController(TimeController *timeController) noexcept;
43
43
44 /**
44 /**
45 * Clones the variable passed in parameter and adds the duplicate to the controller
45 * Clones the variable passed in parameter and adds the duplicate to the controller
46 * @param variable the variable to duplicate
46 * @param variable the variable to duplicate
47 * @return the duplicate created, nullptr if the variable couldn't be created
47 * @return the duplicate created, nullptr if the variable couldn't be created
48 */
48 */
49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
49 std::shared_ptr<Variable> cloneVariable(std::shared_ptr<Variable> variable) noexcept;
50
50
51 /**
51 /**
52 * Deletes from the controller the variable passed in parameter.
52 * Deletes from the controller the variable passed in parameter.
53 *
53 *
54 * Delete a variable includes:
54 * Delete a variable includes:
55 * - the deletion of the various references to the variable in SciQlop
55 * - the deletion of the various references to the variable in SciQlop
56 * - the deletion of the model variable
56 * - the deletion of the model variable
57 * - the deletion of the provider associated with the variable
57 * - the deletion of the provider associated with the variable
58 * - removing the cache associated with the variable
58 * - removing the cache associated with the variable
59 *
59 *
60 * @param variable the variable to delete from the controller.
60 * @param variable the variable to delete from the controller.
61 */
61 */
62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
62 void deleteVariable(std::shared_ptr<Variable> variable) noexcept;
63
63
64 /**
64 /**
65 * Deletes from the controller the variables passed in parameter.
65 * Deletes from the controller the variables passed in parameter.
66 * @param variables the variables to delete from the controller.
66 * @param variables the variables to delete from the controller.
67 * @sa deleteVariable()
67 * @sa deleteVariable()
68 */
68 */
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
70
70
71 /// Returns the MIME data associated to a list of variables
71 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
72 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
73
74 /// Returns the list of variables contained in a MIME data
72 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
75 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
73
76
74 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
77 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
75 signals:
78 signals:
76 /// Signal emitted when a variable is about to be deleted from the controller
79 /// Signal emitted when a variable is about to be deleted from the controller
77 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
80 void variableAboutToBeDeleted(std::shared_ptr<Variable> variable);
78
81
79 /// Signal emitted when a data acquisition is requested on a range for a variable
82 /// Signal emitted when a data acquisition is requested on a range for a variable
80 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
83 void rangeChanged(std::shared_ptr<Variable> variable, const SqpRange &range);
81
84
82 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
85 /// Signal emitted when a sub range of the cacheRange of the variable can be displayed
83 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
86 void updateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
84
87
85 public slots:
88 public slots:
86 /// Request the data loading of the variable whithin range
89 /// Request the data loading of the variable whithin range
87 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
90 void onRequestDataLoading(QVector<std::shared_ptr<Variable> > variables, const SqpRange &range,
88 bool synchronise);
91 bool synchronise);
89 /**
92 /**
90 * Creates a new variable and adds it to the model
93 * Creates a new variable and adds it to the model
91 * @param name the name of the new variable
94 * @param name the name of the new variable
92 * @param metadata the metadata of the new variable
95 * @param metadata the metadata of the new variable
93 * @param provider the data provider for the new variable
96 * @param provider the data provider for the new variable
94 * @return the pointer to the new variable or nullptr if the creation failed
97 * @return the pointer to the new variable or nullptr if the creation failed
95 */
98 */
96 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
99 std::shared_ptr<Variable> createVariable(const QString &name, const QVariantHash &metadata,
97 std::shared_ptr<IDataProvider> provider) noexcept;
100 std::shared_ptr<IDataProvider> provider) noexcept;
98
101
99 /// Update the temporal parameters of every selected variable to dateTime
102 /// Update the temporal parameters of every selected variable to dateTime
100 void onDateTimeOnSelection(const SqpRange &dateTime);
103 void onDateTimeOnSelection(const SqpRange &dateTime);
101
104
102
105
103 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
106 void onDataProvided(QUuid vIdentifier, const SqpRange &rangeRequested,
104 const SqpRange &cacheRangeRequested,
107 const SqpRange &cacheRangeRequested,
105 QVector<AcquisitionDataPacket> dataAcquired);
108 QVector<AcquisitionDataPacket> dataAcquired);
106
109
107 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
110 void onVariableRetrieveDataInProgress(QUuid identifier, double progress);
108
111
109 /// Cancel the current request for the variable
112 /// Cancel the current request for the variable
110 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
113 void onAbortProgressRequested(std::shared_ptr<Variable> variable);
111 void onAbortAcquisitionRequested(QUuid vIdentifier);
114 void onAbortAcquisitionRequested(QUuid vIdentifier);
112
115
113 // synchronization group methods
116 // synchronization group methods
114 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
117 void onAddSynchronizationGroupId(QUuid synchronizationGroupId);
115 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
118 void onRemoveSynchronizationGroupId(QUuid synchronizationGroupId);
116 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
119 void onAddSynchronized(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
117
120
118 /// Desynchronizes the variable of the group whose identifier is passed in parameter
121 /// Desynchronizes the variable of the group whose identifier is passed in parameter
119 /// @remarks the method does nothing if the variable is not part of the group
122 /// @remarks the method does nothing if the variable is not part of the group
120 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
123 void desynchronize(std::shared_ptr<Variable> variable, QUuid synchronizationGroupId);
121
124
122 void initialize();
125 void initialize();
123 void finalize();
126 void finalize();
124
127
125 private:
128 private:
126 void waitForFinish();
129 void waitForFinish();
127
130
128 class VariableControllerPrivate;
131 class VariableControllerPrivate;
129 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
132 spimpl::unique_impl_ptr<VariableControllerPrivate> impl;
130 };
133 };
131
134
132 #endif // SCIQLOP_VARIABLECONTROLLER_H
135 #endif // SCIQLOP_VARIABLECONTROLLER_H
@@ -1,67 +1,65
1
1
2 core_moc_headers = [
2 core_moc_headers = [
3 'include/Data/IDataProvider.h',
3 'include/Data/IDataProvider.h',
4 'include/DataSource/DataSourceController.h',
4 'include/DataSource/DataSourceController.h',
5 'include/DataSource/DataSourceItemAction.h',
5 'include/DataSource/DataSourceItemAction.h',
6 'include/DataSource/DataSourceWidget.h',
7 'include/Network/NetworkController.h',
6 'include/Network/NetworkController.h',
8 'include/Time/TimeController.h',
7 'include/Time/TimeController.h',
9 'include/Variable/Variable.h',
8 'include/Variable/Variable.h',
10 'include/Variable/VariableCacheController.h',
9 'include/Variable/VariableCacheController.h',
11 'include/Variable/VariableController.h',
10 'include/Variable/VariableController.h',
12 'include/Variable/VariableAcquisitionWorker.h',
11 'include/Variable/VariableAcquisitionWorker.h',
13 'include/Variable/VariableCacheStrategy.h',
12 'include/Variable/VariableCacheStrategy.h',
14 'include/Variable/VariableSynchronizationGroup.h',
13 'include/Variable/VariableSynchronizationGroup.h',
15 'include/Variable/VariableModel.h',
14 'include/Variable/VariableModel.h',
16 'include/Visualization/VisualizationController.h'
15 'include/Visualization/VisualizationController.h'
17 ]
16 ]
18
17
19
18
20 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
19 core_moc_files = qt5.preprocess(moc_headers : core_moc_headers)
21
20
22 core_sources = [
21 core_sources = [
23 'src/Common/DateUtils.cpp',
22 'src/Common/DateUtils.cpp',
24 'src/Common/StringUtils.cpp',
23 'src/Common/StringUtils.cpp',
25 'src/Common/MimeTypesDef.cpp',
24 'src/Common/MimeTypesDef.cpp',
26 'src/Data/ScalarSeries.cpp',
25 'src/Data/ScalarSeries.cpp',
27 'src/Data/SpectrogramSeries.cpp',
26 'src/Data/SpectrogramSeries.cpp',
28 'src/Data/DataSeriesIterator.cpp',
27 'src/Data/DataSeriesIterator.cpp',
29 'src/Data/ArrayDataIterator.cpp',
28 'src/Data/ArrayDataIterator.cpp',
30 'src/Data/VectorSeries.cpp',
29 'src/Data/VectorSeries.cpp',
31 'src/Data/OptionalAxis.cpp',
30 'src/Data/OptionalAxis.cpp',
32 'src/DataSource/DataSourceController.cpp',
31 'src/DataSource/DataSourceController.cpp',
33 'src/DataSource/DataSourceItem.cpp',
32 'src/DataSource/DataSourceItem.cpp',
34 'src/DataSource/DataSourceItemAction.cpp',
33 'src/DataSource/DataSourceItemAction.cpp',
35 'src/DataSource/DataSourceWidget.cpp',
36 'src/Network/NetworkController.cpp',
34 'src/Network/NetworkController.cpp',
37 'src/Plugin/PluginManager.cpp',
35 'src/Plugin/PluginManager.cpp',
38 'src/Settings/SqpSettingsDefs.cpp',
36 'src/Settings/SqpSettingsDefs.cpp',
39 'src/Time/TimeController.cpp',
37 'src/Time/TimeController.cpp',
40 'src/Variable/Variable.cpp',
38 'src/Variable/Variable.cpp',
41 'src/Variable/VariableCacheController.cpp',
39 'src/Variable/VariableCacheController.cpp',
42 'src/Variable/VariableController.cpp',
40 'src/Variable/VariableController.cpp',
43 'src/Variable/VariableAcquisitionWorker.cpp',
41 'src/Variable/VariableAcquisitionWorker.cpp',
44 'src/Variable/VariableSynchronizationGroup.cpp',
42 'src/Variable/VariableSynchronizationGroup.cpp',
45 'src/Variable/VariableModel.cpp',
43 'src/Variable/VariableModel.cpp',
46 'src/Visualization/VisualizationController.cpp'
44 'src/Visualization/VisualizationController.cpp'
47 ]
45 ]
48
46
49 core_inc = include_directories(['include', '../plugin/include'])
47 core_inc = include_directories(['include', '../plugin/include'])
50
48
51 sciqlop_core_lib = library('sciqlopcore',
49 sciqlop_core_lib = library('sciqlopcore',
52 core_sources,
50 core_sources,
53 core_moc_files,
51 core_moc_files,
54 cpp_args : '-DCORE_LIB',
52 cpp_args : '-DCORE_LIB',
55 include_directories : core_inc,
53 include_directories : core_inc,
56 dependencies : [qt5core, qt5network],
54 dependencies : [qt5core, qt5network],
57 install : true
55 install : true
58 )
56 )
59
57
60
58
61 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
59 sciqlop_core = declare_dependency(link_with : sciqlop_core_lib,
62 include_directories : core_inc,
60 include_directories : core_inc,
63 dependencies : [qt5core, qt5network])
61 dependencies : [qt5core, qt5network])
64
62
65
63
66 subdir('tests')
64 subdir('tests')
67
65
@@ -1,192 +1,192
1 #include "DataSource/DataSourceController.h"
1 #include "DataSource/DataSourceController.h"
2 #include "DataSource/DataSourceItem.h"
2 #include "DataSource/DataSourceItem.h"
3
3
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5
5
6 #include <QMutex>
6 #include <QMutex>
7 #include <QThread>
7 #include <QThread>
8
8
9 #include <QDataStream>
9 #include <QDataStream>
10 #include <QDir>
10 #include <QDir>
11 #include <QStandardPaths>
11 #include <QStandardPaths>
12
12
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
13 Q_LOGGING_CATEGORY(LOG_DataSourceController, "DataSourceController")
14
14
15 namespace {
15 namespace {
16
16
17 /**
17 /**
18 * Builds the metadata of the variable that will be generated from the loading of an item
18 * Builds the metadata of the variable that will be generated from the loading of an item
19 * @param dataSourceItem the data source item from which to generate the metadata
19 * @param dataSourceItem the data source item from which to generate the metadata
20 * @return the metadata of the variable
20 * @return the metadata of the variable
21 */
21 */
22 QVariantHash variableMetadata(const DataSourceItem &dataSourceItem)
22 QVariantHash variableMetadata(const DataSourceItem &dataSourceItem)
23 {
23 {
24 // Variable metadata contains...
24 // Variable metadata contains...
25
25
26 // ... all metadata of the item
26 // ... all metadata of the item
27 auto result = dataSourceItem.data();
27 auto result = dataSourceItem.data();
28
28
29 // ... and the name of the plugin, recovered from root item
29 // ... and the name of the plugin, recovered from root item
30 result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name());
30 result.insert(QStringLiteral("plugin"), dataSourceItem.rootItem().name());
31
31
32 return result;
32 return result;
33 }
33 }
34
34
35 } // namespace
35 } // namespace
36
36
37 class DataSourceController::DataSourceControllerPrivate {
37 class DataSourceController::DataSourceControllerPrivate {
38 public:
38 public:
39 QMutex m_WorkingMutex;
39 QMutex m_WorkingMutex;
40 /// Data sources registered
40 /// Data sources registered
41 QHash<QUuid, QString> m_DataSources;
41 QHash<QUuid, QString> m_DataSources;
42 /// Data sources structures
42 /// Data sources structures
43 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
43 std::map<QUuid, std::unique_ptr<DataSourceItem> > m_DataSourceItems;
44 /// Data providers registered
44 /// Data providers registered
45 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
45 /// @remarks Data providers are stored as shared_ptr as they can be sent to a variable and
46 /// continue to live without necessarily the data source controller
46 /// continue to live without necessarily the data source controller
47 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
47 std::map<QUuid, std::shared_ptr<IDataProvider> > m_DataProviders;
48
48
49 // Search for the first datasource item matching the specified data
49 // Search for the first datasource item matching the specified data
50 DataSourceItem *findDataSourceItem(const QVariantHash &data)
50 DataSourceItem *findDataSourceItem(const QVariantHash &data)
51 {
51 {
52 DataSourceItem *sourceItem = nullptr;
52 DataSourceItem *sourceItem = nullptr;
53 for (const auto &item : m_DataSourceItems) {
53 for (const auto &item : m_DataSourceItems) {
54 sourceItem = item.second->findItem(data, true);
54 sourceItem = item.second->findItem(data, true);
55 if (sourceItem) {
55 if (sourceItem) {
56 break;
56 break;
57 }
57 }
58 }
58 }
59
59
60 return sourceItem;
60 return sourceItem;
61 }
61 }
62 };
62 };
63
63
64 DataSourceController::DataSourceController(QObject *parent)
64 DataSourceController::DataSourceController(QObject *parent)
65 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
65 : impl{spimpl::make_unique_impl<DataSourceControllerPrivate>()}
66 {
66 {
67 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
67 qCDebug(LOG_DataSourceController()) << tr("DataSourceController construction")
68 << QThread::currentThread();
68 << QThread::currentThread();
69 }
69 }
70
70
71 DataSourceController::~DataSourceController()
71 DataSourceController::~DataSourceController()
72 {
72 {
73 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
73 qCDebug(LOG_DataSourceController()) << tr("DataSourceController destruction")
74 << QThread::currentThread();
74 << QThread::currentThread();
75 this->waitForFinish();
75 this->waitForFinish();
76 }
76 }
77
77
78 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
78 QUuid DataSourceController::registerDataSource(const QString &dataSourceName) noexcept
79 {
79 {
80 auto dataSourceUid = QUuid::createUuid();
80 auto dataSourceUid = QUuid::createUuid();
81 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
81 impl->m_DataSources.insert(dataSourceUid, dataSourceName);
82
82
83 return dataSourceUid;
83 return dataSourceUid;
84 }
84 }
85
85
86 void DataSourceController::setDataSourceItem(
86 void DataSourceController::setDataSourceItem(
87 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
87 const QUuid &dataSourceUid, std::unique_ptr<DataSourceItem> dataSourceItem) noexcept
88 {
88 {
89 if (!dataSourceItem) {
89 if (!dataSourceItem) {
90 qCWarning(LOG_DataSourceController())
90 qCWarning(LOG_DataSourceController())
91 << tr("Data source item can't be registered (null item)");
91 << tr("Data source item can't be registered (null item)");
92 return;
92 return;
93 }
93 }
94
94
95 if (impl->m_DataSources.contains(dataSourceUid)) {
95 if (impl->m_DataSources.contains(dataSourceUid)) {
96 // The data provider is implicitly converted to a shared_ptr
96 // The data provider is implicitly converted to a shared_ptr
97 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
97 impl->m_DataSourceItems.insert(std::make_pair(dataSourceUid, std::move(dataSourceItem)));
98
98
99 // Retrieves the data source item to emit the signal with it
99 // Retrieves the data source item to emit the signal with it
100 auto it = impl->m_DataSourceItems.find(dataSourceUid);
100 auto it = impl->m_DataSourceItems.find(dataSourceUid);
101 if (it != impl->m_DataSourceItems.end()) {
101 if (it != impl->m_DataSourceItems.end()) {
102 emit dataSourceItemSet(it->second.get());
102 emit dataSourceItemSet(it->second.get());
103 }
103 }
104 }
104 }
105 else {
105 else {
106 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
106 qCWarning(LOG_DataSourceController()) << tr("Can't set data source item for uid %1 : no "
107 "data source has been registered with the uid")
107 "data source has been registered with the uid")
108 .arg(dataSourceUid.toString());
108 .arg(dataSourceUid.toString());
109 }
109 }
110 }
110 }
111
111
112 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
112 void DataSourceController::setDataProvider(const QUuid &dataSourceUid,
113 std::unique_ptr<IDataProvider> dataProvider) noexcept
113 std::unique_ptr<IDataProvider> dataProvider) noexcept
114 {
114 {
115 if (impl->m_DataSources.contains(dataSourceUid)) {
115 if (impl->m_DataSources.contains(dataSourceUid)) {
116 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
116 impl->m_DataProviders.insert(std::make_pair(dataSourceUid, std::move(dataProvider)));
117 }
117 }
118 else {
118 else {
119 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
119 qCWarning(LOG_DataSourceController()) << tr("Can't set data provider for uid %1 : no data "
120 "source has been registered with the uid")
120 "source has been registered with the uid")
121 .arg(dataSourceUid.toString());
121 .arg(dataSourceUid.toString());
122 }
122 }
123 }
123 }
124
124
125 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
125 void DataSourceController::loadProductItem(const QUuid &dataSourceUid,
126 const DataSourceItem &productItem) noexcept
126 const DataSourceItem &productItem) noexcept
127 {
127 {
128 if (productItem.type() == DataSourceItemType::PRODUCT
128 if (productItem.type() == DataSourceItemType::PRODUCT
129 || productItem.type() == DataSourceItemType::COMPONENT) {
129 || productItem.type() == DataSourceItemType::COMPONENT) {
130 /// Retrieves the data provider of the data source (if any)
130 /// Retrieves the data provider of the data source (if any)
131 auto it = impl->m_DataProviders.find(dataSourceUid);
131 auto it = impl->m_DataProviders.find(dataSourceUid);
132 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
132 auto dataProvider = (it != impl->m_DataProviders.end()) ? it->second : nullptr;
133
133
134 emit variableCreationRequested(productItem.name(), variableMetadata(productItem),
134 emit variableCreationRequested(productItem.name(), variableMetadata(productItem),
135 dataProvider);
135 dataProvider);
136 }
136 }
137 else {
137 else {
138 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
138 qCWarning(LOG_DataSourceController()) << tr("Can't load an item that is not a product");
139 }
139 }
140 }
140 }
141
141
142 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData) const
142 QByteArray DataSourceController::mimeDataForProductsData(const QVariantList &productsData)
143 {
143 {
144 QByteArray encodedData;
144 QByteArray encodedData;
145 QDataStream stream{&encodedData, QIODevice::WriteOnly};
145 QDataStream stream{&encodedData, QIODevice::WriteOnly};
146
146
147 stream << productsData;
147 stream << productsData;
148
148
149 return encodedData;
149 return encodedData;
150 }
150 }
151
151
152 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData) const
152 QVariantList DataSourceController::productsDataForMimeData(const QByteArray &mimeData)
153 {
153 {
154 QDataStream stream{mimeData};
154 QDataStream stream{mimeData};
155
155
156 QVariantList productList;
156 QVariantList productList;
157 stream >> productList;
157 stream >> productList;
158
158
159 return productList;
159 return productList;
160 }
160 }
161
161
162 void DataSourceController::initialize()
162 void DataSourceController::initialize()
163 {
163 {
164 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
164 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init")
165 << QThread::currentThread();
165 << QThread::currentThread();
166 impl->m_WorkingMutex.lock();
166 impl->m_WorkingMutex.lock();
167 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
167 qCDebug(LOG_DataSourceController()) << tr("DataSourceController init END");
168 }
168 }
169
169
170 void DataSourceController::finalize()
170 void DataSourceController::finalize()
171 {
171 {
172 impl->m_WorkingMutex.unlock();
172 impl->m_WorkingMutex.unlock();
173 }
173 }
174
174
175 void DataSourceController::requestVariable(const QVariantHash &productData)
175 void DataSourceController::requestVariable(const QVariantHash &productData)
176 {
176 {
177 DataSourceItem *sourceItem = impl->findDataSourceItem(productData);
177 auto sourceItem = impl->findDataSourceItem(productData);
178
178
179 if (sourceItem) {
179 if (sourceItem) {
180 auto sourceName = sourceItem->rootItem().name();
180 auto sourceName = sourceItem->rootItem().name();
181 auto sourceId = impl->m_DataSources.key(sourceName);
181 auto sourceId = impl->m_DataSources.key(sourceName);
182 loadProductItem(sourceId, *sourceItem);
182 loadProductItem(sourceId, *sourceItem);
183 }
183 }
184 else {
184 else {
185 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
185 qCWarning(LOG_DataSourceController()) << tr("requestVariable, product data not found");
186 }
186 }
187 }
187 }
188
188
189 void DataSourceController::waitForFinish()
189 void DataSourceController::waitForFinish()
190 {
190 {
191 QMutexLocker locker{&impl->m_WorkingMutex};
191 QMutexLocker locker{&impl->m_WorkingMutex};
192 }
192 }
@@ -1,163 +1,162
1 #include <DataSource/DataSourceItem.h>
1 #include <DataSource/DataSourceItem.h>
2 #include <DataSource/DataSourceItemAction.h>
2 #include <DataSource/DataSourceItemAction.h>
3
3
4 #include <QVector>
4 #include <QVector>
5
5
6 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
6 const QString DataSourceItem::NAME_DATA_KEY = QStringLiteral("name");
7
7
8 struct DataSourceItem::DataSourceItemPrivate {
8 struct DataSourceItem::DataSourceItemPrivate {
9 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
9 explicit DataSourceItemPrivate(DataSourceItemType type, QVariantHash data)
10 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
10 : m_Parent{nullptr}, m_Children{}, m_Type{type}, m_Data{std::move(data)}, m_Actions{}
11 {
11 {
12 }
12 }
13
13
14 DataSourceItem *m_Parent;
14 DataSourceItem *m_Parent;
15 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
15 std::vector<std::unique_ptr<DataSourceItem> > m_Children;
16 DataSourceItemType m_Type;
16 DataSourceItemType m_Type;
17 QVariantHash m_Data;
17 QVariantHash m_Data;
18 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
18 std::vector<std::unique_ptr<DataSourceItemAction> > m_Actions;
19 };
19 };
20
20
21 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
21 DataSourceItem::DataSourceItem(DataSourceItemType type, const QString &name)
22 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
22 : DataSourceItem{type, QVariantHash{{NAME_DATA_KEY, name}}}
23 {
23 {
24 }
24 }
25
25
26 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
26 DataSourceItem::DataSourceItem(DataSourceItemType type, QVariantHash data)
27 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
27 : impl{spimpl::make_unique_impl<DataSourceItemPrivate>(type, std::move(data))}
28 {
28 {
29 }
29 }
30
30
31 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
31 QVector<DataSourceItemAction *> DataSourceItem::actions() const noexcept
32 {
32 {
33 auto result = QVector<DataSourceItemAction *>{};
33 auto result = QVector<DataSourceItemAction *>{};
34
34
35 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
35 std::transform(std::cbegin(impl->m_Actions), std::cend(impl->m_Actions),
36 std::back_inserter(result), [](const auto &action) { return action.get(); });
36 std::back_inserter(result), [](const auto &action) { return action.get(); });
37
37
38 return result;
38 return result;
39 }
39 }
40
40
41 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
41 void DataSourceItem::addAction(std::unique_ptr<DataSourceItemAction> action) noexcept
42 {
42 {
43 action->setDataSourceItem(this);
43 action->setDataSourceItem(this);
44 impl->m_Actions.push_back(std::move(action));
44 impl->m_Actions.push_back(std::move(action));
45 }
45 }
46
46
47 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
47 void DataSourceItem::appendChild(std::unique_ptr<DataSourceItem> child) noexcept
48 {
48 {
49 child->impl->m_Parent = this;
49 child->impl->m_Parent = this;
50 impl->m_Children.push_back(std::move(child));
50 impl->m_Children.push_back(std::move(child));
51 }
51 }
52
52
53 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
53 DataSourceItem *DataSourceItem::child(int childIndex) const noexcept
54 {
54 {
55 if (childIndex < 0 || childIndex >= childCount()) {
55 if (childIndex < 0 || childIndex >= childCount()) {
56 return nullptr;
56 return nullptr;
57 }
57 }
58 else {
58 else {
59 return impl->m_Children.at(childIndex).get();
59 return impl->m_Children.at(childIndex).get();
60 }
60 }
61 }
61 }
62
62
63 int DataSourceItem::childCount() const noexcept
63 int DataSourceItem::childCount() const noexcept
64 {
64 {
65 return impl->m_Children.size();
65 return impl->m_Children.size();
66 }
66 }
67
67
68 QVariant DataSourceItem::data(const QString &key) const noexcept
68 QVariant DataSourceItem::data(const QString &key) const noexcept
69 {
69 {
70 return impl->m_Data.value(key);
70 return impl->m_Data.value(key);
71 }
71 }
72
72
73 QVariantHash DataSourceItem::data() const noexcept
73 QVariantHash DataSourceItem::data() const noexcept
74 {
74 {
75 return impl->m_Data;
75 return impl->m_Data;
76 }
76 }
77
77
78 bool DataSourceItem::isRoot() const noexcept
78 bool DataSourceItem::isRoot() const noexcept
79 {
79 {
80 return impl->m_Parent == nullptr;
80 return impl->m_Parent == nullptr;
81 }
81 }
82
82
83 QString DataSourceItem::name() const noexcept
83 QString DataSourceItem::name() const noexcept
84 {
84 {
85 return data(NAME_DATA_KEY).toString();
85 return data(NAME_DATA_KEY).toString();
86 }
86 }
87
87
88 DataSourceItem *DataSourceItem::parentItem() const noexcept
88 DataSourceItem *DataSourceItem::parentItem() const noexcept
89 {
89 {
90 return impl->m_Parent;
90 return impl->m_Parent;
91 }
91 }
92
92
93 const DataSourceItem &DataSourceItem::rootItem() const noexcept
93 const DataSourceItem &DataSourceItem::rootItem() const noexcept
94 {
94 {
95 return isRoot() ? *this : parentItem()->rootItem();
95 return isRoot() ? *this : parentItem()->rootItem();
96 }
96 }
97
97
98 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
98 void DataSourceItem::setData(const QString &key, const QVariant &value, bool append) noexcept
99 {
99 {
100 auto it = impl->m_Data.constFind(key);
100 auto it = impl->m_Data.constFind(key);
101 if (append && it != impl->m_Data.constEnd()) {
101 if (append && it != impl->m_Data.constEnd()) {
102 // Case of an existing value to which we want to add to the new value
102 // Case of an existing value to which we want to add to the new value
103 if (it->canConvert<QVariantList>()) {
103 if (it->canConvert<QVariantList>()) {
104 auto variantList = it->value<QVariantList>();
104 auto variantList = it->value<QVariantList>();
105 variantList.append(value);
105 variantList.append(value);
106
106
107 impl->m_Data.insert(key, variantList);
107 impl->m_Data.insert(key, variantList);
108 }
108 }
109 else {
109 else {
110 impl->m_Data.insert(key, QVariantList{*it, value});
110 impl->m_Data.insert(key, QVariantList{*it, value});
111 }
111 }
112 }
112 }
113 else {
113 else {
114 // Other cases :
114 // Other cases :
115 // - new value in map OR
115 // - new value in map OR
116 // - replacement of an existing value (not appending)
116 // - replacement of an existing value (not appending)
117 impl->m_Data.insert(key, value);
117 impl->m_Data.insert(key, value);
118 }
118 }
119 }
119 }
120
120
121 DataSourceItemType DataSourceItem::type() const noexcept
121 DataSourceItemType DataSourceItem::type() const noexcept
122 {
122 {
123 return impl->m_Type;
123 return impl->m_Type;
124 }
124 }
125
125
126 DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursive)
126 DataSourceItem *DataSourceItem::findItem(const QVariantHash &data, bool recursive)
127 {
127 {
128 for (const auto &child : impl->m_Children) {
128 for (const auto &child : impl->m_Children) {
129 if (child->impl->m_Data == data) {
129 if (child->impl->m_Data == data) {
130 return child.get();
130 return child.get();
131 }
131 }
132
132
133 if (recursive) {
133 if (recursive) {
134 auto foundItem = child->findItem(data, true);
134 if (auto foundItem = child->findItem(data, true)) {
135 if (foundItem) {
136 return foundItem;
135 return foundItem;
137 }
136 }
138 }
137 }
139 }
138 }
140
139
141 return nullptr;
140 return nullptr;
142 }
141 }
143
142
144 bool DataSourceItem::operator==(const DataSourceItem &other)
143 bool DataSourceItem::operator==(const DataSourceItem &other)
145 {
144 {
146 // Compares items' attributes
145 // Compares items' attributes
147 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
146 if (std::tie(impl->m_Type, impl->m_Data) == std::tie(other.impl->m_Type, other.impl->m_Data)) {
148 // Compares contents of items' children
147 // Compares contents of items' children
149 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
148 return std::equal(std::cbegin(impl->m_Children), std::cend(impl->m_Children),
150 std::cbegin(other.impl->m_Children),
149 std::cbegin(other.impl->m_Children),
151 [](const auto &itemChild, const auto &otherChild) {
150 [](const auto &itemChild, const auto &otherChild) {
152 return *itemChild == *otherChild;
151 return *itemChild == *otherChild;
153 });
152 });
154 }
153 }
155 else {
154 else {
156 return false;
155 return false;
157 }
156 }
158 }
157 }
159
158
160 bool DataSourceItem::operator!=(const DataSourceItem &other)
159 bool DataSourceItem::operator!=(const DataSourceItem &other)
161 {
160 {
162 return !(*this == other);
161 return !(*this == other);
163 }
162 }
@@ -1,29 +1,51
1 #include "Time/TimeController.h"
1 #include "Time/TimeController.h"
2
2
3 #include <QDataStream>
4
3 Q_LOGGING_CATEGORY(LOG_TimeController, "TimeController")
5 Q_LOGGING_CATEGORY(LOG_TimeController, "TimeController")
4
6
5 struct TimeController::TimeControllerPrivate {
7 struct TimeController::TimeControllerPrivate {
6
8
7 SqpRange m_DateTime;
9 SqpRange m_DateTime;
8 };
10 };
9
11
10 TimeController::TimeController(QObject *parent)
12 TimeController::TimeController(QObject *parent)
11 : QObject{parent}, impl{spimpl::make_unique_impl<TimeControllerPrivate>()}
13 : QObject{parent}, impl{spimpl::make_unique_impl<TimeControllerPrivate>()}
12 {
14 {
13 qCDebug(LOG_TimeController()) << tr("TimeController construction");
15 qCDebug(LOG_TimeController()) << tr("TimeController construction");
14 }
16 }
15
17
16 SqpRange TimeController::dateTime() const noexcept
18 SqpRange TimeController::dateTime() const noexcept
17 {
19 {
18 return impl->m_DateTime;
20 return impl->m_DateTime;
19 }
21 }
20
22
23 QByteArray TimeController::mimeDataForTimeRange(const SqpRange &timeRange)
24 {
25 QByteArray encodedData;
26 QDataStream stream{&encodedData, QIODevice::WriteOnly};
27
28 stream << timeRange.m_TStart << timeRange.m_TEnd;
29
30 return encodedData;
31 }
32
33 SqpRange TimeController::timeRangeForMimeData(const QByteArray &mimeData)
34 {
35 QDataStream stream{mimeData};
36
37 SqpRange timeRange;
38 stream >> timeRange.m_TStart >> timeRange.m_TEnd;
39
40 return timeRange;
41 }
42
21 void TimeController::onTimeToUpdate(SqpRange dateTime)
43 void TimeController::onTimeToUpdate(SqpRange dateTime)
22 {
44 {
23 impl->m_DateTime = dateTime;
45 impl->m_DateTime = dateTime;
24 }
46 }
25
47
26 void TimeController::onTimeNotify()
48 void TimeController::onTimeNotify()
27 {
49 {
28 emit timeUpdated(impl->m_DateTime);
50 emit timeUpdated(impl->m_DateTime);
29 }
51 }
@@ -1,368 +1,383
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 #include <Variable/VariableController.h>
3 #include <Variable/VariableModel.h>
3 #include <Variable/VariableModel.h>
4
4
5 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
6 #include <Common/MimeTypesDef.h>
7 #include <Common/StringUtils.h>
7 #include <Common/StringUtils.h>
8
8
9 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
10
10
11 #include <QDataStream>
11 #include <DataSource/DataSourceController.h>
12 #include <Time/TimeController.h>
13
12 #include <QMimeData>
14 #include <QMimeData>
13 #include <QSize>
15 #include <QSize>
14 #include <unordered_map>
16 #include <unordered_map>
15
17
16 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
18 Q_LOGGING_CATEGORY(LOG_VariableModel, "VariableModel")
17
19
18 namespace {
20 namespace {
19
21
20 // Column indexes
22 // Column indexes
21 const auto NAME_COLUMN = 0;
23 const auto NAME_COLUMN = 0;
22 const auto TSTART_COLUMN = 1;
24 const auto TSTART_COLUMN = 1;
23 const auto TEND_COLUMN = 2;
25 const auto TEND_COLUMN = 2;
24 const auto NBPOINTS_COLUMN = 3;
26 const auto NBPOINTS_COLUMN = 3;
25 const auto UNIT_COLUMN = 4;
27 const auto UNIT_COLUMN = 4;
26 const auto MISSION_COLUMN = 5;
28 const auto MISSION_COLUMN = 5;
27 const auto PLUGIN_COLUMN = 6;
29 const auto PLUGIN_COLUMN = 6;
28 const auto NB_COLUMNS = 7;
30 const auto NB_COLUMNS = 7;
29
31
30 // Column properties
32 // Column properties
31 const auto DEFAULT_HEIGHT = 25;
33 const auto DEFAULT_HEIGHT = 25;
32 const auto DEFAULT_WIDTH = 100;
34 const auto DEFAULT_WIDTH = 100;
33
35
34 struct ColumnProperties {
36 struct ColumnProperties {
35 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
37 ColumnProperties(const QString &name = {}, int width = DEFAULT_WIDTH,
36 int height = DEFAULT_HEIGHT)
38 int height = DEFAULT_HEIGHT)
37 : m_Name{name}, m_Width{width}, m_Height{height}
39 : m_Name{name}, m_Width{width}, m_Height{height}
38 {
40 {
39 }
41 }
40
42
41 QString m_Name;
43 QString m_Name;
42 int m_Width;
44 int m_Width;
43 int m_Height;
45 int m_Height;
44 };
46 };
45
47
46 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
48 const auto COLUMN_PROPERTIES = QHash<int, ColumnProperties>{
47 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
49 {NAME_COLUMN, {QObject::tr("Name")}}, {TSTART_COLUMN, {QObject::tr("tStart"), 180}},
48 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
50 {TEND_COLUMN, {QObject::tr("tEnd"), 180}}, {NBPOINTS_COLUMN, {QObject::tr("Nb points")}},
49 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
51 {UNIT_COLUMN, {QObject::tr("Unit")}}, {MISSION_COLUMN, {QObject::tr("Mission")}},
50 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
52 {PLUGIN_COLUMN, {QObject::tr("Plugin")}}};
51
53
52 /// Format for datetimes
54 /// Format for datetimes
53 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
55 const auto DATETIME_FORMAT = QStringLiteral("dd/MM/yyyy \nhh:mm:ss:zzz");
54
56
55 QString uniqueName(const QString &defaultName,
57 QString uniqueName(const QString &defaultName,
56 const std::vector<std::shared_ptr<Variable> > &variables)
58 const std::vector<std::shared_ptr<Variable> > &variables)
57 {
59 {
58 auto forbiddenNames = std::vector<QString>(variables.size());
60 auto forbiddenNames = std::vector<QString>(variables.size());
59 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
61 std::transform(variables.cbegin(), variables.cend(), forbiddenNames.begin(),
60 [](const auto &variable) { return variable->name(); });
62 [](const auto &variable) { return variable->name(); });
61 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
63 auto uniqueName = StringUtils::uniqueName(defaultName, forbiddenNames);
62 Q_ASSERT(!uniqueName.isEmpty());
64 Q_ASSERT(!uniqueName.isEmpty());
63
65
64 return uniqueName;
66 return uniqueName;
65 }
67 }
66
68
67 } // namespace
69 } // namespace
68
70
69 struct VariableModel::VariableModelPrivate {
71 struct VariableModel::VariableModelPrivate {
70 /// Variables created in SciQlop
72 /// Variables created in SciQlop
71 std::vector<std::shared_ptr<Variable> > m_Variables;
73 std::vector<std::shared_ptr<Variable> > m_Variables;
72 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
74 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
73 VariableController *m_VariableController;
75 VariableController *m_VariableController;
74
76
75 /// Return the row index of the variable. -1 if it's not found
77 /// Return the row index of the variable. -1 if it's not found
76 int indexOfVariable(Variable *variable) const noexcept;
78 int indexOfVariable(Variable *variable) const noexcept;
77 };
79 };
78
80
79 VariableModel::VariableModel(VariableController *parent)
81 VariableModel::VariableModel(VariableController *parent)
80 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
82 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
81 {
83 {
82 impl->m_VariableController = parent;
84 impl->m_VariableController = parent;
83 }
85 }
84
86
85 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
87 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
86 {
88 {
87 auto insertIndex = rowCount();
89 auto insertIndex = rowCount();
88 beginInsertRows({}, insertIndex, insertIndex);
90 beginInsertRows({}, insertIndex, insertIndex);
89
91
90 // Generates unique name for the variable
92 // Generates unique name for the variable
91 variable->setName(uniqueName(variable->name(), impl->m_Variables));
93 variable->setName(uniqueName(variable->name(), impl->m_Variables));
92
94
93 impl->m_Variables.push_back(variable);
95 impl->m_Variables.push_back(variable);
94 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
96 connect(variable.get(), &Variable::updated, this, &VariableModel::onVariableUpdated);
95
97
96 endInsertRows();
98 endInsertRows();
97 }
99 }
98
100
99 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
101 bool VariableModel::containsVariable(std::shared_ptr<Variable> variable) const noexcept
100 {
102 {
101 auto end = impl->m_Variables.cend();
103 auto end = impl->m_Variables.cend();
102 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
104 return std::find(impl->m_Variables.cbegin(), end, variable) != end;
103 }
105 }
104
106
105 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
107 std::shared_ptr<Variable> VariableModel::createVariable(const QString &name,
106 const QVariantHash &metadata) noexcept
108 const QVariantHash &metadata) noexcept
107 {
109 {
108 auto variable = std::make_shared<Variable>(name, metadata);
110 auto variable = std::make_shared<Variable>(name, metadata);
109 addVariable(variable);
111 addVariable(variable);
110
112
111 return variable;
113 return variable;
112 }
114 }
113
115
114 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
116 void VariableModel::deleteVariable(std::shared_ptr<Variable> variable) noexcept
115 {
117 {
116 if (!variable) {
118 if (!variable) {
117 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
119 qCCritical(LOG_Variable()) << "Can't delete a null variable from the model";
118 return;
120 return;
119 }
121 }
120
122
121 // Finds variable in the model
123 // Finds variable in the model
122 auto begin = impl->m_Variables.cbegin();
124 auto begin = impl->m_Variables.cbegin();
123 auto end = impl->m_Variables.cend();
125 auto end = impl->m_Variables.cend();
124 auto it = std::find(begin, end, variable);
126 auto it = std::find(begin, end, variable);
125 if (it != end) {
127 if (it != end) {
126 auto removeIndex = std::distance(begin, it);
128 auto removeIndex = std::distance(begin, it);
127
129
128 // Deletes variable
130 // Deletes variable
129 beginRemoveRows({}, removeIndex, removeIndex);
131 beginRemoveRows({}, removeIndex, removeIndex);
130 impl->m_Variables.erase(it);
132 impl->m_Variables.erase(it);
131 endRemoveRows();
133 endRemoveRows();
132 }
134 }
133 else {
135 else {
134 qCritical(LOG_VariableModel())
136 qCritical(LOG_VariableModel())
135 << tr("Can't delete variable %1 from the model: the variable is not in the model")
137 << tr("Can't delete variable %1 from the model: the variable is not in the model")
136 .arg(variable->name());
138 .arg(variable->name());
137 }
139 }
138
140
139 // Removes variable from progress map
141 // Removes variable from progress map
140 impl->m_VariableToProgress.erase(variable);
142 impl->m_VariableToProgress.erase(variable);
141 }
143 }
142
144
143
145
144 std::shared_ptr<Variable> VariableModel::variable(int index) const
146 std::shared_ptr<Variable> VariableModel::variable(int index) const
145 {
147 {
146 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
148 return (index >= 0 && index < impl->m_Variables.size()) ? impl->m_Variables[index] : nullptr;
147 }
149 }
148
150
149 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
151 std::vector<std::shared_ptr<Variable> > VariableModel::variables() const
150 {
152 {
151 return impl->m_Variables;
153 return impl->m_Variables;
152 }
154 }
153
155
154 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
156 void VariableModel::setDataProgress(std::shared_ptr<Variable> variable, double progress)
155 {
157 {
156 if (progress > 0.0) {
158 if (progress > 0.0) {
157 impl->m_VariableToProgress[variable] = progress;
159 impl->m_VariableToProgress[variable] = progress;
158 }
160 }
159 else {
161 else {
160 impl->m_VariableToProgress.erase(variable);
162 impl->m_VariableToProgress.erase(variable);
161 }
163 }
162 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
164 auto modelIndex = createIndex(impl->indexOfVariable(variable.get()), NAME_COLUMN);
163
165
164 emit dataChanged(modelIndex, modelIndex);
166 emit dataChanged(modelIndex, modelIndex);
165 }
167 }
166
168
167 int VariableModel::columnCount(const QModelIndex &parent) const
169 int VariableModel::columnCount(const QModelIndex &parent) const
168 {
170 {
169 Q_UNUSED(parent);
171 Q_UNUSED(parent);
170
172
171 return NB_COLUMNS;
173 return NB_COLUMNS;
172 }
174 }
173
175
174 int VariableModel::rowCount(const QModelIndex &parent) const
176 int VariableModel::rowCount(const QModelIndex &parent) const
175 {
177 {
176 Q_UNUSED(parent);
178 Q_UNUSED(parent);
177
179
178 return impl->m_Variables.size();
180 return impl->m_Variables.size();
179 }
181 }
180
182
181 QVariant VariableModel::data(const QModelIndex &index, int role) const
183 QVariant VariableModel::data(const QModelIndex &index, int role) const
182 {
184 {
183 if (!index.isValid()) {
185 if (!index.isValid()) {
184 return QVariant{};
186 return QVariant{};
185 }
187 }
186
188
187 if (index.row() < 0 || index.row() >= rowCount()) {
189 if (index.row() < 0 || index.row() >= rowCount()) {
188 return QVariant{};
190 return QVariant{};
189 }
191 }
190
192
191 if (role == Qt::DisplayRole) {
193 if (role == Qt::DisplayRole) {
192 if (auto variable = impl->m_Variables.at(index.row()).get()) {
194 if (auto variable = impl->m_Variables.at(index.row()).get()) {
193 switch (index.column()) {
195 switch (index.column()) {
194 case NAME_COLUMN:
196 case NAME_COLUMN:
195 return variable->name();
197 return variable->name();
196 case TSTART_COLUMN: {
198 case TSTART_COLUMN: {
197 auto range = variable->realRange();
199 auto range = variable->realRange();
198 return range != INVALID_RANGE
200 return range != INVALID_RANGE
199 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
201 ? DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT)
200 : QVariant{};
202 : QVariant{};
201 }
203 }
202 case TEND_COLUMN: {
204 case TEND_COLUMN: {
203 auto range = variable->realRange();
205 auto range = variable->realRange();
204 return range != INVALID_RANGE
206 return range != INVALID_RANGE
205 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
207 ? DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT)
206 : QVariant{};
208 : QVariant{};
207 }
209 }
208 case NBPOINTS_COLUMN:
210 case NBPOINTS_COLUMN:
209 return variable->nbPoints();
211 return variable->nbPoints();
210 case UNIT_COLUMN:
212 case UNIT_COLUMN:
211 return variable->metadata().value(QStringLiteral("units"));
213 return variable->metadata().value(QStringLiteral("units"));
212 case MISSION_COLUMN:
214 case MISSION_COLUMN:
213 return variable->metadata().value(QStringLiteral("mission"));
215 return variable->metadata().value(QStringLiteral("mission"));
214 case PLUGIN_COLUMN:
216 case PLUGIN_COLUMN:
215 return variable->metadata().value(QStringLiteral("plugin"));
217 return variable->metadata().value(QStringLiteral("plugin"));
216 default:
218 default:
217 // No action
219 // No action
218 break;
220 break;
219 }
221 }
220
222
221 qWarning(LOG_VariableModel())
223 qWarning(LOG_VariableModel())
222 << tr("Can't get data (unknown column %1)").arg(index.column());
224 << tr("Can't get data (unknown column %1)").arg(index.column());
223 }
225 }
224 else {
226 else {
225 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
227 qWarning(LOG_VariableModel()) << tr("Can't get data (no variable)");
226 }
228 }
227 }
229 }
228 else if (role == VariableRoles::ProgressRole) {
230 else if (role == VariableRoles::ProgressRole) {
229 if (auto variable = impl->m_Variables.at(index.row())) {
231 if (auto variable = impl->m_Variables.at(index.row())) {
230
232
231 auto it = impl->m_VariableToProgress.find(variable);
233 auto it = impl->m_VariableToProgress.find(variable);
232 if (it != impl->m_VariableToProgress.cend()) {
234 if (it != impl->m_VariableToProgress.cend()) {
233 return it->second;
235 return it->second;
234 }
236 }
235 }
237 }
236 }
238 }
237
239
238 return QVariant{};
240 return QVariant{};
239 }
241 }
240
242
241 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
243 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int role) const
242 {
244 {
243 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
245 if (role != Qt::DisplayRole && role != Qt::SizeHintRole) {
244 return QVariant{};
246 return QVariant{};
245 }
247 }
246
248
247 if (orientation == Qt::Horizontal) {
249 if (orientation == Qt::Horizontal) {
248 auto propertiesIt = COLUMN_PROPERTIES.find(section);
250 auto propertiesIt = COLUMN_PROPERTIES.find(section);
249 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
251 if (propertiesIt != COLUMN_PROPERTIES.cend()) {
250 // Role is either DisplayRole or SizeHintRole
252 // Role is either DisplayRole or SizeHintRole
251 return (role == Qt::DisplayRole)
253 return (role == Qt::DisplayRole)
252 ? QVariant{propertiesIt->m_Name}
254 ? QVariant{propertiesIt->m_Name}
253 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
255 : QVariant{QSize{propertiesIt->m_Width, propertiesIt->m_Height}};
254 }
256 }
255 else {
257 else {
256 qWarning(LOG_VariableModel())
258 qWarning(LOG_VariableModel())
257 << tr("Can't get header data (unknown column %1)").arg(section);
259 << tr("Can't get header data (unknown column %1)").arg(section);
258 }
260 }
259 }
261 }
260
262
261 return QVariant{};
263 return QVariant{};
262 }
264 }
263
265
264 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
266 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
265 {
267 {
266 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
268 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
267 }
269 }
268
270
269 Qt::DropActions VariableModel::supportedDropActions() const
271 Qt::DropActions VariableModel::supportedDropActions() const
270 {
272 {
271 return Qt::CopyAction | Qt::MoveAction;
273 return Qt::CopyAction | Qt::MoveAction;
272 }
274 }
273
275
274 Qt::DropActions VariableModel::supportedDragActions() const
276 Qt::DropActions VariableModel::supportedDragActions() const
275 {
277 {
276 return Qt::CopyAction | Qt::MoveAction;
278 return Qt::CopyAction | Qt::MoveAction;
277 }
279 }
278
280
279 QStringList VariableModel::mimeTypes() const
281 QStringList VariableModel::mimeTypes() const
280 {
282 {
281 return {MIME_TYPE_VARIABLE_LIST};
283 return {MIME_TYPE_VARIABLE_LIST, MIME_TYPE_TIME_RANGE};
282 }
284 }
283
285
284 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
286 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
285 {
287 {
286 auto mimeData = new QMimeData;
288 auto mimeData = new QMimeData;
287
289
288 QList<std::shared_ptr<Variable> > variableList;
290 QList<std::shared_ptr<Variable> > variableList;
289
291
292
293 SqpRange firstTimeRange;
290 for (const auto &index : indexes) {
294 for (const auto &index : indexes) {
291 if (index.column() == 0) { // only the first column
295 if (index.column() == 0) { // only the first column
292 auto variable = impl->m_Variables.at(index.row());
296 auto variable = impl->m_Variables.at(index.row());
293 if (variable.get() && index.isValid()) {
297 if (variable.get() && index.isValid()) {
298
299 if (variableList.isEmpty()) {
300 // Gets the range of the first variable
301 firstTimeRange = std::move(variable->range());
302 }
303
294 variableList << variable;
304 variableList << variable;
295 }
305 }
296 }
306 }
297 }
307 }
298
308
299 auto encodedData = impl->m_VariableController->mimeDataForVariables(variableList);
309 auto variablesEncodedData = impl->m_VariableController->mimeDataForVariables(variableList);
300 mimeData->setData(MIME_TYPE_VARIABLE_LIST, encodedData);
310 mimeData->setData(MIME_TYPE_VARIABLE_LIST, variablesEncodedData);
311
312 if (variableList.count() == 1) {
313 // No time range MIME data if multiple variables are dragged
314 auto timeEncodedData = TimeController::mimeDataForTimeRange(firstTimeRange);
315 mimeData->setData(MIME_TYPE_TIME_RANGE, timeEncodedData);
316 }
301
317
302 return mimeData;
318 return mimeData;
303 }
319 }
304
320
305 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
321 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
306 int column, const QModelIndex &parent) const
322 int column, const QModelIndex &parent) const
307 {
323 {
308 // drop of a product
324 // drop of a product
309 return data->hasFormat(MIME_TYPE_PRODUCT_LIST);
325 return data->hasFormat(MIME_TYPE_PRODUCT_LIST);
310 }
326 }
311
327
312 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
328 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
313 const QModelIndex &parent)
329 const QModelIndex &parent)
314 {
330 {
315 bool dropDone = false;
331 auto dropDone = false;
316
332
317 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
333 if (data->hasFormat(MIME_TYPE_PRODUCT_LIST)) {
318 QDataStream stream(data->data(MIME_TYPE_PRODUCT_LIST));
319
334
320 QVariantList productList;
335 auto productList
321 stream >> productList;
336 = DataSourceController::productsDataForMimeData(data->data(MIME_TYPE_PRODUCT_LIST));
322
337
323 for (auto metaData : productList) {
338 for (auto metaData : productList) {
324 emit requestVariable(metaData.toHash());
339 emit requestVariable(metaData.toHash());
325 }
340 }
326
341
327 dropDone = true;
342 dropDone = true;
328 }
343 }
329
344
330 return dropDone;
345 return dropDone;
331 }
346 }
332
347
333 void VariableModel::abortProgress(const QModelIndex &index)
348 void VariableModel::abortProgress(const QModelIndex &index)
334 {
349 {
335 if (auto variable = impl->m_Variables.at(index.row())) {
350 if (auto variable = impl->m_Variables.at(index.row())) {
336 emit abortProgessRequested(variable);
351 emit abortProgessRequested(variable);
337 }
352 }
338 }
353 }
339
354
340 void VariableModel::onVariableUpdated() noexcept
355 void VariableModel::onVariableUpdated() noexcept
341 {
356 {
342 // Finds variable that has been updated in the model
357 // Finds variable that has been updated in the model
343 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
358 if (auto updatedVariable = dynamic_cast<Variable *>(sender())) {
344 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
359 auto updatedVariableIndex = impl->indexOfVariable(updatedVariable);
345
360
346 if (updatedVariableIndex > -1) {
361 if (updatedVariableIndex > -1) {
347 emit dataChanged(createIndex(updatedVariableIndex, 0),
362 emit dataChanged(createIndex(updatedVariableIndex, 0),
348 createIndex(updatedVariableIndex, columnCount() - 1));
363 createIndex(updatedVariableIndex, columnCount() - 1));
349 }
364 }
350 }
365 }
351 }
366 }
352
367
353 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
368 int VariableModel::VariableModelPrivate::indexOfVariable(Variable *variable) const noexcept
354 {
369 {
355 auto begin = std::cbegin(m_Variables);
370 auto begin = std::cbegin(m_Variables);
356 auto end = std::cend(m_Variables);
371 auto end = std::cend(m_Variables);
357 auto it
372 auto it
358 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
373 = std::find_if(begin, end, [variable](const auto &var) { return var.get() == variable; });
359
374
360 if (it != end) {
375 if (it != end) {
361 // Gets the index of the variable in the model: we assume here that views have the same
376 // Gets the index of the variable in the model: we assume here that views have the same
362 // order as the model
377 // order as the model
363 return std::distance(begin, it);
378 return std::distance(begin, it);
364 }
379 }
365 else {
380 else {
366 return -1;
381 return -1;
367 }
382 }
368 }
383 }
@@ -1,23 +1,31
1
1
2
2
3 tests = [
3 tests = [
4 [['Common/TestStringUtils.cpp'],'test_string_utils','StringUtils test'],
4 [['Common/TestStringUtils.cpp'],'test_string_utils','StringUtils test'],
5 [['Data/TestScalarSeries.cpp'],'test_scalar','ScalarSeries test'],
5 [['Data/TestScalarSeries.cpp'],'test_scalar','ScalarSeries test'],
6 [['Data/TestSpectrogramSeries.cpp'],'test_spectrogram','SpectrogramSeries test'],
6 [['Data/TestSpectrogramSeries.cpp'],'test_spectrogram','SpectrogramSeries test'],
7 [['Data/TestVectorSeries.cpp'],'test_vector','VectorSeries test'],
7 [['Data/TestVectorSeries.cpp'],'test_vector','VectorSeries test'],
8 [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'],
8 [['Data/TestOneDimArrayData.cpp'],'test_1d','One Dim Array test'],
9 [['Data/TestOptionalAxis.cpp'],'test_optional_axis','OptionalAxis test'],
9 [['Data/TestOptionalAxis.cpp'],'test_optional_axis','OptionalAxis test'],
10 [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'],
10 [['Data/TestTwoDimArrayData.cpp'],'test_2d','Two Dim Array test'],
11 [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'],
11 [['DataSource/TestDataSourceController.cpp'],'test_data_source','DataSourceController test'],
12 [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'],
12 [['Variable/TestVariableCacheController.cpp'],'test_variable_cache','VariableCacheController test'],
13 [['Variable/TestVariable.cpp'],'test_variable','Variable test'],
13 [['Variable/TestVariable.cpp'],'test_variable','Variable test'],
14 [['Variable/TestVariableSync.cpp'],'test_variable_sync','Variable synchronization test']
14 [['Variable/TestVariableSync.cpp'],'test_variable_sync','Variable synchronization test']
15 ]
15 ]
16
16
17 amdatest_sources = [
18 'Data/DataSeriesBuilders.h',
19 'Data/DataSeriesBuilders.cpp',
20 'Data/DataSeriesUtils.h',
21 'Data/DataSeriesUtils.cpp'
22 ]
23
17 foreach unit_test : tests
24 foreach unit_test : tests
18 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
25 test_moc_files = qt5.preprocess(moc_sources : unit_test[0])
19 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
26 test_exe = executable(unit_test[1],unit_test[0] , test_moc_files,
20 dependencies : [sciqlop_core, qt5test])
27 dependencies : [sciqlop_core, qt5test],
28 sources : [amdatest_sources])
21 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])])
29 test(unit_test[2], test_exe, args: ['-teamcity', '-o', '@0@.teamcity.txt'.format(unit_test[1])])
22 endforeach
30 endforeach
23
31
@@ -1,14 +1,15
1 #ifndef SCIQLOP_DATASOURCETREEWIDGET_H
1 #ifndef SCIQLOP_DATASOURCETREEWIDGET_H
2 #define SCIQLOP_DATASOURCETREEWIDGET_H
2 #define SCIQLOP_DATASOURCETREEWIDGET_H
3
3
4 #include <QTreeWidget>
4 #include <QTreeWidget>
5
5
6 class DataSourceTreeWidget : public QTreeWidget {
6 class DataSourceTreeWidget : public QTreeWidget {
7 public:
7 public:
8 DataSourceTreeWidget(QWidget *parent);
8 DataSourceTreeWidget(QWidget *parent);
9
9
10 protected:
10 protected:
11 QMimeData *mimeData(const QList<QTreeWidgetItem *> items) const override;
11 QMimeData *mimeData(const QList<QTreeWidgetItem *> items) const override;
12 void startDrag(Qt::DropActions supportedActions) override;
12 };
13 };
13
14
14 #endif // SCIQLOP_DATASOURCETREEWIDGET_H
15 #endif // SCIQLOP_DATASOURCETREEWIDGET_H
@@ -1,85 +1,71
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class QVBoxLayout;
8 class QVBoxLayout;
9 class QScrollArea;
9 class QScrollArea;
10 class QTabBar;
10 class VisualizationDragWidget;
11 class VisualizationDragWidget;
11 class VisualizationDragDropContainer;
12 class VisualizationDragDropContainer;
12 class QMimeData;
13 class QMimeData;
13
14
14 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
15
16
16 /**
17 /**
17 * @brief Helper class for drag&drop operations.
18 * @brief Helper class for drag&drop operations.
18 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
19 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
19 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * can interect with the gui.
21 * can interect with the gui.
21 * @see SqpApplication
22 * @see SqpApplication
22 */
23 */
23 class DragDropHelper {
24 class DragDropHelper {
24 public:
25 public:
25 static const QString MIME_TYPE_GRAPH;
26 static const QString MIME_TYPE_GRAPH;
26 static const QString MIME_TYPE_ZONE;
27 static const QString MIME_TYPE_ZONE;
27
28
29 enum class PlaceHolderType { Default, Graph, Zone };
30
28 DragDropHelper();
31 DragDropHelper();
29 virtual ~DragDropHelper();
32 virtual ~DragDropHelper();
30
33
31 /// Resets some internal variables. Must be called before any new drag&drop operation.
34 /// Resets some internal variables. Must be called before any new drag&drop operation.
32 void resetDragAndDrop();
35 void resetDragAndDrop();
33
36
34 /// Sets the visualization widget currently being drag on the visualization.
37 /// Sets the visualization widget currently being drag on the visualization.
35 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
38 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
36
39
37 /// Returns the visualization widget currently being drag on the visualization.
40 /// Returns the visualization widget currently being drag on the visualization.
38 /// Can be null if a new visualization widget is intended to be created by the drag&drop
41 /// Can be null if a new visualization widget is intended to be created by the drag&drop
39 /// operation.
42 /// operation.
40 VisualizationDragWidget *getCurrentDragWidget() const;
43 VisualizationDragWidget *getCurrentDragWidget() const;
41
44
42 QWidget &placeHolder() const;
45 QWidget &placeHolder() const;
43 void insertPlaceHolder(QVBoxLayout *layout, int index);
46 void insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
47 const QString &topLabelText);
44 void removePlaceHolder();
48 void removePlaceHolder();
45 bool isPlaceHolderSet() const;
49 bool isPlaceHolderSet() const;
46
50
47 /// Checks if the specified mime data is valid for a drop in the visualization
51 /// Checks if the specified mime data is valid for a drop in the visualization
48 bool checkMimeDataForVisualization(const QMimeData *mimeData,
52 bool checkMimeDataForVisualization(const QMimeData *mimeData,
49 VisualizationDragDropContainer *dropContainer);
53 VisualizationDragDropContainer *dropContainer);
50
54
51 void addDragDropScrollArea(QScrollArea *scrollArea);
55 void addDragDropScrollArea(QScrollArea *scrollArea);
52 void removeDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
53
57
58 void addDragDropTabBar(QTabBar *tabBar);
59 void removeDragDropTabBar(QTabBar *tabBar);
60
54 QUrl imageTemporaryUrl(const QImage &image) const;
61 QUrl imageTemporaryUrl(const QImage &image) const;
55
62
63 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
64 VisualizationDragWidget *getHightlightedDragWidget() const;
65
56 private:
66 private:
57 class DragDropHelperPrivate;
67 class DragDropHelperPrivate;
58 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
68 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
59 };
69 };
60
70
61 /**
62 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
63 * @note A QScrollArea inside an other QScrollArea is not fully supported.
64 */
65 class DragDropScroller : public QObject {
66 Q_OBJECT
67
68 public:
69 DragDropScroller(QObject *parent = nullptr);
70
71 void addScrollArea(QScrollArea *scrollArea);
72 void removeScrollArea(QScrollArea *scrollArea);
73
74 protected:
75 bool eventFilter(QObject *obj, QEvent *event);
76
77 private:
78 class DragDropScrollerPrivate;
79 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
80
81 private slots:
82 void onTimer();
83 };
84
85 #endif // SCIQLOP_DRAGDROPHELPER_H
71 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -1,32 +1,47
1 #ifndef SCIQLOP_TIMEWIDGET_H
1 #ifndef SCIQLOP_TIMEWIDGET_H
2 #define SCIQLOP_TIMEWIDGET_H
2 #define SCIQLOP_TIMEWIDGET_H
3
3
4 #include <QWidget>
4 #include <QWidget>
5
5
6 #include <Data/SqpRange.h>
6 #include <Data/SqpRange.h>
7
7
8 #include <Common/spimpl.h>
9
8 namespace Ui {
10 namespace Ui {
9 class TimeWidget;
11 class TimeWidget;
10 } // Ui
12 } // Ui
11
13
12 class TimeWidget : public QWidget {
14 class TimeWidget : public QWidget {
13 Q_OBJECT
15 Q_OBJECT
14
16
15 public:
17 public:
16 explicit TimeWidget(QWidget *parent = 0);
18 explicit TimeWidget(QWidget *parent = 0);
17 virtual ~TimeWidget();
19 virtual ~TimeWidget();
18
20
21 void setTimeRange(SqpRange time);
22 SqpRange timeRange() const;
23
19 signals:
24 signals:
20 /// Signal emitted when the time parameters has beed updated
25 /// Signal emitted when the time parameters has beed updated
21 void timeUpdated(SqpRange time);
26 void timeUpdated(SqpRange time);
22
27
23 public slots:
28 public slots:
24 /// slot called when time parameters update has ben requested
29 /// slot called when time parameters update has ben requested
25 void onTimeUpdateRequested();
30 void onTimeUpdateRequested();
26
31
32 protected:
33 void dragEnterEvent(QDragEnterEvent *event) override;
34 void dragLeaveEvent(QDragLeaveEvent *event) override;
35 void dropEvent(QDropEvent *event) override;
36
37 void mousePressEvent(QMouseEvent *event) override;
38 void mouseMoveEvent(QMouseEvent *event) override;
27
39
28 private:
40 private:
29 Ui::TimeWidget *ui;
41 Ui::TimeWidget *ui;
42
43 class TimeWidgetPrivate;
44 spimpl::unique_impl_ptr<TimeWidgetPrivate> impl;
30 };
45 };
31
46
32 #endif // SCIQLOP_ SQPSIDEPANE_H
47 #endif // SCIQLOP_ SQPSIDEPANE_H
@@ -1,51 +1,57
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QFrame>
5 #include <QLoggingCategory>
6 #include <QLoggingCategory>
6 #include <QMimeData>
7 #include <QMimeData>
7 #include <QVBoxLayout>
8 #include <QVBoxLayout>
8 #include <QWidget>
9
9
10 #include <functional>
10 #include <functional>
11
11
12 #include <DragAndDrop/DragDropHelper.h>
13
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
13
15
14 class VisualizationDragWidget;
16 class VisualizationDragWidget;
15
17
16 class VisualizationDragDropContainer : public QWidget {
18 class VisualizationDragDropContainer : public QFrame {
17 Q_OBJECT
19 Q_OBJECT
18
20
19 signals:
21 signals:
20 void dropOccured(int dropIndex, const QMimeData *mimeData);
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
21
24
22 public:
25 public:
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged };
23 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
24
28
25 VisualizationDragDropContainer(QWidget *parent = nullptr);
29 VisualizationDragDropContainer(QWidget *parent = nullptr);
26
30
27 void addDragWidget(VisualizationDragWidget *dragWidget);
31 void addDragWidget(VisualizationDragWidget *dragWidget);
28 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
32 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
29
33
30 void setAcceptedMimeTypes(const QStringList &mimeTypes);
34 void addAcceptedMimeType(const QString &mimeType, DropBehavior behavior);
31 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
32
35
33 int countDragWidget() const;
36 int countDragWidget() const;
34
37
35 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
38 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
36
39
40 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
41 const QString &placeHolderText = QString());
42
37 protected:
43 protected:
38 void dragEnterEvent(QDragEnterEvent *event);
44 void dragEnterEvent(QDragEnterEvent *event);
39 void dragLeaveEvent(QDragLeaveEvent *event);
45 void dragLeaveEvent(QDragLeaveEvent *event);
40 void dragMoveEvent(QDragMoveEvent *event);
46 void dragMoveEvent(QDragMoveEvent *event);
41 void dropEvent(QDropEvent *event);
47 void dropEvent(QDropEvent *event);
42
48
43 private:
49 private:
44 class VisualizationDragDropContainerPrivate;
50 class VisualizationDragDropContainerPrivate;
45 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
51 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
46
52
47 private slots:
53 private slots:
48 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
54 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
49 };
55 };
50
56
51 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
57 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,29 +1,30
1 #ifndef SCIQLOP_VISUALIZATIONDRAGWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGWIDGET_H
2 #define SCIQLOP_VISUALIZATIONDRAGWIDGET_H
2 #define SCIQLOP_VISUALIZATIONDRAGWIDGET_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QMimeData>
5 #include <QMimeData>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class VisualizationDragWidget : public QWidget {
8 class VisualizationDragWidget : public QWidget {
9 Q_OBJECT
9 Q_OBJECT
10
10
11 public:
11 public:
12 VisualizationDragWidget(QWidget *parent = nullptr);
12 VisualizationDragWidget(QWidget *parent = nullptr);
13
13
14 virtual QMimeData *mimeData() const = 0;
14 virtual QMimeData *mimeData() const = 0;
15 virtual bool isDragAllowed() const = 0;
15 virtual bool isDragAllowed() const = 0;
16 virtual void highlightForMerge(bool highlighted) { Q_UNUSED(highlighted); };
16
17
17 protected:
18 protected:
18 virtual void mousePressEvent(QMouseEvent *event) override;
19 virtual void mousePressEvent(QMouseEvent *event) override;
19 virtual void mouseMoveEvent(QMouseEvent *event) override;
20 virtual void mouseMoveEvent(QMouseEvent *event) override;
20
21
21 private:
22 private:
22 class VisualizationDragWidgetPrivate;
23 class VisualizationDragWidgetPrivate;
23 spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl;
24 spimpl::unique_impl_ptr<VisualizationDragWidgetPrivate> impl;
24
25
25 signals:
26 signals:
26 void dragDetected(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
27 void dragDetected(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
27 };
28 };
28
29
29 #endif // SCIQLOP_VISUALIZATIONDRAGWIDGET_H
30 #endif // SCIQLOP_VISUALIZATIONDRAGWIDGET_H
@@ -1,107 +1,108
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
15
15
16 class QCPRange;
16 class QCPRange;
17 class QCustomPlot;
17 class QCustomPlot;
18 class SqpRange;
18 class SqpRange;
19 class Variable;
19 class Variable;
20 class VisualizationZoneWidget;
20 class VisualizationZoneWidget;
21
21
22 namespace Ui {
22 namespace Ui {
23 class VisualizationGraphWidget;
23 class VisualizationGraphWidget;
24 } // namespace Ui
24 } // namespace Ui
25
25
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
26 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
27 Q_OBJECT
27 Q_OBJECT
28
28
29 friend class QCustomPlotSynchronizer;
29 friend class QCustomPlotSynchronizer;
30 friend class VisualizationGraphRenderingDelegate;
30 friend class VisualizationGraphRenderingDelegate;
31
31
32 public:
32 public:
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
33 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
34 virtual ~VisualizationGraphWidget();
34 virtual ~VisualizationGraphWidget();
35
35
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
36 VisualizationZoneWidget *parentZoneWidget() const noexcept;
37
37
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
38 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
39 void enableAcquisition(bool enable);
39 void enableAcquisition(bool enable);
40
40
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
41 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
42
42
43 /// Removes a variable from the graph
43 /// Removes a variable from the graph
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
44 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
45
45
46 /// Returns the list of all variables used in the graph
46 /// Returns the list of all variables used in the graph
47 QList<std::shared_ptr<Variable> > variables() const;
47 QList<std::shared_ptr<Variable> > variables() const;
48
48
49 void setYRange(const SqpRange &range);
49 void setYRange(const SqpRange &range);
50 SqpRange graphRange() const noexcept;
50 SqpRange graphRange() const noexcept;
51 void setGraphRange(const SqpRange &range);
51 void setGraphRange(const SqpRange &range);
52
52
53 // IVisualizationWidget interface
53 // IVisualizationWidget interface
54 void accept(IVisualizationWidgetVisitor *visitor) override;
54 void accept(IVisualizationWidgetVisitor *visitor) override;
55 bool canDrop(const Variable &variable) const override;
55 bool canDrop(const Variable &variable) const override;
56 bool contains(const Variable &variable) const override;
56 bool contains(const Variable &variable) const override;
57 QString name() const override;
57 QString name() const override;
58
58
59 // VisualisationDragWidget
59 // VisualisationDragWidget
60 QMimeData *mimeData() const override;
60 QMimeData *mimeData() const override;
61 bool isDragAllowed() const override;
61 bool isDragAllowed() const override;
62 void highlightForMerge(bool highlighted) override;
62
63
63 signals:
64 signals:
64 void synchronize(const SqpRange &range, const SqpRange &oldRange);
65 void synchronize(const SqpRange &range, const SqpRange &oldRange);
65 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
66 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
66 bool synchronise);
67 bool synchronise);
67
68
68 /// Signal emitted when the variable is about to be removed from the graph
69 /// Signal emitted when the variable is about to be removed from the graph
69 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
70 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
70 /// Signal emitted when the variable has been added to the graph
71 /// Signal emitted when the variable has been added to the graph
71 void variableAdded(std::shared_ptr<Variable> var);
72 void variableAdded(std::shared_ptr<Variable> var);
72
73
73 protected:
74 protected:
74 void closeEvent(QCloseEvent *event) override;
75 void closeEvent(QCloseEvent *event) override;
75 void enterEvent(QEvent *event) override;
76 void enterEvent(QEvent *event) override;
76 void leaveEvent(QEvent *event) override;
77 void leaveEvent(QEvent *event) override;
77
78
78 QCustomPlot &plot() noexcept;
79 QCustomPlot &plot() noexcept;
79
80
80 private:
81 private:
81 Ui::VisualizationGraphWidget *ui;
82 Ui::VisualizationGraphWidget *ui;
82
83
83 class VisualizationGraphWidgetPrivate;
84 class VisualizationGraphWidgetPrivate;
84 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
85 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
85
86
86 private slots:
87 private slots:
87 /// Slot called when right clicking on the graph (displays a menu)
88 /// Slot called when right clicking on the graph (displays a menu)
88 void onGraphMenuRequested(const QPoint &pos) noexcept;
89 void onGraphMenuRequested(const QPoint &pos) noexcept;
89
90
90 /// Rescale the X axe to range parameter
91 /// Rescale the X axe to range parameter
91 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
92 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
92
93
93 /// Slot called when a mouse move was made
94 /// Slot called when a mouse move was made
94 void onMouseMove(QMouseEvent *event) noexcept;
95 void onMouseMove(QMouseEvent *event) noexcept;
95 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
96 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
96 void onMouseWheel(QWheelEvent *event) noexcept;
97 void onMouseWheel(QWheelEvent *event) noexcept;
97 /// Slot called when a mouse press was made, to activate the calibration of a graph
98 /// Slot called when a mouse press was made, to activate the calibration of a graph
98 void onMousePress(QMouseEvent *event) noexcept;
99 void onMousePress(QMouseEvent *event) noexcept;
99 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
100 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
100 void onMouseRelease(QMouseEvent *event) noexcept;
101 void onMouseRelease(QMouseEvent *event) noexcept;
101
102
102 void onDataCacheVariableUpdated();
103 void onDataCacheVariableUpdated();
103
104
104 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
105 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
105 };
106 };
106
107
107 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
108 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,90 +1,91
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
2 #define SCIQLOP_VISUALIZATIONZONEWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationZoneWidget)
15
15
16 namespace Ui {
16 namespace Ui {
17 class VisualizationZoneWidget;
17 class VisualizationZoneWidget;
18 } // namespace Ui
18 } // namespace Ui
19
19
20 class Variable;
20 class Variable;
21 class VisualizationGraphWidget;
21 class VisualizationGraphWidget;
22
22
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
23 class VisualizationZoneWidget : public VisualizationDragWidget, public IVisualizationWidget {
24 Q_OBJECT
24 Q_OBJECT
25
25
26 public:
26 public:
27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
27 explicit VisualizationZoneWidget(const QString &name = {}, QWidget *parent = 0);
28 virtual ~VisualizationZoneWidget();
28 virtual ~VisualizationZoneWidget();
29
29
30 /// Adds a graph widget
30 /// Adds a graph widget
31 void addGraph(VisualizationGraphWidget *graphWidget);
31 void addGraph(VisualizationGraphWidget *graphWidget);
32
32
33 /// Inserts a graph widget
33 /// Inserts a graph widget
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
34 void insertGraph(int index, VisualizationGraphWidget *graphWidget);
35
35
36 /**
36 /**
37 * Creates a graph using a variable. The variable will be displayed in the new graph.
37 * Creates a graph using a variable. The variable will be displayed in the new graph.
38 * The graph is added at the end.
38 * The graph is added at the end.
39 * @param variable the variable for which to create the graph
39 * @param variable the variable for which to create the graph
40 * @return the pointer to the created graph
40 * @return the pointer to the created graph
41 */
41 */
42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
42 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable);
43
43
44 /**
44 /**
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
45 * Creates a graph using a variable. The variable will be displayed in the new graph.
46 * The graph is inserted at the specified index.
46 * The graph is inserted at the specified index.
47 * @param variable the variable for which to create the graph
47 * @param variable the variable for which to create the graph
48 * @param index The index where the graph should be inserted in the layout
48 * @param index The index where the graph should be inserted in the layout
49 * @return the pointer to the created graph
49 * @return the pointer to the created graph
50 */
50 */
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
51 VisualizationGraphWidget *createGraph(std::shared_ptr<Variable> variable, int index);
52
52
53 /**
53 /**
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
54 * Creates a graph using a list of variables. The variables will be displayed in the new graph.
55 * The graph is inserted at the specified index.
55 * The graph is inserted at the specified index.
56 * @param variables List of variables to be added to the graph
56 * @param variables List of variables to be added to the graph
57 * @param index The index where the graph should be inserted in the layout
57 * @param index The index where the graph should be inserted in the layout
58 * @return the pointer to the created graph
58 * @return the pointer to the created graph
59 */
59 */
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
60 VisualizationGraphWidget *createGraph(const QList<std::shared_ptr<Variable> > variables,
61 int index);
61 int index);
62
62
63 // IVisualizationWidget interface
63 // IVisualizationWidget interface
64 void accept(IVisualizationWidgetVisitor *visitor) override;
64 void accept(IVisualizationWidgetVisitor *visitor) override;
65 bool canDrop(const Variable &variable) const override;
65 bool canDrop(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
66 bool contains(const Variable &variable) const override;
67 QString name() const override;
67 QString name() const override;
68
68
69 // VisualisationDragWidget
69 // VisualisationDragWidget
70 QMimeData *mimeData() const override;
70 QMimeData *mimeData() const override;
71 bool isDragAllowed() const override;
71 bool isDragAllowed() const override;
72
72
73 protected:
73 protected:
74 void closeEvent(QCloseEvent *event) override;
74 void closeEvent(QCloseEvent *event) override;
75
75
76 private:
76 private:
77 Ui::VisualizationZoneWidget *ui;
77 Ui::VisualizationZoneWidget *ui;
78
78
79 class VisualizationZoneWidgetPrivate;
79 class VisualizationZoneWidgetPrivate;
80 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
80 spimpl::unique_impl_ptr<VisualizationZoneWidgetPrivate> impl;
81
81
82 private slots:
82 private slots:
83 void onVariableAdded(std::shared_ptr<Variable> variable);
83 void onVariableAdded(std::shared_ptr<Variable> variable);
84 /// Slot called when a variable is about to be removed from a graph contained in the zone
84 /// Slot called when a variable is about to be removed from a graph contained in the zone
85 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
85 void onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable);
86
86
87 void dropMimeData(int index, const QMimeData *mimeData);
87 void dropMimeData(int index, const QMimeData *mimeData);
88 void dropMimeDataOnGraph(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
88 };
89 };
89
90
90 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
91 #endif // SCIQLOP_VISUALIZATIONZONEWIDGET_H
@@ -1,87 +1,95
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/DataSource/DataSourceTreeWidget.h',
4 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/SidePane/SqpSidePane.h',
7 'include/SidePane/SqpSidePane.h',
7 'include/SqpApplication.h',
8 'include/SqpApplication.h',
8 'include/DragDropHelper.h',
9 'include/DragAndDrop/DragDropHelper.h',
10 'include/DragAndDrop/DragDropScroller.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
9 'include/TimeWidget/TimeWidget.h',
12 'include/TimeWidget/TimeWidget.h',
10 'include/Variable/VariableInspectorWidget.h',
13 'include/Variable/VariableInspectorWidget.h',
14 'include/Variable/VariableInspectorTableView.h',
11 'include/Variable/RenameVariableDialog.h',
15 'include/Variable/RenameVariableDialog.h',
12 'include/Visualization/qcustomplot.h',
16 'include/Visualization/qcustomplot.h',
13 'include/Visualization/VisualizationGraphWidget.h',
17 'include/Visualization/VisualizationGraphWidget.h',
14 'include/Visualization/VisualizationTabWidget.h',
18 'include/Visualization/VisualizationTabWidget.h',
15 'include/Visualization/VisualizationWidget.h',
19 'include/Visualization/VisualizationWidget.h',
16 'include/Visualization/VisualizationZoneWidget.h',
20 'include/Visualization/VisualizationZoneWidget.h',
17 'include/Visualization/VisualizationDragDropContainer.h',
21 'include/Visualization/VisualizationDragDropContainer.h',
18 'include/Visualization/VisualizationDragWidget.h'
22 'include/Visualization/VisualizationDragWidget.h'
19 ]
23 ]
20
24
21 gui_ui_files = [
25 gui_ui_files = [
22 'ui/DataSource/DataSourceWidget.ui',
26 'ui/DataSource/DataSourceWidget.ui',
23 'ui/Settings/SqpSettingsDialog.ui',
27 'ui/Settings/SqpSettingsDialog.ui',
24 'ui/Settings/SqpSettingsGeneralWidget.ui',
28 'ui/Settings/SqpSettingsGeneralWidget.ui',
25 'ui/SidePane/SqpSidePane.ui',
29 'ui/SidePane/SqpSidePane.ui',
26 'ui/TimeWidget/TimeWidget.ui',
30 'ui/TimeWidget/TimeWidget.ui',
27 'ui/Variable/VariableInspectorWidget.ui',
31 'ui/Variable/VariableInspectorWidget.ui',
28 'ui/Variable/RenameVariableDialog.ui',
32 'ui/Variable/RenameVariableDialog.ui',
29 'ui/Variable/VariableMenuHeaderWidget.ui',
33 'ui/Variable/VariableMenuHeaderWidget.ui',
30 'ui/Visualization/VisualizationGraphWidget.ui',
34 'ui/Visualization/VisualizationGraphWidget.ui',
31 'ui/Visualization/VisualizationTabWidget.ui',
35 'ui/Visualization/VisualizationTabWidget.ui',
32 'ui/Visualization/VisualizationWidget.ui',
36 'ui/Visualization/VisualizationWidget.ui',
33 'ui/Visualization/VisualizationZoneWidget.ui'
37 'ui/Visualization/VisualizationZoneWidget.ui'
34 ]
38 ]
35
39
36 gui_qresources = ['resources/sqpguiresources.qrc']
40 gui_qresources = ['resources/sqpguiresources.qrc']
37
41
38 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
42 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
39 ui_files : gui_ui_files,
43 ui_files : gui_ui_files,
40 qresources : gui_qresources)
44 qresources : gui_qresources)
41
45
42 gui_sources = [
46 gui_sources = [
43 'src/SqpApplication.cpp',
47 'src/SqpApplication.cpp',
44 'src/DragDropHelper.cpp',
48 'src/DragAndDrop/DragDropHelper.cpp',
49 'src/DragAndDrop/DragDropScroller.cpp',
50 'src/DragAndDrop/DragDropTabSwitcher.cpp',
45 'src/Common/ColorUtils.cpp',
51 'src/Common/ColorUtils.cpp',
46 'src/Common/VisualizationDef.cpp',
52 'src/Common/VisualizationDef.cpp',
47 'src/DataSource/DataSourceTreeWidgetItem.cpp',
53 'src/DataSource/DataSourceTreeWidgetItem.cpp',
48 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
54 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
49 'src/DataSource/DataSourceWidget.cpp',
55 'src/DataSource/DataSourceWidget.cpp',
56 'src/DataSource/DataSourceTreeWidget.cpp',
50 'src/Settings/SqpSettingsDialog.cpp',
57 'src/Settings/SqpSettingsDialog.cpp',
51 'src/Settings/SqpSettingsGeneralWidget.cpp',
58 'src/Settings/SqpSettingsGeneralWidget.cpp',
52 'src/SidePane/SqpSidePane.cpp',
59 'src/SidePane/SqpSidePane.cpp',
53 'src/TimeWidget/TimeWidget.cpp',
60 'src/TimeWidget/TimeWidget.cpp',
54 'src/Variable/VariableInspectorWidget.cpp',
61 'src/Variable/VariableInspectorWidget.cpp',
62 'src/Variable/VariableInspectorTableView.cpp',
55 'src/Variable/VariableMenuHeaderWidget.cpp',
63 'src/Variable/VariableMenuHeaderWidget.cpp',
56 'src/Variable/RenameVariableDialog.cpp',
64 'src/Variable/RenameVariableDialog.cpp',
57 'src/Visualization/VisualizationGraphHelper.cpp',
65 'src/Visualization/VisualizationGraphHelper.cpp',
58 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
66 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
59 'src/Visualization/VisualizationGraphWidget.cpp',
67 'src/Visualization/VisualizationGraphWidget.cpp',
60 'src/Visualization/VisualizationTabWidget.cpp',
68 'src/Visualization/VisualizationTabWidget.cpp',
61 'src/Visualization/VisualizationWidget.cpp',
69 'src/Visualization/VisualizationWidget.cpp',
62 'src/Visualization/VisualizationZoneWidget.cpp',
70 'src/Visualization/VisualizationZoneWidget.cpp',
63 'src/Visualization/qcustomplot.cpp',
71 'src/Visualization/qcustomplot.cpp',
64 'src/Visualization/QCustomPlotSynchronizer.cpp',
72 'src/Visualization/QCustomPlotSynchronizer.cpp',
65 'src/Visualization/operations/FindVariableOperation.cpp',
73 'src/Visualization/operations/FindVariableOperation.cpp',
66 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
74 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
67 'src/Visualization/operations/MenuBuilder.cpp',
75 'src/Visualization/operations/MenuBuilder.cpp',
68 'src/Visualization/operations/RemoveVariableOperation.cpp',
76 'src/Visualization/operations/RemoveVariableOperation.cpp',
69 'src/Visualization/operations/RescaleAxeOperation.cpp',
77 'src/Visualization/operations/RescaleAxeOperation.cpp',
70 'src/Visualization/VisualizationDragDropContainer.cpp',
78 'src/Visualization/VisualizationDragDropContainer.cpp',
71 'src/Visualization/VisualizationDragWidget.cpp'
79 'src/Visualization/VisualizationDragWidget.cpp'
72 ]
80 ]
73
81
74 gui_inc = include_directories(['include'])
82 gui_inc = include_directories(['include'])
75
83
76 sciqlop_gui_lib = library('sciqlopgui',
84 sciqlop_gui_lib = library('sciqlopgui',
77 gui_sources,
85 gui_sources,
78 gui_moc_files,
86 gui_moc_files,
79 include_directories : [gui_inc],
87 include_directories : [gui_inc],
80 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
88 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
81 install : true
89 install : true
82 )
90 )
83
91
84 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
92 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
85 include_directories : gui_inc,
93 include_directories : gui_inc,
86 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
94 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
87
95
@@ -1,37 +1,45
1 #include "DataSource/DataSourceTreeWidget.h"
1 #include "DataSource/DataSourceTreeWidget.h"
2 #include "Common/MimeTypesDef.h"
2 #include "Common/MimeTypesDef.h"
3 #include "DataSource/DataSourceController.h"
3 #include "DataSource/DataSourceController.h"
4 #include "DataSource/DataSourceItem.h"
4 #include "DataSource/DataSourceItem.h"
5 #include "DataSource/DataSourceTreeWidgetItem.h"
5 #include "DataSource/DataSourceTreeWidgetItem.h"
6
6
7 #include "DragAndDrop/DragDropHelper.h"
7 #include "SqpApplication.h"
8 #include "SqpApplication.h"
8
9
9 #include <QMimeData>
10 #include <QMimeData>
10
11
11 DataSourceTreeWidget::DataSourceTreeWidget(QWidget *parent) : QTreeWidget(parent) {}
12 DataSourceTreeWidget::DataSourceTreeWidget(QWidget *parent) : QTreeWidget(parent) {}
12
13
13 QMimeData *DataSourceTreeWidget::mimeData(const QList<QTreeWidgetItem *> items) const
14 QMimeData *DataSourceTreeWidget::mimeData(const QList<QTreeWidgetItem *> items) const
14 {
15 {
15 auto mimeData = new QMimeData;
16 auto mimeData = new QMimeData;
16
17
17 // Basic check to ensure the item are correctly typed
18 // Basic check to ensure the item are correctly typed
18 Q_ASSERT(items.isEmpty() || dynamic_cast<DataSourceTreeWidgetItem *>(items.first()) != nullptr);
19 Q_ASSERT(items.isEmpty() || dynamic_cast<DataSourceTreeWidgetItem *>(items.first()) != nullptr);
19
20
20 QVariantList productData;
21 QVariantList productData;
21
22
22 for (auto item : items) {
23 for (auto item : items) {
23 auto dataSourceTreeItem = static_cast<DataSourceTreeWidgetItem *>(item);
24 auto dataSourceTreeItem = static_cast<DataSourceTreeWidgetItem *>(item);
24 auto dataSource = dataSourceTreeItem->data();
25 auto dataSource = dataSourceTreeItem->data();
25
26
26 if (dataSource->type() == DataSourceItemType::COMPONENT
27 if (dataSource->type() == DataSourceItemType::COMPONENT
27 || dataSource->type() == DataSourceItemType::PRODUCT) {
28 || dataSource->type() == DataSourceItemType::PRODUCT) {
28 auto metaData = dataSource->data();
29 auto metaData = dataSource->data();
29 productData << metaData;
30 productData << metaData;
30 }
31 }
31 }
32 }
32
33
33 auto encodedData = sqpApp->dataSourceController().mimeDataForProductsData(productData);
34 auto encodedData = sqpApp->dataSourceController().mimeDataForProductsData(productData);
34 mimeData->setData(MIME_TYPE_PRODUCT_LIST, encodedData);
35 mimeData->setData(MIME_TYPE_PRODUCT_LIST, encodedData);
35
36
36 return mimeData;
37 return mimeData;
37 }
38 }
39
40 void DataSourceTreeWidget::startDrag(Qt::DropActions supportedActions)
41 {
42 // Resets the drag&drop operations before it's starting
43 sqpApp->dragDropHelper().resetDragAndDrop();
44 QTreeWidget::startDrag(supportedActions);
45 }
@@ -1,295 +1,125
1 #include "DragDropHelper.h"
1 #include "DragAndDrop/DragDropScroller.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
4 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
7
2
8 #include "Variable/VariableController.h"
9
10 #include "Common/MimeTypesDef.h"
11 #include "Common/VisualizationDef.h"
12
13 #include <QDir>
14 #include <QDragEnterEvent>
3 #include <QDragEnterEvent>
15 #include <QDragMoveEvent>
4 #include <QDragMoveEvent>
16 #include <QScrollArea>
17 #include <QScrollBar>
5 #include <QScrollBar>
18 #include <QTimer>
6 #include <QTimer>
19 #include <QVBoxLayout>
20
7
21 const int SCROLL_SPEED = 5;
8 const int SCROLL_SPEED = 5;
22 const int SCROLL_ZONE_SIZE = 50;
9 const int SCROLL_ZONE_SIZE = 50;
23
10
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
25
26 struct DragDropScroller::DragDropScrollerPrivate {
11 struct DragDropScroller::DragDropScrollerPrivate {
27
12
28 QList<QScrollArea *> m_ScrollAreas;
13 QList<QScrollArea *> m_ScrollAreas;
29 QScrollArea *m_CurrentScrollArea = nullptr;
14 QScrollArea *m_CurrentScrollArea = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
15 std::unique_ptr<QTimer> m_Timer = nullptr;
31
16
32
33 enum class ScrollDirection { up, down, unknown };
17 enum class ScrollDirection { up, down, unknown };
34 ScrollDirection m_Direction = ScrollDirection::unknown;
18 ScrollDirection m_Direction = ScrollDirection::unknown;
35
19
36 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
20 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
37 {
21 {
38 m_Timer->setInterval(0);
22 m_Timer->setInterval(0);
39 }
23 }
40 };
24 };
41
25
42 DragDropScroller::DragDropScroller(QObject *parent)
26 DragDropScroller::DragDropScroller(QObject *parent)
43 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
27 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
44 {
28 {
45 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
29 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
46 }
30 }
47
31
48 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
32 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
49 {
33 {
50 impl->m_ScrollAreas << scrollArea;
34 impl->m_ScrollAreas << scrollArea;
51 scrollArea->viewport()->setAcceptDrops(true);
35 scrollArea->viewport()->setAcceptDrops(true);
52 }
36 }
53
37
54 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
38 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
55 {
39 {
56 impl->m_ScrollAreas.removeAll(scrollArea);
40 impl->m_ScrollAreas.removeAll(scrollArea);
57 scrollArea->viewport()->setAcceptDrops(false);
41 scrollArea->viewport()->setAcceptDrops(false);
58 }
42 }
59
43
60 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
44 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
61 {
45 {
62 if (event->type() == QEvent::DragMove) {
46 if (event->type() == QEvent::DragMove) {
63 auto w = static_cast<QWidget *>(obj);
47 auto w = static_cast<QWidget *>(obj);
64
48
65 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
49 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
66 auto moveEvent = static_cast<QDragMoveEvent *>(event);
50 auto moveEvent = static_cast<QDragMoveEvent *>(event);
67
51
68 auto pos = moveEvent->pos();
52 auto pos = moveEvent->pos();
69 if (impl->m_CurrentScrollArea->viewport() != w) {
53 if (impl->m_CurrentScrollArea->viewport() != w) {
70 auto globalPos = w->mapToGlobal(moveEvent->pos());
54 auto globalPos = w->mapToGlobal(moveEvent->pos());
71 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
55 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
72 }
56 }
73
57
74 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
58 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
75 - SCROLL_ZONE_SIZE;
59 - SCROLL_ZONE_SIZE;
76 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
60 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
77
61
78 if (!isInTopZone && !isInBottomZone) {
62 if (!isInTopZone && !isInBottomZone) {
79 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
63 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
80 impl->m_Timer->stop();
64 impl->m_Timer->stop();
81 }
65 }
82 else if (!impl->m_Timer->isActive()) {
66 else if (!impl->m_Timer->isActive()) {
83 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
67 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
84 : DragDropScrollerPrivate::ScrollDirection::down;
68 : DragDropScrollerPrivate::ScrollDirection::down;
85 impl->m_Timer->start();
69 impl->m_Timer->start();
86 }
70 }
87 }
71 }
88 }
72 }
89 else if (event->type() == QEvent::DragEnter) {
73 else if (event->type() == QEvent::DragEnter) {
90 auto w = static_cast<QWidget *>(obj);
74 auto w = static_cast<QWidget *>(obj);
91
75
92 for (auto scrollArea : impl->m_ScrollAreas) {
76 for (auto scrollArea : impl->m_ScrollAreas) {
93 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
77 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
94 auto enterEvent = static_cast<QDragEnterEvent *>(event);
78 auto enterEvent = static_cast<QDragEnterEvent *>(event);
95 enterEvent->acceptProposedAction();
79 enterEvent->acceptProposedAction();
96 enterEvent->setDropAction(Qt::IgnoreAction);
80 enterEvent->setDropAction(Qt::IgnoreAction);
97 impl->m_CurrentScrollArea = scrollArea;
81 impl->m_CurrentScrollArea = scrollArea;
98 break;
82 break;
99 }
83 }
100 }
84 }
101 }
85 }
102 else if (event->type() == QEvent::DragLeave) {
86 else if (event->type() == QEvent::DragLeave) {
103 if (impl->m_CurrentScrollArea) {
87 if (impl->m_CurrentScrollArea) {
104 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
88 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
105 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
89 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
106 impl->m_CurrentScrollArea = nullptr;
90 impl->m_CurrentScrollArea = nullptr;
107 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
91 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
108 impl->m_Timer->stop();
92 impl->m_Timer->stop();
109 }
93 }
110 }
94 }
111 }
95 }
112 else if (event->type() == QEvent::Drop) {
96 else if (event->type() == QEvent::Drop) {
113 if (impl->m_CurrentScrollArea) {
97 if (impl->m_CurrentScrollArea) {
114 impl->m_CurrentScrollArea = nullptr;
98 impl->m_CurrentScrollArea = nullptr;
115 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
99 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
116 impl->m_Timer->stop();
100 impl->m_Timer->stop();
117 }
101 }
118 }
102 }
119
103
120 return false;
104 return false;
121 }
105 }
122
106
123 void DragDropScroller::onTimer()
107 void DragDropScroller::onTimer()
124 {
108 {
125 if (impl->m_CurrentScrollArea) {
109 if (impl->m_CurrentScrollArea) {
126 auto mvt = 0;
110 auto mvt = 0;
127 switch (impl->m_Direction) {
111 switch (impl->m_Direction) {
128 case DragDropScrollerPrivate::ScrollDirection::up:
112 case DragDropScrollerPrivate::ScrollDirection::up:
129 mvt = SCROLL_SPEED;
113 mvt = SCROLL_SPEED;
130 break;
114 break;
131 case DragDropScrollerPrivate::ScrollDirection::down:
115 case DragDropScrollerPrivate::ScrollDirection::down:
132 mvt = -SCROLL_SPEED;
116 mvt = -SCROLL_SPEED;
133 break;
117 break;
134 default:
118 default:
135 break;
119 break;
136 }
120 }
137
121
138 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
122 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
139 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
123 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
140 }
124 }
141 }
125 }
142
143 struct DragDropHelper::DragDropHelperPrivate {
144
145 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
146 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
147 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
148 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
149 // QTemporaryFile to have a name which is not generated.
150
151 explicit DragDropHelperPrivate()
152 : m_PlaceHolder{std::make_unique<QWidget>()},
153 m_DragDropScroller{std::make_unique<DragDropScroller>()}
154 {
155 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
156 sqpApp->installEventFilter(m_DragDropScroller.get());
157
158
159 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
160 }
161
162 void preparePlaceHolder() const
163 {
164 if (m_CurrentDragWidget) {
165 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
166 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
167 }
168 else {
169 // Configuration of the placeHolder when there is no dragWidget
170 // (for instance with a drag from a variable)
171
172 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
173 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
174 }
175 }
176 };
177
178
179 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
180 {
181 }
182
183 DragDropHelper::~DragDropHelper()
184 {
185 QFile::remove(impl->m_ImageTempUrl);
186 }
187
188 void DragDropHelper::resetDragAndDrop()
189 {
190 setCurrentDragWidget(nullptr);
191 }
192
193 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
194 {
195 impl->m_CurrentDragWidget = dragWidget;
196 }
197
198 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
199 {
200 return impl->m_CurrentDragWidget;
201 }
202
203
204 QWidget &DragDropHelper::placeHolder() const
205 {
206 return *impl->m_PlaceHolder;
207 }
208
209 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
210 {
211 removePlaceHolder();
212 impl->preparePlaceHolder();
213 layout->insertWidget(index, impl->m_PlaceHolder.get());
214 impl->m_PlaceHolder->show();
215 }
216
217 void DragDropHelper::removePlaceHolder()
218 {
219 auto parentWidget = impl->m_PlaceHolder->parentWidget();
220 if (parentWidget) {
221 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
222 impl->m_PlaceHolder->setParent(nullptr);
223 impl->m_PlaceHolder->hide();
224 }
225 }
226
227 bool DragDropHelper::isPlaceHolderSet() const
228 {
229 return impl->m_PlaceHolder->parentWidget();
230 }
231
232 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
233 {
234 impl->m_DragDropScroller->addScrollArea(scrollArea);
235 }
236
237 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
238 {
239 impl->m_DragDropScroller->removeScrollArea(scrollArea);
240 }
241
242 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
243 {
244 image.save(impl->m_ImageTempUrl);
245 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
246 }
247
248 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
249 VisualizationDragDropContainer *dropContainer)
250 {
251 if (!mimeData || !dropContainer) {
252 qCWarning(LOG_DragDropHelper()) << QObject::tr(
253 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
254 Q_ASSERT(false);
255 }
256
257 auto result = true;
258
259 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
260 auto variables = sqpApp->variableController().variablesForMimeData(
261 mimeData->data(MIME_TYPE_VARIABLE_LIST));
262
263 if (variables.count() == 1) {
264 // Check that the viariable is not already in a graph
265
266 // Search for the top level VisualizationWidget
267 auto parent = dropContainer->parentWidget();
268 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
269 parent = parent->parentWidget();
270 }
271
272 if (parent) {
273 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
274
275 FindVariableOperation findVariableOperation{variables.first()};
276 visualizationWidget->accept(&findVariableOperation);
277 auto variableContainers = findVariableOperation.result();
278 if (!variableContainers.empty()) {
279 result = false;
280 }
281 }
282 else {
283 qCWarning(LOG_DragDropHelper()) << QObject::tr(
284 "DragDropHelper::checkMimeDataForVisualization, the parent "
285 "VisualizationWidget cannot be found.");
286 result = false;
287 }
288 }
289 else {
290 result = false;
291 }
292 }
293
294 return result;
295 }
@@ -1,163 +1,163
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 <DragAndDrop/DragDropHelper.h>
6 #include <Network/NetworkController.h>
6 #include <Network/NetworkController.h>
7 #include <QThread>
7 #include <QThread>
8 #include <Time/TimeController.h>
8 #include <Time/TimeController.h>
9 #include <Variable/Variable.h>
9 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
10 #include <Variable/VariableController.h>
11 #include <Variable/VariableModel.h>
11 #include <Variable/VariableModel.h>
12 #include <Visualization/VisualizationController.h>
12 #include <Visualization/VisualizationController.h>
13
13
14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
14 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
15
15
16 class SqpApplication::SqpApplicationPrivate {
16 class SqpApplication::SqpApplicationPrivate {
17 public:
17 public:
18 SqpApplicationPrivate()
18 SqpApplicationPrivate()
19 : m_DataSourceController{std::make_unique<DataSourceController>()},
19 : m_DataSourceController{std::make_unique<DataSourceController>()},
20 m_NetworkController{std::make_unique<NetworkController>()},
20 m_NetworkController{std::make_unique<NetworkController>()},
21 m_TimeController{std::make_unique<TimeController>()},
21 m_TimeController{std::make_unique<TimeController>()},
22 m_VariableController{std::make_unique<VariableController>()},
22 m_VariableController{std::make_unique<VariableController>()},
23 m_VisualizationController{std::make_unique<VisualizationController>()},
23 m_VisualizationController{std::make_unique<VisualizationController>()},
24 m_DragDropHelper{std::make_unique<DragDropHelper>()}
24 m_DragDropHelper{std::make_unique<DragDropHelper>()}
25 {
25 {
26 // /////////////////////////////// //
26 // /////////////////////////////// //
27 // Connections between controllers //
27 // Connections between controllers //
28 // /////////////////////////////// //
28 // /////////////////////////////// //
29
29
30 // VariableController <-> DataSourceController
30 // VariableController <-> DataSourceController
31 connect(m_DataSourceController.get(),
31 connect(m_DataSourceController.get(),
32 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
32 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
33 std::shared_ptr<IDataProvider>)),
33 std::shared_ptr<IDataProvider>)),
34 m_VariableController.get(),
34 m_VariableController.get(),
35 SLOT(createVariable(const QString &, const QVariantHash &,
35 SLOT(createVariable(const QString &, const QVariantHash &,
36 std::shared_ptr<IDataProvider>)));
36 std::shared_ptr<IDataProvider>)));
37
37
38 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
38 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
39 m_DataSourceController.get(), &DataSourceController::requestVariable);
39 m_DataSourceController.get(), &DataSourceController::requestVariable);
40
40
41 // VariableController <-> VisualizationController
41 // VariableController <-> VisualizationController
42 connect(m_VariableController.get(),
42 connect(m_VariableController.get(),
43 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
43 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
44 m_VisualizationController.get(),
44 m_VisualizationController.get(),
45 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
45 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
46
46
47 connect(m_VariableController.get(),
47 connect(m_VariableController.get(),
48 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
48 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
49 m_VisualizationController.get(),
49 m_VisualizationController.get(),
50 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
50 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
51
51
52
52
53 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
53 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
54 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
54 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
55 m_NetworkController->moveToThread(&m_NetworkControllerThread);
55 m_NetworkController->moveToThread(&m_NetworkControllerThread);
56 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
56 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
57 m_VariableController->moveToThread(&m_VariableControllerThread);
57 m_VariableController->moveToThread(&m_VariableControllerThread);
58 m_VariableControllerThread.setObjectName("VariableControllerThread");
58 m_VariableControllerThread.setObjectName("VariableControllerThread");
59 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
59 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
60 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
60 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
61
61
62
62
63 // Additionnal init
63 // Additionnal init
64 m_VariableController->setTimeController(m_TimeController.get());
64 m_VariableController->setTimeController(m_TimeController.get());
65 }
65 }
66
66
67 virtual ~SqpApplicationPrivate()
67 virtual ~SqpApplicationPrivate()
68 {
68 {
69 m_DataSourceControllerThread.quit();
69 m_DataSourceControllerThread.quit();
70 m_DataSourceControllerThread.wait();
70 m_DataSourceControllerThread.wait();
71
71
72 m_NetworkControllerThread.quit();
72 m_NetworkControllerThread.quit();
73 m_NetworkControllerThread.wait();
73 m_NetworkControllerThread.wait();
74
74
75 m_VariableControllerThread.quit();
75 m_VariableControllerThread.quit();
76 m_VariableControllerThread.wait();
76 m_VariableControllerThread.wait();
77
77
78 m_VisualizationControllerThread.quit();
78 m_VisualizationControllerThread.quit();
79 m_VisualizationControllerThread.wait();
79 m_VisualizationControllerThread.wait();
80 }
80 }
81
81
82 std::unique_ptr<DataSourceController> m_DataSourceController;
82 std::unique_ptr<DataSourceController> m_DataSourceController;
83 std::unique_ptr<VariableController> m_VariableController;
83 std::unique_ptr<VariableController> m_VariableController;
84 std::unique_ptr<TimeController> m_TimeController;
84 std::unique_ptr<TimeController> m_TimeController;
85 std::unique_ptr<NetworkController> m_NetworkController;
85 std::unique_ptr<NetworkController> m_NetworkController;
86 std::unique_ptr<VisualizationController> m_VisualizationController;
86 std::unique_ptr<VisualizationController> m_VisualizationController;
87 QThread m_DataSourceControllerThread;
87 QThread m_DataSourceControllerThread;
88 QThread m_NetworkControllerThread;
88 QThread m_NetworkControllerThread;
89 QThread m_VariableControllerThread;
89 QThread m_VariableControllerThread;
90 QThread m_VisualizationControllerThread;
90 QThread m_VisualizationControllerThread;
91
91
92 std::unique_ptr<DragDropHelper> m_DragDropHelper;
92 std::unique_ptr<DragDropHelper> m_DragDropHelper;
93 };
93 };
94
94
95
95
96 SqpApplication::SqpApplication(int &argc, char **argv)
96 SqpApplication::SqpApplication(int &argc, char **argv)
97 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
97 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
98 {
98 {
99 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
99 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
100
100
101 connect(&impl->m_DataSourceControllerThread, &QThread::started,
101 connect(&impl->m_DataSourceControllerThread, &QThread::started,
102 impl->m_DataSourceController.get(), &DataSourceController::initialize);
102 impl->m_DataSourceController.get(), &DataSourceController::initialize);
103 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
103 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
104 impl->m_DataSourceController.get(), &DataSourceController::finalize);
104 impl->m_DataSourceController.get(), &DataSourceController::finalize);
105
105
106 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
106 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
107 &NetworkController::initialize);
107 &NetworkController::initialize);
108 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
108 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
109 &NetworkController::finalize);
109 &NetworkController::finalize);
110
110
111 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
111 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
112 &VariableController::initialize);
112 &VariableController::initialize);
113 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
113 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
114 &VariableController::finalize);
114 &VariableController::finalize);
115
115
116 connect(&impl->m_VisualizationControllerThread, &QThread::started,
116 connect(&impl->m_VisualizationControllerThread, &QThread::started,
117 impl->m_VisualizationController.get(), &VisualizationController::initialize);
117 impl->m_VisualizationController.get(), &VisualizationController::initialize);
118 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
118 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
119 impl->m_VisualizationController.get(), &VisualizationController::finalize);
119 impl->m_VisualizationController.get(), &VisualizationController::finalize);
120
120
121 impl->m_DataSourceControllerThread.start();
121 impl->m_DataSourceControllerThread.start();
122 impl->m_NetworkControllerThread.start();
122 impl->m_NetworkControllerThread.start();
123 impl->m_VariableControllerThread.start();
123 impl->m_VariableControllerThread.start();
124 impl->m_VisualizationControllerThread.start();
124 impl->m_VisualizationControllerThread.start();
125 }
125 }
126
126
127 SqpApplication::~SqpApplication()
127 SqpApplication::~SqpApplication()
128 {
128 {
129 }
129 }
130
130
131 void SqpApplication::initialize()
131 void SqpApplication::initialize()
132 {
132 {
133 }
133 }
134
134
135 DataSourceController &SqpApplication::dataSourceController() noexcept
135 DataSourceController &SqpApplication::dataSourceController() noexcept
136 {
136 {
137 return *impl->m_DataSourceController;
137 return *impl->m_DataSourceController;
138 }
138 }
139
139
140 NetworkController &SqpApplication::networkController() noexcept
140 NetworkController &SqpApplication::networkController() noexcept
141 {
141 {
142 return *impl->m_NetworkController;
142 return *impl->m_NetworkController;
143 }
143 }
144
144
145 TimeController &SqpApplication::timeController() noexcept
145 TimeController &SqpApplication::timeController() noexcept
146 {
146 {
147 return *impl->m_TimeController;
147 return *impl->m_TimeController;
148 }
148 }
149
149
150 VariableController &SqpApplication::variableController() noexcept
150 VariableController &SqpApplication::variableController() noexcept
151 {
151 {
152 return *impl->m_VariableController;
152 return *impl->m_VariableController;
153 }
153 }
154
154
155 VisualizationController &SqpApplication::visualizationController() noexcept
155 VisualizationController &SqpApplication::visualizationController() noexcept
156 {
156 {
157 return *impl->m_VisualizationController;
157 return *impl->m_VisualizationController;
158 }
158 }
159
159
160 DragDropHelper &SqpApplication::dragDropHelper() noexcept
160 DragDropHelper &SqpApplication::dragDropHelper() noexcept
161 {
161 {
162 return *impl->m_DragDropHelper;
162 return *impl->m_DragDropHelper;
163 }
163 }
@@ -1,50 +1,156
1 #include "TimeWidget/TimeWidget.h"
1 #include "TimeWidget/TimeWidget.h"
2 #include "ui_TimeWidget.h"
2 #include "ui_TimeWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
6
7 #include <DragAndDrop/DragDropHelper.h>
5 #include <SqpApplication.h>
8 #include <SqpApplication.h>
6 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
7
10
8 TimeWidget::TimeWidget(QWidget *parent) : QWidget{parent}, ui{new Ui::TimeWidget}
11 #include <QDrag>
12 #include <QDragEnterEvent>
13 #include <QDropEvent>
14 #include <QMimeData>
15
16
17 struct TimeWidget::TimeWidgetPrivate {
18
19 explicit TimeWidgetPrivate() {}
20
21 QPoint m_DragStartPosition;
22 };
23
24 TimeWidget::TimeWidget(QWidget *parent)
25 : QWidget{parent},
26 ui{new Ui::TimeWidget},
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
9 {
28 {
10 ui->setupUi(this);
29 ui->setupUi(this);
11
30
12 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
31 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
13
32
14 // Connection
33 // Connection
15 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
34 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
16 &TimeWidget::onTimeUpdateRequested);
35 &TimeWidget::onTimeUpdateRequested);
17
36
18 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
37 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
19 &TimeWidget::onTimeUpdateRequested);
38 &TimeWidget::onTimeUpdateRequested);
20
39
21
40
22 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
41 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
23 &TimeController::onTimeNotify);
42 &TimeController::onTimeNotify);
24
43
25 // Initialisation
44 // Initialisation
26 auto endDateTime = QDateTime::currentDateTimeUtc();
45 auto endDateTime = QDateTime::currentDateTimeUtc();
27 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
46 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
28
47
29 ui->startDateTimeEdit->setDateTime(startDateTime);
48 ui->startDateTimeEdit->setDateTime(startDateTime);
30 ui->endDateTimeEdit->setDateTime(endDateTime);
49 ui->endDateTimeEdit->setDateTime(endDateTime);
31
50
32 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
51 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
33 DateUtils::secondsSinceEpoch(endDateTime)};
52 DateUtils::secondsSinceEpoch(endDateTime)};
34
53
35 sqpApp->timeController().onTimeToUpdate(dateTime);
54 sqpApp->timeController().onTimeToUpdate(dateTime);
36 }
55 }
37
56
38
57
39 TimeWidget::~TimeWidget()
58 TimeWidget::~TimeWidget()
40 {
59 {
41 delete ui;
60 delete ui;
42 }
61 }
43
62
44 void TimeWidget::onTimeUpdateRequested()
63 void TimeWidget::setTimeRange(SqpRange time)
64 {
65 auto startDateTime = DateUtils::dateTime(time.m_TStart);
66 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
67
68 ui->startDateTimeEdit->setDateTime(startDateTime);
69 ui->endDateTimeEdit->setDateTime(endDateTime);
70 }
71
72 SqpRange TimeWidget::timeRange() const
45 {
73 {
46 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
47 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
76 }
48
77
78 void TimeWidget::onTimeUpdateRequested()
79 {
80 auto dateTime = timeRange();
49 emit timeUpdated(std::move(dateTime));
81 emit timeUpdated(std::move(dateTime));
50 }
82 }
83
84 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
85 {
86 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
87 event->acceptProposedAction();
88 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
89 }
90 else {
91 event->ignore();
92 }
93 }
94
95 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
96 {
97 setStyleSheet(QString());
98 }
99
100 void TimeWidget::dropEvent(QDropEvent *event)
101 {
102 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
103 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
104 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
105
106 setTimeRange(timeRange);
107 }
108 else {
109 event->ignore();
110 }
111
112 setStyleSheet(QString());
113 }
114
115
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
117 {
118 if (event->button() == Qt::LeftButton) {
119 impl->m_DragStartPosition = event->pos();
120 }
121
122 QWidget::mousePressEvent(event);
123 }
124
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
126 {
127 if (!(event->buttons() & Qt::LeftButton)) {
128 return;
129 }
130
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
132 < QApplication::startDragDistance()) {
133 return;
134 }
135
136 // Note: The management of the drag object is done by Qt
137 auto drag = new QDrag{this};
138
139 auto mimeData = new QMimeData;
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
142
143 drag->setMimeData(mimeData);
144
145 auto pixmap = QPixmap(size());
146 render(&pixmap);
147 drag->setPixmap(pixmap);
148 drag->setHotSpot(impl->m_DragStartPosition);
149
150 sqpApp->dragDropHelper().resetDragAndDrop();
151
152 // Note: The exec() is blocking on windows but not on linux and macOS
153 drag->exec(Qt::MoveAction | Qt::CopyAction);
154
155 QWidget::mouseMoveEvent(event);
156 }
@@ -1,245 +1,240
1 #include <Variable/RenameVariableDialog.h>
1 #include <Variable/RenameVariableDialog.h>
2 #include <Variable/Variable.h>
2 #include <Variable/Variable.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableInspectorWidget.h>
4 #include <Variable/VariableInspectorWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7
7
8 #include <ui_VariableInspectorWidget.h>
8 #include <ui_VariableInspectorWidget.h>
9
9
10 #include <QMouseEvent>
10 #include <QMouseEvent>
11 #include <QSortFilterProxyModel>
11 #include <QSortFilterProxyModel>
12 #include <QStyledItemDelegate>
12 #include <QStyledItemDelegate>
13 #include <QWidgetAction>
13 #include <QWidgetAction>
14
14
15 #include <DragDropHelper.h>
15 #include <DragAndDrop/DragDropHelper.h>
16 #include <SqpApplication.h>
16 #include <SqpApplication.h>
17
17
18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
19
19
20
20
21 class QProgressBarItemDelegate : public QStyledItemDelegate {
21 class QProgressBarItemDelegate : public QStyledItemDelegate {
22
22
23 public:
23 public:
24 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
24 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
25
25
26 void paint(QPainter *painter, const QStyleOptionViewItem &option,
26 void paint(QPainter *painter, const QStyleOptionViewItem &option,
27 const QModelIndex &index) const
27 const QModelIndex &index) const
28 {
28 {
29 auto data = index.data(Qt::DisplayRole);
29 auto data = index.data(Qt::DisplayRole);
30 auto progressData = index.data(VariableRoles::ProgressRole);
30 auto progressData = index.data(VariableRoles::ProgressRole);
31 if (data.isValid() && progressData.isValid()) {
31 if (data.isValid() && progressData.isValid()) {
32 auto name = data.value<QString>();
32 auto name = data.value<QString>();
33 auto progress = progressData.value<double>();
33 auto progress = progressData.value<double>();
34 if (progress > 0) {
34 if (progress > 0) {
35 auto cancelButtonWidth = 20;
35 auto cancelButtonWidth = 20;
36 auto progressBarOption = QStyleOptionProgressBar{};
36 auto progressBarOption = QStyleOptionProgressBar{};
37 auto progressRect = option.rect;
37 auto progressRect = option.rect;
38 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
38 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
39 progressBarOption.rect = progressRect;
39 progressBarOption.rect = progressRect;
40 progressBarOption.minimum = 0;
40 progressBarOption.minimum = 0;
41 progressBarOption.maximum = 100;
41 progressBarOption.maximum = 100;
42 progressBarOption.progress = progress;
42 progressBarOption.progress = progress;
43 progressBarOption.text
43 progressBarOption.text
44 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
44 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
45 progressBarOption.textVisible = true;
45 progressBarOption.textVisible = true;
46 progressBarOption.textAlignment = Qt::AlignCenter;
46 progressBarOption.textAlignment = Qt::AlignCenter;
47
47
48
48
49 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
49 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
50 painter);
50 painter);
51
51
52 // Cancel button
52 // Cancel button
53 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
53 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
54 option.rect.height());
54 option.rect.height());
55 auto buttonOption = QStyleOptionButton{};
55 auto buttonOption = QStyleOptionButton{};
56 buttonOption.rect = buttonRect;
56 buttonOption.rect = buttonRect;
57 buttonOption.text = "X";
57 buttonOption.text = "X";
58
58
59 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
59 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
60 }
60 }
61 else {
61 else {
62 QStyledItemDelegate::paint(painter, option, index);
62 QStyledItemDelegate::paint(painter, option, index);
63 }
63 }
64 }
64 }
65 else {
65 else {
66 QStyledItemDelegate::paint(painter, option, index);
66 QStyledItemDelegate::paint(painter, option, index);
67 }
67 }
68 }
68 }
69
69
70 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
70 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
71 const QModelIndex &index)
71 const QModelIndex &index)
72 {
72 {
73 if (event->type() == QEvent::MouseButtonRelease) {
73 if (event->type() == QEvent::MouseButtonRelease) {
74 auto data = index.data(Qt::DisplayRole);
74 auto data = index.data(Qt::DisplayRole);
75 auto progressData = index.data(VariableRoles::ProgressRole);
75 auto progressData = index.data(VariableRoles::ProgressRole);
76 if (data.isValid() && progressData.isValid()) {
76 if (data.isValid() && progressData.isValid()) {
77 auto cancelButtonWidth = 20;
77 auto cancelButtonWidth = 20;
78 auto progressRect = option.rect;
78 auto progressRect = option.rect;
79 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
79 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
80 // Cancel button
80 // Cancel button
81 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
81 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
82 option.rect.height());
82 option.rect.height());
83
83
84 auto e = (QMouseEvent *)event;
84 auto e = (QMouseEvent *)event;
85 auto clickX = e->x();
85 auto clickX = e->x();
86 auto clickY = e->y();
86 auto clickY = e->y();
87
87
88 auto x = buttonRect.left(); // the X coordinate
88 auto x = buttonRect.left(); // the X coordinate
89 auto y = buttonRect.top(); // the Y coordinate
89 auto y = buttonRect.top(); // the Y coordinate
90 auto w = buttonRect.width(); // button width
90 auto w = buttonRect.width(); // button width
91 auto h = buttonRect.height(); // button height
91 auto h = buttonRect.height(); // button height
92
92
93 if (clickX > x && clickX < x + w) {
93 if (clickX > x && clickX < x + w) {
94 if (clickY > y && clickY < y + h) {
94 if (clickY > y && clickY < y + h) {
95 auto variableModel = sqpApp->variableController().variableModel();
95 auto variableModel = sqpApp->variableController().variableModel();
96 variableModel->abortProgress(index);
96 variableModel->abortProgress(index);
97 }
97 }
98 return true;
98 return true;
99 }
99 }
100 else {
100 else {
101 return QStyledItemDelegate::editorEvent(event, model, option, index);
101 return QStyledItemDelegate::editorEvent(event, model, option, index);
102 }
102 }
103 }
103 }
104 else {
104 else {
105 return QStyledItemDelegate::editorEvent(event, model, option, index);
105 return QStyledItemDelegate::editorEvent(event, model, option, index);
106 }
106 }
107 }
107 }
108 else {
108 else {
109 return QStyledItemDelegate::editorEvent(event, model, option, index);
109 return QStyledItemDelegate::editorEvent(event, model, option, index);
110 }
110 }
111
111
112
112
113 return QStyledItemDelegate::editorEvent(event, model, option, index);
113 return QStyledItemDelegate::editorEvent(event, model, option, index);
114 }
114 }
115 };
115 };
116
116
117 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
117 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
118 : QWidget{parent},
118 : QWidget{parent},
119 ui{new Ui::VariableInspectorWidget},
119 ui{new Ui::VariableInspectorWidget},
120 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
120 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
121 {
121 {
122 ui->setupUi(this);
122 ui->setupUi(this);
123
123
124 // Sets model for table
124 // Sets model for table
125 // auto sortFilterModel = new QSortFilterProxyModel{this};
125 // auto sortFilterModel = new QSortFilterProxyModel{this};
126 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
126 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
127
127
128 auto variableModel = sqpApp->variableController().variableModel();
128 auto variableModel = sqpApp->variableController().variableModel();
129 ui->tableView->setModel(variableModel);
129 ui->tableView->setModel(variableModel);
130
130
131 // Adds extra signal/slot between view and model, so the view can be updated instantly when
131 // Adds extra signal/slot between view and model, so the view can be updated instantly when
132 // there is a change of data in the model
132 // there is a change of data in the model
133 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
133 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
134 SLOT(refresh()));
134 SLOT(refresh()));
135
135
136 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
136 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
137 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
137 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
138
138
139 // Fixes column sizes
139 // Fixes column sizes
140 auto model = ui->tableView->model();
140 auto model = ui->tableView->model();
141 const auto count = model->columnCount();
141 const auto count = model->columnCount();
142 for (auto i = 0; i < count; ++i) {
142 for (auto i = 0; i < count; ++i) {
143 ui->tableView->setColumnWidth(
143 ui->tableView->setColumnWidth(
144 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
144 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
145 }
145 }
146
146
147 // Sets selection options
147 // Sets selection options
148 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
148 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
149 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
149 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
150
150
151 // Connection to show a menu when right clicking on the tree
151 // Connection to show a menu when right clicking on the tree
152 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
152 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
153 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
153 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
154 &VariableInspectorWidget::onTableMenuRequested);
154 &VariableInspectorWidget::onTableMenuRequested);
155
156 // Resets the drag&drop operation on a left-click (the drag&drop is also started by a left
157 // click).
158 connect(ui->tableView, &QTableView::clicked,
159 [](const auto &modelIndex) { sqpApp->dragDropHelper().resetDragAndDrop(); });
160 }
155 }
161
156
162 VariableInspectorWidget::~VariableInspectorWidget()
157 VariableInspectorWidget::~VariableInspectorWidget()
163 {
158 {
164 delete ui;
159 delete ui;
165 }
160 }
166
161
167 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
162 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
168 {
163 {
169 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
164 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
170
165
171 // Gets the model to retrieve the underlying selected variables
166 // Gets the model to retrieve the underlying selected variables
172 auto model = sqpApp->variableController().variableModel();
167 auto model = sqpApp->variableController().variableModel();
173 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
168 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
174 for (const auto &selectedRow : qAsConst(selectedRows)) {
169 for (const auto &selectedRow : qAsConst(selectedRows)) {
175 if (auto selectedVariable = model->variable(selectedRow.row())) {
170 if (auto selectedVariable = model->variable(selectedRow.row())) {
176 selectedVariables.push_back(selectedVariable);
171 selectedVariables.push_back(selectedVariable);
177 }
172 }
178 }
173 }
179
174
180 QMenu tableMenu{};
175 QMenu tableMenu{};
181
176
182 // Emits a signal so that potential receivers can populate the menu before displaying it
177 // Emits a signal so that potential receivers can populate the menu before displaying it
183 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
178 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
184
179
185 // Adds menu-specific actions
180 // Adds menu-specific actions
186 if (!selectedVariables.isEmpty()) {
181 if (!selectedVariables.isEmpty()) {
187 tableMenu.addSeparator();
182 tableMenu.addSeparator();
188
183
189 // 'Rename' and 'Duplicate' actions (only if one variable selected)
184 // 'Rename' and 'Duplicate' actions (only if one variable selected)
190 if (selectedVariables.size() == 1) {
185 if (selectedVariables.size() == 1) {
191 auto selectedVariable = selectedVariables.front();
186 auto selectedVariable = selectedVariables.front();
192
187
193 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
188 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
194 {
189 {
195 if (auto var = varW.lock()) {
190 if (auto var = varW.lock()) {
196 sqpApp->variableController().cloneVariable(var);
191 sqpApp->variableController().cloneVariable(var);
197 }
192 }
198 };
193 };
199
194
200 tableMenu.addAction(tr("Duplicate"), duplicateFun);
195 tableMenu.addAction(tr("Duplicate"), duplicateFun);
201
196
202 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]()
197 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]()
203 {
198 {
204 if (auto var = varW.lock()) {
199 if (auto var = varW.lock()) {
205 // Generates forbidden names (names associated to existing variables)
200 // Generates forbidden names (names associated to existing variables)
206 auto allVariables = model->variables();
201 auto allVariables = model->variables();
207 auto forbiddenNames = QVector<QString>(allVariables.size());
202 auto forbiddenNames = QVector<QString>(allVariables.size());
208 std::transform(allVariables.cbegin(), allVariables.cend(),
203 std::transform(allVariables.cbegin(), allVariables.cend(),
209 forbiddenNames.begin(),
204 forbiddenNames.begin(),
210 [](const auto &variable) { return variable->name(); });
205 [](const auto &variable) { return variable->name(); });
211
206
212 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
207 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
213 if (dialog.exec() == QDialog::Accepted) {
208 if (dialog.exec() == QDialog::Accepted) {
214 var->setName(dialog.name());
209 var->setName(dialog.name());
215 }
210 }
216 }
211 }
217 };
212 };
218
213
219 tableMenu.addAction(tr("Rename..."), renameFun);
214 tableMenu.addAction(tr("Rename..."), renameFun);
220 }
215 }
221
216
222 // 'Delete' action
217 // 'Delete' action
223 auto deleteFun = [&selectedVariables]() {
218 auto deleteFun = [&selectedVariables]() {
224 sqpApp->variableController().deleteVariables(selectedVariables);
219 sqpApp->variableController().deleteVariables(selectedVariables);
225 };
220 };
226
221
227 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
222 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
228 }
223 }
229
224
230 if (!tableMenu.isEmpty()) {
225 if (!tableMenu.isEmpty()) {
231 // Generates menu header (inserted before first action)
226 // Generates menu header (inserted before first action)
232 auto firstAction = tableMenu.actions().first();
227 auto firstAction = tableMenu.actions().first();
233 auto headerAction = new QWidgetAction{&tableMenu};
228 auto headerAction = new QWidgetAction{&tableMenu};
234 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
229 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
235 tableMenu.insertAction(firstAction, headerAction);
230 tableMenu.insertAction(firstAction, headerAction);
236
231
237 // Displays menu
232 // Displays menu
238 tableMenu.exec(QCursor::pos());
233 tableMenu.exec(QCursor::pos());
239 }
234 }
240 }
235 }
241
236
242 void VariableInspectorWidget::refresh() noexcept
237 void VariableInspectorWidget::refresh() noexcept
243 {
238 {
244 ui->tableView->viewport()->update();
239 ui->tableView->viewport()->update();
245 }
240 }
@@ -1,362 +1,453
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
2 #include "DragAndDrop/DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "Common/VisualizationDef.h"
6 #include "Common/VisualizationDef.h"
7
7
8 #include <QDrag>
8 #include <QDrag>
9 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
10 #include <QVBoxLayout>
10 #include <QVBoxLayout>
11
11
12 #include <cmath>
12 #include <cmath>
13 #include <memory>
13 #include <memory>
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
16
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
18
18
19 QVBoxLayout *m_Layout;
19 QVBoxLayout *m_Layout;
20 QStringList m_AcceptedMimeTypes;
20 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
21 QString m_PlaceHolderText;
22 DragDropHelper::PlaceHolderType m_PlaceHolderType = DragDropHelper::PlaceHolderType::Graph;
23
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
24 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 = [](auto mimeData) { return true; };
25 = [](auto mimeData) { return true; };
24
26
27 int m_MinContainerHeight = 0;
28
25 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
29 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
26 {
30 {
27 m_Layout = new QVBoxLayout(widget);
31 m_Layout = new QVBoxLayout(widget);
28 m_Layout->setContentsMargins(0, 0, 0, 0);
32 m_Layout->setContentsMargins(0, 0, 0, 0);
29 }
33 }
30
34
31 bool acceptMimeData(const QMimeData *data) const
35 bool acceptMimeData(const QMimeData *data) const
32 {
36 {
33 for (const auto &type : m_AcceptedMimeTypes) {
37 for (const auto &type : m_AcceptedMimeTypes.keys()) {
34 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
38 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
35 return true;
39 return true;
36 }
40 }
37 }
41 }
38
42
39 return false;
43 return false;
40 }
44 }
41
45
42 bool allowMergeMimeData(const QMimeData *data) const
46 bool allowMergeForMimeData(const QMimeData *data) const
47 {
48 bool result = false;
49 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
50 ++it) {
51
52 if (data->hasFormat(it.key())
53 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
54 || it.value()
55 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
56 result = true;
57 }
58 else if (data->hasFormat(it.key())
59 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
60 // Merge is forbidden if the mime data contain an acceptable type which cannot be
61 // merged
62 result = false;
63 break;
64 }
65 }
66
67 return result;
68 }
69
70 bool allowInsertForMimeData(const QMimeData *data) const
43 {
71 {
44 for (const auto &type : m_MergeAllowedMimeTypes) {
72 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
45 if (data->hasFormat(type)) {
73 ++it) {
74 if (data->hasFormat(it.key())
75 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
76 || it.value()
77 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
46 return true;
78 return true;
47 }
79 }
48 }
80 }
49
81
50 return false;
82 return false;
51 }
83 }
52
84
53 bool hasPlaceHolder() const
85 bool hasPlaceHolder() const
54 {
86 {
55 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
87 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
56 }
88 }
57
89
58 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
90 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
59 {
91 {
60 VisualizationDragWidget *dragWidget = nullptr;
92 VisualizationDragWidget *dragWidget = nullptr;
61
93
62 for (auto child : parent->children()) {
94 for (auto child : parent->children()) {
63 auto widget = qobject_cast<VisualizationDragWidget *>(child);
95 auto widget = qobject_cast<VisualizationDragWidget *>(child);
64 if (widget && widget->isVisible()) {
96 if (widget && widget->isVisible()) {
65 if (widget->frameGeometry().contains(pos)) {
97 if (widget->frameGeometry().contains(pos)) {
66 dragWidget = widget;
98 dragWidget = widget;
67 break;
99 break;
68 }
100 }
69 }
101 }
70 }
102 }
71
103
72 return dragWidget;
104 return dragWidget;
73 }
105 }
74
106
75 bool cursorIsInContainer(QWidget *container) const
107 bool cursorIsInContainer(QWidget *container) const
76 {
108 {
77 auto adustNum = 18; // to be safe, in case of scrollbar on the side
109 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
78 auto containerRect = QRect(QPoint(), container->contentsRect().size())
110 }
79 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
111
80 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
112 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
113 {
114 auto nbGraph = 0;
115 for (auto child : parent->children()) {
116 if (qobject_cast<VisualizationDragWidget *>(child)) {
117 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
118 nbGraph += 1;
119 }
120 }
121 }
122
123 return nbGraph;
81 }
124 }
125
126 void findPlaceHolderPosition(const QPoint &pos, bool canInsert, bool canMerge,
127 const VisualizationDragDropContainer *container);
82 };
128 };
83
129
84 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
130 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
85 : QWidget{parent},
131 : QFrame{parent},
86 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
132 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
87 {
133 {
88 setAcceptDrops(true);
134 setAcceptDrops(true);
89 }
135 }
90
136
91 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
137 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
92 {
138 {
93 impl->m_Layout->addWidget(dragWidget);
139 impl->m_Layout->addWidget(dragWidget);
94 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
140 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
95 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
141 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
96 &VisualizationDragDropContainer::startDrag);
142 &VisualizationDragDropContainer::startDrag);
97 }
143 }
98
144
99 void VisualizationDragDropContainer::insertDragWidget(int index,
145 void VisualizationDragDropContainer::insertDragWidget(int index,
100 VisualizationDragWidget *dragWidget)
146 VisualizationDragWidget *dragWidget)
101 {
147 {
102 impl->m_Layout->insertWidget(index, dragWidget);
148 impl->m_Layout->insertWidget(index, dragWidget);
103 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
149 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
104 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
150 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
105 &VisualizationDragDropContainer::startDrag);
151 &VisualizationDragDropContainer::startDrag);
106 }
152 }
107
153
108 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
154 void VisualizationDragDropContainer::addAcceptedMimeType(
109 {
155 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
110 impl->m_AcceptedMimeTypes = mimeTypes;
111 }
112
113 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
114 {
156 {
115 impl->m_MergeAllowedMimeTypes = mimeTypes;
157 impl->m_AcceptedMimeTypes[mimeType] = behavior;
116 }
158 }
117
159
118 int VisualizationDragDropContainer::countDragWidget() const
160 int VisualizationDragDropContainer::countDragWidget() const
119 {
161 {
120 auto nbGraph = 0;
162 return impl->countDragWidget(this);
121 for (auto child : children()) {
122 if (qobject_cast<VisualizationDragWidget *>(child)) {
123 nbGraph += 1;
124 }
125 }
126
127 return nbGraph;
128 }
163 }
129
164
130 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
165 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
131 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
166 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
132 {
167 {
133 impl->m_AcceptMimeDataFun = fun;
168 impl->m_AcceptMimeDataFun = fun;
134 }
169 }
135
170
171 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
172 const QString &placeHolderText)
173 {
174 impl->m_PlaceHolderType = type;
175 impl->m_PlaceHolderText = placeHolderText;
176 }
177
136 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
178 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
137 const QPoint &dragPosition)
179 const QPoint &dragPosition)
138 {
180 {
139 auto &helper = sqpApp->dragDropHelper();
181 auto &helper = sqpApp->dragDropHelper();
140 helper.resetDragAndDrop();
182 helper.resetDragAndDrop();
141
183
142 // Note: The management of the drag object is done by Qt
184 // Note: The management of the drag object is done by Qt
143 auto drag = new QDrag{dragWidget};
185 auto drag = new QDrag{dragWidget};
144 drag->setHotSpot(dragPosition);
186 drag->setHotSpot(dragPosition);
145
187
146 auto mimeData = dragWidget->mimeData();
188 auto mimeData = dragWidget->mimeData();
147 drag->setMimeData(mimeData);
189 drag->setMimeData(mimeData);
148
190
149 auto pixmap = QPixmap(dragWidget->size());
191 auto pixmap = QPixmap(dragWidget->size());
150 dragWidget->render(&pixmap);
192 dragWidget->render(&pixmap);
151 drag->setPixmap(pixmap);
193 drag->setPixmap(pixmap);
152
194
153 auto image = pixmap.toImage();
195 auto image = pixmap.toImage();
154 mimeData->setImageData(image);
196 mimeData->setImageData(image);
155 mimeData->setUrls({helper.imageTemporaryUrl(image)});
197 mimeData->setUrls({helper.imageTemporaryUrl(image)});
156
198
157 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
199 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
158 helper.setCurrentDragWidget(dragWidget);
200 helper.setCurrentDragWidget(dragWidget);
159
201
160 if (impl->cursorIsInContainer(this)) {
202 if (impl->cursorIsInContainer(this)) {
161 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
203 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
162 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
204 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
205 impl->m_PlaceHolderText);
163 dragWidget->setVisible(false);
206 dragWidget->setVisible(false);
164 }
207 }
208 else {
209 // The drag starts directly outside the drop zone
210 // do not add the placeHolder
211 }
165
212
166 // Note: The exec() is blocking on windows but not on linux and macOS
213 // Note: The exec() is blocking on windows but not on linux and macOS
167 drag->exec(Qt::MoveAction | Qt::CopyAction);
214 drag->exec(Qt::MoveAction | Qt::CopyAction);
168 }
215 }
169 else {
216 else {
170 qCWarning(LOG_VisualizationDragDropContainer())
217 qCWarning(LOG_VisualizationDragDropContainer())
171 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
218 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
172 "VisualizationDragWidget is not found in this container.");
219 "VisualizationDragWidget is not found in this container.");
173 }
220 }
174 }
221 }
175
222
176 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
223 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
177 {
224 {
178 if (impl->acceptMimeData(event->mimeData())) {
225 if (impl->acceptMimeData(event->mimeData())) {
179 event->acceptProposedAction();
226 event->acceptProposedAction();
180
227
181 auto &helper = sqpApp->dragDropHelper();
228 auto &helper = sqpApp->dragDropHelper();
182
229
183 if (!impl->hasPlaceHolder()) {
230 if (!impl->hasPlaceHolder()) {
184 auto dragWidget = helper.getCurrentDragWidget();
231 auto dragWidget = helper.getCurrentDragWidget();
185
232
186 if (dragWidget) {
233 if (dragWidget) {
187 // If the drag&drop is internal to the visualization, entering the container hide
234 // If the drag&drop is internal to the visualization, entering the container hide
188 // the dragWidget which was hidden by the dragLeaveEvent
235 // the dragWidget which was made visible by the dragLeaveEvent
189 auto parentWidget
236 auto parentWidget
190 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
237 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
191 if (parentWidget) {
238 if (parentWidget) {
192 dragWidget->setVisible(false);
239 dragWidget->setVisible(false);
193 }
240 }
194 }
241 }
195
242
196 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
243 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
197
244 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
198 if (dragWidgetHovered) {
245 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
199 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
200
201 if (dragWidget) {
202 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
203 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
204 // Correction of the index if the drop occurs in the same container
205 // and if the drag is started from the visualization (in that case, the
206 // dragWidget is hidden)
207 hoveredWidgetIndex += 1;
208 }
209 }
210
211 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
212 }
213 else {
214 helper.insertPlaceHolder(impl->m_Layout, 0);
215 }
216 }
246 }
217 else {
247 else {
218 // do nothing
248 // do nothing
219 }
249 }
220 }
250 }
221 else {
251 else {
222 event->ignore();
252 event->ignore();
223 }
253 }
224
254
225 QWidget::dragEnterEvent(event);
255 QWidget::dragEnterEvent(event);
226 }
256 }
227
257
228 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
258 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
229 {
259 {
230 Q_UNUSED(event);
260 Q_UNUSED(event);
231
261
232 auto &helper = sqpApp->dragDropHelper();
262 auto &helper = sqpApp->dragDropHelper();
233
263
234 if (!impl->cursorIsInContainer(this)) {
264 if (!impl->cursorIsInContainer(this)) {
235 helper.removePlaceHolder();
265 helper.removePlaceHolder();
266 helper.setHightlightedDragWidget(nullptr);
267 impl->m_MinContainerHeight = 0;
236
268
237 auto dragWidget = helper.getCurrentDragWidget();
269 auto dragWidget = helper.getCurrentDragWidget();
238 if (dragWidget) {
270 if (dragWidget) {
239 // dragWidget has a value only if the drag is started from the visualization
271 // dragWidget has a value only if the drag is started from the visualization
240 // In that case, shows the drag widget at its original place
272 // In that case, shows the drag widget at its original place
241 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
273 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
242 // drop zone (It is not possible to catch a drop event outside of the application)
274 // drop zone (It is not possible to catch a drop event outside of the application)
243
275
244 if (dragWidget) {
276 if (dragWidget) {
245 dragWidget->setVisible(true);
277 dragWidget->setVisible(true);
246 }
278 }
247 }
279 }
248 }
280 }
249 else {
281 else {
250 // Leave event probably received for a child widget.
282 // Leave event probably received for a child widget.
251 // Do nothing.
283 // Do nothing.
252 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
284 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
253 }
285 }
254
286
255 QWidget::dragLeaveEvent(event);
287 QWidget::dragLeaveEvent(event);
256 }
288 }
257
289
258 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
290 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
259 {
291 {
260 if (impl->acceptMimeData(event->mimeData())) {
292 if (impl->acceptMimeData(event->mimeData())) {
261 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
293 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
262 if (dragWidgetHovered) {
294 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
263 auto canMerge = impl->allowMergeMimeData(event->mimeData());
295 impl->findPlaceHolderPosition(event->pos(), canInsert, canMerge, this);
264
296 }
265 auto nbDragWidget = countDragWidget();
297 else {
266 if (nbDragWidget > 0) {
298 event->ignore();
267 auto graphHeight = qMax(size().height() / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
299 }
268
300
269 auto dropIndex = floor(event->pos().y() / graphHeight);
301 QWidget::dragMoveEvent(event);
270 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
302 }
271
303
272 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
304 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
273 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
305 {
306 auto &helper = sqpApp->dragDropHelper();
274
307
275 auto &helper = sqpApp->dragDropHelper();
308 if (impl->acceptMimeData(event->mimeData())) {
276 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
309 auto dragWidget = helper.getCurrentDragWidget();
310 if (impl->hasPlaceHolder()) {
311 // drop where the placeHolder is located
277
312
278 if (isOnTop || isOnBottom) {
313 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
279 if (isOnBottom) {
314 if (canInsert) {
280 dropIndex += 1;
315 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
281 }
282
316
283 if (helper.getCurrentDragWidget()) {
317 if (dragWidget) {
284 auto dragWidgetIndex
318 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
285 = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
319 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
286 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
320 // Correction of the index if the drop occurs in the same container
287 // Correction of the index if the drop occurs in the same container
321 // and if the drag is started from the visualization (in that case, the
288 // and if the drag is started from the visualization (in that case, the
322 // dragWidget is hidden)
289 // dragWidget is hidden)
323 droppedIndex -= 1;
290 dropIndex += 1;
291 }
292 }
324 }
293
325
294 if (dropIndex != placeHolderIndex) {
326 dragWidget->setVisible(true);
295 helper.insertPlaceHolder(impl->m_Layout, dropIndex);
296 }
297 }
298 else if (canMerge) {
299 // drop on the middle -> merge
300 if (impl->hasPlaceHolder()) {
301 helper.removePlaceHolder();
302 }
303 }
327 }
328
329 event->acceptProposedAction();
330
331 helper.removePlaceHolder();
332
333 emit dropOccuredInContainer(droppedIndex, event->mimeData());
304 }
334 }
305 else {
335 else {
306 qCWarning(LOG_VisualizationDragDropContainer())
336 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
307 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
337 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
308 "container");
338 "the insertion is forbidden.");
339 Q_ASSERT(false);
309 }
340 }
310 }
341 }
311 else {
342 else if (helper.getHightlightedDragWidget()) {
312 // No hovered drag widget, the mouse is probably hover the placeHolder
343 // drop on the highlighted widget
313 // Do nothing
344
345 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
346 if (canMerge) {
347 event->acceptProposedAction();
348 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
349 }
350 else {
351 qCWarning(LOG_VisualizationDragDropContainer())
352 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
353 "the merge is forbidden.");
354 Q_ASSERT(false);
355 }
314 }
356 }
315 }
357 }
316 else {
358 else {
317 event->ignore();
359 event->ignore();
318 }
360 }
319
361
320 QWidget::dragMoveEvent(event);
362 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
363 impl->m_MinContainerHeight = 0;
364
365 QWidget::dropEvent(event);
321 }
366 }
322
367
323 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
368
369 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
370 const QPoint &pos, bool canInsert, bool canMerge,
371 const VisualizationDragDropContainer *container)
324 {
372 {
325 if (impl->acceptMimeData(event->mimeData())) {
373 auto &helper = sqpApp->dragDropHelper();
326 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
327 if (impl->hasPlaceHolder()) {
328 auto &helper = sqpApp->dragDropHelper();
329
374
330 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
375 auto absPos = container->mapToGlobal(pos);
376 auto isOnPlaceHolder = sqpApp->widgetAt(absPos) == &(helper.placeHolder());
331
377
332 if (dragWidget) {
378 if (countDragWidget(container, true) == 0) {
333 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
379 // Drop on an empty container, just add the placeHolder at the top
334 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
380 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
335 // Correction of the index if the drop occurs in the same container
381 }
336 // and if the drag is started from the visualization (in that case, the
382 else if (!isOnPlaceHolder) {
337 // dragWidget is hidden)
383 auto nbDragWidget = countDragWidget(container);
338 droppedIndex -= 1;
384 if (nbDragWidget > 0) {
339 }
340
385
341 dragWidget->setVisible(true);
386 if (m_MinContainerHeight == 0) {
387 m_MinContainerHeight = container->size().height();
342 }
388 }
343
389
344 event->acceptProposedAction();
390 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
391 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
392
393 auto posY = pos.y();
394 auto dropIndex = floor(posY / graphHeight);
395 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
396
397
398 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
399 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
400
401 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
402
403 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
345
404
346 helper.removePlaceHolder();
405 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
406 if (isOnBottom) {
407 dropIndex += 1;
408 }
347
409
348 emit dropOccured(droppedIndex, event->mimeData());
410 if (helper.getCurrentDragWidget()) {
411 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
412 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
413 // Correction of the index if the drop occurs in the same container
414 // and if the drag is started from the visualization (in that case, the
415 // dragWidget is hidden)
416 dropIndex += 1;
417 }
418 }
419
420 if (dropIndex != placeHolderIndex) {
421 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
422 m_PlaceHolderText);
423 }
424
425 helper.setHightlightedDragWidget(nullptr);
426 }
427 else if (canMerge && dragWidgetHovered) {
428 // drop on the middle -> merge
429 if (hasPlaceHolder()) {
430 helper.removePlaceHolder();
431 }
432
433 helper.setHightlightedDragWidget(dragWidgetHovered);
434 }
435 else {
436 qCWarning(LOG_VisualizationDragDropContainer())
437 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
438 "action.");
439 Q_ASSERT(false);
440 }
349 }
441 }
350 else {
442 else {
351 qCWarning(LOG_VisualizationDragDropContainer())
443 qCWarning(LOG_VisualizationDragDropContainer())
352 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
444 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
353 "placeHolder is not found.");
445 "found in the "
354 Q_ASSERT(false);
446 "container");
355 }
447 }
356 }
448 }
357 else {
449 else {
358 event->ignore();
450 // the mouse is hover the placeHolder
451 // Do nothing
359 }
452 }
360
361 QWidget::dropEvent(event);
362 }
453 }
@@ -1,385 +1,401
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 <Common/MimeTypesDef.h>
9 #include <Common/MimeTypesDef.h>
10 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
11 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
12 #include <DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13 #include <Settings/SqpSettingsDefs.h>
13 #include <Settings/SqpSettingsDefs.h>
14 #include <SqpApplication.h>
14 #include <SqpApplication.h>
15 #include <Time/TimeController.h>
15 #include <Variable/Variable.h>
16 #include <Variable/Variable.h>
16 #include <Variable/VariableController.h>
17 #include <Variable/VariableController.h>
17
18
18 #include <unordered_map>
19 #include <unordered_map>
19
20
20 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
21 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
21
22
22 namespace {
23 namespace {
23
24
24 /// Key pressed to enable zoom on horizontal axis
25 /// Key pressed to enable zoom on horizontal axis
25 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
26 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::NoModifier;
26
27
27 /// Key pressed to enable zoom on vertical axis
28 /// Key pressed to enable zoom on vertical axis
28 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
29 const auto VERTICAL_ZOOM_MODIFIER = Qt::ControlModifier;
29
30
30 } // namespace
31 } // namespace
31
32
32 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
33 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
33
34
34 explicit VisualizationGraphWidgetPrivate(const QString &name)
35 explicit VisualizationGraphWidgetPrivate(const QString &name)
35 : m_Name{name},
36 : m_Name{name},
36 m_DoAcquisition{true},
37 m_DoAcquisition{true},
37 m_IsCalibration{false},
38 m_IsCalibration{false},
38 m_RenderingDelegate{nullptr}
39 m_RenderingDelegate{nullptr}
39 {
40 {
40 }
41 }
41
42
42 QString m_Name;
43 QString m_Name;
43 // 1 variable -> n qcpplot
44 // 1 variable -> n qcpplot
44 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
45 bool m_DoAcquisition;
46 bool m_DoAcquisition;
46 bool m_IsCalibration;
47 bool m_IsCalibration;
47 QCPItemTracer *m_TextTracer;
48 QCPItemTracer *m_TextTracer;
48 /// Delegate used to attach rendering features to the plot
49 /// Delegate used to attach rendering features to the plot
49 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
50 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
50 };
51 };
51
52
52 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
53 : VisualizationDragWidget{parent},
54 : VisualizationDragWidget{parent},
54 ui{new Ui::VisualizationGraphWidget},
55 ui{new Ui::VisualizationGraphWidget},
55 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
56 {
57 {
57 ui->setupUi(this);
58 ui->setupUi(this);
58
59
59 // 'Close' options : widget is deleted when closed
60 // 'Close' options : widget is deleted when closed
60 setAttribute(Qt::WA_DeleteOnClose);
61 setAttribute(Qt::WA_DeleteOnClose);
61
62
62 // Set qcpplot properties :
63 // Set qcpplot properties :
63 // - Drag (on x-axis) and zoom are enabled
64 // - Drag (on x-axis) and zoom are enabled
64 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
65 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->setInteractions(QCP::iRangeDrag | QCP::iRangeZoom | QCP::iSelectItems);
66 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal);
67
68
68 // The delegate must be initialized after the ui as it uses the plot
69 // The delegate must be initialized after the ui as it uses the plot
69 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
70
71
71 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
72 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 connect(ui->widget, &QCustomPlot::mouseRelease, this,
73 &VisualizationGraphWidget::onMouseRelease);
74 &VisualizationGraphWidget::onMouseRelease);
74 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
75 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
76 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 connect(ui->widget->xAxis, static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(
77 &QCPAxis::rangeChanged),
78 &QCPAxis::rangeChanged),
78 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
79
80
80 // Activates menu when right clicking on the graph
81 // Activates menu when right clicking on the graph
81 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
82 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
83 &VisualizationGraphWidget::onGraphMenuRequested);
84 &VisualizationGraphWidget::onGraphMenuRequested);
84
85
85 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
86 &VariableController::onRequestDataLoading);
87 &VariableController::onRequestDataLoading);
87
88
88 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
89 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 &VisualizationGraphWidget::onUpdateVarDisplaying);
90 }
91 }
91
92
92
93
93 VisualizationGraphWidget::~VisualizationGraphWidget()
94 VisualizationGraphWidget::~VisualizationGraphWidget()
94 {
95 {
95 delete ui;
96 delete ui;
96 }
97 }
97
98
98 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
99 {
100 {
100 auto parent = parentWidget();
101 auto parent = parentWidget();
101 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
102 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
102 parent = parent->parentWidget();
103 parent = parent->parentWidget();
103 }
104 }
104
105
105 return qobject_cast<VisualizationZoneWidget *>(parent);
106 return qobject_cast<VisualizationZoneWidget *>(parent);
106 }
107 }
107
108
108 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 void VisualizationGraphWidget::enableAcquisition(bool enable)
109 {
110 {
110 impl->m_DoAcquisition = enable;
111 impl->m_DoAcquisition = enable;
111 }
112 }
112
113
113 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
114 {
115 {
115 // Uses delegate to create the qcpplot components according to the variable
116 // Uses delegate to create the qcpplot components according to the variable
116 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
117 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
118 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
118
119
119 // Set axes properties according to the units of the data series
120 // 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
121 /// @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
122 /// are fixed for the default x-axis and y-axis of the plot, and according to the new graph
122 auto xAxisUnit = Unit{};
123 auto xAxisUnit = Unit{};
123 auto valuesUnit = Unit{};
124 auto valuesUnit = Unit{};
124
125
125 if (auto dataSeries = variable->dataSeries()) {
126 if (auto dataSeries = variable->dataSeries()) {
126 dataSeries->lockRead();
127 dataSeries->lockRead();
127 xAxisUnit = dataSeries->xAxisUnit();
128 xAxisUnit = dataSeries->xAxisUnit();
128 valuesUnit = dataSeries->valuesUnit();
129 valuesUnit = dataSeries->valuesUnit();
129 dataSeries->unlock();
130 dataSeries->unlock();
130 }
131 }
131 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
132 impl->m_RenderingDelegate->setAxesProperties(xAxisUnit, valuesUnit);
132
133
133 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
134 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
134
135
135 this->enableAcquisition(false);
136 this->enableAcquisition(false);
136 this->setGraphRange(range);
137 this->setGraphRange(range);
137 this->enableAcquisition(true);
138 this->enableAcquisition(true);
138
139
139 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
140 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
140
141
141 emit variableAdded(variable);
142 emit variableAdded(variable);
142 }
143 }
143
144
144 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
145 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
145 {
146 {
146 // Each component associated to the variable :
147 // Each component associated to the variable :
147 // - is removed from qcpplot (which deletes it)
148 // - is removed from qcpplot (which deletes it)
148 // - is no longer referenced in the map
149 // - is no longer referenced in the map
149 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
150 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
150 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
151 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
151 emit variableAboutToBeRemoved(variable);
152 emit variableAboutToBeRemoved(variable);
152
153
153 auto &plottablesMap = variableIt->second;
154 auto &plottablesMap = variableIt->second;
154
155
155 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
156 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
156 plottableIt != plottableEnd;) {
157 plottableIt != plottableEnd;) {
157 ui->widget->removePlottable(plottableIt->second);
158 ui->widget->removePlottable(plottableIt->second);
158 plottableIt = plottablesMap.erase(plottableIt);
159 plottableIt = plottablesMap.erase(plottableIt);
159 }
160 }
160
161
161 impl->m_VariableToPlotMultiMap.erase(variableIt);
162 impl->m_VariableToPlotMultiMap.erase(variableIt);
162 }
163 }
163
164
164 // Updates graph
165 // Updates graph
165 ui->widget->replot();
166 ui->widget->replot();
166 }
167 }
167
168
168 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
169 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
169 {
170 {
170 auto variables = QList<std::shared_ptr<Variable> >{};
171 auto variables = QList<std::shared_ptr<Variable> >{};
171 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
172 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
172 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
173 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
173 variables << it->first;
174 variables << it->first;
174 }
175 }
175
176
176 return variables;
177 return variables;
177 }
178 }
178
179
179 void VisualizationGraphWidget::setYRange(const SqpRange &range)
180 void VisualizationGraphWidget::setYRange(const SqpRange &range)
180 {
181 {
181 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
182 ui->widget->yAxis->setRange(range.m_TStart, range.m_TEnd);
182 }
183 }
183
184
184 SqpRange VisualizationGraphWidget::graphRange() const noexcept
185 SqpRange VisualizationGraphWidget::graphRange() const noexcept
185 {
186 {
186 auto graphRange = ui->widget->xAxis->range();
187 auto graphRange = ui->widget->xAxis->range();
187 return SqpRange{graphRange.lower, graphRange.upper};
188 return SqpRange{graphRange.lower, graphRange.upper};
188 }
189 }
189
190
190 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
191 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
191 {
192 {
192 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
193 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
193 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
194 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
194 ui->widget->replot();
195 ui->widget->replot();
195 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
196 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
196 }
197 }
197
198
198 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
199 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
199 {
200 {
200 if (visitor) {
201 if (visitor) {
201 visitor->visit(this);
202 visitor->visit(this);
202 }
203 }
203 else {
204 else {
204 qCCritical(LOG_VisualizationGraphWidget())
205 qCCritical(LOG_VisualizationGraphWidget())
205 << tr("Can't visit widget : the visitor is null");
206 << tr("Can't visit widget : the visitor is null");
206 }
207 }
207 }
208 }
208
209
209 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
210 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
210 {
211 {
211 /// @todo : for the moment, a graph can always accomodate a variable
212 /// @todo : for the moment, a graph can always accomodate a variable
212 Q_UNUSED(variable);
213 Q_UNUSED(variable);
213 return true;
214 return true;
214 }
215 }
215
216
216 bool VisualizationGraphWidget::contains(const Variable &variable) const
217 bool VisualizationGraphWidget::contains(const Variable &variable) const
217 {
218 {
218 // Finds the variable among the keys of the map
219 // Finds the variable among the keys of the map
219 auto variablePtr = &variable;
220 auto variablePtr = &variable;
220 auto findVariable
221 auto findVariable
221 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
222 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
222
223
223 auto end = impl->m_VariableToPlotMultiMap.cend();
224 auto end = impl->m_VariableToPlotMultiMap.cend();
224 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
225 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
225 return it != end;
226 return it != end;
226 }
227 }
227
228
228 QString VisualizationGraphWidget::name() const
229 QString VisualizationGraphWidget::name() const
229 {
230 {
230 return impl->m_Name;
231 return impl->m_Name;
231 }
232 }
232
233
233 QMimeData *VisualizationGraphWidget::mimeData() const
234 QMimeData *VisualizationGraphWidget::mimeData() const
234 {
235 {
235 auto mimeData = new QMimeData;
236 auto mimeData = new QMimeData;
236 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
237 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
237
238
239 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
240 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
241
238 return mimeData;
242 return mimeData;
239 }
243 }
240
244
241 bool VisualizationGraphWidget::isDragAllowed() const
245 bool VisualizationGraphWidget::isDragAllowed() const
242 {
246 {
243 return true;
247 return true;
244 }
248 }
245
249
250 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
251 {
252 if (highlighted) {
253 plot().setBackground(QBrush(QColor("#BBD5EE")));
254 }
255 else {
256 plot().setBackground(QBrush(Qt::white));
257 }
258
259 plot().update();
260 }
261
246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
262 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
247 {
263 {
248 Q_UNUSED(event);
264 Q_UNUSED(event);
249
265
250 // Prevents that all variables will be removed from graph when it will be closed
266 // Prevents that all variables will be removed from graph when it will be closed
251 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
267 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
252 emit variableAboutToBeRemoved(variableEntry.first);
268 emit variableAboutToBeRemoved(variableEntry.first);
253 }
269 }
254 }
270 }
255
271
256 void VisualizationGraphWidget::enterEvent(QEvent *event)
272 void VisualizationGraphWidget::enterEvent(QEvent *event)
257 {
273 {
258 Q_UNUSED(event);
274 Q_UNUSED(event);
259 impl->m_RenderingDelegate->showGraphOverlay(true);
275 impl->m_RenderingDelegate->showGraphOverlay(true);
260 }
276 }
261
277
262 void VisualizationGraphWidget::leaveEvent(QEvent *event)
278 void VisualizationGraphWidget::leaveEvent(QEvent *event)
263 {
279 {
264 Q_UNUSED(event);
280 Q_UNUSED(event);
265 impl->m_RenderingDelegate->showGraphOverlay(false);
281 impl->m_RenderingDelegate->showGraphOverlay(false);
266 }
282 }
267
283
268 QCustomPlot &VisualizationGraphWidget::plot() noexcept
284 QCustomPlot &VisualizationGraphWidget::plot() noexcept
269 {
285 {
270 return *ui->widget;
286 return *ui->widget;
271 }
287 }
272
288
273 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
289 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
274 {
290 {
275 QMenu graphMenu{};
291 QMenu graphMenu{};
276
292
277 // Iterates on variables (unique keys)
293 // Iterates on variables (unique keys)
278 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
294 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
279 end = impl->m_VariableToPlotMultiMap.cend();
295 end = impl->m_VariableToPlotMultiMap.cend();
280 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
296 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
281 // 'Remove variable' action
297 // 'Remove variable' action
282 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
298 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
283 [ this, var = it->first ]() { removeVariable(var); });
299 [ this, var = it->first ]() { removeVariable(var); });
284 }
300 }
285
301
286 if (!graphMenu.isEmpty()) {
302 if (!graphMenu.isEmpty()) {
287 graphMenu.exec(QCursor::pos());
303 graphMenu.exec(QCursor::pos());
288 }
304 }
289 }
305 }
290
306
291 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
307 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
292 {
308 {
293 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
309 qCDebug(LOG_VisualizationGraphWidget()) << tr("TORM: VisualizationGraphWidget::onRangeChanged")
294 << QThread::currentThread()->objectName() << "DoAcqui"
310 << QThread::currentThread()->objectName() << "DoAcqui"
295 << impl->m_DoAcquisition;
311 << impl->m_DoAcquisition;
296
312
297 auto graphRange = SqpRange{t1.lower, t1.upper};
313 auto graphRange = SqpRange{t1.lower, t1.upper};
298 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
314 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
299
315
300 if (impl->m_DoAcquisition) {
316 if (impl->m_DoAcquisition) {
301 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
317 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
302
318
303 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
319 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
304 end = impl->m_VariableToPlotMultiMap.end();
320 end = impl->m_VariableToPlotMultiMap.end();
305 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
321 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
306 variableUnderGraphVector.push_back(it->first);
322 variableUnderGraphVector.push_back(it->first);
307 }
323 }
308 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
324 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
309 !impl->m_IsCalibration);
325 !impl->m_IsCalibration);
310
326
311 if (!impl->m_IsCalibration) {
327 if (!impl->m_IsCalibration) {
312 qCDebug(LOG_VisualizationGraphWidget())
328 qCDebug(LOG_VisualizationGraphWidget())
313 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
329 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
314 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
330 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
315 emit synchronize(graphRange, oldGraphRange);
331 emit synchronize(graphRange, oldGraphRange);
316 }
332 }
317 }
333 }
318 }
334 }
319
335
320 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
336 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
321 {
337 {
322 // Handles plot rendering when mouse is moving
338 // Handles plot rendering when mouse is moving
323 impl->m_RenderingDelegate->onMouseMove(event);
339 impl->m_RenderingDelegate->onMouseMove(event);
324
340
325 VisualizationDragWidget::mouseMoveEvent(event);
341 VisualizationDragWidget::mouseMoveEvent(event);
326 }
342 }
327
343
328 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
344 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
329 {
345 {
330 auto zoomOrientations = QFlags<Qt::Orientation>{};
346 auto zoomOrientations = QFlags<Qt::Orientation>{};
331
347
332 // Lambda that enables a zoom orientation if the key modifier related to this orientation
348 // Lambda that enables a zoom orientation if the key modifier related to this orientation
333 // has
349 // has
334 // been pressed
350 // been pressed
335 auto enableOrientation
351 auto enableOrientation
336 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
352 = [&zoomOrientations, event](const auto &orientation, const auto &modifier) {
337 auto orientationEnabled = event->modifiers().testFlag(modifier);
353 auto orientationEnabled = event->modifiers().testFlag(modifier);
338 zoomOrientations.setFlag(orientation, orientationEnabled);
354 zoomOrientations.setFlag(orientation, orientationEnabled);
339 };
355 };
340 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
356 enableOrientation(Qt::Vertical, VERTICAL_ZOOM_MODIFIER);
341 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
357 enableOrientation(Qt::Horizontal, HORIZONTAL_ZOOM_MODIFIER);
342
358
343 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
359 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
344 }
360 }
345
361
346 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
362 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
347 {
363 {
348 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
364 impl->m_IsCalibration = event->modifiers().testFlag(Qt::ControlModifier);
349
365
350 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
366 plot().setInteraction(QCP::iRangeDrag, !event->modifiers().testFlag(Qt::AltModifier));
351
367
352 VisualizationDragWidget::mousePressEvent(event);
368 VisualizationDragWidget::mousePressEvent(event);
353 }
369 }
354
370
355 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
371 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
356 {
372 {
357 impl->m_IsCalibration = false;
373 impl->m_IsCalibration = false;
358 }
374 }
359
375
360 void VisualizationGraphWidget::onDataCacheVariableUpdated()
376 void VisualizationGraphWidget::onDataCacheVariableUpdated()
361 {
377 {
362 auto graphRange = ui->widget->xAxis->range();
378 auto graphRange = ui->widget->xAxis->range();
363 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
379 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
364
380
365 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
381 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
366 auto variable = variableEntry.first;
382 auto variable = variableEntry.first;
367 qCDebug(LOG_VisualizationGraphWidget())
383 qCDebug(LOG_VisualizationGraphWidget())
368 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
384 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
369 qCDebug(LOG_VisualizationGraphWidget())
385 qCDebug(LOG_VisualizationGraphWidget())
370 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
386 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
371 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
387 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
372 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
388 VisualizationGraphHelper::updateData(variableEntry.second, variable->dataSeries(),
373 variable->range());
389 variable->range());
374 }
390 }
375 }
391 }
376 }
392 }
377
393
378 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
394 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
379 const SqpRange &range)
395 const SqpRange &range)
380 {
396 {
381 auto it = impl->m_VariableToPlotMultiMap.find(variable);
397 auto it = impl->m_VariableToPlotMultiMap.find(variable);
382 if (it != impl->m_VariableToPlotMultiMap.end()) {
398 if (it != impl->m_VariableToPlotMultiMap.end()) {
383 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
399 VisualizationGraphHelper::updateData(it->second, variable->dataSeries(), range);
384 }
400 }
385 }
401 }
@@ -1,300 +1,309
1 #include "Visualization/VisualizationTabWidget.h"
1 #include "Visualization/VisualizationTabWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "ui_VisualizationTabWidget.h"
3 #include "ui_VisualizationTabWidget.h"
4
4
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7
7
8 #include "Variable/VariableController.h"
8 #include "Variable/VariableController.h"
9
9
10 #include "Common/MimeTypesDef.h"
10 #include "Common/MimeTypesDef.h"
11
11
12 #include "DragDropHelper.h"
12 #include "DragAndDrop/DragDropHelper.h"
13 #include "SqpApplication.h"
13 #include "SqpApplication.h"
14
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
16
16
17 namespace {
17 namespace {
18
18
19 /// Generates a default name for a new zone, according to the number of zones already displayed in
19 /// Generates a default name for a new zone, according to the number of zones already displayed in
20 /// the tab
20 /// the tab
21 QString defaultZoneName(const QLayout &layout)
21 QString defaultZoneName(const QLayout &layout)
22 {
22 {
23 auto count = 0;
23 auto count = 0;
24 for (auto i = 0; i < layout.count(); ++i) {
24 for (auto i = 0; i < layout.count(); ++i) {
25 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
25 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
26 count++;
26 count++;
27 }
27 }
28 }
28 }
29
29
30 return QObject::tr("Zone %1").arg(count + 1);
30 return QObject::tr("Zone %1").arg(count + 1);
31 }
31 }
32
32
33 /**
33 /**
34 * Applies a function to all zones of the tab represented by its layout
34 * Applies a function to all zones of the tab represented by its layout
35 * @param layout the layout that contains zones
35 * @param layout the layout that contains zones
36 * @param fun the function to apply to each zone
36 * @param fun the function to apply to each zone
37 */
37 */
38 template <typename Fun>
38 template <typename Fun>
39 void processZones(QLayout &layout, Fun fun)
39 void processZones(QLayout &layout, Fun fun)
40 {
40 {
41 for (auto i = 0; i < layout.count(); ++i) {
41 for (auto i = 0; i < layout.count(); ++i) {
42 if (auto item = layout.itemAt(i)) {
42 if (auto item = layout.itemAt(i)) {
43 if (auto visualizationZoneWidget
43 if (auto visualizationZoneWidget
44 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
44 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
45 fun(*visualizationZoneWidget);
45 fun(*visualizationZoneWidget);
46 }
46 }
47 }
47 }
48 }
48 }
49 }
49 }
50
50
51 } // namespace
51 } // namespace
52
52
53 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
53 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
55
55
56 QString m_Name;
56 QString m_Name;
57
57
58 void dropGraph(int index, VisualizationTabWidget *tabWidget);
58 void dropGraph(int index, VisualizationTabWidget *tabWidget);
59 void dropZone(int index, VisualizationTabWidget *tabWidget);
59 void dropZone(int index, VisualizationTabWidget *tabWidget);
60 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
60 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
61 VisualizationTabWidget *tabWidget);
61 VisualizationTabWidget *tabWidget);
62 };
62 };
63
63
64 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
64 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
65 : QWidget{parent},
65 : QWidget{parent},
66 ui{new Ui::VisualizationTabWidget},
66 ui{new Ui::VisualizationTabWidget},
67 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
67 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
68 {
68 {
69 ui->setupUi(this);
69 ui->setupUi(this);
70
70
71 ui->dragDropContainer->setAcceptedMimeTypes(
71 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
72 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 5);
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
73 ui->dragDropContainer->addAcceptedMimeType(
74 &VisualizationTabWidget::dropMimeData);
74 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
75 ui->dragDropContainer->addAcceptedMimeType(
76 MIME_TYPE_ZONE, VisualizationDragDropContainer::DropBehavior::Inserted);
77 ui->dragDropContainer->addAcceptedMimeType(
78 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::Inserted);
79
75 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
80 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
76 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
81 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
77 ui->dragDropContainer);
82 ui->dragDropContainer);
78 });
83 });
84
85 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
86 &VisualizationTabWidget::dropMimeData);
87
79 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
88 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
80
89
81 // Widget is deleted when closed
90 // Widget is deleted when closed
82 setAttribute(Qt::WA_DeleteOnClose);
91 setAttribute(Qt::WA_DeleteOnClose);
83 }
92 }
84
93
85 VisualizationTabWidget::~VisualizationTabWidget()
94 VisualizationTabWidget::~VisualizationTabWidget()
86 {
95 {
87 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
96 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
88 delete ui;
97 delete ui;
89 }
98 }
90
99
91 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
100 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
92 {
101 {
93 ui->dragDropContainer->addDragWidget(zoneWidget);
102 ui->dragDropContainer->addDragWidget(zoneWidget);
94 }
103 }
95
104
96 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
105 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
97 {
106 {
98 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
107 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
99 }
108 }
100
109
101 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
110 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
102 {
111 {
103 return createZone({variable}, -1);
112 return createZone({variable}, -1);
104 }
113 }
105
114
106 VisualizationZoneWidget *
115 VisualizationZoneWidget *
107 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
116 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
108 {
117 {
109 auto zoneWidget = createEmptyZone(index);
118 auto zoneWidget = createEmptyZone(index);
110
119
111 // Creates a new graph into the zone
120 // Creates a new graph into the zone
112 zoneWidget->createGraph(variables, index);
121 zoneWidget->createGraph(variables, index);
113
122
114 return zoneWidget;
123 return zoneWidget;
115 }
124 }
116
125
117 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
126 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
118 {
127 {
119 auto zoneWidget
128 auto zoneWidget
120 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
129 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
121 this->insertZone(index, zoneWidget);
130 this->insertZone(index, zoneWidget);
122
131
123 return zoneWidget;
132 return zoneWidget;
124 }
133 }
125
134
126 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
135 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
127 {
136 {
128 if (visitor) {
137 if (visitor) {
129 visitor->visitEnter(this);
138 visitor->visitEnter(this);
130
139
131 // Apply visitor to zone children: widgets different from zones are not visited (no action)
140 // Apply visitor to zone children: widgets different from zones are not visited (no action)
132 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
141 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
133 zoneWidget.accept(visitor);
142 zoneWidget.accept(visitor);
134 });
143 });
135
144
136 visitor->visitLeave(this);
145 visitor->visitLeave(this);
137 }
146 }
138 else {
147 else {
139 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
148 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
140 }
149 }
141 }
150 }
142
151
143 bool VisualizationTabWidget::canDrop(const Variable &variable) const
152 bool VisualizationTabWidget::canDrop(const Variable &variable) const
144 {
153 {
145 // A tab can always accomodate a variable
154 // A tab can always accomodate a variable
146 Q_UNUSED(variable);
155 Q_UNUSED(variable);
147 return true;
156 return true;
148 }
157 }
149
158
150 bool VisualizationTabWidget::contains(const Variable &variable) const
159 bool VisualizationTabWidget::contains(const Variable &variable) const
151 {
160 {
152 Q_UNUSED(variable);
161 Q_UNUSED(variable);
153 return false;
162 return false;
154 }
163 }
155
164
156 QString VisualizationTabWidget::name() const
165 QString VisualizationTabWidget::name() const
157 {
166 {
158 return impl->m_Name;
167 return impl->m_Name;
159 }
168 }
160
169
161 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
170 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
162 {
171 {
163 // Closes zones in the tab
172 // Closes zones in the tab
164 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
173 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
165
174
166 QWidget::closeEvent(event);
175 QWidget::closeEvent(event);
167 }
176 }
168
177
169 QLayout &VisualizationTabWidget::tabLayout() const noexcept
178 QLayout &VisualizationTabWidget::tabLayout() const noexcept
170 {
179 {
171 return *ui->dragDropContainer->layout();
180 return *ui->dragDropContainer->layout();
172 }
181 }
173
182
174 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
183 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
175 {
184 {
176 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
185 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
177 impl->dropGraph(index, this);
186 impl->dropGraph(index, this);
178 }
187 }
179 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
188 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
180 impl->dropZone(index, this);
189 impl->dropZone(index, this);
181 }
190 }
182 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
191 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
183 auto variables = sqpApp->variableController().variablesForMimeData(
192 auto variables = sqpApp->variableController().variablesForMimeData(
184 mimeData->data(MIME_TYPE_VARIABLE_LIST));
193 mimeData->data(MIME_TYPE_VARIABLE_LIST));
185 impl->dropVariables(variables, index, this);
194 impl->dropVariables(variables, index, this);
186 }
195 }
187 else {
196 else {
188 qCWarning(LOG_VisualizationZoneWidget())
197 qCWarning(LOG_VisualizationZoneWidget())
189 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
198 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
190 }
199 }
191 }
200 }
192
201
193 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
202 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
194 int index, VisualizationTabWidget *tabWidget)
203 int index, VisualizationTabWidget *tabWidget)
195 {
204 {
196 auto &helper = sqpApp->dragDropHelper();
205 auto &helper = sqpApp->dragDropHelper();
197
206
198 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
207 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
199 if (!graphWidget) {
208 if (!graphWidget) {
200 qCWarning(LOG_VisualizationZoneWidget())
209 qCWarning(LOG_VisualizationZoneWidget())
201 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
210 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
202 "found or invalid.");
211 "found or invalid.");
203 Q_ASSERT(false);
212 Q_ASSERT(false);
204 return;
213 return;
205 }
214 }
206
215
207 auto parentDragDropContainer
216 auto parentDragDropContainer
208 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
217 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
209 if (!parentDragDropContainer) {
218 if (!parentDragDropContainer) {
210 qCWarning(LOG_VisualizationZoneWidget())
219 qCWarning(LOG_VisualizationZoneWidget())
211 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
220 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
212 "the dropped graph is not found.");
221 "the dropped graph is not found.");
213 Q_ASSERT(false);
222 Q_ASSERT(false);
214 return;
223 return;
215 }
224 }
216
225
217 auto nbGraph = parentDragDropContainer->countDragWidget();
226 auto nbGraph = parentDragDropContainer->countDragWidget();
218
227
219 const auto &variables = graphWidget->variables();
228 const auto &variables = graphWidget->variables();
220
229
221 if (!variables.isEmpty()) {
230 if (!variables.isEmpty()) {
222 // Abort the requests for the variables (if any)
231 // Abort the requests for the variables (if any)
223 // Commented, because it's not sure if it's needed or not
232 // Commented, because it's not sure if it's needed or not
224 // for (const auto& var : variables)
233 // for (const auto& var : variables)
225 //{
234 //{
226 // sqpApp->variableController().onAbortProgressRequested(var);
235 // sqpApp->variableController().onAbortProgressRequested(var);
227 //}
236 //}
228
237
229 if (nbGraph == 1) {
238 if (nbGraph == 1) {
230 // This is the only graph in the previous zone, close the zone
239 // This is the only graph in the previous zone, close the zone
231 graphWidget->parentZoneWidget()->close();
240 graphWidget->parentZoneWidget()->close();
232 }
241 }
233 else {
242 else {
234 // Close the graph
243 // Close the graph
235 graphWidget->close();
244 graphWidget->close();
236 }
245 }
237
246
238 tabWidget->createZone(variables, index);
247 tabWidget->createZone(variables, index);
239 }
248 }
240 else {
249 else {
241 // The graph is empty, create an empty zone and move the graph inside
250 // The graph is empty, create an empty zone and move the graph inside
242
251
243 auto parentZoneWidget = graphWidget->parentZoneWidget();
252 auto parentZoneWidget = graphWidget->parentZoneWidget();
244
253
245 parentDragDropContainer->layout()->removeWidget(graphWidget);
254 parentDragDropContainer->layout()->removeWidget(graphWidget);
246
255
247 auto zoneWidget = tabWidget->createEmptyZone(index);
256 auto zoneWidget = tabWidget->createEmptyZone(index);
248 zoneWidget->addGraph(graphWidget);
257 zoneWidget->addGraph(graphWidget);
249
258
250 // Close the old zone if it was the only graph inside
259 // Close the old zone if it was the only graph inside
251 if (nbGraph == 1) {
260 if (nbGraph == 1) {
252 parentZoneWidget->close();
261 parentZoneWidget->close();
253 }
262 }
254 }
263 }
255 }
264 }
256
265
257 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
266 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
258 int index, VisualizationTabWidget *tabWidget)
267 int index, VisualizationTabWidget *tabWidget)
259 {
268 {
260 auto &helper = sqpApp->dragDropHelper();
269 auto &helper = sqpApp->dragDropHelper();
261
270
262 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
271 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
263 if (!zoneWidget) {
272 if (!zoneWidget) {
264 qCWarning(LOG_VisualizationZoneWidget())
273 qCWarning(LOG_VisualizationZoneWidget())
265 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
274 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
266 "found or invalid.");
275 "found or invalid.");
267 Q_ASSERT(false);
276 Q_ASSERT(false);
268 return;
277 return;
269 }
278 }
270
279
271 auto parentDragDropContainer
280 auto parentDragDropContainer
272 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
281 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
273 if (!parentDragDropContainer) {
282 if (!parentDragDropContainer) {
274 qCWarning(LOG_VisualizationZoneWidget())
283 qCWarning(LOG_VisualizationZoneWidget())
275 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
284 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
276 "the dropped zone is not found.");
285 "the dropped zone is not found.");
277 Q_ASSERT(false);
286 Q_ASSERT(false);
278 return;
287 return;
279 }
288 }
280
289
281 // Simple move of the zone, no variable operation associated
290 // Simple move of the zone, no variable operation associated
282 parentDragDropContainer->layout()->removeWidget(zoneWidget);
291 parentDragDropContainer->layout()->removeWidget(zoneWidget);
283 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
292 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
284 }
293 }
285
294
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
295 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
287 const QList<std::shared_ptr<Variable> > &variables, int index,
296 const QList<std::shared_ptr<Variable> > &variables, int index,
288 VisualizationTabWidget *tabWidget)
297 VisualizationTabWidget *tabWidget)
289 {
298 {
290 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
299 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
291 // compatible variable here
300 // compatible variable here
292 if (variables.count() > 1) {
301 if (variables.count() > 1) {
293 qCWarning(LOG_VisualizationZoneWidget())
302 qCWarning(LOG_VisualizationZoneWidget())
294 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
303 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
295 "aborted.");
304 "aborted.");
296 return;
305 return;
297 }
306 }
298
307
299 tabWidget->createZone(variables, index);
308 tabWidget->createZone(variables, index);
300 }
309 }
@@ -1,172 +1,178
1 #include "Visualization/VisualizationWidget.h"
1 #include "Visualization/VisualizationWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationTabWidget.h"
4 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationZoneWidget.h"
5 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
6 #include "Visualization/operations/FindVariableOperation.h"
7 #include "Visualization/operations/GenerateVariableMenuOperation.h"
7 #include "Visualization/operations/GenerateVariableMenuOperation.h"
8 #include "Visualization/operations/RemoveVariableOperation.h"
8 #include "Visualization/operations/RemoveVariableOperation.h"
9 #include "Visualization/operations/RescaleAxeOperation.h"
9 #include "Visualization/operations/RescaleAxeOperation.h"
10 #include "Visualization/qcustomplot.h"
10 #include "Visualization/qcustomplot.h"
11
11
12 #include "ui_VisualizationWidget.h"
12 #include "ui_VisualizationWidget.h"
13
13
14 #include "DragAndDrop/DragDropHelper.h"
15 #include "SqpApplication.h"
16
14 #include <QToolButton>
17 #include <QToolButton>
15
18
16 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
19 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
17
20
18 VisualizationWidget::VisualizationWidget(QWidget *parent)
21 VisualizationWidget::VisualizationWidget(QWidget *parent)
19 : QWidget{parent}, ui{new Ui::VisualizationWidget}
22 : QWidget{parent}, ui{new Ui::VisualizationWidget}
20 {
23 {
21 ui->setupUi(this);
24 ui->setupUi(this);
22
25
23 auto addTabViewButton = new QToolButton{ui->tabWidget};
26 auto addTabViewButton = new QToolButton{ui->tabWidget};
24 addTabViewButton->setText(tr("Add View"));
27 addTabViewButton->setText(tr("Add View"));
25 addTabViewButton->setCursor(Qt::ArrowCursor);
28 addTabViewButton->setCursor(Qt::ArrowCursor);
26 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
29 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
27
30
28 auto enableMinimumCornerWidgetSize = [this](bool enable) {
31 auto enableMinimumCornerWidgetSize = [this](bool enable) {
29
32
30 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
33 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
31 auto width = enable ? tabViewCornerWidget->width() : 0;
34 auto width = enable ? tabViewCornerWidget->width() : 0;
32 auto height = enable ? tabViewCornerWidget->height() : 0;
35 auto height = enable ? tabViewCornerWidget->height() : 0;
33 tabViewCornerWidget->setMinimumHeight(height);
36 tabViewCornerWidget->setMinimumHeight(height);
34 tabViewCornerWidget->setMinimumWidth(width);
37 tabViewCornerWidget->setMinimumWidth(width);
35 ui->tabWidget->setMinimumHeight(height);
38 ui->tabWidget->setMinimumHeight(height);
36 ui->tabWidget->setMinimumWidth(width);
39 ui->tabWidget->setMinimumWidth(width);
37 };
40 };
38
41
39 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
42 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
40 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
43 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
41 ui->tabWidget};
44 ui->tabWidget};
42 auto index = ui->tabWidget->addTab(widget, widget->name());
45 auto index = ui->tabWidget->addTab(widget, widget->name());
43 if (ui->tabWidget->count() > 0) {
46 if (ui->tabWidget->count() > 0) {
44 enableMinimumCornerWidgetSize(false);
47 enableMinimumCornerWidgetSize(false);
45 }
48 }
46 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
49 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
47 };
50 };
48
51
49 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
52 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
50 if (ui->tabWidget->count() == 1) {
53 if (ui->tabWidget->count() == 1) {
51 enableMinimumCornerWidgetSize(true);
54 enableMinimumCornerWidgetSize(true);
52 }
55 }
53
56
54 // Removes widget from tab and closes it
57 // Removes widget from tab and closes it
55 auto widget = ui->tabWidget->widget(index);
58 auto widget = ui->tabWidget->widget(index);
56 ui->tabWidget->removeTab(index);
59 ui->tabWidget->removeTab(index);
57 if (widget) {
60 if (widget) {
58 widget->close();
61 widget->close();
59 }
62 }
60
63
61 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
64 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
62
65
63 };
66 };
64
67
65 ui->tabWidget->setTabsClosable(true);
68 ui->tabWidget->setTabsClosable(true);
66
69
67 connect(addTabViewButton, &QToolButton::clicked, addTabView);
70 connect(addTabViewButton, &QToolButton::clicked, addTabView);
68 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
71 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
69
72
73 sqpApp->dragDropHelper().addDragDropTabBar(ui->tabWidget->tabBar());
74
70 // Adds default tab
75 // Adds default tab
71 addTabView();
76 addTabView();
72 }
77 }
73
78
74 VisualizationWidget::~VisualizationWidget()
79 VisualizationWidget::~VisualizationWidget()
75 {
80 {
81 sqpApp->dragDropHelper().removeDragDropTabBar(ui->tabWidget->tabBar());
76 delete ui;
82 delete ui;
77 }
83 }
78
84
79 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
85 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
80 {
86 {
81 if (visitor) {
87 if (visitor) {
82 visitor->visitEnter(this);
88 visitor->visitEnter(this);
83
89
84 // Apply visitor for tab children
90 // Apply visitor for tab children
85 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
91 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
86 // Widgets different from tabs are not visited (no action)
92 // Widgets different from tabs are not visited (no action)
87 if (auto visualizationTabWidget
93 if (auto visualizationTabWidget
88 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
94 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
89 visualizationTabWidget->accept(visitor);
95 visualizationTabWidget->accept(visitor);
90 }
96 }
91 }
97 }
92
98
93 visitor->visitLeave(this);
99 visitor->visitLeave(this);
94 }
100 }
95 else {
101 else {
96 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
102 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
97 }
103 }
98 }
104 }
99
105
100 bool VisualizationWidget::canDrop(const Variable &variable) const
106 bool VisualizationWidget::canDrop(const Variable &variable) const
101 {
107 {
102 // The main widget can never accomodate a variable
108 // The main widget can never accomodate a variable
103 Q_UNUSED(variable);
109 Q_UNUSED(variable);
104 return false;
110 return false;
105 }
111 }
106
112
107 bool VisualizationWidget::contains(const Variable &variable) const
113 bool VisualizationWidget::contains(const Variable &variable) const
108 {
114 {
109 Q_UNUSED(variable);
115 Q_UNUSED(variable);
110 return false;
116 return false;
111 }
117 }
112
118
113 QString VisualizationWidget::name() const
119 QString VisualizationWidget::name() const
114 {
120 {
115 return QStringLiteral("MainView");
121 return QStringLiteral("MainView");
116 }
122 }
117
123
118 void VisualizationWidget::attachVariableMenu(
124 void VisualizationWidget::attachVariableMenu(
119 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
125 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
120 {
126 {
121 // Menu is generated only if there is a single variable
127 // Menu is generated only if there is a single variable
122 if (variables.size() == 1) {
128 if (variables.size() == 1) {
123 if (auto variable = variables.first()) {
129 if (auto variable = variables.first()) {
124 // Gets the containers of the variable
130 // Gets the containers of the variable
125 FindVariableOperation findVariableOperation{variable};
131 FindVariableOperation findVariableOperation{variable};
126 accept(&findVariableOperation);
132 accept(&findVariableOperation);
127 auto variableContainers = findVariableOperation.result();
133 auto variableContainers = findVariableOperation.result();
128
134
129 // Generates the actions that make it possible to visualize the variable
135 // Generates the actions that make it possible to visualize the variable
130 GenerateVariableMenuOperation generateVariableMenuOperation{
136 GenerateVariableMenuOperation generateVariableMenuOperation{
131 menu, variable, std::move(variableContainers)};
137 menu, variable, std::move(variableContainers)};
132 accept(&generateVariableMenuOperation);
138 accept(&generateVariableMenuOperation);
133 }
139 }
134 else {
140 else {
135 qCCritical(LOG_VisualizationWidget()) << tr(
141 qCCritical(LOG_VisualizationWidget()) << tr(
136 "Can't generate the menu relative to the visualization: the variable is null");
142 "Can't generate the menu relative to the visualization: the variable is null");
137 }
143 }
138 }
144 }
139 else {
145 else {
140 qCDebug(LOG_VisualizationWidget())
146 qCDebug(LOG_VisualizationWidget())
141 << tr("No generation of the menu related to the visualization: several variables are "
147 << tr("No generation of the menu related to the visualization: several variables are "
142 "selected");
148 "selected");
143 }
149 }
144 }
150 }
145
151
146 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
152 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
147 {
153 {
148 // Calls the operation of removing all references to the variable in the visualization
154 // Calls the operation of removing all references to the variable in the visualization
149 auto removeVariableOperation = RemoveVariableOperation{variable};
155 auto removeVariableOperation = RemoveVariableOperation{variable};
150 accept(&removeVariableOperation);
156 accept(&removeVariableOperation);
151 }
157 }
152
158
153 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
159 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
154 const SqpRange &range) noexcept
160 const SqpRange &range) noexcept
155 {
161 {
156 // Calls the operation of rescaling all graph that contrains variable in the visualization
162 // Calls the operation of rescaling all graph that contrains variable in the visualization
157 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
163 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
158 accept(&rescaleVariableOperation);
164 accept(&rescaleVariableOperation);
159 }
165 }
160
166
161 void VisualizationWidget::closeEvent(QCloseEvent *event)
167 void VisualizationWidget::closeEvent(QCloseEvent *event)
162 {
168 {
163 // Closes tabs in the widget
169 // Closes tabs in the widget
164 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
170 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
165 if (auto visualizationTabWidget
171 if (auto visualizationTabWidget
166 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
172 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
167 visualizationTabWidget->close();
173 visualizationTabWidget->close();
168 }
174 }
169 }
175 }
170
176
171 QWidget::closeEvent(event);
177 QWidget::closeEvent(event);
172 }
178 }
@@ -1,468 +1,516
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
15
16
16 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
17
18
18 #include <DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <QUuid>
20 #include <QUuid>
20 #include <SqpApplication.h>
21 #include <SqpApplication.h>
21 #include <cmath>
22 #include <cmath>
22
23
23 #include <QLayout>
24 #include <QLayout>
24
25
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26
27
27 namespace {
28 namespace {
28
29
29
30
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// the zone
32 /// the zone
32 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
33 {
34 {
34 auto count = 0;
35 auto count = 0;
35 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 count++;
38 count++;
38 }
39 }
39 }
40 }
40
41
41 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
42 }
43 }
43
44
44 /**
45 /**
45 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
46 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
47 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
48 */
49 */
49 template <typename Fun>
50 template <typename Fun>
50 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
51 {
52 {
52 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
53 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
57 }
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61
62
62 } // namespace
63 } // namespace
63
64
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65
66
66 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
67 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 {
70 {
70 }
71 }
71 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73
74
75 // Returns the first graph in the zone or nullptr if there is no graph inside
76 VisualizationGraphWidget *firstGraph(const VisualizationZoneWidget *zoneWidget) const
77 {
78 VisualizationGraphWidget *firstGraph = nullptr;
79 auto layout = zoneWidget->ui->dragDropContainer->layout();
80 if (layout->count() > 0) {
81 if (auto visualizationGraphWidget
82 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
83 firstGraph = visualizationGraphWidget;
84 }
85 }
86
87 return firstGraph;
88 }
89
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
90 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
91 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 VisualizationZoneWidget *zoneWidget);
92 VisualizationZoneWidget *zoneWidget);
77 };
93 };
78
94
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
95 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
80 : VisualizationDragWidget{parent},
96 : VisualizationDragWidget{parent},
81 ui{new Ui::VisualizationZoneWidget},
97 ui{new Ui::VisualizationZoneWidget},
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
98 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
83 {
99 {
84 ui->setupUi(this);
100 ui->setupUi(this);
85
101
86 ui->zoneNameLabel->setText(name);
102 ui->zoneNameLabel->setText(name);
87
103
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
104 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
105 ui->dragDropContainer->addAcceptedMimeType(
106 MIME_TYPE_GRAPH, VisualizationDragDropContainer::DropBehavior::Inserted);
107 ui->dragDropContainer->addAcceptedMimeType(
108 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
109 ui->dragDropContainer->addAcceptedMimeType(
110 MIME_TYPE_TIME_RANGE, VisualizationDragDropContainer::DropBehavior::Merged);
89 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
111 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
112 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 ui->dragDropContainer);
113 ui->dragDropContainer);
92 });
114 });
93 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
115
116 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
94 &VisualizationZoneWidget::dropMimeData);
117 &VisualizationZoneWidget::dropMimeData);
118 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
119 &VisualizationZoneWidget::dropMimeDataOnGraph);
95
120
96 // 'Close' options : widget is deleted when closed
121 // 'Close' options : widget is deleted when closed
97 setAttribute(Qt::WA_DeleteOnClose);
122 setAttribute(Qt::WA_DeleteOnClose);
98 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
123 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
99 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
124 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
100
125
101 // Synchronisation id
126 // Synchronisation id
102 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
127 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
103 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
128 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
104 }
129 }
105
130
106 VisualizationZoneWidget::~VisualizationZoneWidget()
131 VisualizationZoneWidget::~VisualizationZoneWidget()
107 {
132 {
108 delete ui;
133 delete ui;
109 }
134 }
110
135
111 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
136 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
112 {
137 {
113 // Synchronize new graph with others in the zone
138 // Synchronize new graph with others in the zone
114 impl->m_Synchronizer->addGraph(*graphWidget);
139 impl->m_Synchronizer->addGraph(*graphWidget);
115
140
116 ui->dragDropContainer->addDragWidget(graphWidget);
141 ui->dragDropContainer->addDragWidget(graphWidget);
117 }
142 }
118
143
119 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
144 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
120 {
145 {
121 // Synchronize new graph with others in the zone
146 // Synchronize new graph with others in the zone
122 impl->m_Synchronizer->addGraph(*graphWidget);
147 impl->m_Synchronizer->addGraph(*graphWidget);
123
148
124 ui->dragDropContainer->insertDragWidget(index, graphWidget);
149 ui->dragDropContainer->insertDragWidget(index, graphWidget);
125 }
150 }
126
151
127 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
152 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
128 {
153 {
129 return createGraph(variable, -1);
154 return createGraph(variable, -1);
130 }
155 }
131
156
132 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
157 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
133 int index)
158 int index)
134 {
159 {
135 auto graphWidget
160 auto graphWidget
136 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
161 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
137
162
138
163
139 // Set graph properties
164 // Set graph properties
140 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
165 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
141 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
166 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
142
167
143
168
144 // Lambda to synchronize zone widget
169 // Lambda to synchronize zone widget
145 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
170 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
146 const SqpRange &oldGraphRange) {
171 const SqpRange &oldGraphRange) {
147
172
148 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
173 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
149 auto frameLayout = ui->dragDropContainer->layout();
174 auto frameLayout = ui->dragDropContainer->layout();
150 for (auto i = 0; i < frameLayout->count(); ++i) {
175 for (auto i = 0; i < frameLayout->count(); ++i) {
151 auto graphChild
176 auto graphChild
152 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
177 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
153 if (graphChild && (graphChild != graphWidget)) {
178 if (graphChild && (graphChild != graphWidget)) {
154
179
155 auto graphChildRange = graphChild->graphRange();
180 auto graphChildRange = graphChild->graphRange();
156 switch (zoomType) {
181 switch (zoomType) {
157 case AcquisitionZoomType::ZoomIn: {
182 case AcquisitionZoomType::ZoomIn: {
158 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
183 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
159 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
184 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
160 graphChildRange.m_TStart += deltaLeft;
185 graphChildRange.m_TStart += deltaLeft;
161 graphChildRange.m_TEnd -= deltaRight;
186 graphChildRange.m_TEnd -= deltaRight;
162 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
187 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
164 << deltaLeft;
189 << deltaLeft;
165 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
190 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
166 << deltaRight;
191 << deltaRight;
167 qCDebug(LOG_VisualizationZoneWidget())
192 qCDebug(LOG_VisualizationZoneWidget())
168 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
193 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
169
194
170 break;
195 break;
171 }
196 }
172
197
173 case AcquisitionZoomType::ZoomOut: {
198 case AcquisitionZoomType::ZoomOut: {
174 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
175 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
176 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
201 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
177 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
178 << deltaLeft;
203 << deltaLeft;
179 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
204 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
180 << deltaRight;
205 << deltaRight;
181 qCDebug(LOG_VisualizationZoneWidget())
206 qCDebug(LOG_VisualizationZoneWidget())
182 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
207 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
183 graphChildRange.m_TStart -= deltaLeft;
208 graphChildRange.m_TStart -= deltaLeft;
184 graphChildRange.m_TEnd += deltaRight;
209 graphChildRange.m_TEnd += deltaRight;
185 break;
210 break;
186 }
211 }
187 case AcquisitionZoomType::PanRight: {
212 case AcquisitionZoomType::PanRight: {
188 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
213 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
189 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
214 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
190 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
215 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
191 graphChildRange.m_TStart += deltaLeft;
216 graphChildRange.m_TStart += deltaLeft;
192 graphChildRange.m_TEnd += deltaRight;
217 graphChildRange.m_TEnd += deltaRight;
193 qCDebug(LOG_VisualizationZoneWidget())
218 qCDebug(LOG_VisualizationZoneWidget())
194 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
195 break;
220 break;
196 }
221 }
197 case AcquisitionZoomType::PanLeft: {
222 case AcquisitionZoomType::PanLeft: {
198 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
199 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
224 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
200 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
225 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
201 graphChildRange.m_TStart -= deltaLeft;
226 graphChildRange.m_TStart -= deltaLeft;
202 graphChildRange.m_TEnd -= deltaRight;
227 graphChildRange.m_TEnd -= deltaRight;
203 break;
228 break;
204 }
229 }
205 case AcquisitionZoomType::Unknown: {
230 case AcquisitionZoomType::Unknown: {
206 qCDebug(LOG_VisualizationZoneWidget())
231 qCDebug(LOG_VisualizationZoneWidget())
207 << tr("Impossible to synchronize: zoom type unknown");
232 << tr("Impossible to synchronize: zoom type unknown");
208 break;
233 break;
209 }
234 }
210 default:
235 default:
211 qCCritical(LOG_VisualizationZoneWidget())
236 qCCritical(LOG_VisualizationZoneWidget())
212 << tr("Impossible to synchronize: zoom type not take into account");
237 << tr("Impossible to synchronize: zoom type not take into account");
213 // No action
238 // No action
214 break;
239 break;
215 }
240 }
216 graphChild->enableAcquisition(false);
241 graphChild->enableAcquisition(false);
217 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
242 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
218 << graphChild->graphRange();
243 << graphChild->graphRange();
219 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
244 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
220 << graphChildRange;
245 << graphChildRange;
221 qCDebug(LOG_VisualizationZoneWidget())
246 qCDebug(LOG_VisualizationZoneWidget())
222 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
247 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
223 graphChild->setGraphRange(graphChildRange);
248 graphChild->setGraphRange(graphChildRange);
224 graphChild->enableAcquisition(true);
249 graphChild->enableAcquisition(true);
225 }
250 }
226 }
251 }
227 };
252 };
228
253
229 // connection for synchronization
254 // connection for synchronization
230 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
255 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
231 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
256 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
232 &VisualizationZoneWidget::onVariableAdded);
257 &VisualizationZoneWidget::onVariableAdded);
233 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
258 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
234 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
259 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
235
260
236 auto range = SqpRange{};
261 auto range = SqpRange{};
237
262 if (auto firstGraph = impl->firstGraph(this)) {
238 // Apply visitor to graph children
239 auto layout = ui->dragDropContainer->layout();
240 if (layout->count() > 0) {
241 // Case of a new graph in a existant zone
263 // Case of a new graph in a existant zone
242 if (auto visualizationGraphWidget
264 range = firstGraph->graphRange();
243 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
244 range = visualizationGraphWidget->graphRange();
245 }
246 }
265 }
247 else {
266 else {
248 // Case of a new graph as the first of the zone
267 // Case of a new graph as the first of the zone
249 range = variable->range();
268 range = variable->range();
250 }
269 }
251
270
252 this->insertGraph(index, graphWidget);
271 this->insertGraph(index, graphWidget);
253
272
254 graphWidget->addVariable(variable, range);
273 graphWidget->addVariable(variable, range);
255
274
256 // get y using variable range
275 // get y using variable range
257 if (auto dataSeries = variable->dataSeries()) {
276 if (auto dataSeries = variable->dataSeries()) {
258 dataSeries->lockRead();
277 dataSeries->lockRead();
259 auto valuesBounds
278 auto valuesBounds
260 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
279 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
261 auto end = dataSeries->cend();
280 auto end = dataSeries->cend();
262 if (valuesBounds.first != end && valuesBounds.second != end) {
281 if (valuesBounds.first != end && valuesBounds.second != end) {
263 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
282 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
264
283
265 auto minValue = rangeValue(valuesBounds.first->minValue());
284 auto minValue = rangeValue(valuesBounds.first->minValue());
266 auto maxValue = rangeValue(valuesBounds.second->maxValue());
285 auto maxValue = rangeValue(valuesBounds.second->maxValue());
267
286
268 graphWidget->setYRange(SqpRange{minValue, maxValue});
287 graphWidget->setYRange(SqpRange{minValue, maxValue});
269 }
288 }
270 dataSeries->unlock();
289 dataSeries->unlock();
271 }
290 }
272
291
273 return graphWidget;
292 return graphWidget;
274 }
293 }
275
294
276 VisualizationGraphWidget *
295 VisualizationGraphWidget *
277 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
296 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
278 {
297 {
279 if (variables.isEmpty()) {
298 if (variables.isEmpty()) {
280 return nullptr;
299 return nullptr;
281 }
300 }
282
301
283 auto graphWidget = createGraph(variables.first(), index);
302 auto graphWidget = createGraph(variables.first(), index);
284 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
303 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
285 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
304 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
286 }
305 }
287
306
288 return graphWidget;
307 return graphWidget;
289 }
308 }
290
309
291 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
310 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
292 {
311 {
293 if (visitor) {
312 if (visitor) {
294 visitor->visitEnter(this);
313 visitor->visitEnter(this);
295
314
296 // Apply visitor to graph children: widgets different from graphs are not visited (no
315 // Apply visitor to graph children: widgets different from graphs are not visited (no
297 // action)
316 // action)
298 processGraphs(
317 processGraphs(
299 *ui->dragDropContainer->layout(),
318 *ui->dragDropContainer->layout(),
300 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
319 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
301
320
302 visitor->visitLeave(this);
321 visitor->visitLeave(this);
303 }
322 }
304 else {
323 else {
305 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
324 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
306 }
325 }
307 }
326 }
308
327
309 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
328 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
310 {
329 {
311 // A tab can always accomodate a variable
330 // A tab can always accomodate a variable
312 Q_UNUSED(variable);
331 Q_UNUSED(variable);
313 return true;
332 return true;
314 }
333 }
315
334
316 bool VisualizationZoneWidget::contains(const Variable &variable) const
335 bool VisualizationZoneWidget::contains(const Variable &variable) const
317 {
336 {
318 Q_UNUSED(variable);
337 Q_UNUSED(variable);
319 return false;
338 return false;
320 }
339 }
321
340
322 QString VisualizationZoneWidget::name() const
341 QString VisualizationZoneWidget::name() const
323 {
342 {
324 return ui->zoneNameLabel->text();
343 return ui->zoneNameLabel->text();
325 }
344 }
326
345
327 QMimeData *VisualizationZoneWidget::mimeData() const
346 QMimeData *VisualizationZoneWidget::mimeData() const
328 {
347 {
329 auto mimeData = new QMimeData;
348 auto mimeData = new QMimeData;
330 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
349 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
331
350
332 return mimeData;
351 return mimeData;
333 }
352 }
334
353
335 bool VisualizationZoneWidget::isDragAllowed() const
354 bool VisualizationZoneWidget::isDragAllowed() const
336 {
355 {
337 return true;
356 return true;
338 }
357 }
339
358
340 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
359 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
341 {
360 {
342 // Closes graphs in the zone
361 // Closes graphs in the zone
343 processGraphs(*ui->dragDropContainer->layout(),
362 processGraphs(*ui->dragDropContainer->layout(),
344 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
363 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
345
364
346 // Delete synchronization group from variable controller
365 // Delete synchronization group from variable controller
347 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
366 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
348 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
367 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
349
368
350 QWidget::closeEvent(event);
369 QWidget::closeEvent(event);
351 }
370 }
352
371
353 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
372 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
354 {
373 {
355 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
374 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
356 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
375 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
357 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
376 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
358 }
377 }
359
378
360 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
379 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
361 {
380 {
362 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
381 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
363 Q_ARG(std::shared_ptr<Variable>, variable),
382 Q_ARG(std::shared_ptr<Variable>, variable),
364 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
383 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
365 }
384 }
366
385
367 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
386 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
368 {
387 {
369 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
388 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
370 impl->dropGraph(index, this);
389 impl->dropGraph(index, this);
371 }
390 }
372 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
391 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
373 auto variables = sqpApp->variableController().variablesForMimeData(
392 auto variables = sqpApp->variableController().variablesForMimeData(
374 mimeData->data(MIME_TYPE_VARIABLE_LIST));
393 mimeData->data(MIME_TYPE_VARIABLE_LIST));
375 impl->dropVariables(variables, index, this);
394 impl->dropVariables(variables, index, this);
376 }
395 }
377 else {
396 else {
378 qCWarning(LOG_VisualizationZoneWidget())
397 qCWarning(LOG_VisualizationZoneWidget())
379 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
398 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
380 }
399 }
381 }
400 }
382
401
402 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
403 const QMimeData *mimeData)
404 {
405 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
406 if (!graphWidget) {
407 qCWarning(LOG_VisualizationZoneWidget())
408 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
409 "drop aborted");
410 Q_ASSERT(false);
411 return;
412 }
413
414 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
415 auto variables = sqpApp->variableController().variablesForMimeData(
416 mimeData->data(MIME_TYPE_VARIABLE_LIST));
417 for (const auto &var : variables) {
418 graphWidget->addVariable(var, graphWidget->graphRange());
419 }
420 }
421 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
422 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
423 graphWidget->setGraphRange(range);
424 }
425 else {
426 qCWarning(LOG_VisualizationZoneWidget())
427 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
428 }
429 }
430
383 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
431 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
384 int index, VisualizationZoneWidget *zoneWidget)
432 int index, VisualizationZoneWidget *zoneWidget)
385 {
433 {
386 auto &helper = sqpApp->dragDropHelper();
434 auto &helper = sqpApp->dragDropHelper();
387
435
388 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
436 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
389 if (!graphWidget) {
437 if (!graphWidget) {
390 qCWarning(LOG_VisualizationZoneWidget())
438 qCWarning(LOG_VisualizationZoneWidget())
391 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
439 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
392 "found or invalid.");
440 "found or invalid.");
393 Q_ASSERT(false);
441 Q_ASSERT(false);
394 return;
442 return;
395 }
443 }
396
444
397 auto parentDragDropContainer
445 auto parentDragDropContainer
398 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
446 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
399 if (!parentDragDropContainer) {
447 if (!parentDragDropContainer) {
400 qCWarning(LOG_VisualizationZoneWidget())
448 qCWarning(LOG_VisualizationZoneWidget())
401 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
449 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
402 "the dropped graph is not found.");
450 "the dropped graph is not found.");
403 Q_ASSERT(false);
451 Q_ASSERT(false);
404 return;
452 return;
405 }
453 }
406
454
407 const auto &variables = graphWidget->variables();
455 const auto &variables = graphWidget->variables();
408
456
409 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
457 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
410 // The drop didn't occur in the same zone
458 // The drop didn't occur in the same zone
411
459
412 // Abort the requests for the variables (if any)
460 // Abort the requests for the variables (if any)
413 // Commented, because it's not sure if it's needed or not
461 // Commented, because it's not sure if it's needed or not
414 // for (const auto& var : variables)
462 // for (const auto& var : variables)
415 //{
463 //{
416 // sqpApp->variableController().onAbortProgressRequested(var);
464 // sqpApp->variableController().onAbortProgressRequested(var);
417 //}
465 //}
418
466
419 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
467 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
420 auto nbGraph = parentDragDropContainer->countDragWidget();
468 auto nbGraph = parentDragDropContainer->countDragWidget();
421 if (nbGraph == 1) {
469 if (nbGraph == 1) {
422 // This is the only graph in the previous zone, close the zone
470 // This is the only graph in the previous zone, close the zone
423 previousParentZoneWidget->close();
471 previousParentZoneWidget->close();
424 }
472 }
425 else {
473 else {
426 // Close the graph
474 // Close the graph
427 graphWidget->close();
475 graphWidget->close();
428 }
476 }
429
477
430 // Creates the new graph in the zone
478 // Creates the new graph in the zone
431 zoneWidget->createGraph(variables, index);
479 zoneWidget->createGraph(variables, index);
432 }
480 }
433 else {
481 else {
434 // The drop occurred in the same zone or the graph is empty
482 // The drop occurred in the same zone or the graph is empty
435 // Simple move of the graph, no variable operation associated
483 // Simple move of the graph, no variable operation associated
436 parentDragDropContainer->layout()->removeWidget(graphWidget);
484 parentDragDropContainer->layout()->removeWidget(graphWidget);
437
485
438 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
486 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
439 // The graph is empty and dropped in a different zone.
487 // The graph is empty and dropped in a different zone.
440 // Take the range of the first graph in the zone (if existing).
488 // Take the range of the first graph in the zone (if existing).
441 auto layout = zoneWidget->ui->dragDropContainer->layout();
489 auto layout = zoneWidget->ui->dragDropContainer->layout();
442 if (layout->count() > 0) {
490 if (layout->count() > 0) {
443 if (auto visualizationGraphWidget
491 if (auto visualizationGraphWidget
444 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
492 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
445 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
493 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
446 }
494 }
447 }
495 }
448 }
496 }
449
497
450 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
498 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
451 }
499 }
452 }
500 }
453
501
454 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
502 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
455 const QList<std::shared_ptr<Variable> > &variables, int index,
503 const QList<std::shared_ptr<Variable> > &variables, int index,
456 VisualizationZoneWidget *zoneWidget)
504 VisualizationZoneWidget *zoneWidget)
457 {
505 {
458 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
506 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
459 // compatible variable here
507 // compatible variable here
460 if (variables.count() > 1) {
508 if (variables.count() > 1) {
461 qCWarning(LOG_VisualizationZoneWidget())
509 qCWarning(LOG_VisualizationZoneWidget())
462 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
510 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
463 "aborted.");
511 "aborted.");
464 return;
512 return;
465 }
513 }
466
514
467 zoneWidget->createGraph(variables, index);
515 zoneWidget->createGraph(variables, index);
468 }
516 }
@@ -1,98 +1,104
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>TimeWidget</class>
3 <class>TimeWidget</class>
4 <widget class="QWidget" name="TimeWidget">
4 <widget class="QWidget" name="TimeWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>716</width>
9 <width>716</width>
10 <height>48</height>
10 <height>48</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="sizePolicy">
13 <property name="sizePolicy">
14 <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
14 <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
15 <horstretch>0</horstretch>
15 <horstretch>0</horstretch>
16 <verstretch>0</verstretch>
16 <verstretch>0</verstretch>
17 </sizepolicy>
17 </sizepolicy>
18 </property>
18 </property>
19 <property name="acceptDrops">
20 <bool>true</bool>
21 </property>
19 <property name="windowTitle">
22 <property name="windowTitle">
20 <string>Form</string>
23 <string>Form</string>
21 </property>
24 </property>
25 <property name="styleSheet">
26 <string notr="true">b</string>
27 </property>
22 <layout class="QHBoxLayout" name="horizontalLayout_2">
28 <layout class="QHBoxLayout" name="horizontalLayout_2">
23 <item>
29 <item>
24 <widget class="QLabel" name="label">
30 <widget class="QLabel" name="label">
25 <property name="sizePolicy">
31 <property name="sizePolicy">
26 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
32 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
27 <horstretch>0</horstretch>
33 <horstretch>0</horstretch>
28 <verstretch>0</verstretch>
34 <verstretch>0</verstretch>
29 </sizepolicy>
35 </sizepolicy>
30 </property>
36 </property>
31 <property name="text">
37 <property name="text">
32 <string>TStart :</string>
38 <string>TStart :</string>
33 </property>
39 </property>
34 </widget>
40 </widget>
35 </item>
41 </item>
36 <item>
42 <item>
37 <widget class="QDateTimeEdit" name="startDateTimeEdit">
43 <widget class="QDateTimeEdit" name="startDateTimeEdit">
38 <property name="sizePolicy">
44 <property name="sizePolicy">
39 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
45 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
40 <horstretch>0</horstretch>
46 <horstretch>0</horstretch>
41 <verstretch>0</verstretch>
47 <verstretch>0</verstretch>
42 </sizepolicy>
48 </sizepolicy>
43 </property>
49 </property>
44 <property name="displayFormat">
50 <property name="displayFormat">
45 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
51 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
46 </property>
52 </property>
47 <property name="calendarPopup">
53 <property name="calendarPopup">
48 <bool>true</bool>
54 <bool>true</bool>
49 </property>
55 </property>
50 <property name="timeSpec">
56 <property name="timeSpec">
51 <enum>Qt::UTC</enum>
57 <enum>Qt::UTC</enum>
52 </property>
58 </property>
53 </widget>
59 </widget>
54 </item>
60 </item>
55 <item>
61 <item>
56 <widget class="QLabel" name="label_2">
62 <widget class="QLabel" name="label_2">
57 <property name="sizePolicy">
63 <property name="sizePolicy">
58 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
64 <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
59 <horstretch>0</horstretch>
65 <horstretch>0</horstretch>
60 <verstretch>0</verstretch>
66 <verstretch>0</verstretch>
61 </sizepolicy>
67 </sizepolicy>
62 </property>
68 </property>
63 <property name="text">
69 <property name="text">
64 <string>TEnd :</string>
70 <string>TEnd :</string>
65 </property>
71 </property>
66 </widget>
72 </widget>
67 </item>
73 </item>
68 <item>
74 <item>
69 <widget class="QDateTimeEdit" name="endDateTimeEdit">
75 <widget class="QDateTimeEdit" name="endDateTimeEdit">
70 <property name="sizePolicy">
76 <property name="sizePolicy">
71 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
77 <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
72 <horstretch>0</horstretch>
78 <horstretch>0</horstretch>
73 <verstretch>0</verstretch>
79 <verstretch>0</verstretch>
74 </sizepolicy>
80 </sizepolicy>
75 </property>
81 </property>
76 <property name="displayFormat">
82 <property name="displayFormat">
77 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
83 <string>dd/MM/yyyy HH:mm:ss:zzz</string>
78 </property>
84 </property>
79 <property name="calendarPopup">
85 <property name="calendarPopup">
80 <bool>true</bool>
86 <bool>true</bool>
81 </property>
87 </property>
82 <property name="timeSpec">
88 <property name="timeSpec">
83 <enum>Qt::UTC</enum>
89 <enum>Qt::UTC</enum>
84 </property>
90 </property>
85 </widget>
91 </widget>
86 </item>
92 </item>
87 <item>
93 <item>
88 <widget class="QToolButton" name="applyToolButton">
94 <widget class="QToolButton" name="applyToolButton">
89 <property name="text">
95 <property name="text">
90 <string>...</string>
96 <string>...</string>
91 </property>
97 </property>
92 </widget>
98 </widget>
93 </item>
99 </item>
94 </layout>
100 </layout>
95 </widget>
101 </widget>
96 <resources/>
102 <resources/>
97 <connections/>
103 <connections/>
98 </ui>
104 </ui>
@@ -1,40 +1,47
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VariableInspectorWidget</class>
3 <class>VariableInspectorWidget</class>
4 <widget class="QWidget" name="VariableInspectorWidget">
4 <widget class="QWidget" name="VariableInspectorWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Variables</string>
14 <string>Variables</string>
15 </property>
15 </property>
16 <layout class="QGridLayout" name="gridLayout">
16 <layout class="QGridLayout" name="gridLayout">
17 <item row="0" column="0">
17 <item row="0" column="0">
18 <widget class="QTableView" name="tableView">
18 <widget class="VariableInspectorTableView" name="tableView">
19 <property name="acceptDrops">
19 <property name="acceptDrops">
20 <bool>true</bool>
20 <bool>true</bool>
21 </property>
21 </property>
22 <property name="dragEnabled">
22 <property name="dragEnabled">
23 <bool>true</bool>
23 <bool>true</bool>
24 </property>
24 </property>
25 <property name="dragDropMode">
25 <property name="dragDropMode">
26 <enum>QAbstractItemView::DragDrop</enum>
26 <enum>QAbstractItemView::DragDrop</enum>
27 </property>
27 </property>
28 <property name="sortingEnabled">
28 <property name="sortingEnabled">
29 <bool>true</bool>
29 <bool>true</bool>
30 </property>
30 </property>
31 <attribute name="horizontalHeaderStretchLastSection">
31 <attribute name="horizontalHeaderStretchLastSection">
32 <bool>true</bool>
32 <bool>true</bool>
33 </attribute>
33 </attribute>
34 </widget>
34 </widget>
35 </item>
35 </item>
36 </layout>
36 </layout>
37 </widget>
37 </widget>
38 <customwidgets>
39 <customwidget>
40 <class>VariableInspectorTableView</class>
41 <extends>QTableView</extends>
42 <header>Variable/VariableInspectorTableView.h</header>
43 </customwidget>
44 </customwidgets>
38 <resources/>
45 <resources/>
39 <connections/>
46 <connections/>
40 </ui>
47 </ui>
@@ -1,84 +1,88
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationTabWidget</class>
3 <class>VisualizationTabWidget</class>
4 <widget class="QWidget" name="VisualizationTabWidget">
4 <widget class="QWidget" name="VisualizationTabWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="leftMargin">
17 <property name="leftMargin">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="topMargin">
20 <property name="topMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="rightMargin">
23 <property name="rightMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="bottomMargin">
26 <property name="bottomMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <item>
29 <item>
30 <widget class="QScrollArea" name="scrollArea">
30 <widget class="QScrollArea" name="scrollArea">
31 <property name="frameShape">
31 <property name="frameShape">
32 <enum>QFrame::NoFrame</enum>
32 <enum>QFrame::NoFrame</enum>
33 </property>
33 </property>
34 <property name="frameShadow">
34 <property name="frameShadow">
35 <enum>QFrame::Sunken</enum>
35 <enum>QFrame::Sunken</enum>
36 </property>
36 </property>
37 <property name="widgetResizable">
37 <property name="widgetResizable">
38 <bool>true</bool>
38 <bool>true</bool>
39 </property>
39 </property>
40 <widget class="QWidget" name="scrollAreaWidgetContents">
40 <widget class="QWidget" name="scrollAreaWidgetContents">
41 <property name="geometry">
41 <property name="geometry">
42 <rect>
42 <rect>
43 <x>0</x>
43 <x>0</x>
44 <y>0</y>
44 <y>0</y>
45 <width>400</width>
45 <width>400</width>
46 <height>300</height>
46 <height>300</height>
47 </rect>
47 </rect>
48 </property>
48 </property>
49 <layout class="QVBoxLayout" name="verticalLayout_3">
49 <layout class="QVBoxLayout" name="verticalLayout_3">
50 <property name="spacing">
50 <property name="spacing">
51 <number>3</number>
51 <number>3</number>
52 </property>
52 </property>
53 <property name="leftMargin">
53 <property name="leftMargin">
54 <number>0</number>
54 <number>0</number>
55 </property>
55 </property>
56 <property name="topMargin">
56 <property name="topMargin">
57 <number>0</number>
57 <number>0</number>
58 </property>
58 </property>
59 <property name="rightMargin">
59 <property name="rightMargin">
60 <number>0</number>
60 <number>0</number>
61 </property>
61 </property>
62 <property name="bottomMargin">
62 <property name="bottomMargin">
63 <number>0</number>
63 <number>0</number>
64 </property>
64 </property>
65 <item>
65 <item>
66 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
66 <widget class="VisualizationDragDropContainer" name="dragDropContainer">
67 <property name="lineWidth">
68 <number>0</number>
69 </property>
70 </widget>
67 </item>
71 </item>
68 </layout>
72 </layout>
69 </widget>
73 </widget>
70 </widget>
74 </widget>
71 </item>
75 </item>
72 </layout>
76 </layout>
73 </widget>
77 </widget>
74 <customwidgets>
78 <customwidgets>
75 <customwidget>
79 <customwidget>
76 <class>VisualizationDragDropContainer</class>
80 <class>VisualizationDragDropContainer</class>
77 <extends>QWidget</extends>
81 <extends>QFrame</extends>
78 <header>Visualization/VisualizationDragDropContainer.h</header>
82 <header>Visualization/VisualizationDragDropContainer.h</header>
79 <container>1</container>
83 <container>1</container>
80 </customwidget>
84 </customwidget>
81 </customwidgets>
85 </customwidgets>
82 <resources/>
86 <resources/>
83 <connections/>
87 <connections/>
84 </ui>
88 </ui>
@@ -1,128 +1,125
1 <?xml version="1.0" encoding="UTF-8"?>
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
2 <ui version="4.0">
3 <class>VisualizationZoneWidget</class>
3 <class>VisualizationZoneWidget</class>
4 <widget class="QWidget" name="VisualizationZoneWidget">
4 <widget class="QWidget" name="VisualizationZoneWidget">
5 <property name="geometry">
5 <property name="geometry">
6 <rect>
6 <rect>
7 <x>0</x>
7 <x>0</x>
8 <y>0</y>
8 <y>0</y>
9 <width>400</width>
9 <width>400</width>
10 <height>300</height>
10 <height>300</height>
11 </rect>
11 </rect>
12 </property>
12 </property>
13 <property name="windowTitle">
13 <property name="windowTitle">
14 <string>Form</string>
14 <string>Form</string>
15 </property>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout_2">
16 <layout class="QVBoxLayout" name="verticalLayout_2">
17 <property name="spacing">
17 <property name="spacing">
18 <number>0</number>
18 <number>0</number>
19 </property>
19 </property>
20 <property name="leftMargin">
20 <property name="leftMargin">
21 <number>0</number>
21 <number>0</number>
22 </property>
22 </property>
23 <property name="topMargin">
23 <property name="topMargin">
24 <number>0</number>
24 <number>0</number>
25 </property>
25 </property>
26 <property name="rightMargin">
26 <property name="rightMargin">
27 <number>0</number>
27 <number>0</number>
28 </property>
28 </property>
29 <property name="bottomMargin">
29 <property name="bottomMargin">
30 <number>0</number>
30 <number>0</number>
31 </property>
31 </property>
32 <item>
32 <item>
33 <widget class="QWidget" name="infobar" native="true">
33 <widget class="QWidget" name="infobar" native="true">
34 <property name="sizePolicy">
34 <property name="sizePolicy">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
35 <sizepolicy hsizetype="Preferred" vsizetype="Minimum">
36 <horstretch>0</horstretch>
36 <horstretch>0</horstretch>
37 <verstretch>0</verstretch>
37 <verstretch>0</verstretch>
38 </sizepolicy>
38 </sizepolicy>
39 </property>
39 </property>
40 <layout class="QHBoxLayout" name="horizontalLayout">
40 <layout class="QHBoxLayout" name="horizontalLayout">
41 <property name="spacing">
41 <property name="spacing">
42 <number>0</number>
42 <number>0</number>
43 </property>
43 </property>
44 <property name="leftMargin">
44 <property name="leftMargin">
45 <number>0</number>
45 <number>0</number>
46 </property>
46 </property>
47 <property name="topMargin">
47 <property name="topMargin">
48 <number>0</number>
48 <number>0</number>
49 </property>
49 </property>
50 <property name="rightMargin">
50 <property name="rightMargin">
51 <number>0</number>
51 <number>0</number>
52 </property>
52 </property>
53 <property name="bottomMargin">
53 <property name="bottomMargin">
54 <number>0</number>
54 <number>0</number>
55 </property>
55 </property>
56 <item>
56 <item>
57 <widget class="QLabel" name="zoneNameLabel">
57 <widget class="QLabel" name="zoneNameLabel">
58 <property name="styleSheet">
58 <property name="styleSheet">
59 <string notr="true">color: rgb(127, 127, 127);
59 <string notr="true">color: rgb(127, 127, 127);
60 </string>
60 </string>
61 </property>
61 </property>
62 <property name="text">
62 <property name="text">
63 <string>TextLabel</string>
63 <string>TextLabel</string>
64 </property>
64 </property>
65 </widget>
65 </widget>
66 </item>
66 </item>
67 <item>
67 <item>
68 <widget class="QToolButton" name="closeButton">
68 <widget class="QToolButton" name="closeButton">
69 <property name="styleSheet">
69 <property name="styleSheet">
70 <string notr="true">background-color: transparent;</string>
70 <string notr="true">background-color: transparent;</string>
71 </property>
71 </property>
72 <property name="text">
72 <property name="text">
73 <string>Close</string>
73 <string>Close</string>
74 </property>
74 </property>
75 </widget>
75 </widget>
76 </item>
76 </item>
77 </layout>
77 </layout>
78 </widget>
78 </widget>
79 </item>
79 </item>
80 <item>
80 <item>
81 <widget class="QFrame" name="visualizationZoneFrame">
81 <widget class="VisualizationDragDropContainer" name="dragDropContainer">
82 <property name="sizePolicy">
82 <property name="sizePolicy">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
83 <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
84 <horstretch>0</horstretch>
84 <horstretch>0</horstretch>
85 <verstretch>0</verstretch>
85 <verstretch>0</verstretch>
86 </sizepolicy>
86 </sizepolicy>
87 </property>
87 </property>
88 <property name="frameShape">
88 <property name="frameShape">
89 <enum>QFrame::Box</enum>
89 <enum>QFrame::Box</enum>
90 </property>
90 </property>
91 <property name="frameShadow">
91 <property name="frameShadow">
92 <enum>QFrame::Raised</enum>
92 <enum>QFrame::Raised</enum>
93 </property>
93 </property>
94 <property name="lineWidth">
94 <property name="lineWidth">
95 <number>1</number>
95 <number>1</number>
96 </property>
96 </property>
97 <layout class="QVBoxLayout" name="verticalLayout">
97 <layout class="QVBoxLayout" name="verticalLayout">
98 <property name="leftMargin">
98 <property name="leftMargin">
99 <number>0</number>
99 <number>0</number>
100 </property>
100 </property>
101 <property name="topMargin">
101 <property name="topMargin">
102 <number>0</number>
102 <number>0</number>
103 </property>
103 </property>
104 <property name="rightMargin">
104 <property name="rightMargin">
105 <number>0</number>
105 <number>0</number>
106 </property>
106 </property>
107 <property name="bottomMargin">
107 <property name="bottomMargin">
108 <number>0</number>
108 <number>0</number>
109 </property>
109 </property>
110 <item>
111 <widget class="VisualizationDragDropContainer" name="dragDropContainer" native="true"/>
112 </item>
113 </layout>
110 </layout>
114 </widget>
111 </widget>
115 </item>
112 </item>
116 </layout>
113 </layout>
117 </widget>
114 </widget>
118 <customwidgets>
115 <customwidgets>
119 <customwidget>
116 <customwidget>
120 <class>VisualizationDragDropContainer</class>
117 <class>VisualizationDragDropContainer</class>
121 <extends>QWidget</extends>
118 <extends>QFrame</extends>
122 <header>Visualization/VisualizationDragDropContainer.h</header>
119 <header>Visualization/VisualizationDragDropContainer.h</header>
123 <container>1</container>
120 <container>1</container>
124 </customwidget>
121 </customwidget>
125 </customwidgets>
122 </customwidgets>
126 <resources/>
123 <resources/>
127 <connections/>
124 <connections/>
128 </ui>
125 </ui>
General Comments 0
You need to be logged in to leave comments. Login now