##// END OF EJS Templates
Improves visual effect of dropping a variable in a graph
trabillard -
r873:5662e2f354c4
parent child
Show More
@@ -53,6 +53,8 public:
53
53
54 QUrl imageTemporaryUrl(const QImage &image) const;
54 QUrl imageTemporaryUrl(const QImage &image) const;
55
55
56 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
57
56 private:
58 private:
57 class DragDropHelperPrivate;
59 class DragDropHelperPrivate;
58 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
60 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
@@ -13,6 +13,7 public:
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;
@@ -59,6 +59,7 public:
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);
@@ -29,7 +29,6 struct DragDropScroller::DragDropScrollerPrivate {
29 QScrollArea *m_CurrentScrollArea = nullptr;
29 QScrollArea *m_CurrentScrollArea = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
30 std::unique_ptr<QTimer> m_Timer = nullptr;
31
31
32
33 enum class ScrollDirection { up, down, unknown };
32 enum class ScrollDirection { up, down, unknown };
34 ScrollDirection m_Direction = ScrollDirection::unknown;
33 ScrollDirection m_Direction = ScrollDirection::unknown;
35
34
@@ -148,6 +147,8 struct DragDropHelper::DragDropHelperPrivate {
148 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
147 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.
148 // QTemporaryFile to have a name which is not generated.
150
149
150 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
151
151 explicit DragDropHelperPrivate()
152 explicit DragDropHelperPrivate()
152 : m_PlaceHolder{std::make_unique<QWidget>()},
153 : m_PlaceHolder{std::make_unique<QWidget>()},
153 m_DragDropScroller{std::make_unique<DragDropScroller>()}
154 m_DragDropScroller{std::make_unique<DragDropScroller>()}
@@ -188,6 +189,7 DragDropHelper::~DragDropHelper()
188 void DragDropHelper::resetDragAndDrop()
189 void DragDropHelper::resetDragAndDrop()
189 {
190 {
190 setCurrentDragWidget(nullptr);
191 setCurrentDragWidget(nullptr);
192 impl->m_HighlightedDragWidget = nullptr;
191 }
193 }
192
194
193 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
195 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
@@ -245,6 +247,18 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
245 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
247 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
246 }
248 }
247
249
250 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
251 {
252 if (impl->m_HighlightedDragWidget) {
253 impl->m_HighlightedDragWidget->highlightForMerge(false);
254 }
255
256 if (dragWidget) {
257 impl->m_HighlightedDragWidget = dragWidget;
258 impl->m_HighlightedDragWidget->highlightForMerge(true);
259 }
260 }
261
248 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
262 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
249 VisualizationDragDropContainer *dropContainer)
263 VisualizationDragDropContainer *dropContainer)
250 {
264 {
@@ -21,6 +21,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
21 QStringList m_MergeAllowedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 = [](auto mimeData) { return true; };
23 = [](auto mimeData) { return true; };
24 int m_MinContainerHeight = 0;
24
25
25 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
26 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
26 {
27 {
@@ -55,7 +56,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
55 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
56 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
56 }
57 }
57
58
58 VisualizationDragWidget *getChildDragWidgetAt(QWidget *parent, const QPoint &pos) const
59 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
59 {
60 {
60 VisualizationDragWidget *dragWidget = nullptr;
61 VisualizationDragWidget *dragWidget = nullptr;
61
62
@@ -79,6 +80,21 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
79 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
80 .adjusted(adustNum, adustNum, -adustNum, -adustNum);
80 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
81 return containerRect.contains(container->mapFromGlobal(QCursor::pos()));
81 }
82 }
83
84 int countDragWidget(const QWidget *parent) const
85 {
86 auto nbGraph = 0;
87 for (auto child : parent->children()) {
88 if (qobject_cast<VisualizationDragWidget *>(child)) {
89 nbGraph += 1;
90 }
91 }
92
93 return nbGraph;
94 }
95
96 void findPlaceHolderPosition(const QPoint &pos, bool canMerge,
97 const VisualizationDragDropContainer *container);
82 };
98 };
83
99
84 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
100 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
@@ -117,14 +133,7 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList
117
133
118 int VisualizationDragDropContainer::countDragWidget() const
134 int VisualizationDragDropContainer::countDragWidget() const
119 {
135 {
120 auto nbGraph = 0;
136 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 }
137 }
129
138
130 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
139 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
@@ -185,7 +194,7 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
185
194
186 if (dragWidget) {
195 if (dragWidget) {
187 // If the drag&drop is internal to the visualization, entering the container hide
196 // If the drag&drop is internal to the visualization, entering the container hide
188 // the dragWidget which was hidden by the dragLeaveEvent
197 // the dragWidget which was made visible by the dragLeaveEvent
189 auto parentWidget
198 auto parentWidget
190 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
199 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
191 if (parentWidget) {
200 if (parentWidget) {
@@ -193,26 +202,8 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
193 }
202 }
194 }
203 }
195
204
196 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
205 auto canMerge = impl->allowMergeMimeData(event->mimeData());
197
206 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
198 if (dragWidgetHovered) {
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 }
207 }
217 else {
208 else {
218 // do nothing
209 // do nothing
@@ -233,6 +224,8 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
233
224
234 if (!impl->cursorIsInContainer(this)) {
225 if (!impl->cursorIsInContainer(this)) {
235 helper.removePlaceHolder();
226 helper.removePlaceHolder();
227 helper.setHightlightedDragWidget(nullptr);
228 impl->m_MinContainerHeight = 0;
236
229
237 auto dragWidget = helper.getCurrentDragWidget();
230 auto dragWidget = helper.getCurrentDragWidget();
238 if (dragWidget) {
231 if (dragWidget) {
@@ -258,60 +251,8 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
258 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
251 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
259 {
252 {
260 if (impl->acceptMimeData(event->mimeData())) {
253 if (impl->acceptMimeData(event->mimeData())) {
261 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
254 auto canMerge = impl->allowMergeMimeData(event->mimeData());
262 if (dragWidgetHovered) {
255 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
263 auto canMerge = impl->allowMergeMimeData(event->mimeData());
264
265 auto nbDragWidget = countDragWidget();
266 if (nbDragWidget > 0) {
267 auto graphHeight = qMax(size().height() / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
268
269 auto dropIndex = floor(event->pos().y() / graphHeight);
270 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
271
272 auto isOnTop = event->pos().y() < dropIndex * graphHeight + zoneSize;
273 auto isOnBottom = event->pos().y() > (dropIndex + 1) * graphHeight - zoneSize;
274
275 auto &helper = sqpApp->dragDropHelper();
276 auto placeHolderIndex = impl->m_Layout->indexOf(&(helper.placeHolder()));
277
278 if (isOnTop || isOnBottom) {
279 if (isOnBottom) {
280 dropIndex += 1;
281 }
282
283 if (helper.getCurrentDragWidget()) {
284 auto dragWidgetIndex
285 = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
286 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
287 // Correction of the index if the drop occurs in the same container
288 // and if the drag is started from the visualization (in that case, the
289 // dragWidget is hidden)
290 dropIndex += 1;
291 }
292 }
293
294 if (dropIndex != placeHolderIndex) {
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 }
304 }
305 else {
306 qCWarning(LOG_VisualizationDragDropContainer())
307 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
308 "container");
309 }
310 }
311 else {
312 // No hovered drag widget, the mouse is probably hover the placeHolder
313 // Do nothing
314 }
315 }
256 }
316 else {
257 else {
317 event->ignore();
258 event->ignore();
@@ -351,12 +292,89 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
351 qCWarning(LOG_VisualizationDragDropContainer())
292 qCWarning(LOG_VisualizationDragDropContainer())
352 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
293 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
353 "placeHolder is not found.");
294 "placeHolder is not found.");
354 Q_ASSERT(false);
295 // Q_ASSERT(false);
355 }
296 }
356 }
297 }
357 else {
298 else {
358 event->ignore();
299 event->ignore();
359 }
300 }
360
301
302 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
303 impl->m_MinContainerHeight = 0;
304
361 QWidget::dropEvent(event);
305 QWidget::dropEvent(event);
362 }
306 }
307
308
309 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
310 const QPoint &pos, bool canMerge, const VisualizationDragDropContainer *container)
311 {
312 auto &helper = sqpApp->dragDropHelper();
313
314 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
315 if (dragWidgetHovered) {
316 auto nbDragWidget = countDragWidget(container);
317 if (nbDragWidget > 0) {
318
319 if (m_MinContainerHeight == 0) {
320 m_MinContainerHeight = container->size().height();
321 }
322
323 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
324 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
325
326 auto posY = pos.y();
327 auto dropIndex = floor(posY / graphHeight);
328 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
329
330
331 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
332 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
333
334 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
335
336 if (isOnTop || isOnBottom || !canMerge) {
337 if (isOnBottom) {
338 dropIndex += 1;
339 }
340
341 if (helper.getCurrentDragWidget()) {
342 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
343 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
344 // Correction of the index if the drop occurs in the same container
345 // and if the drag is started from the visualization (in that case, the
346 // dragWidget is hidden)
347 dropIndex += 1;
348 }
349 }
350
351 if (dropIndex != placeHolderIndex) {
352 helper.insertPlaceHolder(m_Layout, dropIndex);
353 }
354
355 helper.setHightlightedDragWidget(nullptr);
356 }
357 else if (canMerge) {
358 // drop on the middle -> merge
359 if (hasPlaceHolder()) {
360 helper.removePlaceHolder();
361 }
362
363 helper.setHightlightedDragWidget(dragWidgetHovered);
364 }
365 }
366 else {
367 qCWarning(LOG_VisualizationDragDropContainer())
368 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
369 "container");
370 }
371 }
372 else if (!hasPlaceHolder()) {
373 // Drop on an empty container, just add the placeHolder at the top
374 helper.insertPlaceHolder(m_Layout, 0);
375 }
376 else {
377 // No hovered drag widget, the mouse is probably hover the placeHolder
378 // Do nothing
379 }
380 }
@@ -243,6 +243,18 bool VisualizationGraphWidget::isDragAllowed() const
243 return true;
243 return true;
244 }
244 }
245
245
246 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
247 {
248 if (highlighted) {
249 plot().setBackground(QBrush(QColor("#BBD5EE")));
250 }
251 else {
252 plot().setBackground(QBrush(Qt::white));
253 }
254
255 plot().update();
256 }
257
246 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
258 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
247 {
259 {
248 Q_UNUSED(event);
260 Q_UNUSED(event);
@@ -86,6 +86,7 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
86 ui->zoneNameLabel->setText(name);
86 ui->zoneNameLabel->setText(name);
87
87
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
89 ui->dragDropContainer->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST});
89 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 ui->dragDropContainer);
92 ui->dragDropContainer);
General Comments 0
You need to be logged in to leave comments. Login now