##// END OF EJS Templates
drop of variable inside an existing graph
trabillard -
r881:0e9a8e47fcce
parent child
Show More
@@ -1,87 +1,88
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 VisualizationDragWidget;
10 class VisualizationDragWidget;
11 class VisualizationDragDropContainer;
11 class VisualizationDragDropContainer;
12 class QMimeData;
12 class QMimeData;
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
15
15
16 /**
16 /**
17 * @brief Helper class for drag&drop operations.
17 * @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
18 * @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
19 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * can interect with the gui.
20 * can interect with the gui.
21 * @see SqpApplication
21 * @see SqpApplication
22 */
22 */
23 class DragDropHelper {
23 class DragDropHelper {
24 public:
24 public:
25 static const QString MIME_TYPE_GRAPH;
25 static const QString MIME_TYPE_GRAPH;
26 static const QString MIME_TYPE_ZONE;
26 static const QString MIME_TYPE_ZONE;
27
27
28 DragDropHelper();
28 DragDropHelper();
29 virtual ~DragDropHelper();
29 virtual ~DragDropHelper();
30
30
31 /// Resets some internal variables. Must be called before any new drag&drop operation.
31 /// Resets some internal variables. Must be called before any new drag&drop operation.
32 void resetDragAndDrop();
32 void resetDragAndDrop();
33
33
34 /// Sets the visualization widget currently being drag on the visualization.
34 /// Sets the visualization widget currently being drag on the visualization.
35 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
35 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
36
36
37 /// Returns the visualization widget currently being drag on the visualization.
37 /// 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
38 /// Can be null if a new visualization widget is intended to be created by the drag&drop
39 /// operation.
39 /// operation.
40 VisualizationDragWidget *getCurrentDragWidget() const;
40 VisualizationDragWidget *getCurrentDragWidget() const;
41
41
42 QWidget &placeHolder() const;
42 QWidget &placeHolder() const;
43 void insertPlaceHolder(QVBoxLayout *layout, int index);
43 void insertPlaceHolder(QVBoxLayout *layout, int index);
44 void removePlaceHolder();
44 void removePlaceHolder();
45 bool isPlaceHolderSet() const;
45 bool isPlaceHolderSet() const;
46
46
47 /// Checks if the specified mime data is valid for a drop in the visualization
47 /// Checks if the specified mime data is valid for a drop in the visualization
48 bool checkMimeDataForVisualization(const QMimeData *mimeData,
48 bool checkMimeDataForVisualization(const QMimeData *mimeData,
49 VisualizationDragDropContainer *dropContainer);
49 VisualizationDragDropContainer *dropContainer);
50
50
51 void addDragDropScrollArea(QScrollArea *scrollArea);
51 void addDragDropScrollArea(QScrollArea *scrollArea);
52 void removeDragDropScrollArea(QScrollArea *scrollArea);
52 void removeDragDropScrollArea(QScrollArea *scrollArea);
53
53
54 QUrl imageTemporaryUrl(const QImage &image) const;
54 QUrl imageTemporaryUrl(const QImage &image) const;
55
55
56 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
56 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
57 VisualizationDragWidget *getHightlightedDragWidget() const;
57
58
58 private:
59 private:
59 class DragDropHelperPrivate;
60 class DragDropHelperPrivate;
60 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
61 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
61 };
62 };
62
63
63 /**
64 /**
64 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
65 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
65 * @note A QScrollArea inside an other QScrollArea is not fully supported.
66 * @note A QScrollArea inside an other QScrollArea is not fully supported.
66 */
67 */
67 class DragDropScroller : public QObject {
68 class DragDropScroller : public QObject {
68 Q_OBJECT
69 Q_OBJECT
69
70
70 public:
71 public:
71 DragDropScroller(QObject *parent = nullptr);
72 DragDropScroller(QObject *parent = nullptr);
72
73
73 void addScrollArea(QScrollArea *scrollArea);
74 void addScrollArea(QScrollArea *scrollArea);
74 void removeScrollArea(QScrollArea *scrollArea);
75 void removeScrollArea(QScrollArea *scrollArea);
75
76
76 protected:
77 protected:
77 bool eventFilter(QObject *obj, QEvent *event);
78 bool eventFilter(QObject *obj, QEvent *event);
78
79
79 private:
80 private:
80 class DragDropScrollerPrivate;
81 class DragDropScrollerPrivate;
81 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
82 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
82
83
83 private slots:
84 private slots:
84 void onTimer();
85 void onTimer();
85 };
86 };
86
87
87 #endif // SCIQLOP_DRAGDROPHELPER_H
88 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -1,51 +1,52
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 <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QMimeData>
6 #include <QMimeData>
7 #include <QVBoxLayout>
7 #include <QVBoxLayout>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <functional>
10 #include <functional>
11
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
13
13
14 class VisualizationDragWidget;
14 class VisualizationDragWidget;
15
15
16 class VisualizationDragDropContainer : public QWidget {
16 class VisualizationDragDropContainer : public QWidget {
17 Q_OBJECT
17 Q_OBJECT
18
18
19 signals:
19 signals:
20 void dropOccured(int dropIndex, const QMimeData *mimeData);
20 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
21 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
21
22
22 public:
23 public:
23 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
24 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
24
25
25 VisualizationDragDropContainer(QWidget *parent = nullptr);
26 VisualizationDragDropContainer(QWidget *parent = nullptr);
26
27
27 void addDragWidget(VisualizationDragWidget *dragWidget);
28 void addDragWidget(VisualizationDragWidget *dragWidget);
28 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
29 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
29
30
30 void setAcceptedMimeTypes(const QStringList &mimeTypes);
31 void setAcceptedMimeTypes(const QStringList &mimeTypes);
31 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
32 void setMergeAllowedMimeTypes(const QStringList &mimeTypes);
32
33
33 int countDragWidget() const;
34 int countDragWidget() const;
34
35
35 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
36 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
36
37
37 protected:
38 protected:
38 void dragEnterEvent(QDragEnterEvent *event);
39 void dragEnterEvent(QDragEnterEvent *event);
39 void dragLeaveEvent(QDragLeaveEvent *event);
40 void dragLeaveEvent(QDragLeaveEvent *event);
40 void dragMoveEvent(QDragMoveEvent *event);
41 void dragMoveEvent(QDragMoveEvent *event);
41 void dropEvent(QDropEvent *event);
42 void dropEvent(QDropEvent *event);
42
43
43 private:
44 private:
44 class VisualizationDragDropContainerPrivate;
45 class VisualizationDragDropContainerPrivate;
45 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
46 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
46
47
47 private slots:
48 private slots:
48 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
49 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
49 };
50 };
50
51
51 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
52 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_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,331 +1,336
1 #include "DragDropHelper.h"
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationWidget.h"
5 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
6 #include "Visualization/operations/FindVariableOperation.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 #include "Common/VisualizationDef.h"
11 #include "Common/VisualizationDef.h"
12
12
13 #include <QDir>
13 #include <QDir>
14 #include <QDragEnterEvent>
14 #include <QDragEnterEvent>
15 #include <QDragMoveEvent>
15 #include <QDragMoveEvent>
16 #include <QScrollArea>
16 #include <QScrollArea>
17 #include <QScrollBar>
17 #include <QScrollBar>
18 #include <QTimer>
18 #include <QTimer>
19 #include <QVBoxLayout>
19 #include <QVBoxLayout>
20
20
21 const int SCROLL_SPEED = 5;
21 const int SCROLL_SPEED = 5;
22 const int SCROLL_ZONE_SIZE = 50;
22 const int SCROLL_ZONE_SIZE = 50;
23
23
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
25
25
26 struct DragDropScroller::DragDropScrollerPrivate {
26 struct DragDropScroller::DragDropScrollerPrivate {
27
27
28 QList<QScrollArea *> m_ScrollAreas;
28 QList<QScrollArea *> m_ScrollAreas;
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 enum class ScrollDirection { up, down, unknown };
32 enum class ScrollDirection { up, down, unknown };
33 ScrollDirection m_Direction = ScrollDirection::unknown;
33 ScrollDirection m_Direction = ScrollDirection::unknown;
34
34
35 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
35 explicit DragDropScrollerPrivate() : m_Timer{std::make_unique<QTimer>()}
36 {
36 {
37 m_Timer->setInterval(0);
37 m_Timer->setInterval(0);
38 }
38 }
39 };
39 };
40
40
41 DragDropScroller::DragDropScroller(QObject *parent)
41 DragDropScroller::DragDropScroller(QObject *parent)
42 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
42 : QObject{parent}, impl{spimpl::make_unique_impl<DragDropScrollerPrivate>()}
43 {
43 {
44 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
44 connect(impl->m_Timer.get(), &QTimer::timeout, this, &DragDropScroller::onTimer);
45 }
45 }
46
46
47 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
47 void DragDropScroller::addScrollArea(QScrollArea *scrollArea)
48 {
48 {
49 impl->m_ScrollAreas << scrollArea;
49 impl->m_ScrollAreas << scrollArea;
50 scrollArea->viewport()->setAcceptDrops(true);
50 scrollArea->viewport()->setAcceptDrops(true);
51 }
51 }
52
52
53 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
53 void DragDropScroller::removeScrollArea(QScrollArea *scrollArea)
54 {
54 {
55 impl->m_ScrollAreas.removeAll(scrollArea);
55 impl->m_ScrollAreas.removeAll(scrollArea);
56 scrollArea->viewport()->setAcceptDrops(false);
56 scrollArea->viewport()->setAcceptDrops(false);
57 }
57 }
58
58
59 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
59 bool DragDropScroller::eventFilter(QObject *obj, QEvent *event)
60 {
60 {
61 if (event->type() == QEvent::DragMove) {
61 if (event->type() == QEvent::DragMove) {
62 auto w = static_cast<QWidget *>(obj);
62 auto w = static_cast<QWidget *>(obj);
63
63
64 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
64 if (impl->m_CurrentScrollArea && impl->m_CurrentScrollArea->isAncestorOf(w)) {
65 auto moveEvent = static_cast<QDragMoveEvent *>(event);
65 auto moveEvent = static_cast<QDragMoveEvent *>(event);
66
66
67 auto pos = moveEvent->pos();
67 auto pos = moveEvent->pos();
68 if (impl->m_CurrentScrollArea->viewport() != w) {
68 if (impl->m_CurrentScrollArea->viewport() != w) {
69 auto globalPos = w->mapToGlobal(moveEvent->pos());
69 auto globalPos = w->mapToGlobal(moveEvent->pos());
70 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
70 pos = impl->m_CurrentScrollArea->viewport()->mapFromGlobal(globalPos);
71 }
71 }
72
72
73 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
73 auto isInTopZone = pos.y() > impl->m_CurrentScrollArea->viewport()->size().height()
74 - SCROLL_ZONE_SIZE;
74 - SCROLL_ZONE_SIZE;
75 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
75 auto isInBottomZone = pos.y() < SCROLL_ZONE_SIZE;
76
76
77 if (!isInTopZone && !isInBottomZone) {
77 if (!isInTopZone && !isInBottomZone) {
78 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
78 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
79 impl->m_Timer->stop();
79 impl->m_Timer->stop();
80 }
80 }
81 else if (!impl->m_Timer->isActive()) {
81 else if (!impl->m_Timer->isActive()) {
82 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
82 impl->m_Direction = isInTopZone ? DragDropScrollerPrivate::ScrollDirection::up
83 : DragDropScrollerPrivate::ScrollDirection::down;
83 : DragDropScrollerPrivate::ScrollDirection::down;
84 impl->m_Timer->start();
84 impl->m_Timer->start();
85 }
85 }
86 }
86 }
87 }
87 }
88 else if (event->type() == QEvent::DragEnter) {
88 else if (event->type() == QEvent::DragEnter) {
89 auto w = static_cast<QWidget *>(obj);
89 auto w = static_cast<QWidget *>(obj);
90
90
91 for (auto scrollArea : impl->m_ScrollAreas) {
91 for (auto scrollArea : impl->m_ScrollAreas) {
92 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
92 if (impl->m_CurrentScrollArea != scrollArea && scrollArea->isAncestorOf(w)) {
93 auto enterEvent = static_cast<QDragEnterEvent *>(event);
93 auto enterEvent = static_cast<QDragEnterEvent *>(event);
94 enterEvent->acceptProposedAction();
94 enterEvent->acceptProposedAction();
95 enterEvent->setDropAction(Qt::IgnoreAction);
95 enterEvent->setDropAction(Qt::IgnoreAction);
96 impl->m_CurrentScrollArea = scrollArea;
96 impl->m_CurrentScrollArea = scrollArea;
97 break;
97 break;
98 }
98 }
99 }
99 }
100 }
100 }
101 else if (event->type() == QEvent::DragLeave) {
101 else if (event->type() == QEvent::DragLeave) {
102 if (impl->m_CurrentScrollArea) {
102 if (impl->m_CurrentScrollArea) {
103 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
103 if (!QRect(QPoint(), impl->m_CurrentScrollArea->size())
104 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
104 .contains(impl->m_CurrentScrollArea->mapFromGlobal(QCursor::pos()))) {
105 impl->m_CurrentScrollArea = nullptr;
105 impl->m_CurrentScrollArea = nullptr;
106 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
106 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
107 impl->m_Timer->stop();
107 impl->m_Timer->stop();
108 }
108 }
109 }
109 }
110 }
110 }
111 else if (event->type() == QEvent::Drop) {
111 else if (event->type() == QEvent::Drop) {
112 if (impl->m_CurrentScrollArea) {
112 if (impl->m_CurrentScrollArea) {
113 impl->m_CurrentScrollArea = nullptr;
113 impl->m_CurrentScrollArea = nullptr;
114 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
114 impl->m_Direction = DragDropScrollerPrivate::ScrollDirection::unknown;
115 impl->m_Timer->stop();
115 impl->m_Timer->stop();
116 }
116 }
117 }
117 }
118
118
119 return false;
119 return false;
120 }
120 }
121
121
122 void DragDropScroller::onTimer()
122 void DragDropScroller::onTimer()
123 {
123 {
124 if (impl->m_CurrentScrollArea) {
124 if (impl->m_CurrentScrollArea) {
125 auto mvt = 0;
125 auto mvt = 0;
126 switch (impl->m_Direction) {
126 switch (impl->m_Direction) {
127 case DragDropScrollerPrivate::ScrollDirection::up:
127 case DragDropScrollerPrivate::ScrollDirection::up:
128 mvt = SCROLL_SPEED;
128 mvt = SCROLL_SPEED;
129 break;
129 break;
130 case DragDropScrollerPrivate::ScrollDirection::down:
130 case DragDropScrollerPrivate::ScrollDirection::down:
131 mvt = -SCROLL_SPEED;
131 mvt = -SCROLL_SPEED;
132 break;
132 break;
133 default:
133 default:
134 break;
134 break;
135 }
135 }
136
136
137 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
137 impl->m_CurrentScrollArea->verticalScrollBar()->setValue(
138 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
138 impl->m_CurrentScrollArea->verticalScrollBar()->value() + mvt);
139 }
139 }
140 }
140 }
141
141
142 struct DragDropHelper::DragDropHelperPrivate {
142 struct DragDropHelper::DragDropHelperPrivate {
143
143
144 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
144 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
145 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
145 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
146 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
146 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
147 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
148 // QTemporaryFile to have a name which is not generated.
148 // QTemporaryFile to have a name which is not generated.
149
149
150 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
150 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
151
151
152 QMetaObject::Connection m_DragWidgetDestroyedConnection;
152 QMetaObject::Connection m_DragWidgetDestroyedConnection;
153 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
153 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
154
154
155 explicit DragDropHelperPrivate()
155 explicit DragDropHelperPrivate()
156 : m_PlaceHolder{std::make_unique<QWidget>()},
156 : m_PlaceHolder{std::make_unique<QWidget>()},
157 m_DragDropScroller{std::make_unique<DragDropScroller>()}
157 m_DragDropScroller{std::make_unique<DragDropScroller>()}
158 {
158 {
159 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
159 m_PlaceHolder->setStyleSheet("background-color: #BBD5EE; border:2px solid #2A7FD4");
160 sqpApp->installEventFilter(m_DragDropScroller.get());
160 sqpApp->installEventFilter(m_DragDropScroller.get());
161
161
162
162
163 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
163 m_ImageTempUrl = QDir::temp().absoluteFilePath("Scqlop_graph.png");
164 }
164 }
165
165
166 void preparePlaceHolder() const
166 void preparePlaceHolder() const
167 {
167 {
168 if (m_CurrentDragWidget) {
168 if (m_CurrentDragWidget) {
169 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
169 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
170 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
170 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
171 }
171 }
172 else {
172 else {
173 // Configuration of the placeHolder when there is no dragWidget
173 // Configuration of the placeHolder when there is no dragWidget
174 // (for instance with a drag from a variable)
174 // (for instance with a drag from a variable)
175
175
176 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
176 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
177 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
177 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
178 }
178 }
179 }
179 }
180 };
180 };
181
181
182
182
183 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
183 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
184 {
184 {
185 }
185 }
186
186
187 DragDropHelper::~DragDropHelper()
187 DragDropHelper::~DragDropHelper()
188 {
188 {
189 QFile::remove(impl->m_ImageTempUrl);
189 QFile::remove(impl->m_ImageTempUrl);
190 }
190 }
191
191
192 void DragDropHelper::resetDragAndDrop()
192 void DragDropHelper::resetDragAndDrop()
193 {
193 {
194 setCurrentDragWidget(nullptr);
194 setCurrentDragWidget(nullptr);
195 impl->m_HighlightedDragWidget = nullptr;
195 impl->m_HighlightedDragWidget = nullptr;
196 }
196 }
197
197
198 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
198 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
199 {
199 {
200 if (impl->m_CurrentDragWidget) {
200 if (impl->m_CurrentDragWidget) {
201
201
202 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
202 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
203 }
203 }
204
204
205 if (dragWidget) {
205 if (dragWidget) {
206 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
206 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
207 impl->m_DragWidgetDestroyedConnection
207 impl->m_DragWidgetDestroyedConnection
208 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
208 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
209 [this]() { impl->m_CurrentDragWidget = nullptr; });
209 [this]() { impl->m_CurrentDragWidget = nullptr; });
210 }
210 }
211
211
212 impl->m_CurrentDragWidget = dragWidget;
212 impl->m_CurrentDragWidget = dragWidget;
213 }
213 }
214
214
215 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
215 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
216 {
216 {
217 return impl->m_CurrentDragWidget;
217 return impl->m_CurrentDragWidget;
218 }
218 }
219
219
220
220
221 QWidget &DragDropHelper::placeHolder() const
221 QWidget &DragDropHelper::placeHolder() const
222 {
222 {
223 return *impl->m_PlaceHolder;
223 return *impl->m_PlaceHolder;
224 }
224 }
225
225
226 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
226 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index)
227 {
227 {
228 removePlaceHolder();
228 removePlaceHolder();
229 impl->preparePlaceHolder();
229 impl->preparePlaceHolder();
230 layout->insertWidget(index, impl->m_PlaceHolder.get());
230 layout->insertWidget(index, impl->m_PlaceHolder.get());
231 impl->m_PlaceHolder->show();
231 impl->m_PlaceHolder->show();
232 }
232 }
233
233
234 void DragDropHelper::removePlaceHolder()
234 void DragDropHelper::removePlaceHolder()
235 {
235 {
236 auto parentWidget = impl->m_PlaceHolder->parentWidget();
236 auto parentWidget = impl->m_PlaceHolder->parentWidget();
237 if (parentWidget) {
237 if (parentWidget) {
238 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
238 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
239 impl->m_PlaceHolder->setParent(nullptr);
239 impl->m_PlaceHolder->setParent(nullptr);
240 impl->m_PlaceHolder->hide();
240 impl->m_PlaceHolder->hide();
241 }
241 }
242 }
242 }
243
243
244 bool DragDropHelper::isPlaceHolderSet() const
244 bool DragDropHelper::isPlaceHolderSet() const
245 {
245 {
246 return impl->m_PlaceHolder->parentWidget();
246 return impl->m_PlaceHolder->parentWidget();
247 }
247 }
248
248
249 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
249 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
250 {
250 {
251 impl->m_DragDropScroller->addScrollArea(scrollArea);
251 impl->m_DragDropScroller->addScrollArea(scrollArea);
252 }
252 }
253
253
254 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
254 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
255 {
255 {
256 impl->m_DragDropScroller->removeScrollArea(scrollArea);
256 impl->m_DragDropScroller->removeScrollArea(scrollArea);
257 }
257 }
258
258
259 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
259 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
260 {
260 {
261 image.save(impl->m_ImageTempUrl);
261 image.save(impl->m_ImageTempUrl);
262 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
262 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
263 }
263 }
264
264
265 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
265 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
266 {
266 {
267 if (impl->m_HighlightedDragWidget) {
267 if (impl->m_HighlightedDragWidget) {
268 impl->m_HighlightedDragWidget->highlightForMerge(false);
268 impl->m_HighlightedDragWidget->highlightForMerge(false);
269 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
269 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
270 }
270 }
271
271
272 if (dragWidget) {
272 if (dragWidget) {
273 dragWidget->highlightForMerge(true);
273 dragWidget->highlightForMerge(true);
274
274
275 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
275 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
276 impl->m_DragWidgetDestroyedConnection
276 impl->m_DragWidgetDestroyedConnection
277 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
277 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
278 [this]() { impl->m_HighlightedDragWidget = nullptr; });
278 [this]() { impl->m_HighlightedDragWidget = nullptr; });
279 }
279 }
280
280
281 impl->m_HighlightedDragWidget = dragWidget;
281 impl->m_HighlightedDragWidget = dragWidget;
282 }
282 }
283
283
284 VisualizationDragWidget *DragDropHelper::getHightlightedDragWidget() const
285 {
286 return impl->m_HighlightedDragWidget;
287 }
288
284 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
289 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
285 VisualizationDragDropContainer *dropContainer)
290 VisualizationDragDropContainer *dropContainer)
286 {
291 {
287 if (!mimeData || !dropContainer) {
292 if (!mimeData || !dropContainer) {
288 qCWarning(LOG_DragDropHelper()) << QObject::tr(
293 qCWarning(LOG_DragDropHelper()) << QObject::tr(
289 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
294 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
290 Q_ASSERT(false);
295 Q_ASSERT(false);
291 }
296 }
292
297
293 auto result = true;
298 auto result = true;
294
299
295 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
300 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
296 auto variables = sqpApp->variableController().variablesForMimeData(
301 auto variables = sqpApp->variableController().variablesForMimeData(
297 mimeData->data(MIME_TYPE_VARIABLE_LIST));
302 mimeData->data(MIME_TYPE_VARIABLE_LIST));
298
303
299 if (variables.count() == 1) {
304 if (variables.count() == 1) {
300 // Check that the viariable is not already in a graph
305 // Check that the viariable is not already in a graph
301
306
302 // Search for the top level VisualizationWidget
307 // Search for the top level VisualizationWidget
303 auto parent = dropContainer->parentWidget();
308 auto parent = dropContainer->parentWidget();
304 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
309 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
305 parent = parent->parentWidget();
310 parent = parent->parentWidget();
306 }
311 }
307
312
308 if (parent) {
313 if (parent) {
309 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
314 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
310
315
311 FindVariableOperation findVariableOperation{variables.first()};
316 FindVariableOperation findVariableOperation{variables.first()};
312 visualizationWidget->accept(&findVariableOperation);
317 visualizationWidget->accept(&findVariableOperation);
313 auto variableContainers = findVariableOperation.result();
318 auto variableContainers = findVariableOperation.result();
314 if (!variableContainers.empty()) {
319 if (!variableContainers.empty()) {
315 result = false;
320 result = false;
316 }
321 }
317 }
322 }
318 else {
323 else {
319 qCWarning(LOG_DragDropHelper()) << QObject::tr(
324 qCWarning(LOG_DragDropHelper()) << QObject::tr(
320 "DragDropHelper::checkMimeDataForVisualization, the parent "
325 "DragDropHelper::checkMimeDataForVisualization, the parent "
321 "VisualizationWidget cannot be found.");
326 "VisualizationWidget cannot be found.");
322 result = false;
327 result = false;
323 }
328 }
324 }
329 }
325 else {
330 else {
326 result = false;
331 result = false;
327 }
332 }
328 }
333 }
329
334
330 return result;
335 return result;
331 }
336 }
@@ -1,381 +1,392
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragDropHelper.h"
2 #include "DragDropHelper.h"
3 #include "SqpApplication.h"
3 #include "SqpApplication.h"
4 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5
5
6 #include "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 QStringList m_AcceptedMimeTypes;
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 int m_MinContainerHeight = 0;
25
25
26 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
26 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
27 {
27 {
28 m_Layout = new QVBoxLayout(widget);
28 m_Layout = new QVBoxLayout(widget);
29 m_Layout->setContentsMargins(0, 0, 0, 0);
29 m_Layout->setContentsMargins(0, 0, 0, 0);
30 }
30 }
31
31
32 bool acceptMimeData(const QMimeData *data) const
32 bool acceptMimeData(const QMimeData *data) const
33 {
33 {
34 for (const auto &type : m_AcceptedMimeTypes) {
34 for (const auto &type : m_AcceptedMimeTypes) {
35 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
35 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
36 return true;
36 return true;
37 }
37 }
38 }
38 }
39
39
40 return false;
40 return false;
41 }
41 }
42
42
43 bool allowMergeMimeData(const QMimeData *data) const
43 bool allowMergeMimeData(const QMimeData *data) const
44 {
44 {
45 for (const auto &type : m_MergeAllowedMimeTypes) {
45 for (const auto &type : m_MergeAllowedMimeTypes) {
46 if (data->hasFormat(type)) {
46 if (data->hasFormat(type)) {
47 return true;
47 return true;
48 }
48 }
49 }
49 }
50
50
51 return false;
51 return false;
52 }
52 }
53
53
54 bool hasPlaceHolder() const
54 bool hasPlaceHolder() const
55 {
55 {
56 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
56 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
57 }
57 }
58
58
59 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
59 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
60 {
60 {
61 VisualizationDragWidget *dragWidget = nullptr;
61 VisualizationDragWidget *dragWidget = nullptr;
62
62
63 for (auto child : parent->children()) {
63 for (auto child : parent->children()) {
64 auto widget = qobject_cast<VisualizationDragWidget *>(child);
64 auto widget = qobject_cast<VisualizationDragWidget *>(child);
65 if (widget && widget->isVisible()) {
65 if (widget && widget->isVisible()) {
66 if (widget->frameGeometry().contains(pos)) {
66 if (widget->frameGeometry().contains(pos)) {
67 dragWidget = widget;
67 dragWidget = widget;
68 break;
68 break;
69 }
69 }
70 }
70 }
71 }
71 }
72
72
73 return dragWidget;
73 return dragWidget;
74 }
74 }
75
75
76 bool cursorIsInContainer(QWidget *container) const
76 bool cursorIsInContainer(QWidget *container) const
77 {
77 {
78 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
78 return container->isAncestorOf(sqpApp->widgetAt(QCursor::pos()));
79 }
79 }
80
80
81 int countDragWidget(const QWidget *parent) const
81 int countDragWidget(const QWidget *parent) const
82 {
82 {
83 auto nbGraph = 0;
83 auto nbGraph = 0;
84 for (auto child : parent->children()) {
84 for (auto child : parent->children()) {
85 if (qobject_cast<VisualizationDragWidget *>(child)) {
85 if (qobject_cast<VisualizationDragWidget *>(child)) {
86 nbGraph += 1;
86 nbGraph += 1;
87 }
87 }
88 }
88 }
89
89
90 return nbGraph;
90 return nbGraph;
91 }
91 }
92
92
93 void findPlaceHolderPosition(const QPoint &pos, bool canMerge,
93 void findPlaceHolderPosition(const QPoint &pos, bool canMerge,
94 const VisualizationDragDropContainer *container);
94 const VisualizationDragDropContainer *container);
95 };
95 };
96
96
97 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
97 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
98 : QWidget{parent},
98 : QWidget{parent},
99 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
99 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
100 {
100 {
101 setAcceptDrops(true);
101 setAcceptDrops(true);
102 }
102 }
103
103
104 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
104 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
105 {
105 {
106 impl->m_Layout->addWidget(dragWidget);
106 impl->m_Layout->addWidget(dragWidget);
107 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
107 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
108 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
108 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
109 &VisualizationDragDropContainer::startDrag);
109 &VisualizationDragDropContainer::startDrag);
110 }
110 }
111
111
112 void VisualizationDragDropContainer::insertDragWidget(int index,
112 void VisualizationDragDropContainer::insertDragWidget(int index,
113 VisualizationDragWidget *dragWidget)
113 VisualizationDragWidget *dragWidget)
114 {
114 {
115 impl->m_Layout->insertWidget(index, dragWidget);
115 impl->m_Layout->insertWidget(index, dragWidget);
116 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
116 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
117 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
117 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
118 &VisualizationDragDropContainer::startDrag);
118 &VisualizationDragDropContainer::startDrag);
119 }
119 }
120
120
121 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
121 void VisualizationDragDropContainer::setAcceptedMimeTypes(const QStringList &mimeTypes)
122 {
122 {
123 impl->m_AcceptedMimeTypes = mimeTypes;
123 impl->m_AcceptedMimeTypes = mimeTypes;
124 }
124 }
125
125
126 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
126 void VisualizationDragDropContainer::setMergeAllowedMimeTypes(const QStringList &mimeTypes)
127 {
127 {
128 impl->m_MergeAllowedMimeTypes = mimeTypes;
128 impl->m_MergeAllowedMimeTypes = mimeTypes;
129 }
129 }
130
130
131 int VisualizationDragDropContainer::countDragWidget() const
131 int VisualizationDragDropContainer::countDragWidget() const
132 {
132 {
133 return impl->countDragWidget(this);
133 return impl->countDragWidget(this);
134 }
134 }
135
135
136 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
136 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
137 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
137 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
138 {
138 {
139 impl->m_AcceptMimeDataFun = fun;
139 impl->m_AcceptMimeDataFun = fun;
140 }
140 }
141
141
142 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
142 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
143 const QPoint &dragPosition)
143 const QPoint &dragPosition)
144 {
144 {
145 auto &helper = sqpApp->dragDropHelper();
145 auto &helper = sqpApp->dragDropHelper();
146 helper.resetDragAndDrop();
146 helper.resetDragAndDrop();
147
147
148 // Note: The management of the drag object is done by Qt
148 // Note: The management of the drag object is done by Qt
149 auto drag = new QDrag{dragWidget};
149 auto drag = new QDrag{dragWidget};
150 drag->setHotSpot(dragPosition);
150 drag->setHotSpot(dragPosition);
151
151
152 auto mimeData = dragWidget->mimeData();
152 auto mimeData = dragWidget->mimeData();
153 drag->setMimeData(mimeData);
153 drag->setMimeData(mimeData);
154
154
155 auto pixmap = QPixmap(dragWidget->size());
155 auto pixmap = QPixmap(dragWidget->size());
156 dragWidget->render(&pixmap);
156 dragWidget->render(&pixmap);
157 drag->setPixmap(pixmap);
157 drag->setPixmap(pixmap);
158
158
159 auto image = pixmap.toImage();
159 auto image = pixmap.toImage();
160 mimeData->setImageData(image);
160 mimeData->setImageData(image);
161 mimeData->setUrls({helper.imageTemporaryUrl(image)});
161 mimeData->setUrls({helper.imageTemporaryUrl(image)});
162
162
163 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
163 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
164 helper.setCurrentDragWidget(dragWidget);
164 helper.setCurrentDragWidget(dragWidget);
165
165
166 if (impl->cursorIsInContainer(this)) {
166 if (impl->cursorIsInContainer(this)) {
167 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
167 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
168 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
168 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
169 dragWidget->setVisible(false);
169 dragWidget->setVisible(false);
170 }
170 }
171 else {
171 else {
172 // The drag starts directly outside the drop zone
172 // The drag starts directly outside the drop zone
173 // do not add the placeHolder
173 // do not add the placeHolder
174 }
174 }
175
175
176 // Note: The exec() is blocking on windows but not on linux and macOS
176 // Note: The exec() is blocking on windows but not on linux and macOS
177 drag->exec(Qt::MoveAction | Qt::CopyAction);
177 drag->exec(Qt::MoveAction | Qt::CopyAction);
178 }
178 }
179 else {
179 else {
180 qCWarning(LOG_VisualizationDragDropContainer())
180 qCWarning(LOG_VisualizationDragDropContainer())
181 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
181 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
182 "VisualizationDragWidget is not found in this container.");
182 "VisualizationDragWidget is not found in this container.");
183 }
183 }
184 }
184 }
185
185
186 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
186 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
187 {
187 {
188 if (impl->acceptMimeData(event->mimeData())) {
188 if (impl->acceptMimeData(event->mimeData())) {
189 event->acceptProposedAction();
189 event->acceptProposedAction();
190
190
191 auto &helper = sqpApp->dragDropHelper();
191 auto &helper = sqpApp->dragDropHelper();
192
192
193 if (!impl->hasPlaceHolder()) {
193 if (!impl->hasPlaceHolder()) {
194 auto dragWidget = helper.getCurrentDragWidget();
194 auto dragWidget = helper.getCurrentDragWidget();
195
195
196 if (dragWidget) {
196 if (dragWidget) {
197 // If the drag&drop is internal to the visualization, entering the container hide
197 // If the drag&drop is internal to the visualization, entering the container hide
198 // the dragWidget which was made visible by the dragLeaveEvent
198 // the dragWidget which was made visible by the dragLeaveEvent
199 auto parentWidget
199 auto parentWidget
200 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
200 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
201 if (parentWidget) {
201 if (parentWidget) {
202 dragWidget->setVisible(false);
202 dragWidget->setVisible(false);
203 }
203 }
204 }
204 }
205
205
206 auto canMerge = impl->allowMergeMimeData(event->mimeData());
206 auto canMerge = impl->allowMergeMimeData(event->mimeData());
207 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
207 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
208 }
208 }
209 else {
209 else {
210 // do nothing
210 // do nothing
211 }
211 }
212 }
212 }
213 else {
213 else {
214 event->ignore();
214 event->ignore();
215 }
215 }
216
216
217 QWidget::dragEnterEvent(event);
217 QWidget::dragEnterEvent(event);
218 }
218 }
219
219
220 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
220 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
221 {
221 {
222 Q_UNUSED(event);
222 Q_UNUSED(event);
223
223
224 auto &helper = sqpApp->dragDropHelper();
224 auto &helper = sqpApp->dragDropHelper();
225
225
226 if (!impl->cursorIsInContainer(this)) {
226 if (!impl->cursorIsInContainer(this)) {
227 helper.removePlaceHolder();
227 helper.removePlaceHolder();
228 helper.setHightlightedDragWidget(nullptr);
228 helper.setHightlightedDragWidget(nullptr);
229 impl->m_MinContainerHeight = 0;
229 impl->m_MinContainerHeight = 0;
230
230
231 auto dragWidget = helper.getCurrentDragWidget();
231 auto dragWidget = helper.getCurrentDragWidget();
232 if (dragWidget) {
232 if (dragWidget) {
233 // dragWidget has a value only if the drag is started from the visualization
233 // dragWidget has a value only if the drag is started from the visualization
234 // In that case, shows the drag widget at its original place
234 // In that case, shows the drag widget at its original place
235 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
235 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
236 // drop zone (It is not possible to catch a drop event outside of the application)
236 // drop zone (It is not possible to catch a drop event outside of the application)
237
237
238 if (dragWidget) {
238 if (dragWidget) {
239 dragWidget->setVisible(true);
239 dragWidget->setVisible(true);
240 }
240 }
241 }
241 }
242 }
242 }
243 else {
243 else {
244 // Leave event probably received for a child widget.
244 // Leave event probably received for a child widget.
245 // Do nothing.
245 // Do nothing.
246 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
246 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
247 }
247 }
248
248
249 QWidget::dragLeaveEvent(event);
249 QWidget::dragLeaveEvent(event);
250 }
250 }
251
251
252 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
252 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
253 {
253 {
254 if (impl->acceptMimeData(event->mimeData())) {
254 if (impl->acceptMimeData(event->mimeData())) {
255 auto canMerge = impl->allowMergeMimeData(event->mimeData());
255 auto canMerge = impl->allowMergeMimeData(event->mimeData());
256 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
256 impl->findPlaceHolderPosition(event->pos(), canMerge, this);
257 }
257 }
258 else {
258 else {
259 event->ignore();
259 event->ignore();
260 }
260 }
261
261
262 QWidget::dragMoveEvent(event);
262 QWidget::dragMoveEvent(event);
263 }
263 }
264
264
265 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
265 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
266 {
266 {
267 auto &helper = sqpApp->dragDropHelper();
268
267 if (impl->acceptMimeData(event->mimeData())) {
269 if (impl->acceptMimeData(event->mimeData())) {
268 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
270 auto dragWidget = helper.getCurrentDragWidget();
269 if (impl->hasPlaceHolder()) {
271 if (impl->hasPlaceHolder()) {
270 auto &helper = sqpApp->dragDropHelper();
272 // drop where the placeHolder is located
271
273
272 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
274 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
273
275
274 if (dragWidget) {
276 if (dragWidget) {
275 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
277 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
276 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
278 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
277 // Correction of the index if the drop occurs in the same container
279 // Correction of the index if the drop occurs in the same container
278 // and if the drag is started from the visualization (in that case, the
280 // and if the drag is started from the visualization (in that case, the
279 // dragWidget is hidden)
281 // dragWidget is hidden)
280 droppedIndex -= 1;
282 droppedIndex -= 1;
281 }
283 }
282
284
283 dragWidget->setVisible(true);
285 dragWidget->setVisible(true);
284 }
286 }
285
287
286 event->acceptProposedAction();
288 event->acceptProposedAction();
287
289
288 helper.removePlaceHolder();
290 helper.removePlaceHolder();
289
291
290 emit dropOccured(droppedIndex, event->mimeData());
292 emit dropOccuredInContainer(droppedIndex, event->mimeData());
291 }
293 }
292 else {
294 else if (helper.getHightlightedDragWidget()) {
293 qCWarning(LOG_VisualizationDragDropContainer())
295 // drop on the highlighted widget
294 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
296
295 "placeHolder is not found.");
297 auto canMerge = impl->allowMergeMimeData(event->mimeData());
296 // Q_ASSERT(false);
298 if (canMerge) {
299 event->acceptProposedAction();
300 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
301 }
302 else {
303 qCWarning(LOG_VisualizationDragDropContainer())
304 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
305 "the merge is forbidden.");
306 Q_ASSERT(false);
307 }
297 }
308 }
298 }
309 }
299 else {
310 else {
300 event->ignore();
311 event->ignore();
301 }
312 }
302
313
303 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
314 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
304 impl->m_MinContainerHeight = 0;
315 impl->m_MinContainerHeight = 0;
305
316
306 QWidget::dropEvent(event);
317 QWidget::dropEvent(event);
307 }
318 }
308
319
309
320
310 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
321 void VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
311 const QPoint &pos, bool canMerge, const VisualizationDragDropContainer *container)
322 const QPoint &pos, bool canMerge, const VisualizationDragDropContainer *container)
312 {
323 {
313 auto &helper = sqpApp->dragDropHelper();
324 auto &helper = sqpApp->dragDropHelper();
314
325
315 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
326 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
316 if (dragWidgetHovered) {
327 if (dragWidgetHovered) {
317 auto nbDragWidget = countDragWidget(container);
328 auto nbDragWidget = countDragWidget(container);
318 if (nbDragWidget > 0) {
329 if (nbDragWidget > 0) {
319
330
320 if (m_MinContainerHeight == 0) {
331 if (m_MinContainerHeight == 0) {
321 m_MinContainerHeight = container->size().height();
332 m_MinContainerHeight = container->size().height();
322 }
333 }
323
334
324 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
335 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
325 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
336 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
326
337
327 auto posY = pos.y();
338 auto posY = pos.y();
328 auto dropIndex = floor(posY / graphHeight);
339 auto dropIndex = floor(posY / graphHeight);
329 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
340 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
330
341
331
342
332 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
343 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
333 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
344 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
334
345
335 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
346 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
336
347
337 if (isOnTop || isOnBottom || !canMerge) {
348 if (isOnTop || isOnBottom || !canMerge) {
338 if (isOnBottom) {
349 if (isOnBottom) {
339 dropIndex += 1;
350 dropIndex += 1;
340 }
351 }
341
352
342 if (helper.getCurrentDragWidget()) {
353 if (helper.getCurrentDragWidget()) {
343 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
354 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
344 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
355 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
345 // Correction of the index if the drop occurs in the same container
356 // Correction of the index if the drop occurs in the same container
346 // and if the drag is started from the visualization (in that case, the
357 // and if the drag is started from the visualization (in that case, the
347 // dragWidget is hidden)
358 // dragWidget is hidden)
348 dropIndex += 1;
359 dropIndex += 1;
349 }
360 }
350 }
361 }
351
362
352 if (dropIndex != placeHolderIndex) {
363 if (dropIndex != placeHolderIndex) {
353 helper.insertPlaceHolder(m_Layout, dropIndex);
364 helper.insertPlaceHolder(m_Layout, dropIndex);
354 }
365 }
355
366
356 helper.setHightlightedDragWidget(nullptr);
367 helper.setHightlightedDragWidget(nullptr);
357 }
368 }
358 else if (canMerge) {
369 else if (canMerge) {
359 // drop on the middle -> merge
370 // drop on the middle -> merge
360 if (hasPlaceHolder()) {
371 if (hasPlaceHolder()) {
361 helper.removePlaceHolder();
372 helper.removePlaceHolder();
362 }
373 }
363
374
364 helper.setHightlightedDragWidget(dragWidgetHovered);
375 helper.setHightlightedDragWidget(dragWidgetHovered);
365 }
376 }
366 }
377 }
367 else {
378 else {
368 qCWarning(LOG_VisualizationDragDropContainer())
379 qCWarning(LOG_VisualizationDragDropContainer())
369 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
380 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
370 "container");
381 "container");
371 }
382 }
372 }
383 }
373 else if (!hasPlaceHolder()) {
384 else if (!hasPlaceHolder()) {
374 // Drop on an empty container, just add the placeHolder at the top
385 // Drop on an empty container, just add the placeHolder at the top
375 helper.insertPlaceHolder(m_Layout, 0);
386 helper.insertPlaceHolder(m_Layout, 0);
376 }
387 }
377 else {
388 else {
378 // No hovered drag widget, the mouse is probably hover the placeHolder
389 // No hovered drag widget, the mouse is probably hover the placeHolder
379 // Do nothing
390 // Do nothing
380 }
391 }
381 }
392 }
@@ -1,300 +1,300
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 "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->setAcceptedMimeTypes(
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
74 &VisualizationTabWidget::dropMimeData);
74 &VisualizationTabWidget::dropMimeData);
75 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
75 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
76 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
76 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
77 ui->dragDropContainer);
77 ui->dragDropContainer);
78 });
78 });
79 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
79 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
80
80
81 // Widget is deleted when closed
81 // Widget is deleted when closed
82 setAttribute(Qt::WA_DeleteOnClose);
82 setAttribute(Qt::WA_DeleteOnClose);
83 }
83 }
84
84
85 VisualizationTabWidget::~VisualizationTabWidget()
85 VisualizationTabWidget::~VisualizationTabWidget()
86 {
86 {
87 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
87 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
88 delete ui;
88 delete ui;
89 }
89 }
90
90
91 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
91 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
92 {
92 {
93 ui->dragDropContainer->addDragWidget(zoneWidget);
93 ui->dragDropContainer->addDragWidget(zoneWidget);
94 }
94 }
95
95
96 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
96 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
97 {
97 {
98 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
98 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
99 }
99 }
100
100
101 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
101 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
102 {
102 {
103 return createZone({variable}, -1);
103 return createZone({variable}, -1);
104 }
104 }
105
105
106 VisualizationZoneWidget *
106 VisualizationZoneWidget *
107 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
107 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
108 {
108 {
109 auto zoneWidget = createEmptyZone(index);
109 auto zoneWidget = createEmptyZone(index);
110
110
111 // Creates a new graph into the zone
111 // Creates a new graph into the zone
112 zoneWidget->createGraph(variables, index);
112 zoneWidget->createGraph(variables, index);
113
113
114 return zoneWidget;
114 return zoneWidget;
115 }
115 }
116
116
117 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
117 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
118 {
118 {
119 auto zoneWidget
119 auto zoneWidget
120 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
120 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
121 this->insertZone(index, zoneWidget);
121 this->insertZone(index, zoneWidget);
122
122
123 return zoneWidget;
123 return zoneWidget;
124 }
124 }
125
125
126 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
126 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
127 {
127 {
128 if (visitor) {
128 if (visitor) {
129 visitor->visitEnter(this);
129 visitor->visitEnter(this);
130
130
131 // Apply visitor to zone children: widgets different from zones are not visited (no action)
131 // Apply visitor to zone children: widgets different from zones are not visited (no action)
132 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
132 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
133 zoneWidget.accept(visitor);
133 zoneWidget.accept(visitor);
134 });
134 });
135
135
136 visitor->visitLeave(this);
136 visitor->visitLeave(this);
137 }
137 }
138 else {
138 else {
139 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
139 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
140 }
140 }
141 }
141 }
142
142
143 bool VisualizationTabWidget::canDrop(const Variable &variable) const
143 bool VisualizationTabWidget::canDrop(const Variable &variable) const
144 {
144 {
145 // A tab can always accomodate a variable
145 // A tab can always accomodate a variable
146 Q_UNUSED(variable);
146 Q_UNUSED(variable);
147 return true;
147 return true;
148 }
148 }
149
149
150 bool VisualizationTabWidget::contains(const Variable &variable) const
150 bool VisualizationTabWidget::contains(const Variable &variable) const
151 {
151 {
152 Q_UNUSED(variable);
152 Q_UNUSED(variable);
153 return false;
153 return false;
154 }
154 }
155
155
156 QString VisualizationTabWidget::name() const
156 QString VisualizationTabWidget::name() const
157 {
157 {
158 return impl->m_Name;
158 return impl->m_Name;
159 }
159 }
160
160
161 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
161 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
162 {
162 {
163 // Closes zones in the tab
163 // Closes zones in the tab
164 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
164 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
165
165
166 QWidget::closeEvent(event);
166 QWidget::closeEvent(event);
167 }
167 }
168
168
169 QLayout &VisualizationTabWidget::tabLayout() const noexcept
169 QLayout &VisualizationTabWidget::tabLayout() const noexcept
170 {
170 {
171 return *ui->dragDropContainer->layout();
171 return *ui->dragDropContainer->layout();
172 }
172 }
173
173
174 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
174 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
175 {
175 {
176 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
176 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
177 impl->dropGraph(index, this);
177 impl->dropGraph(index, this);
178 }
178 }
179 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
179 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
180 impl->dropZone(index, this);
180 impl->dropZone(index, this);
181 }
181 }
182 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
182 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
183 auto variables = sqpApp->variableController().variablesForMimeData(
183 auto variables = sqpApp->variableController().variablesForMimeData(
184 mimeData->data(MIME_TYPE_VARIABLE_LIST));
184 mimeData->data(MIME_TYPE_VARIABLE_LIST));
185 impl->dropVariables(variables, index, this);
185 impl->dropVariables(variables, index, this);
186 }
186 }
187 else {
187 else {
188 qCWarning(LOG_VisualizationZoneWidget())
188 qCWarning(LOG_VisualizationZoneWidget())
189 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
189 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
190 }
190 }
191 }
191 }
192
192
193 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
193 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
194 int index, VisualizationTabWidget *tabWidget)
194 int index, VisualizationTabWidget *tabWidget)
195 {
195 {
196 auto &helper = sqpApp->dragDropHelper();
196 auto &helper = sqpApp->dragDropHelper();
197
197
198 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
198 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
199 if (!graphWidget) {
199 if (!graphWidget) {
200 qCWarning(LOG_VisualizationZoneWidget())
200 qCWarning(LOG_VisualizationZoneWidget())
201 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
201 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
202 "found or invalid.");
202 "found or invalid.");
203 Q_ASSERT(false);
203 Q_ASSERT(false);
204 return;
204 return;
205 }
205 }
206
206
207 auto parentDragDropContainer
207 auto parentDragDropContainer
208 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
208 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
209 if (!parentDragDropContainer) {
209 if (!parentDragDropContainer) {
210 qCWarning(LOG_VisualizationZoneWidget())
210 qCWarning(LOG_VisualizationZoneWidget())
211 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
211 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
212 "the dropped graph is not found.");
212 "the dropped graph is not found.");
213 Q_ASSERT(false);
213 Q_ASSERT(false);
214 return;
214 return;
215 }
215 }
216
216
217 auto nbGraph = parentDragDropContainer->countDragWidget();
217 auto nbGraph = parentDragDropContainer->countDragWidget();
218
218
219 const auto &variables = graphWidget->variables();
219 const auto &variables = graphWidget->variables();
220
220
221 if (!variables.isEmpty()) {
221 if (!variables.isEmpty()) {
222 // Abort the requests for the variables (if any)
222 // Abort the requests for the variables (if any)
223 // Commented, because it's not sure if it's needed or not
223 // Commented, because it's not sure if it's needed or not
224 // for (const auto& var : variables)
224 // for (const auto& var : variables)
225 //{
225 //{
226 // sqpApp->variableController().onAbortProgressRequested(var);
226 // sqpApp->variableController().onAbortProgressRequested(var);
227 //}
227 //}
228
228
229 if (nbGraph == 1) {
229 if (nbGraph == 1) {
230 // This is the only graph in the previous zone, close the zone
230 // This is the only graph in the previous zone, close the zone
231 graphWidget->parentZoneWidget()->close();
231 graphWidget->parentZoneWidget()->close();
232 }
232 }
233 else {
233 else {
234 // Close the graph
234 // Close the graph
235 graphWidget->close();
235 graphWidget->close();
236 }
236 }
237
237
238 tabWidget->createZone(variables, index);
238 tabWidget->createZone(variables, index);
239 }
239 }
240 else {
240 else {
241 // The graph is empty, create an empty zone and move the graph inside
241 // The graph is empty, create an empty zone and move the graph inside
242
242
243 auto parentZoneWidget = graphWidget->parentZoneWidget();
243 auto parentZoneWidget = graphWidget->parentZoneWidget();
244
244
245 parentDragDropContainer->layout()->removeWidget(graphWidget);
245 parentDragDropContainer->layout()->removeWidget(graphWidget);
246
246
247 auto zoneWidget = tabWidget->createEmptyZone(index);
247 auto zoneWidget = tabWidget->createEmptyZone(index);
248 zoneWidget->addGraph(graphWidget);
248 zoneWidget->addGraph(graphWidget);
249
249
250 // Close the old zone if it was the only graph inside
250 // Close the old zone if it was the only graph inside
251 if (nbGraph == 1) {
251 if (nbGraph == 1) {
252 parentZoneWidget->close();
252 parentZoneWidget->close();
253 }
253 }
254 }
254 }
255 }
255 }
256
256
257 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
257 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
258 int index, VisualizationTabWidget *tabWidget)
258 int index, VisualizationTabWidget *tabWidget)
259 {
259 {
260 auto &helper = sqpApp->dragDropHelper();
260 auto &helper = sqpApp->dragDropHelper();
261
261
262 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
262 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
263 if (!zoneWidget) {
263 if (!zoneWidget) {
264 qCWarning(LOG_VisualizationZoneWidget())
264 qCWarning(LOG_VisualizationZoneWidget())
265 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
265 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
266 "found or invalid.");
266 "found or invalid.");
267 Q_ASSERT(false);
267 Q_ASSERT(false);
268 return;
268 return;
269 }
269 }
270
270
271 auto parentDragDropContainer
271 auto parentDragDropContainer
272 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
272 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
273 if (!parentDragDropContainer) {
273 if (!parentDragDropContainer) {
274 qCWarning(LOG_VisualizationZoneWidget())
274 qCWarning(LOG_VisualizationZoneWidget())
275 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
275 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
276 "the dropped zone is not found.");
276 "the dropped zone is not found.");
277 Q_ASSERT(false);
277 Q_ASSERT(false);
278 return;
278 return;
279 }
279 }
280
280
281 // Simple move of the zone, no variable operation associated
281 // Simple move of the zone, no variable operation associated
282 parentDragDropContainer->layout()->removeWidget(zoneWidget);
282 parentDragDropContainer->layout()->removeWidget(zoneWidget);
283 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
283 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
284 }
284 }
285
285
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
287 const QList<std::shared_ptr<Variable> > &variables, int index,
287 const QList<std::shared_ptr<Variable> > &variables, int index,
288 VisualizationTabWidget *tabWidget)
288 VisualizationTabWidget *tabWidget)
289 {
289 {
290 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
290 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
291 // compatible variable here
291 // compatible variable here
292 if (variables.count() > 1) {
292 if (variables.count() > 1) {
293 qCWarning(LOG_VisualizationZoneWidget())
293 qCWarning(LOG_VisualizationZoneWidget())
294 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
294 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
295 "aborted.");
295 "aborted.");
296 return;
296 return;
297 }
297 }
298
298
299 tabWidget->createZone(variables, index);
299 tabWidget->createZone(variables, index);
300 }
300 }
@@ -1,469 +1,497
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 <Variable/Variable.h>
13 #include <Variable/Variable.h>
14 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
15
15
16 #include <Visualization/operations/FindVariableOperation.h>
16 #include <Visualization/operations/FindVariableOperation.h>
17
17
18 #include <DragDropHelper.h>
18 #include <DragDropHelper.h>
19 #include <QUuid>
19 #include <QUuid>
20 #include <SqpApplication.h>
20 #include <SqpApplication.h>
21 #include <cmath>
21 #include <cmath>
22
22
23 #include <QLayout>
23 #include <QLayout>
24
24
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
25 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26
26
27 namespace {
27 namespace {
28
28
29
29
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// the zone
31 /// the zone
32 QString defaultGraphName(const QLayout &layout)
32 QString defaultGraphName(const QLayout &layout)
33 {
33 {
34 auto count = 0;
34 auto count = 0;
35 for (auto i = 0; i < layout.count(); ++i) {
35 for (auto i = 0; i < layout.count(); ++i) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
36 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 count++;
37 count++;
38 }
38 }
39 }
39 }
40
40
41 return QObject::tr("Graph %1").arg(count + 1);
41 return QObject::tr("Graph %1").arg(count + 1);
42 }
42 }
43
43
44 /**
44 /**
45 * Applies a function to all graphs of the zone represented by its layout
45 * Applies a function to all graphs of the zone represented by its layout
46 * @param layout the layout that contains graphs
46 * @param layout the layout that contains graphs
47 * @param fun the function to apply to each graph
47 * @param fun the function to apply to each graph
48 */
48 */
49 template <typename Fun>
49 template <typename Fun>
50 void processGraphs(QLayout &layout, Fun fun)
50 void processGraphs(QLayout &layout, Fun fun)
51 {
51 {
52 for (auto i = 0; i < layout.count(); ++i) {
52 for (auto i = 0; i < layout.count(); ++i) {
53 if (auto item = layout.itemAt(i)) {
53 if (auto item = layout.itemAt(i)) {
54 if (auto visualizationGraphWidget
54 if (auto visualizationGraphWidget
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
55 = dynamic_cast<VisualizationGraphWidget *>(item->widget())) {
56 fun(*visualizationGraphWidget);
56 fun(*visualizationGraphWidget);
57 }
57 }
58 }
58 }
59 }
59 }
60 }
60 }
61
61
62 } // namespace
62 } // namespace
63
63
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
64 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65
65
66 explicit VisualizationZoneWidgetPrivate()
66 explicit VisualizationZoneWidgetPrivate()
67 : m_SynchronisationGroupId{QUuid::createUuid()},
67 : m_SynchronisationGroupId{QUuid::createUuid()},
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
68 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 {
69 {
70 }
70 }
71 QUuid m_SynchronisationGroupId;
71 QUuid m_SynchronisationGroupId;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73
73
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 VisualizationZoneWidget *zoneWidget);
76 VisualizationZoneWidget *zoneWidget);
77 };
77 };
78
78
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
80 : VisualizationDragWidget{parent},
80 : VisualizationDragWidget{parent},
81 ui{new Ui::VisualizationZoneWidget},
81 ui{new Ui::VisualizationZoneWidget},
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
82 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
83 {
83 {
84 ui->setupUi(this);
84 ui->setupUi(this);
85
85
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->setMergeAllowedMimeTypes({MIME_TYPE_VARIABLE_LIST});
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
92 ui->dragDropContainer);
92 ui->dragDropContainer);
93 });
93 });
94 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
94
95 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
95 &VisualizationZoneWidget::dropMimeData);
96 &VisualizationZoneWidget::dropMimeData);
97 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
98 &VisualizationZoneWidget::dropMimeDataOnGraph);
96
99
97 // 'Close' options : widget is deleted when closed
100 // 'Close' options : widget is deleted when closed
98 setAttribute(Qt::WA_DeleteOnClose);
101 setAttribute(Qt::WA_DeleteOnClose);
99 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
102 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
100 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
103 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
101
104
102 // Synchronisation id
105 // Synchronisation id
103 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
106 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
104 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
107 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
105 }
108 }
106
109
107 VisualizationZoneWidget::~VisualizationZoneWidget()
110 VisualizationZoneWidget::~VisualizationZoneWidget()
108 {
111 {
109 delete ui;
112 delete ui;
110 }
113 }
111
114
112 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
115 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
113 {
116 {
114 // Synchronize new graph with others in the zone
117 // Synchronize new graph with others in the zone
115 impl->m_Synchronizer->addGraph(*graphWidget);
118 impl->m_Synchronizer->addGraph(*graphWidget);
116
119
117 ui->dragDropContainer->addDragWidget(graphWidget);
120 ui->dragDropContainer->addDragWidget(graphWidget);
118 }
121 }
119
122
120 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
123 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
121 {
124 {
122 // Synchronize new graph with others in the zone
125 // Synchronize new graph with others in the zone
123 impl->m_Synchronizer->addGraph(*graphWidget);
126 impl->m_Synchronizer->addGraph(*graphWidget);
124
127
125 ui->dragDropContainer->insertDragWidget(index, graphWidget);
128 ui->dragDropContainer->insertDragWidget(index, graphWidget);
126 }
129 }
127
130
128 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
131 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
129 {
132 {
130 return createGraph(variable, -1);
133 return createGraph(variable, -1);
131 }
134 }
132
135
133 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
136 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
134 int index)
137 int index)
135 {
138 {
136 auto graphWidget
139 auto graphWidget
137 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
140 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
138
141
139
142
140 // Set graph properties
143 // Set graph properties
141 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
144 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
142 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
145 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
143
146
144
147
145 // Lambda to synchronize zone widget
148 // Lambda to synchronize zone widget
146 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
149 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
147 const SqpRange &oldGraphRange) {
150 const SqpRange &oldGraphRange) {
148
151
149 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
152 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
150 auto frameLayout = ui->dragDropContainer->layout();
153 auto frameLayout = ui->dragDropContainer->layout();
151 for (auto i = 0; i < frameLayout->count(); ++i) {
154 for (auto i = 0; i < frameLayout->count(); ++i) {
152 auto graphChild
155 auto graphChild
153 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
156 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
154 if (graphChild && (graphChild != graphWidget)) {
157 if (graphChild && (graphChild != graphWidget)) {
155
158
156 auto graphChildRange = graphChild->graphRange();
159 auto graphChildRange = graphChild->graphRange();
157 switch (zoomType) {
160 switch (zoomType) {
158 case AcquisitionZoomType::ZoomIn: {
161 case AcquisitionZoomType::ZoomIn: {
159 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
162 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
160 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
163 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
161 graphChildRange.m_TStart += deltaLeft;
164 graphChildRange.m_TStart += deltaLeft;
162 graphChildRange.m_TEnd -= deltaRight;
165 graphChildRange.m_TEnd -= deltaRight;
163 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
166 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
164 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
167 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
165 << deltaLeft;
168 << deltaLeft;
166 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
169 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
167 << deltaRight;
170 << deltaRight;
168 qCDebug(LOG_VisualizationZoneWidget())
171 qCDebug(LOG_VisualizationZoneWidget())
169 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
172 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
170
173
171 break;
174 break;
172 }
175 }
173
176
174 case AcquisitionZoomType::ZoomOut: {
177 case AcquisitionZoomType::ZoomOut: {
175 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
178 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
176 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
179 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
177 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
180 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
178 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
181 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
179 << deltaLeft;
182 << deltaLeft;
180 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
183 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
181 << deltaRight;
184 << deltaRight;
182 qCDebug(LOG_VisualizationZoneWidget())
185 qCDebug(LOG_VisualizationZoneWidget())
183 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
186 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
184 graphChildRange.m_TStart -= deltaLeft;
187 graphChildRange.m_TStart -= deltaLeft;
185 graphChildRange.m_TEnd += deltaRight;
188 graphChildRange.m_TEnd += deltaRight;
186 break;
189 break;
187 }
190 }
188 case AcquisitionZoomType::PanRight: {
191 case AcquisitionZoomType::PanRight: {
189 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
192 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
190 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
193 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
191 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
194 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
192 graphChildRange.m_TStart += deltaLeft;
195 graphChildRange.m_TStart += deltaLeft;
193 graphChildRange.m_TEnd += deltaRight;
196 graphChildRange.m_TEnd += deltaRight;
194 qCDebug(LOG_VisualizationZoneWidget())
197 qCDebug(LOG_VisualizationZoneWidget())
195 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
198 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
196 break;
199 break;
197 }
200 }
198 case AcquisitionZoomType::PanLeft: {
201 case AcquisitionZoomType::PanLeft: {
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
200 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
203 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
201 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
204 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
202 graphChildRange.m_TStart -= deltaLeft;
205 graphChildRange.m_TStart -= deltaLeft;
203 graphChildRange.m_TEnd -= deltaRight;
206 graphChildRange.m_TEnd -= deltaRight;
204 break;
207 break;
205 }
208 }
206 case AcquisitionZoomType::Unknown: {
209 case AcquisitionZoomType::Unknown: {
207 qCDebug(LOG_VisualizationZoneWidget())
210 qCDebug(LOG_VisualizationZoneWidget())
208 << tr("Impossible to synchronize: zoom type unknown");
211 << tr("Impossible to synchronize: zoom type unknown");
209 break;
212 break;
210 }
213 }
211 default:
214 default:
212 qCCritical(LOG_VisualizationZoneWidget())
215 qCCritical(LOG_VisualizationZoneWidget())
213 << tr("Impossible to synchronize: zoom type not take into account");
216 << tr("Impossible to synchronize: zoom type not take into account");
214 // No action
217 // No action
215 break;
218 break;
216 }
219 }
217 graphChild->enableAcquisition(false);
220 graphChild->enableAcquisition(false);
218 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
221 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
219 << graphChild->graphRange();
222 << graphChild->graphRange();
220 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
223 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
221 << graphChildRange;
224 << graphChildRange;
222 qCDebug(LOG_VisualizationZoneWidget())
225 qCDebug(LOG_VisualizationZoneWidget())
223 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
226 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
224 graphChild->setGraphRange(graphChildRange);
227 graphChild->setGraphRange(graphChildRange);
225 graphChild->enableAcquisition(true);
228 graphChild->enableAcquisition(true);
226 }
229 }
227 }
230 }
228 };
231 };
229
232
230 // connection for synchronization
233 // connection for synchronization
231 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
234 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
232 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
235 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
233 &VisualizationZoneWidget::onVariableAdded);
236 &VisualizationZoneWidget::onVariableAdded);
234 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
237 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
235 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
238 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
236
239
237 auto range = SqpRange{};
240 auto range = SqpRange{};
238
241
239 // Apply visitor to graph children
242 // Apply visitor to graph children
240 auto layout = ui->dragDropContainer->layout();
243 auto layout = ui->dragDropContainer->layout();
241 if (layout->count() > 0) {
244 if (layout->count() > 0) {
242 // Case of a new graph in a existant zone
245 // Case of a new graph in a existant zone
243 if (auto visualizationGraphWidget
246 if (auto visualizationGraphWidget
244 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
247 = dynamic_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
245 range = visualizationGraphWidget->graphRange();
248 range = visualizationGraphWidget->graphRange();
246 }
249 }
247 }
250 }
248 else {
251 else {
249 // Case of a new graph as the first of the zone
252 // Case of a new graph as the first of the zone
250 range = variable->range();
253 range = variable->range();
251 }
254 }
252
255
253 this->insertGraph(index, graphWidget);
256 this->insertGraph(index, graphWidget);
254
257
255 graphWidget->addVariable(variable, range);
258 graphWidget->addVariable(variable, range);
256
259
257 // get y using variable range
260 // get y using variable range
258 if (auto dataSeries = variable->dataSeries()) {
261 if (auto dataSeries = variable->dataSeries()) {
259 dataSeries->lockRead();
262 dataSeries->lockRead();
260 auto valuesBounds
263 auto valuesBounds
261 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
264 = dataSeries->valuesBounds(variable->range().m_TStart, variable->range().m_TEnd);
262 auto end = dataSeries->cend();
265 auto end = dataSeries->cend();
263 if (valuesBounds.first != end && valuesBounds.second != end) {
266 if (valuesBounds.first != end && valuesBounds.second != end) {
264 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
267 auto rangeValue = [](const auto &value) { return std::isnan(value) ? 0. : value; };
265
268
266 auto minValue = rangeValue(valuesBounds.first->minValue());
269 auto minValue = rangeValue(valuesBounds.first->minValue());
267 auto maxValue = rangeValue(valuesBounds.second->maxValue());
270 auto maxValue = rangeValue(valuesBounds.second->maxValue());
268
271
269 graphWidget->setYRange(SqpRange{minValue, maxValue});
272 graphWidget->setYRange(SqpRange{minValue, maxValue});
270 }
273 }
271 dataSeries->unlock();
274 dataSeries->unlock();
272 }
275 }
273
276
274 return graphWidget;
277 return graphWidget;
275 }
278 }
276
279
277 VisualizationGraphWidget *
280 VisualizationGraphWidget *
278 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
281 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
279 {
282 {
280 if (variables.isEmpty()) {
283 if (variables.isEmpty()) {
281 return nullptr;
284 return nullptr;
282 }
285 }
283
286
284 auto graphWidget = createGraph(variables.first(), index);
287 auto graphWidget = createGraph(variables.first(), index);
285 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
288 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
286 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
289 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
287 }
290 }
288
291
289 return graphWidget;
292 return graphWidget;
290 }
293 }
291
294
292 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
295 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
293 {
296 {
294 if (visitor) {
297 if (visitor) {
295 visitor->visitEnter(this);
298 visitor->visitEnter(this);
296
299
297 // Apply visitor to graph children: widgets different from graphs are not visited (no
300 // Apply visitor to graph children: widgets different from graphs are not visited (no
298 // action)
301 // action)
299 processGraphs(
302 processGraphs(
300 *ui->dragDropContainer->layout(),
303 *ui->dragDropContainer->layout(),
301 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
304 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
302
305
303 visitor->visitLeave(this);
306 visitor->visitLeave(this);
304 }
307 }
305 else {
308 else {
306 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
309 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
307 }
310 }
308 }
311 }
309
312
310 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
313 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
311 {
314 {
312 // A tab can always accomodate a variable
315 // A tab can always accomodate a variable
313 Q_UNUSED(variable);
316 Q_UNUSED(variable);
314 return true;
317 return true;
315 }
318 }
316
319
317 bool VisualizationZoneWidget::contains(const Variable &variable) const
320 bool VisualizationZoneWidget::contains(const Variable &variable) const
318 {
321 {
319 Q_UNUSED(variable);
322 Q_UNUSED(variable);
320 return false;
323 return false;
321 }
324 }
322
325
323 QString VisualizationZoneWidget::name() const
326 QString VisualizationZoneWidget::name() const
324 {
327 {
325 return ui->zoneNameLabel->text();
328 return ui->zoneNameLabel->text();
326 }
329 }
327
330
328 QMimeData *VisualizationZoneWidget::mimeData() const
331 QMimeData *VisualizationZoneWidget::mimeData() const
329 {
332 {
330 auto mimeData = new QMimeData;
333 auto mimeData = new QMimeData;
331 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
334 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
332
335
333 return mimeData;
336 return mimeData;
334 }
337 }
335
338
336 bool VisualizationZoneWidget::isDragAllowed() const
339 bool VisualizationZoneWidget::isDragAllowed() const
337 {
340 {
338 return true;
341 return true;
339 }
342 }
340
343
341 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
344 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
342 {
345 {
343 // Closes graphs in the zone
346 // Closes graphs in the zone
344 processGraphs(*ui->dragDropContainer->layout(),
347 processGraphs(*ui->dragDropContainer->layout(),
345 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
348 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
346
349
347 // Delete synchronization group from variable controller
350 // Delete synchronization group from variable controller
348 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
351 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
349 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
352 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
350
353
351 QWidget::closeEvent(event);
354 QWidget::closeEvent(event);
352 }
355 }
353
356
354 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
357 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
355 {
358 {
356 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
359 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
357 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
360 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
358 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
361 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
359 }
362 }
360
363
361 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
364 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
362 {
365 {
363 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
366 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
364 Q_ARG(std::shared_ptr<Variable>, variable),
367 Q_ARG(std::shared_ptr<Variable>, variable),
365 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
368 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
366 }
369 }
367
370
368 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
371 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
369 {
372 {
370 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
373 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
371 impl->dropGraph(index, this);
374 impl->dropGraph(index, this);
372 }
375 }
373 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
376 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
374 auto variables = sqpApp->variableController().variablesForMimeData(
377 auto variables = sqpApp->variableController().variablesForMimeData(
375 mimeData->data(MIME_TYPE_VARIABLE_LIST));
378 mimeData->data(MIME_TYPE_VARIABLE_LIST));
376 impl->dropVariables(variables, index, this);
379 impl->dropVariables(variables, index, this);
377 }
380 }
378 else {
381 else {
379 qCWarning(LOG_VisualizationZoneWidget())
382 qCWarning(LOG_VisualizationZoneWidget())
380 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
383 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
381 }
384 }
382 }
385 }
383
386
387 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
388 const QMimeData *mimeData)
389 {
390 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
391 if (!graphWidget) {
392 qCWarning(LOG_VisualizationZoneWidget())
393 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
394 "drop aborted");
395 Q_ASSERT(false);
396 return;
397 }
398
399 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
400 auto variables = sqpApp->variableController().variablesForMimeData(
401 mimeData->data(MIME_TYPE_VARIABLE_LIST));
402 for (const auto &var : variables) {
403 graphWidget->addVariable(var, graphWidget->graphRange());
404 }
405 }
406 else {
407 qCWarning(LOG_VisualizationZoneWidget())
408 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
409 }
410 }
411
384 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
412 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
385 int index, VisualizationZoneWidget *zoneWidget)
413 int index, VisualizationZoneWidget *zoneWidget)
386 {
414 {
387 auto &helper = sqpApp->dragDropHelper();
415 auto &helper = sqpApp->dragDropHelper();
388
416
389 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
417 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
390 if (!graphWidget) {
418 if (!graphWidget) {
391 qCWarning(LOG_VisualizationZoneWidget())
419 qCWarning(LOG_VisualizationZoneWidget())
392 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
420 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
393 "found or invalid.");
421 "found or invalid.");
394 Q_ASSERT(false);
422 Q_ASSERT(false);
395 return;
423 return;
396 }
424 }
397
425
398 auto parentDragDropContainer
426 auto parentDragDropContainer
399 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
427 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
400 if (!parentDragDropContainer) {
428 if (!parentDragDropContainer) {
401 qCWarning(LOG_VisualizationZoneWidget())
429 qCWarning(LOG_VisualizationZoneWidget())
402 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
430 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
403 "the dropped graph is not found.");
431 "the dropped graph is not found.");
404 Q_ASSERT(false);
432 Q_ASSERT(false);
405 return;
433 return;
406 }
434 }
407
435
408 const auto &variables = graphWidget->variables();
436 const auto &variables = graphWidget->variables();
409
437
410 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
438 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
411 // The drop didn't occur in the same zone
439 // The drop didn't occur in the same zone
412
440
413 // Abort the requests for the variables (if any)
441 // Abort the requests for the variables (if any)
414 // Commented, because it's not sure if it's needed or not
442 // Commented, because it's not sure if it's needed or not
415 // for (const auto& var : variables)
443 // for (const auto& var : variables)
416 //{
444 //{
417 // sqpApp->variableController().onAbortProgressRequested(var);
445 // sqpApp->variableController().onAbortProgressRequested(var);
418 //}
446 //}
419
447
420 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
448 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
421 auto nbGraph = parentDragDropContainer->countDragWidget();
449 auto nbGraph = parentDragDropContainer->countDragWidget();
422 if (nbGraph == 1) {
450 if (nbGraph == 1) {
423 // This is the only graph in the previous zone, close the zone
451 // This is the only graph in the previous zone, close the zone
424 previousParentZoneWidget->close();
452 previousParentZoneWidget->close();
425 }
453 }
426 else {
454 else {
427 // Close the graph
455 // Close the graph
428 graphWidget->close();
456 graphWidget->close();
429 }
457 }
430
458
431 // Creates the new graph in the zone
459 // Creates the new graph in the zone
432 zoneWidget->createGraph(variables, index);
460 zoneWidget->createGraph(variables, index);
433 }
461 }
434 else {
462 else {
435 // The drop occurred in the same zone or the graph is empty
463 // The drop occurred in the same zone or the graph is empty
436 // Simple move of the graph, no variable operation associated
464 // Simple move of the graph, no variable operation associated
437 parentDragDropContainer->layout()->removeWidget(graphWidget);
465 parentDragDropContainer->layout()->removeWidget(graphWidget);
438
466
439 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
467 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
440 // The graph is empty and dropped in a different zone.
468 // The graph is empty and dropped in a different zone.
441 // Take the range of the first graph in the zone (if existing).
469 // Take the range of the first graph in the zone (if existing).
442 auto layout = zoneWidget->ui->dragDropContainer->layout();
470 auto layout = zoneWidget->ui->dragDropContainer->layout();
443 if (layout->count() > 0) {
471 if (layout->count() > 0) {
444 if (auto visualizationGraphWidget
472 if (auto visualizationGraphWidget
445 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
473 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
446 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
474 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
447 }
475 }
448 }
476 }
449 }
477 }
450
478
451 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
479 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
452 }
480 }
453 }
481 }
454
482
455 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
483 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
456 const QList<std::shared_ptr<Variable> > &variables, int index,
484 const QList<std::shared_ptr<Variable> > &variables, int index,
457 VisualizationZoneWidget *zoneWidget)
485 VisualizationZoneWidget *zoneWidget)
458 {
486 {
459 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
487 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
460 // compatible variable here
488 // compatible variable here
461 if (variables.count() > 1) {
489 if (variables.count() > 1) {
462 qCWarning(LOG_VisualizationZoneWidget())
490 qCWarning(LOG_VisualizationZoneWidget())
463 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
491 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
464 "aborted.");
492 "aborted.");
465 return;
493 return;
466 }
494 }
467
495
468 zoneWidget->createGraph(variables, index);
496 zoneWidget->createGraph(variables, index);
469 }
497 }
General Comments 3
Under Review
author

Pull request updated. Auto status change to "Under Review"

Changed commits:
  * 1 added
  * 0 removed

Changed files:
  * A core/tests/meson.build
You need to be logged in to leave comments. Login now