##// END OF EJS Templates
Merge branch 'feature/DragDropTabSwitcher' into develop
trabillard -
r887:ed1115191677 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,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 }
@@ -7,6 +7,7
7 7
8 8 class QVBoxLayout;
9 9 class QScrollArea;
10 class QTabBar;
10 11 class VisualizationDragWidget;
11 12 class VisualizationDragDropContainer;
12 13 class QMimeData;
@@ -54,6 +55,9 public:
54 55 void addDragDropScrollArea(QScrollArea *scrollArea);
55 56 void removeDragDropScrollArea(QScrollArea *scrollArea);
56 57
58 void addDragDropTabBar(QTabBar *tabBar);
59 void removeDragDropTabBar(QTabBar *tabBar);
60
57 61 QUrl imageTemporaryUrl(const QImage &image) const;
58 62
59 63 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
@@ -64,28 +68,4 private:
64 68 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
65 69 };
66 70
67 /**
68 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
69 * @note A QScrollArea inside an other QScrollArea is not fully supported.
70 */
71 class DragDropScroller : public QObject {
72 Q_OBJECT
73
74 public:
75 DragDropScroller(QObject *parent = nullptr);
76
77 void addScrollArea(QScrollArea *scrollArea);
78 void removeScrollArea(QScrollArea *scrollArea);
79
80 protected:
81 bool eventFilter(QObject *obj, QEvent *event);
82
83 private:
84 class DragDropScrollerPrivate;
85 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
86
87 private slots:
88 void onTimer();
89 };
90
91 71 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -9,7 +9,7
9 9
10 10 #include <functional>
11 11
12 #include <DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13 13
14 14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
15 15
@@ -6,7 +6,9 gui_moc_headers = [
6 6 'include/Settings/SqpSettingsGeneralWidget.h',
7 7 'include/SidePane/SqpSidePane.h',
8 8 'include/SqpApplication.h',
9 'include/DragDropHelper.h',
9 'include/DragAndDrop/DragDropHelper.h',
10 'include/DragAndDrop/DragDropScroller.h',
11 'include/DragAndDrop/DragDropTabSwitcher.h',
10 12 'include/TimeWidget/TimeWidget.h',
11 13 'include/Variable/VariableInspectorWidget.h',
12 14 'include/Variable/VariableInspectorTableView.h',
@@ -43,7 +45,9 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
43 45
44 46 gui_sources = [
45 47 'src/SqpApplication.cpp',
46 'src/DragDropHelper.cpp',
48 'src/DragAndDrop/DragDropHelper.cpp',
49 'src/DragAndDrop/DragDropScroller.cpp',
50 'src/DragAndDrop/DragDropTabSwitcher.cpp',
47 51 'src/Common/ColorUtils.cpp',
48 52 'src/Common/VisualizationDef.cpp',
49 53 'src/DataSource/DataSourceTreeWidgetItem.cpp',
@@ -4,7 +4,7
4 4 #include "DataSource/DataSourceItem.h"
5 5 #include "DataSource/DataSourceTreeWidgetItem.h"
6 6
7 #include "DragDropHelper.h"
7 #include "DragAndDrop/DragDropHelper.h"
8 8 #include "SqpApplication.h"
9 9
10 10 #include <QMimeData>
@@ -1,30 +1,13
1 #include "DragDropHelper.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"
1 #include "DragAndDrop/DragDropScroller.h"
7 2
8 #include "Variable/Variable.h"
9 #include "Variable/VariableController.h"
10
11 #include "Common/MimeTypesDef.h"
12 #include "Common/VisualizationDef.h"
13
14 #include <QDir>
15 3 #include <QDragEnterEvent>
16 4 #include <QDragMoveEvent>
17 #include <QLabel>
18 #include <QScrollArea>
19 5 #include <QScrollBar>
20 6 #include <QTimer>
21 #include <QVBoxLayout>
22 7
23 8 const int SCROLL_SPEED = 5;
24 9 const int SCROLL_ZONE_SIZE = 50;
25 10
26 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
27
28 11 struct DragDropScroller::DragDropScrollerPrivate {
29 12
30 13 QList<QScrollArea *> m_ScrollAreas;
@@ -140,244 +123,3 void DragDropScroller::onTimer()
140 123 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
141 124 }
142 125 }
143
144 struct DragDropHelper::DragDropHelperPrivate {
145
146 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
147 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
148 QLabel *m_PlaceHolderLabel;
149 QWidget *m_PlaceBackground;
150 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
151 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
152 // QTemporaryFile to have a name which is not generated.
153
154 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
155
156 QMetaObject::Connection m_DragWidgetDestroyedConnection;
157 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
158
159 explicit DragDropHelperPrivate()
160 : m_PlaceHolder{std::make_unique<QWidget>()},
161 m_DragDropScroller{std::make_unique<DragDropScroller>()}
162 {
163
164 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
165 layout->setSpacing(0);
166 layout->setContentsMargins(0, 0, 0, 0);
167
168 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
169 m_PlaceHolderLabel->setMinimumHeight(25);
170 layout->addWidget(m_PlaceHolderLabel);
171
172 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
173 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
174 layout->addWidget(m_PlaceBackground);
175
176 sqpApp->installEventFilter(m_DragDropScroller.get());
177
178 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
179 }
180
181 void preparePlaceHolder(DragDropHelper::PlaceHolderType type, const QString &topLabelText) const
182 {
183 if (m_CurrentDragWidget) {
184 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
185 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
186 }
187 else {
188 // Configuration of the placeHolder when there is no dragWidget
189 // (for instance with a drag from a variable)
190
191 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
192 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
193 }
194
195 switch (type) {
196 case DragDropHelper::PlaceHolderType::Graph:
197 m_PlaceBackground->setStyleSheet(
198 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
199 break;
200 case DragDropHelper::PlaceHolderType::Zone:
201 case DragDropHelper::PlaceHolderType::Default:
202 m_PlaceBackground->setStyleSheet(
203 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
204 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
205 break;
206 }
207
208 m_PlaceHolderLabel->setText(topLabelText);
209 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
210 }
211 };
212
213
214 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
215 {
216 }
217
218 DragDropHelper::~DragDropHelper()
219 {
220 QFile::remove(impl->m_ImageTempUrl);
221 }
222
223 void DragDropHelper::resetDragAndDrop()
224 {
225 setCurrentDragWidget(nullptr);
226 impl->m_HighlightedDragWidget = nullptr;
227 }
228
229 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
230 {
231 if (impl->m_CurrentDragWidget) {
232
233 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
234 }
235
236 if (dragWidget) {
237 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
238 impl->m_DragWidgetDestroyedConnection
239 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
240 [this]() { impl->m_CurrentDragWidget = nullptr; });
241 }
242
243 impl->m_CurrentDragWidget = dragWidget;
244 }
245
246 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
247 {
248 return impl->m_CurrentDragWidget;
249 }
250
251 QWidget &DragDropHelper::placeHolder() const
252 {
253 return *impl->m_PlaceHolder;
254 }
255
256 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
257 const QString &topLabelText)
258 {
259 removePlaceHolder();
260 impl->preparePlaceHolder(type, topLabelText);
261 layout->insertWidget(index, impl->m_PlaceHolder.get());
262 impl->m_PlaceHolder->show();
263 }
264
265 void DragDropHelper::removePlaceHolder()
266 {
267 auto parentWidget = impl->m_PlaceHolder->parentWidget();
268 if (parentWidget) {
269 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
270 impl->m_PlaceHolder->setParent(nullptr);
271 impl->m_PlaceHolder->hide();
272 }
273 }
274
275 bool DragDropHelper::isPlaceHolderSet() const
276 {
277 return impl->m_PlaceHolder->parentWidget();
278 }
279
280 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
281 {
282 impl->m_DragDropScroller->addScrollArea(scrollArea);
283 }
284
285 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
286 {
287 impl->m_DragDropScroller->removeScrollArea(scrollArea);
288 }
289
290 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
291 {
292 image.save(impl->m_ImageTempUrl);
293 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
294 }
295
296 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
297 {
298 if (impl->m_HighlightedDragWidget) {
299 impl->m_HighlightedDragWidget->highlightForMerge(false);
300 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
301 }
302
303 if (dragWidget) {
304 dragWidget->highlightForMerge(true);
305
306 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
307 impl->m_DragWidgetDestroyedConnection
308 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
309 [this]() { impl->m_HighlightedDragWidget = nullptr; });
310 }
311
312 impl->m_HighlightedDragWidget = dragWidget;
313 }
314
315 VisualizationDragWidget *DragDropHelper::getHightlightedDragWidget() const
316 {
317 return impl->m_HighlightedDragWidget;
318 }
319
320 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
321 VisualizationDragDropContainer *dropContainer)
322 {
323 if (!mimeData || !dropContainer) {
324 qCWarning(LOG_DragDropHelper()) << QObject::tr(
325 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
326 Q_ASSERT(false);
327 return false;
328 }
329
330 auto result = false;
331
332 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
333 auto variables = sqpApp->variableController().variablesForMimeData(
334 mimeData->data(MIME_TYPE_VARIABLE_LIST));
335
336 if (variables.count() == 1) {
337
338 auto variable = variables.first();
339 if (variable->dataSeries() != nullptr) {
340
341 // Check that the variable is not already in a graph
342
343 auto parent = dropContainer->parentWidget();
344 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
345 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
346 }
347
348 if (parent) {
349 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
350
351 FindVariableOperation findVariableOperation{variable};
352 visualizationWidget->accept(&findVariableOperation);
353 auto variableContainers = findVariableOperation.result();
354 if (variableContainers.empty()) {
355 result = true;
356 }
357 else {
358 // result = false: the variable already exist in the visualisation
359 }
360 }
361 else {
362 qCWarning(LOG_DragDropHelper()) << QObject::tr(
363 "DragDropHelper::checkMimeDataForVisualization, the parent "
364 "VisualizationWidget cannot be found. Cannot check if the variable is "
365 "already used or not.");
366 }
367 }
368 else {
369 // result = false: the variable is not fully loaded
370 }
371 }
372 else {
373 // result = false: cannot drop multiple variables in the visualisation
374 }
375 }
376 else {
377 // Other MIME data
378 // no special rules, accepted by default
379 result = true;
380 }
381
382 return result;
383 }
@@ -2,7 +2,7
2 2
3 3 #include <Data/IDataProvider.h>
4 4 #include <DataSource/DataSourceController.h>
5 #include <DragDropHelper.h>
5 #include <DragAndDrop/DragDropHelper.h>
6 6 #include <Network/NetworkController.h>
7 7 #include <QThread>
8 8 #include <Time/TimeController.h>
@@ -4,7 +4,7
4 4 #include <Common/DateUtils.h>
5 5 #include <Common/MimeTypesDef.h>
6 6
7 #include <DragDropHelper.h>
7 #include <DragAndDrop/DragDropHelper.h>
8 8 #include <SqpApplication.h>
9 9 #include <Time/TimeController.h>
10 10
@@ -1,6 +1,6
1 1 #include "Variable/VariableInspectorTableView.h"
2 2
3 #include "DragDropHelper.h"
3 #include "DragAndDrop/DragDropHelper.h"
4 4 #include "SqpApplication.h"
5 5
6 6 VariableInspectorTableView::VariableInspectorTableView(QWidget *parent) : QTableView(parent) {}
@@ -12,7 +12,7
12 12 #include <QStyledItemDelegate>
13 13 #include <QWidgetAction>
14 14
15 #include <DragDropHelper.h>
15 #include <DragAndDrop/DragDropHelper.h>
16 16 #include <SqpApplication.h>
17 17
18 18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
@@ -1,5 +1,5
1 1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
2 #include "DragAndDrop/DragDropHelper.h"
3 3 #include "SqpApplication.h"
4 4 #include "Visualization/VisualizationDragWidget.h"
5 5
@@ -9,7 +9,7
9 9 #include <Common/MimeTypesDef.h>
10 10 #include <Data/ArrayData.h>
11 11 #include <Data/IDataSeries.h>
12 #include <DragDropHelper.h>
12 #include <DragAndDrop/DragDropHelper.h>
13 13 #include <Settings/SqpSettingsDefs.h>
14 14 #include <SqpApplication.h>
15 15 #include <Time/TimeController.h>
@@ -9,7 +9,7
9 9
10 10 #include "Common/MimeTypesDef.h"
11 11
12 #include "DragDropHelper.h"
12 #include "DragAndDrop/DragDropHelper.h"
13 13 #include "SqpApplication.h"
14 14
15 15 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
@@ -11,6 +11,9
11 11
12 12 #include "ui_VisualizationWidget.h"
13 13
14 #include "DragAndDrop/DragDropHelper.h"
15 #include "SqpApplication.h"
16
14 17 #include <QToolButton>
15 18
16 19 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
@@ -67,12 +70,15 VisualizationWidget::VisualizationWidget(QWidget *parent)
67 70 connect(addTabViewButton, &QToolButton::clicked, addTabView);
68 71 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
69 72
73 sqpApp->dragDropHelper().addDragDropTabBar(ui->tabWidget->tabBar());
74
70 75 // Adds default tab
71 76 addTabView();
72 77 }
73 78
74 79 VisualizationWidget::~VisualizationWidget()
75 80 {
81 sqpApp->dragDropHelper().removeDragDropTabBar(ui->tabWidget->tabBar());
76 82 delete ui;
77 83 }
78 84
@@ -16,7 +16,7
16 16
17 17 #include <Visualization/operations/FindVariableOperation.h>
18 18
19 #include <DragDropHelper.h>
19 #include <DragAndDrop/DragDropHelper.h>
20 20 #include <QUuid>
21 21 #include <SqpApplication.h>
22 22 #include <cmath>
General Comments 0
You need to be logged in to leave comments. Login now