##// END OF EJS Templates
Rename "DragDropHelper" in "DragDropGuiController"
trabillard -
r1110:029fbf916457
parent child
Show More
@@ -1,75 +1,75
1 #ifndef SCIQLOP_DRAGDROPHELPER_H
1 #ifndef SCIQLOP_DRAGDROPGUICONTROLLER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPGUICONTROLLER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QLoggingCategory>
6 #include <QWidget>
6 #include <QWidget>
7
7
8 class QVBoxLayout;
8 class QVBoxLayout;
9 class QScrollArea;
9 class QScrollArea;
10 class QTabBar;
10 class QTabBar;
11 class VisualizationDragWidget;
11 class VisualizationDragWidget;
12 class VisualizationDragDropContainer;
12 class VisualizationDragDropContainer;
13 class QMimeData;
13 class QMimeData;
14
14
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
15 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropGuiController)
16
16
17 /**
17 /**
18 * @brief Helper class for drag&drop operations.
18 * @brief Helper class for drag&drop operations.
19 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
19 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
20 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
21 * can interect with the gui.
21 * can interect with the gui.
22 * @see SqpApplication
22 * @see SqpApplication
23 */
23 */
24 class DragDropHelper {
24 class DragDropGuiController {
25 public:
25 public:
26 static const QString MIME_TYPE_GRAPH;
26 static const QString MIME_TYPE_GRAPH;
27 static const QString MIME_TYPE_ZONE;
27 static const QString MIME_TYPE_ZONE;
28
28
29 enum class PlaceHolderType { Default, Graph, Zone };
29 enum class PlaceHolderType { Default, Graph, Zone };
30
30
31 DragDropHelper();
31 DragDropGuiController();
32 virtual ~DragDropHelper();
32 virtual ~DragDropGuiController();
33
33
34 /// Resets some internal variables. Must be called before any new drag&drop operation.
34 /// Resets some internal variables. Must be called before any new drag&drop operation.
35 void resetDragAndDrop();
35 void resetDragAndDrop();
36
36
37 /// Sets the visualization widget currently being drag on the visualization.
37 /// Sets the visualization widget currently being drag on the visualization.
38 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
38 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
39
39
40 /// Returns the visualization widget currently being drag on the visualization.
40 /// Returns the visualization widget currently being drag on the visualization.
41 /// Can be null if a new visualization widget is intended to be created by the drag&drop
41 /// Can be null if a new visualization widget is intended to be created by the drag&drop
42 /// operation.
42 /// operation.
43 VisualizationDragWidget *getCurrentDragWidget() const;
43 VisualizationDragWidget *getCurrentDragWidget() const;
44
44
45 QWidget &placeHolder() const;
45 QWidget &placeHolder() const;
46 void insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
46 void insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
47 const QString &topLabelText);
47 const QString &topLabelText);
48 void removePlaceHolder();
48 void removePlaceHolder();
49 bool isPlaceHolderSet() const;
49 bool isPlaceHolderSet() const;
50
50
51 /// Checks if the specified mime data is valid for a drop in the visualization
51 /// Checks if the specified mime data is valid for a drop in the visualization
52 bool checkMimeDataForVisualization(const QMimeData *mimeData,
52 bool checkMimeDataForVisualization(const QMimeData *mimeData,
53 VisualizationDragDropContainer *dropContainer);
53 VisualizationDragDropContainer *dropContainer);
54
54
55 void addDragDropScrollArea(QScrollArea *scrollArea);
55 void addDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
57
57
58 void addDragDropTabBar(QTabBar *tabBar);
58 void addDragDropTabBar(QTabBar *tabBar);
59 void removeDragDropTabBar(QTabBar *tabBar);
59 void removeDragDropTabBar(QTabBar *tabBar);
60
60
61 QUrl imageTemporaryUrl(const QImage &image) const;
61 QUrl imageTemporaryUrl(const QImage &image) const;
62
62
63 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
63 void setHightlightedDragWidget(VisualizationDragWidget *dragWidget);
64 VisualizationDragWidget *getHightlightedDragWidget() const;
64 VisualizationDragWidget *getHightlightedDragWidget() const;
65
65
66 /// Delays the closing of a widget during a drag&drop operation
66 /// Delays the closing of a widget during a drag&drop operation
67 void delayedCloseWidget(QWidget *widget);
67 void delayedCloseWidget(QWidget *widget);
68 void doCloseWidgets();
68 void doCloseWidgets();
69
69
70 private:
70 private:
71 class DragDropHelperPrivate;
71 class DragDropGuiControllerPrivate;
72 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
72 spimpl::unique_impl_ptr<DragDropGuiControllerPrivate> impl;
73 };
73 };
74
74
75 #endif // SCIQLOP_DRAGDROPHELPER_H
75 #endif // SCIQLOP_DRAGDROPGUICONTROLLER_H
@@ -1,67 +1,67
1 #ifndef SCIQLOP_SQPAPPLICATION_H
1 #ifndef SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
2 #define SCIQLOP_SQPAPPLICATION_H
3
3
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5
5
6 #include <QApplication>
6 #include <QApplication>
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8
8
9 #include <Common/spimpl.h>
9 #include <Common/spimpl.h>
10
10
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
11 Q_DECLARE_LOGGING_CATEGORY(LOG_SqpApplication)
12
12
13 #if defined(sqpApp)
13 #if defined(sqpApp)
14 #undef sqpApp
14 #undef sqpApp
15 #endif
15 #endif
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
16 #define sqpApp (static_cast<SqpApplication *>(QCoreApplication::instance()))
17
17
18 class DataSourceController;
18 class DataSourceController;
19 class NetworkController;
19 class NetworkController;
20 class TimeController;
20 class TimeController;
21 class VariableController;
21 class VariableController;
22 class VisualizationController;
22 class VisualizationController;
23 class DragDropHelper;
23 class DragDropGuiController;
24
24
25 /**
25 /**
26 * @brief The SqpApplication class aims to make the link between SciQlop
26 * @brief The SqpApplication class aims to make the link between SciQlop
27 * and its plugins. This is the intermediate class that SciQlop has to use
27 * and its plugins. This is the intermediate class that SciQlop has to use
28 * in the way to connect a data source. Please first use load method to initialize
28 * in the way to connect a data source. Please first use load method to initialize
29 * a plugin specified by its metadata name (JSON plugin source) then others specifics
29 * a plugin specified by its metadata name (JSON plugin source) then others specifics
30 * method will be able to access it.
30 * method will be able to access it.
31 * You can load a data source driver plugin then create a data source.
31 * You can load a data source driver plugin then create a data source.
32 */
32 */
33
33
34 class SqpApplication : public QApplication {
34 class SqpApplication : public QApplication {
35 Q_OBJECT
35 Q_OBJECT
36 public:
36 public:
37 explicit SqpApplication(int &argc, char **argv);
37 explicit SqpApplication(int &argc, char **argv);
38 virtual ~SqpApplication();
38 virtual ~SqpApplication();
39 void initialize();
39 void initialize();
40
40
41 /// Accessors for the differents sciqlop controllers
41 /// Accessors for the differents sciqlop controllers
42 DataSourceController &dataSourceController() noexcept;
42 DataSourceController &dataSourceController() noexcept;
43 NetworkController &networkController() noexcept;
43 NetworkController &networkController() noexcept;
44 TimeController &timeController() noexcept;
44 TimeController &timeController() noexcept;
45 VariableController &variableController() noexcept;
45 VariableController &variableController() noexcept;
46 VisualizationController &visualizationController() noexcept;
46 VisualizationController &visualizationController() noexcept;
47
47
48 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
48 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
49 /// doesn't live in a thread and access gui
49 /// doesn't live in a thread and access gui
50 DragDropHelper &dragDropHelper() noexcept;
50 DragDropGuiController &dragDropGuiController() noexcept;
51
51
52 enum class PlotsInteractionMode { None, ZoomBox, DragAndDrop, SelectionZones };
52 enum class PlotsInteractionMode { None, ZoomBox, DragAndDrop, SelectionZones };
53
53
54 enum class PlotsCursorMode { NoCursor, Vertical, Temporal, Horizontal, Cross };
54 enum class PlotsCursorMode { NoCursor, Vertical, Temporal, Horizontal, Cross };
55
55
56 PlotsInteractionMode plotsInteractionMode() const;
56 PlotsInteractionMode plotsInteractionMode() const;
57 void setPlotsInteractionMode(PlotsInteractionMode mode);
57 void setPlotsInteractionMode(PlotsInteractionMode mode);
58
58
59 PlotsCursorMode plotsCursorMode() const;
59 PlotsCursorMode plotsCursorMode() const;
60 void setPlotsCursorMode(PlotsCursorMode mode);
60 void setPlotsCursorMode(PlotsCursorMode mode);
61
61
62 private:
62 private:
63 class SqpApplicationPrivate;
63 class SqpApplicationPrivate;
64 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
64 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
65 };
65 };
66
66
67 #endif // SCIQLOP_SQPAPPLICATION_H
67 #endif // SCIQLOP_SQPAPPLICATION_H
@@ -1,61 +1,61
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
1 #ifndef SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QFrame>
5 #include <QFrame>
6 #include <QLoggingCategory>
6 #include <QLoggingCategory>
7 #include <QMimeData>
7 #include <QMimeData>
8 #include <QVBoxLayout>
8 #include <QVBoxLayout>
9
9
10 #include <functional>
10 #include <functional>
11
11
12 #include <DragAndDrop/DragDropHelper.h>
12 #include <DragAndDrop/DragDropGuiController.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
15
15
16 class VisualizationDragWidget;
16 class VisualizationDragWidget;
17
17
18 class VisualizationDragDropContainer : public QFrame {
18 class VisualizationDragDropContainer : public QFrame {
19 Q_OBJECT
19 Q_OBJECT
20
20
21 signals:
21 signals:
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
22 void dropOccuredInContainer(int dropIndex, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
23 void dropOccuredOnWidget(VisualizationDragWidget *dragWidget, const QMimeData *mimeData);
24
24
25 public:
25 public:
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged, Forbidden };
26 enum class DropBehavior { Inserted, Merged, InsertedAndMerged, Forbidden };
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
27 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
28 using AcceptDragWidgetFunction
28 using AcceptDragWidgetFunction
29 = std::function<bool(const VisualizationDragWidget *dragWidget, const QMimeData *mimeData)>;
29 = std::function<bool(const VisualizationDragWidget *dragWidget, const QMimeData *mimeData)>;
30
30
31 VisualizationDragDropContainer(QWidget *parent = nullptr);
31 VisualizationDragDropContainer(QWidget *parent = nullptr);
32
32
33 void addDragWidget(VisualizationDragWidget *dragWidget);
33 void addDragWidget(VisualizationDragWidget *dragWidget);
34 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
34 void insertDragWidget(int index, VisualizationDragWidget *dragWidget);
35
35
36 void setMimeType(const QString &mimeType, DropBehavior behavior);
36 void setMimeType(const QString &mimeType, DropBehavior behavior);
37
37
38 int countDragWidget() const;
38 int countDragWidget() const;
39
39
40 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
40 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
41
41
42 void setAcceptDragWidgetFunction(AcceptDragWidgetFunction fun);
42 void setAcceptDragWidgetFunction(AcceptDragWidgetFunction fun);
43
43
44 void setPlaceHolderType(DragDropHelper::PlaceHolderType type,
44 void setPlaceHolderType(DragDropGuiController::PlaceHolderType type,
45 const QString &placeHolderText = QString());
45 const QString &placeHolderText = QString());
46
46
47 protected:
47 protected:
48 void dragEnterEvent(QDragEnterEvent *event);
48 void dragEnterEvent(QDragEnterEvent *event);
49 void dragLeaveEvent(QDragLeaveEvent *event);
49 void dragLeaveEvent(QDragLeaveEvent *event);
50 void dragMoveEvent(QDragMoveEvent *event);
50 void dragMoveEvent(QDragMoveEvent *event);
51 void dropEvent(QDropEvent *event);
51 void dropEvent(QDropEvent *event);
52
52
53 private:
53 private:
54 class VisualizationDragDropContainerPrivate;
54 class VisualizationDragDropContainerPrivate;
55 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
55 spimpl::unique_impl_ptr<VisualizationDragDropContainerPrivate> impl;
56
56
57 private slots:
57 private slots:
58 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
58 void startDrag(VisualizationDragWidget *dragWidget, const QPoint &dragPosition);
59 };
59 };
60
60
61 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
61 #endif // SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
@@ -1,47 +1,47
1 #include "DataSource/DataSourceTreeWidget.h"
1 #include "DataSource/DataSourceTreeWidget.h"
2 #include "Common/MimeTypesDef.h"
2 #include "Common/MimeTypesDef.h"
3 #include "DataSource/DataSourceController.h"
3 #include "DataSource/DataSourceController.h"
4 #include "DataSource/DataSourceItem.h"
4 #include "DataSource/DataSourceItem.h"
5 #include "DataSource/DataSourceTreeWidgetItem.h"
5 #include "DataSource/DataSourceTreeWidgetItem.h"
6
6
7 #include "DragAndDrop/DragDropHelper.h"
7 #include "DragAndDrop/DragDropGuiController.h"
8 #include "SqpApplication.h"
8 #include "SqpApplication.h"
9
9
10 #include <QMimeData>
10 #include <QMimeData>
11
11
12 DataSourceTreeWidget::DataSourceTreeWidget(QWidget *parent) : QTreeWidget(parent)
12 DataSourceTreeWidget::DataSourceTreeWidget(QWidget *parent) : QTreeWidget(parent)
13 {
13 {
14 }
14 }
15
15
16 QMimeData *DataSourceTreeWidget::mimeData(const QList<QTreeWidgetItem *> items) const
16 QMimeData *DataSourceTreeWidget::mimeData(const QList<QTreeWidgetItem *> items) const
17 {
17 {
18 auto mimeData = new QMimeData;
18 auto mimeData = new QMimeData;
19
19
20 // Basic check to ensure the item are correctly typed
20 // Basic check to ensure the item are correctly typed
21 Q_ASSERT(items.isEmpty() || dynamic_cast<DataSourceTreeWidgetItem *>(items.first()) != nullptr);
21 Q_ASSERT(items.isEmpty() || dynamic_cast<DataSourceTreeWidgetItem *>(items.first()) != nullptr);
22
22
23 QVariantList productData;
23 QVariantList productData;
24
24
25 for (auto item : items) {
25 for (auto item : items) {
26 auto dataSourceTreeItem = static_cast<DataSourceTreeWidgetItem *>(item);
26 auto dataSourceTreeItem = static_cast<DataSourceTreeWidgetItem *>(item);
27 auto dataSource = dataSourceTreeItem->data();
27 auto dataSource = dataSourceTreeItem->data();
28
28
29 if (dataSource->type() == DataSourceItemType::COMPONENT
29 if (dataSource->type() == DataSourceItemType::COMPONENT
30 || dataSource->type() == DataSourceItemType::PRODUCT) {
30 || dataSource->type() == DataSourceItemType::PRODUCT) {
31 auto metaData = dataSource->data();
31 auto metaData = dataSource->data();
32 productData << metaData;
32 productData << metaData;
33 }
33 }
34 }
34 }
35
35
36 auto encodedData = sqpApp->dataSourceController().mimeDataForProductsData(productData);
36 auto encodedData = sqpApp->dataSourceController().mimeDataForProductsData(productData);
37 mimeData->setData(MIME_TYPE_PRODUCT_LIST, encodedData);
37 mimeData->setData(MIME_TYPE_PRODUCT_LIST, encodedData);
38
38
39 return mimeData;
39 return mimeData;
40 }
40 }
41
41
42 void DataSourceTreeWidget::startDrag(Qt::DropActions supportedActions)
42 void DataSourceTreeWidget::startDrag(Qt::DropActions supportedActions)
43 {
43 {
44 // Resets the drag&drop operations before it's starting
44 // Resets the drag&drop operations before it's starting
45 sqpApp->dragDropHelper().resetDragAndDrop();
45 sqpApp->dragDropGuiController().resetDragAndDrop();
46 QTreeWidget::startDrag(supportedActions);
46 QTreeWidget::startDrag(supportedActions);
47 }
47 }
@@ -1,294 +1,296
1 #include "DragAndDrop/DragDropHelper.h"
1 #include "DragAndDrop/DragDropGuiController.h"
2 #include "DragAndDrop/DragDropScroller.h"
2 #include "DragAndDrop/DragDropScroller.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
3 #include "DragAndDrop/DragDropTabSwitcher.h"
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
5 #include "Visualization/VisualizationDragDropContainer.h"
6 #include "Visualization/VisualizationDragWidget.h"
6 #include "Visualization/VisualizationDragWidget.h"
7 #include "Visualization/VisualizationWidget.h"
7 #include "Visualization/VisualizationWidget.h"
8 #include "Visualization/operations/FindVariableOperation.h"
8 #include "Visualization/operations/FindVariableOperation.h"
9
9
10 #include "Variable/Variable.h"
10 #include "Variable/Variable.h"
11 #include "Variable/VariableController.h"
11 #include "Variable/VariableController.h"
12
12
13 #include "Common/MimeTypesDef.h"
13 #include "Common/MimeTypesDef.h"
14 #include "Common/VisualizationDef.h"
14 #include "Common/VisualizationDef.h"
15
15
16 #include <QDir>
16 #include <QDir>
17 #include <QLabel>
17 #include <QLabel>
18 #include <QUrl>
18 #include <QUrl>
19 #include <QVBoxLayout>
19 #include <QVBoxLayout>
20
20
21
21
22 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDropHelper")
22 Q_LOGGING_CATEGORY(LOG_DragDropGuiController, "DragDropGuiController")
23
23
24
24
25 struct DragDropHelper::DragDropHelperPrivate {
25 struct DragDropGuiController::DragDropGuiControllerPrivate {
26
26
27 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
27 VisualizationDragWidget *m_CurrentDragWidget = nullptr;
28 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
28 std::unique_ptr<QWidget> m_PlaceHolder = nullptr;
29 QLabel *m_PlaceHolderLabel;
29 QLabel *m_PlaceHolderLabel;
30 QWidget *m_PlaceBackground;
30 QWidget *m_PlaceBackground;
31 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
31 std::unique_ptr<DragDropScroller> m_DragDropScroller = nullptr;
32 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
32 std::unique_ptr<DragDropTabSwitcher> m_DragDropTabSwitcher = nullptr;
33 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
33 QString m_ImageTempUrl; // Temporary file for image url generated by the drag & drop. Not using
34 // QTemporaryFile to have a name which is not generated.
34 // QTemporaryFile to have a name which is not generated.
35
35
36 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
36 VisualizationDragWidget *m_HighlightedDragWidget = nullptr;
37
37
38 QMetaObject::Connection m_DragWidgetDestroyedConnection;
38 QMetaObject::Connection m_DragWidgetDestroyedConnection;
39 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
39 QMetaObject::Connection m_HighlightedWidgetDestroyedConnection;
40
40
41 QList<QWidget *> m_WidgetToClose;
41 QList<QWidget *> m_WidgetToClose;
42
42
43 explicit DragDropHelperPrivate()
43 explicit DragDropGuiControllerPrivate()
44 : m_PlaceHolder{std::make_unique<QWidget>()},
44 : m_PlaceHolder{std::make_unique<QWidget>()},
45 m_DragDropScroller{std::make_unique<DragDropScroller>()},
45 m_DragDropScroller{std::make_unique<DragDropScroller>()},
46 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
46 m_DragDropTabSwitcher{std::make_unique<DragDropTabSwitcher>()}
47 {
47 {
48
48
49 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
49 auto layout = new QVBoxLayout{m_PlaceHolder.get()};
50 layout->setSpacing(0);
50 layout->setSpacing(0);
51 layout->setContentsMargins(0, 0, 0, 0);
51 layout->setContentsMargins(0, 0, 0, 0);
52
52
53 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
53 m_PlaceHolderLabel = new QLabel{"", m_PlaceHolder.get()};
54 m_PlaceHolderLabel->setMinimumHeight(25);
54 m_PlaceHolderLabel->setMinimumHeight(25);
55 layout->addWidget(m_PlaceHolderLabel);
55 layout->addWidget(m_PlaceHolderLabel);
56
56
57 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
57 m_PlaceBackground = new QWidget{m_PlaceHolder.get()};
58 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
58 m_PlaceBackground->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
59 layout->addWidget(m_PlaceBackground);
59 layout->addWidget(m_PlaceBackground);
60
60
61 sqpApp->installEventFilter(m_DragDropScroller.get());
61 sqpApp->installEventFilter(m_DragDropScroller.get());
62 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
62 sqpApp->installEventFilter(m_DragDropTabSwitcher.get());
63
63
64 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
64 m_ImageTempUrl = QDir::temp().absoluteFilePath("Sciqlop_graph.png");
65 }
65 }
66
66
67 void preparePlaceHolder(DragDropHelper::PlaceHolderType type, const QString &topLabelText) const
67 void preparePlaceHolder(DragDropGuiController::PlaceHolderType type,
68 const QString &topLabelText) const
68 {
69 {
69 if (m_CurrentDragWidget) {
70 if (m_CurrentDragWidget) {
70 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
71 m_PlaceHolder->setMinimumSize(m_CurrentDragWidget->size());
71 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
72 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
72 }
73 }
73 else {
74 else {
74 // Configuration of the placeHolder when there is no dragWidget
75 // Configuration of the placeHolder when there is no dragWidget
75 // (for instance with a drag from a variable)
76 // (for instance with a drag from a variable)
76
77
77 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
78 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
78 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
79 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
79 }
80 }
80
81
81 switch (type) {
82 switch (type) {
82 case DragDropHelper::PlaceHolderType::Graph:
83 case DragDropGuiController::PlaceHolderType::Graph:
83 m_PlaceBackground->setStyleSheet(
84 m_PlaceBackground->setStyleSheet(
84 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
85 "background-color: #BBD5EE; border: 1px solid #2A7FD4");
85 break;
86 break;
86 case DragDropHelper::PlaceHolderType::Zone:
87 case DragDropGuiController::PlaceHolderType::Zone:
87 case DragDropHelper::PlaceHolderType::Default:
88 case DragDropGuiController::PlaceHolderType::Default:
88 m_PlaceBackground->setStyleSheet(
89 m_PlaceBackground->setStyleSheet(
89 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
90 "background-color: #BBD5EE; border: 2px solid #2A7FD4");
90 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
91 m_PlaceHolderLabel->setStyleSheet("color: #2A7FD4");
91 break;
92 break;
92 }
93 }
93
94
94 m_PlaceHolderLabel->setText(topLabelText);
95 m_PlaceHolderLabel->setText(topLabelText);
95 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
96 m_PlaceHolderLabel->setVisible(!topLabelText.isEmpty());
96 }
97 }
97 };
98 };
98
99
99
100
100 DragDropHelper::DragDropHelper() : impl{spimpl::make_unique_impl<DragDropHelperPrivate>()}
101 DragDropGuiController::DragDropGuiController()
102 : impl{spimpl::make_unique_impl<DragDropGuiControllerPrivate>()}
101 {
103 {
102 }
104 }
103
105
104 DragDropHelper::~DragDropHelper()
106 DragDropGuiController::~DragDropGuiController()
105 {
107 {
106 QFile::remove(impl->m_ImageTempUrl);
108 QFile::remove(impl->m_ImageTempUrl);
107 }
109 }
108
110
109 void DragDropHelper::resetDragAndDrop()
111 void DragDropGuiController::resetDragAndDrop()
110 {
112 {
111 setCurrentDragWidget(nullptr);
113 setCurrentDragWidget(nullptr);
112 impl->m_HighlightedDragWidget = nullptr;
114 impl->m_HighlightedDragWidget = nullptr;
113 }
115 }
114
116
115 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
117 void DragDropGuiController::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
116 {
118 {
117 if (impl->m_CurrentDragWidget) {
119 if (impl->m_CurrentDragWidget) {
118
120
119 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
121 QObject::disconnect(impl->m_DragWidgetDestroyedConnection);
120 }
122 }
121
123
122 if (dragWidget) {
124 if (dragWidget) {
123 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
125 // ensures the impl->m_CurrentDragWidget is reset when the widget is destroyed
124 impl->m_DragWidgetDestroyedConnection
126 impl->m_DragWidgetDestroyedConnection
125 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
127 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
126 [this]() { impl->m_CurrentDragWidget = nullptr; });
128 [this]() { impl->m_CurrentDragWidget = nullptr; });
127 }
129 }
128
130
129 impl->m_CurrentDragWidget = dragWidget;
131 impl->m_CurrentDragWidget = dragWidget;
130 }
132 }
131
133
132 VisualizationDragWidget *DragDropHelper::getCurrentDragWidget() const
134 VisualizationDragWidget *DragDropGuiController::getCurrentDragWidget() const
133 {
135 {
134 return impl->m_CurrentDragWidget;
136 return impl->m_CurrentDragWidget;
135 }
137 }
136
138
137 QWidget &DragDropHelper::placeHolder() const
139 QWidget &DragDropGuiController::placeHolder() const
138 {
140 {
139 return *impl->m_PlaceHolder;
141 return *impl->m_PlaceHolder;
140 }
142 }
141
143
142 void DragDropHelper::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
144 void DragDropGuiController::insertPlaceHolder(QVBoxLayout *layout, int index, PlaceHolderType type,
143 const QString &topLabelText)
145 const QString &topLabelText)
144 {
146 {
145 removePlaceHolder();
147 removePlaceHolder();
146 impl->preparePlaceHolder(type, topLabelText);
148 impl->preparePlaceHolder(type, topLabelText);
147 layout->insertWidget(index, impl->m_PlaceHolder.get());
149 layout->insertWidget(index, impl->m_PlaceHolder.get());
148 impl->m_PlaceHolder->show();
150 impl->m_PlaceHolder->show();
149 }
151 }
150
152
151 void DragDropHelper::removePlaceHolder()
153 void DragDropGuiController::removePlaceHolder()
152 {
154 {
153 auto parentWidget = impl->m_PlaceHolder->parentWidget();
155 auto parentWidget = impl->m_PlaceHolder->parentWidget();
154 if (parentWidget) {
156 if (parentWidget) {
155 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
157 parentWidget->layout()->removeWidget(impl->m_PlaceHolder.get());
156 impl->m_PlaceHolder->setParent(nullptr);
158 impl->m_PlaceHolder->setParent(nullptr);
157 impl->m_PlaceHolder->hide();
159 impl->m_PlaceHolder->hide();
158 }
160 }
159 }
161 }
160
162
161 bool DragDropHelper::isPlaceHolderSet() const
163 bool DragDropGuiController::isPlaceHolderSet() const
162 {
164 {
163 return impl->m_PlaceHolder->parentWidget();
165 return impl->m_PlaceHolder->parentWidget();
164 }
166 }
165
167
166 void DragDropHelper::addDragDropScrollArea(QScrollArea *scrollArea)
168 void DragDropGuiController::addDragDropScrollArea(QScrollArea *scrollArea)
167 {
169 {
168 impl->m_DragDropScroller->addScrollArea(scrollArea);
170 impl->m_DragDropScroller->addScrollArea(scrollArea);
169 }
171 }
170
172
171 void DragDropHelper::removeDragDropScrollArea(QScrollArea *scrollArea)
173 void DragDropGuiController::removeDragDropScrollArea(QScrollArea *scrollArea)
172 {
174 {
173 impl->m_DragDropScroller->removeScrollArea(scrollArea);
175 impl->m_DragDropScroller->removeScrollArea(scrollArea);
174 }
176 }
175
177
176 void DragDropHelper::addDragDropTabBar(QTabBar *tabBar)
178 void DragDropGuiController::addDragDropTabBar(QTabBar *tabBar)
177 {
179 {
178 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
180 impl->m_DragDropTabSwitcher->addTabBar(tabBar);
179 }
181 }
180
182
181 void DragDropHelper::removeDragDropTabBar(QTabBar *tabBar)
183 void DragDropGuiController::removeDragDropTabBar(QTabBar *tabBar)
182 {
184 {
183 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
185 impl->m_DragDropTabSwitcher->removeTabBar(tabBar);
184 }
186 }
185
187
186 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
188 QUrl DragDropGuiController::imageTemporaryUrl(const QImage &image) const
187 {
189 {
188 image.save(impl->m_ImageTempUrl);
190 image.save(impl->m_ImageTempUrl);
189 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
191 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
190 }
192 }
191
193
192 void DragDropHelper::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
194 void DragDropGuiController::setHightlightedDragWidget(VisualizationDragWidget *dragWidget)
193 {
195 {
194 if (impl->m_HighlightedDragWidget) {
196 if (impl->m_HighlightedDragWidget) {
195 impl->m_HighlightedDragWidget->highlightForMerge(false);
197 impl->m_HighlightedDragWidget->highlightForMerge(false);
196 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
198 QObject::disconnect(impl->m_HighlightedWidgetDestroyedConnection);
197 }
199 }
198
200
199 if (dragWidget) {
201 if (dragWidget) {
200 dragWidget->highlightForMerge(true);
202 dragWidget->highlightForMerge(true);
201
203
202 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
204 // ensures the impl->m_HighlightedDragWidget is reset when the widget is destroyed
203 impl->m_DragWidgetDestroyedConnection
205 impl->m_DragWidgetDestroyedConnection
204 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
206 = QObject::connect(dragWidget, &VisualizationDragWidget::destroyed,
205 [this]() { impl->m_HighlightedDragWidget = nullptr; });
207 [this]() { impl->m_HighlightedDragWidget = nullptr; });
206 }
208 }
207
209
208 impl->m_HighlightedDragWidget = dragWidget;
210 impl->m_HighlightedDragWidget = dragWidget;
209 }
211 }
210
212
211 VisualizationDragWidget *DragDropHelper::getHightlightedDragWidget() const
213 VisualizationDragWidget *DragDropGuiController::getHightlightedDragWidget() const
212 {
214 {
213 return impl->m_HighlightedDragWidget;
215 return impl->m_HighlightedDragWidget;
214 }
216 }
215
217
216 void DragDropHelper::delayedCloseWidget(QWidget *widget)
218 void DragDropGuiController::delayedCloseWidget(QWidget *widget)
217 {
219 {
218 widget->hide();
220 widget->hide();
219 impl->m_WidgetToClose << widget;
221 impl->m_WidgetToClose << widget;
220 }
222 }
221
223
222 void DragDropHelper::doCloseWidgets()
224 void DragDropGuiController::doCloseWidgets()
223 {
225 {
224 for (auto widget : impl->m_WidgetToClose) {
226 for (auto widget : impl->m_WidgetToClose) {
225 widget->close();
227 widget->close();
226 }
228 }
227
229
228 impl->m_WidgetToClose.clear();
230 impl->m_WidgetToClose.clear();
229 }
231 }
230
232
231 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
233 bool DragDropGuiController::checkMimeDataForVisualization(
232 VisualizationDragDropContainer *dropContainer)
234 const QMimeData *mimeData, VisualizationDragDropContainer *dropContainer)
233 {
235 {
234 if (!mimeData || !dropContainer) {
236 if (!mimeData || !dropContainer) {
235 qCWarning(LOG_DragDropHelper()) << QObject::tr(
237 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
236 "DragDropHelper::checkMimeDataForVisualization, invalid input parameters.");
238 "DragDropGuiController::checkMimeDataForVisualization, invalid input parameters.");
237 Q_ASSERT(false);
239 Q_ASSERT(false);
238 return false;
240 return false;
239 }
241 }
240
242
241 auto result = false;
243 auto result = false;
242
244
243 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
245 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
244 auto variables = sqpApp->variableController().variablesForMimeData(
246 auto variables = sqpApp->variableController().variablesForMimeData(
245 mimeData->data(MIME_TYPE_VARIABLE_LIST));
247 mimeData->data(MIME_TYPE_VARIABLE_LIST));
246
248
247 if (variables.count() == 1) {
249 if (variables.count() == 1) {
248
250
249 auto variable = variables.first();
251 auto variable = variables.first();
250 if (variable->dataSeries() != nullptr) {
252 if (variable->dataSeries() != nullptr) {
251
253
252 // Check that the variable is not already in a graph
254 // Check that the variable is not already in a graph
253
255
254 auto parent = dropContainer->parentWidget();
256 auto parent = dropContainer->parentWidget();
255 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
257 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
256 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
258 parent = parent->parentWidget(); // Search for the top level VisualizationWidget
257 }
259 }
258
260
259 if (parent) {
261 if (parent) {
260 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
262 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
261
263
262 FindVariableOperation findVariableOperation{variable};
264 FindVariableOperation findVariableOperation{variable};
263 visualizationWidget->accept(&findVariableOperation);
265 visualizationWidget->accept(&findVariableOperation);
264 auto variableContainers = findVariableOperation.result();
266 auto variableContainers = findVariableOperation.result();
265 if (variableContainers.empty()) {
267 if (variableContainers.empty()) {
266 result = true;
268 result = true;
267 }
269 }
268 else {
270 else {
269 // result = false: the variable already exist in the visualisation
271 // result = false: the variable already exist in the visualisation
270 }
272 }
271 }
273 }
272 else {
274 else {
273 qCWarning(LOG_DragDropHelper()) << QObject::tr(
275 qCWarning(LOG_DragDropGuiController()) << QObject::tr(
274 "DragDropHelper::checkMimeDataForVisualization, the parent "
276 "DragDropGuiController::checkMimeDataForVisualization, the parent "
275 "VisualizationWidget cannot be found. Cannot check if the variable is "
277 "VisualizationWidget cannot be found. Cannot check if the variable is "
276 "already used or not.");
278 "already used or not.");
277 }
279 }
278 }
280 }
279 else {
281 else {
280 // result = false: the variable is not fully loaded
282 // result = false: the variable is not fully loaded
281 }
283 }
282 }
284 }
283 else {
285 else {
284 // result = false: cannot drop multiple variables in the visualisation
286 // result = false: cannot drop multiple variables in the visualisation
285 }
287 }
286 }
288 }
287 else {
289 else {
288 // Other MIME data
290 // Other MIME data
289 // no special rules, accepted by default
291 // no special rules, accepted by default
290 result = true;
292 result = true;
291 }
293 }
292
294
293 return result;
295 return result;
294 }
296 }
@@ -1,203 +1,203
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Catalogue/CatalogueController.h>
3 #include <Catalogue/CatalogueController.h>
4 #include <Data/IDataProvider.h>
4 #include <Data/IDataProvider.h>
5 #include <DataSource/DataSourceController.h>
5 #include <DataSource/DataSourceController.h>
6 #include <DragAndDrop/DragDropHelper.h>
6 #include <DragAndDrop/DragDropGuiController.h>
7 #include <Network/NetworkController.h>
7 #include <Network/NetworkController.h>
8 #include <QThread>
8 #include <QThread>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10 #include <Variable/Variable.h>
10 #include <Variable/Variable.h>
11 #include <Variable/VariableController.h>
11 #include <Variable/VariableController.h>
12 #include <Variable/VariableModel.h>
12 #include <Variable/VariableModel.h>
13 #include <Visualization/VisualizationController.h>
13 #include <Visualization/VisualizationController.h>
14
14
15 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
15 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
16
16
17 class SqpApplication::SqpApplicationPrivate {
17 class SqpApplication::SqpApplicationPrivate {
18 public:
18 public:
19 SqpApplicationPrivate()
19 SqpApplicationPrivate()
20 : m_DataSourceController{std::make_unique<DataSourceController>()},
20 : m_DataSourceController{std::make_unique<DataSourceController>()},
21 m_VariableController{std::make_unique<VariableController>()},
21 m_VariableController{std::make_unique<VariableController>()},
22 m_TimeController{std::make_unique<TimeController>()},
22 m_TimeController{std::make_unique<TimeController>()},
23 m_NetworkController{std::make_unique<NetworkController>()},
23 m_NetworkController{std::make_unique<NetworkController>()},
24 m_VisualizationController{std::make_unique<VisualizationController>()},
24 m_VisualizationController{std::make_unique<VisualizationController>()},
25 m_DragDropHelper{std::make_unique<DragDropHelper>()},
25 m_DragDropGuiController{std::make_unique<DragDropGuiController>()},
26 m_CatalogueController{std::make_unique<CatalogueController>()},
26 m_CatalogueController{std::make_unique<CatalogueController>()},
27 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
27 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
28 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
28 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
29 {
29 {
30 // /////////////////////////////// //
30 // /////////////////////////////// //
31 // Connections between controllers //
31 // Connections between controllers //
32 // /////////////////////////////// //
32 // /////////////////////////////// //
33
33
34 // VariableController <-> DataSourceController
34 // VariableController <-> DataSourceController
35 connect(m_DataSourceController.get(),
35 connect(m_DataSourceController.get(),
36 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
36 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
37 std::shared_ptr<IDataProvider>)),
37 std::shared_ptr<IDataProvider>)),
38 m_VariableController.get(),
38 m_VariableController.get(),
39 SLOT(createVariable(const QString &, const QVariantHash &,
39 SLOT(createVariable(const QString &, const QVariantHash &,
40 std::shared_ptr<IDataProvider>)));
40 std::shared_ptr<IDataProvider>)));
41
41
42 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
42 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
43 m_DataSourceController.get(), &DataSourceController::requestVariable);
43 m_DataSourceController.get(), &DataSourceController::requestVariable);
44
44
45 // VariableController <-> VisualizationController
45 // VariableController <-> VisualizationController
46 connect(m_VariableController.get(),
46 connect(m_VariableController.get(),
47 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
47 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
48 m_VisualizationController.get(),
48 m_VisualizationController.get(),
49 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
49 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
50
50
51 connect(m_VariableController.get(),
51 connect(m_VariableController.get(),
52 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
52 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
53 m_VisualizationController.get(),
53 m_VisualizationController.get(),
54 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
54 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
55
55
56
56
57 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
57 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
58 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
58 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
59 m_NetworkController->moveToThread(&m_NetworkControllerThread);
59 m_NetworkController->moveToThread(&m_NetworkControllerThread);
60 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
60 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
61 m_VariableController->moveToThread(&m_VariableControllerThread);
61 m_VariableController->moveToThread(&m_VariableControllerThread);
62 m_VariableControllerThread.setObjectName("VariableControllerThread");
62 m_VariableControllerThread.setObjectName("VariableControllerThread");
63 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
63 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
64 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
64 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
65 m_CatalogueController->moveToThread(&m_CatalogueControllerThread);
65 m_CatalogueController->moveToThread(&m_CatalogueControllerThread);
66 m_CatalogueControllerThread.setObjectName("CatalogueControllerThread");
66 m_CatalogueControllerThread.setObjectName("CatalogueControllerThread");
67
67
68
68
69 // Additionnal init
69 // Additionnal init
70 m_VariableController->setTimeController(m_TimeController.get());
70 m_VariableController->setTimeController(m_TimeController.get());
71 }
71 }
72
72
73 virtual ~SqpApplicationPrivate()
73 virtual ~SqpApplicationPrivate()
74 {
74 {
75 m_DataSourceControllerThread.quit();
75 m_DataSourceControllerThread.quit();
76 m_DataSourceControllerThread.wait();
76 m_DataSourceControllerThread.wait();
77
77
78 m_NetworkControllerThread.quit();
78 m_NetworkControllerThread.quit();
79 m_NetworkControllerThread.wait();
79 m_NetworkControllerThread.wait();
80
80
81 m_VariableControllerThread.quit();
81 m_VariableControllerThread.quit();
82 m_VariableControllerThread.wait();
82 m_VariableControllerThread.wait();
83
83
84 m_VisualizationControllerThread.quit();
84 m_VisualizationControllerThread.quit();
85 m_VisualizationControllerThread.wait();
85 m_VisualizationControllerThread.wait();
86
86
87 m_CatalogueControllerThread.quit();
87 m_CatalogueControllerThread.quit();
88 m_CatalogueControllerThread.wait();
88 m_CatalogueControllerThread.wait();
89 }
89 }
90
90
91 std::unique_ptr<DataSourceController> m_DataSourceController;
91 std::unique_ptr<DataSourceController> m_DataSourceController;
92 std::unique_ptr<VariableController> m_VariableController;
92 std::unique_ptr<VariableController> m_VariableController;
93 std::unique_ptr<TimeController> m_TimeController;
93 std::unique_ptr<TimeController> m_TimeController;
94 std::unique_ptr<NetworkController> m_NetworkController;
94 std::unique_ptr<NetworkController> m_NetworkController;
95 std::unique_ptr<VisualizationController> m_VisualizationController;
95 std::unique_ptr<VisualizationController> m_VisualizationController;
96 std::unique_ptr<CatalogueController> m_CatalogueController;
96 std::unique_ptr<CatalogueController> m_CatalogueController;
97 QThread m_DataSourceControllerThread;
97 QThread m_DataSourceControllerThread;
98 QThread m_NetworkControllerThread;
98 QThread m_NetworkControllerThread;
99 QThread m_VariableControllerThread;
99 QThread m_VariableControllerThread;
100 QThread m_VisualizationControllerThread;
100 QThread m_VisualizationControllerThread;
101 QThread m_CatalogueControllerThread;
101 QThread m_CatalogueControllerThread;
102
102
103 std::unique_ptr<DragDropHelper> m_DragDropHelper;
103 std::unique_ptr<DragDropGuiController> m_DragDropGuiController;
104
104
105 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
105 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
106 SqpApplication::PlotsCursorMode m_PlotCursorMode;
106 SqpApplication::PlotsCursorMode m_PlotCursorMode;
107 };
107 };
108
108
109
109
110 SqpApplication::SqpApplication(int &argc, char **argv)
110 SqpApplication::SqpApplication(int &argc, char **argv)
111 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
111 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
112 {
112 {
113 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
113 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
114
114
115 connect(&impl->m_DataSourceControllerThread, &QThread::started,
115 connect(&impl->m_DataSourceControllerThread, &QThread::started,
116 impl->m_DataSourceController.get(), &DataSourceController::initialize);
116 impl->m_DataSourceController.get(), &DataSourceController::initialize);
117 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
117 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
118 impl->m_DataSourceController.get(), &DataSourceController::finalize);
118 impl->m_DataSourceController.get(), &DataSourceController::finalize);
119
119
120 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
120 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
121 &NetworkController::initialize);
121 &NetworkController::initialize);
122 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
122 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
123 &NetworkController::finalize);
123 &NetworkController::finalize);
124
124
125 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
125 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
126 &VariableController::initialize);
126 &VariableController::initialize);
127 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
127 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
128 &VariableController::finalize);
128 &VariableController::finalize);
129
129
130 connect(&impl->m_VisualizationControllerThread, &QThread::started,
130 connect(&impl->m_VisualizationControllerThread, &QThread::started,
131 impl->m_VisualizationController.get(), &VisualizationController::initialize);
131 impl->m_VisualizationController.get(), &VisualizationController::initialize);
132 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
132 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
133 impl->m_VisualizationController.get(), &VisualizationController::finalize);
133 impl->m_VisualizationController.get(), &VisualizationController::finalize);
134
134
135 connect(&impl->m_CatalogueControllerThread, &QThread::started,
135 connect(&impl->m_CatalogueControllerThread, &QThread::started,
136 impl->m_CatalogueController.get(), &CatalogueController::initialize);
136 impl->m_CatalogueController.get(), &CatalogueController::initialize);
137 connect(&impl->m_CatalogueControllerThread, &QThread::finished,
137 connect(&impl->m_CatalogueControllerThread, &QThread::finished,
138 impl->m_CatalogueController.get(), &CatalogueController::finalize);
138 impl->m_CatalogueController.get(), &CatalogueController::finalize);
139
139
140 impl->m_DataSourceControllerThread.start();
140 impl->m_DataSourceControllerThread.start();
141 impl->m_NetworkControllerThread.start();
141 impl->m_NetworkControllerThread.start();
142 impl->m_VariableControllerThread.start();
142 impl->m_VariableControllerThread.start();
143 impl->m_VisualizationControllerThread.start();
143 impl->m_VisualizationControllerThread.start();
144 impl->m_CatalogueControllerThread.start();
144 impl->m_CatalogueControllerThread.start();
145 }
145 }
146
146
147 SqpApplication::~SqpApplication()
147 SqpApplication::~SqpApplication()
148 {
148 {
149 }
149 }
150
150
151 void SqpApplication::initialize()
151 void SqpApplication::initialize()
152 {
152 {
153 }
153 }
154
154
155 DataSourceController &SqpApplication::dataSourceController() noexcept
155 DataSourceController &SqpApplication::dataSourceController() noexcept
156 {
156 {
157 return *impl->m_DataSourceController;
157 return *impl->m_DataSourceController;
158 }
158 }
159
159
160 NetworkController &SqpApplication::networkController() noexcept
160 NetworkController &SqpApplication::networkController() noexcept
161 {
161 {
162 return *impl->m_NetworkController;
162 return *impl->m_NetworkController;
163 }
163 }
164
164
165 TimeController &SqpApplication::timeController() noexcept
165 TimeController &SqpApplication::timeController() noexcept
166 {
166 {
167 return *impl->m_TimeController;
167 return *impl->m_TimeController;
168 }
168 }
169
169
170 VariableController &SqpApplication::variableController() noexcept
170 VariableController &SqpApplication::variableController() noexcept
171 {
171 {
172 return *impl->m_VariableController;
172 return *impl->m_VariableController;
173 }
173 }
174
174
175 VisualizationController &SqpApplication::visualizationController() noexcept
175 VisualizationController &SqpApplication::visualizationController() noexcept
176 {
176 {
177 return *impl->m_VisualizationController;
177 return *impl->m_VisualizationController;
178 }
178 }
179
179
180 DragDropHelper &SqpApplication::dragDropHelper() noexcept
180 DragDropGuiController &SqpApplication::dragDropGuiController() noexcept
181 {
181 {
182 return *impl->m_DragDropHelper;
182 return *impl->m_DragDropGuiController;
183 }
183 }
184
184
185 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
185 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
186 {
186 {
187 return impl->m_PlotInterractionMode;
187 return impl->m_PlotInterractionMode;
188 }
188 }
189
189
190 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
190 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
191 {
191 {
192 impl->m_PlotInterractionMode = mode;
192 impl->m_PlotInterractionMode = mode;
193 }
193 }
194
194
195 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
195 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
196 {
196 {
197 return impl->m_PlotCursorMode;
197 return impl->m_PlotCursorMode;
198 }
198 }
199
199
200 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
200 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
201 {
201 {
202 impl->m_PlotCursorMode = mode;
202 impl->m_PlotCursorMode = mode;
203 }
203 }
@@ -1,154 +1,154
1 #include "TimeWidget/TimeWidget.h"
1 #include "TimeWidget/TimeWidget.h"
2 #include "ui_TimeWidget.h"
2 #include "ui_TimeWidget.h"
3
3
4 #include <Common/DateUtils.h>
4 #include <Common/DateUtils.h>
5 #include <Common/MimeTypesDef.h>
5 #include <Common/MimeTypesDef.h>
6
6
7 #include <DragAndDrop/DragDropHelper.h>
7 #include <DragAndDrop/DragDropGuiController.h>
8 #include <SqpApplication.h>
8 #include <SqpApplication.h>
9 #include <Time/TimeController.h>
9 #include <Time/TimeController.h>
10
10
11 #include <QDrag>
11 #include <QDrag>
12 #include <QDragEnterEvent>
12 #include <QDragEnterEvent>
13 #include <QDropEvent>
13 #include <QDropEvent>
14 #include <QMimeData>
14 #include <QMimeData>
15
15
16
16
17 struct TimeWidget::TimeWidgetPrivate {
17 struct TimeWidget::TimeWidgetPrivate {
18
18
19 explicit TimeWidgetPrivate() {}
19 explicit TimeWidgetPrivate() {}
20
20
21 QPoint m_DragStartPosition;
21 QPoint m_DragStartPosition;
22 };
22 };
23
23
24 TimeWidget::TimeWidget(QWidget *parent)
24 TimeWidget::TimeWidget(QWidget *parent)
25 : QWidget{parent},
25 : QWidget{parent},
26 ui{new Ui::TimeWidget},
26 ui{new Ui::TimeWidget},
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
27 impl{spimpl::make_unique_impl<TimeWidgetPrivate>()}
28 {
28 {
29 ui->setupUi(this);
29 ui->setupUi(this);
30
30
31 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
31 ui->applyToolButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_DialogApplyButton));
32
32
33 // Connection
33 // Connection
34 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
34 connect(ui->startDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
35 &TimeWidget::onTimeUpdateRequested);
35 &TimeWidget::onTimeUpdateRequested);
36
36
37 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
37 connect(ui->endDateTimeEdit, &QDateTimeEdit::dateTimeChanged, this,
38 &TimeWidget::onTimeUpdateRequested);
38 &TimeWidget::onTimeUpdateRequested);
39
39
40
40
41 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
41 connect(ui->applyToolButton, &QToolButton::clicked, &sqpApp->timeController(),
42 &TimeController::onTimeNotify);
42 &TimeController::onTimeNotify);
43
43
44 // Initialisation
44 // Initialisation
45 auto endDateTime = QDateTime::currentDateTimeUtc();
45 auto endDateTime = QDateTime::currentDateTimeUtc();
46 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
46 auto startDateTime = endDateTime.addSecs(-3600); // one hour before
47
47
48 ui->startDateTimeEdit->setDateTime(startDateTime);
48 ui->startDateTimeEdit->setDateTime(startDateTime);
49 ui->endDateTimeEdit->setDateTime(endDateTime);
49 ui->endDateTimeEdit->setDateTime(endDateTime);
50
50
51 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
51 auto dateTime = SqpRange{DateUtils::secondsSinceEpoch(startDateTime),
52 DateUtils::secondsSinceEpoch(endDateTime)};
52 DateUtils::secondsSinceEpoch(endDateTime)};
53
53
54 sqpApp->timeController().onTimeToUpdate(dateTime);
54 sqpApp->timeController().onTimeToUpdate(dateTime);
55 }
55 }
56
56
57
57
58 TimeWidget::~TimeWidget()
58 TimeWidget::~TimeWidget()
59 {
59 {
60 delete ui;
60 delete ui;
61 }
61 }
62
62
63 void TimeWidget::setTimeRange(SqpRange time)
63 void TimeWidget::setTimeRange(SqpRange time)
64 {
64 {
65 auto startDateTime = DateUtils::dateTime(time.m_TStart);
65 auto startDateTime = DateUtils::dateTime(time.m_TStart);
66 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
66 auto endDateTime = DateUtils::dateTime(time.m_TEnd);
67
67
68 ui->startDateTimeEdit->setDateTime(startDateTime);
68 ui->startDateTimeEdit->setDateTime(startDateTime);
69 ui->endDateTimeEdit->setDateTime(endDateTime);
69 ui->endDateTimeEdit->setDateTime(endDateTime);
70 }
70 }
71
71
72 SqpRange TimeWidget::timeRange() const
72 SqpRange TimeWidget::timeRange() const
73 {
73 {
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
74 return SqpRange{DateUtils::secondsSinceEpoch(ui->startDateTimeEdit->dateTime()),
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
75 DateUtils::secondsSinceEpoch(ui->endDateTimeEdit->dateTime())};
76 }
76 }
77
77
78 void TimeWidget::onTimeUpdateRequested()
78 void TimeWidget::onTimeUpdateRequested()
79 {
79 {
80 auto dateTime = timeRange();
80 auto dateTime = timeRange();
81 emit timeUpdated(std::move(dateTime));
81 emit timeUpdated(std::move(dateTime));
82 }
82 }
83
83
84 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
84 void TimeWidget::dragEnterEvent(QDragEnterEvent *event)
85 {
85 {
86 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
86 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
87 event->acceptProposedAction();
87 event->acceptProposedAction();
88 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
88 setStyleSheet("QDateTimeEdit{background-color: #BBD5EE; border:2px solid #2A7FD4}");
89 }
89 }
90 else {
90 else {
91 event->ignore();
91 event->ignore();
92 }
92 }
93 }
93 }
94
94
95 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
95 void TimeWidget::dragLeaveEvent(QDragLeaveEvent *event)
96 {
96 {
97 setStyleSheet(QString{});
97 setStyleSheet(QString{});
98 }
98 }
99
99
100 void TimeWidget::dropEvent(QDropEvent *event)
100 void TimeWidget::dropEvent(QDropEvent *event)
101 {
101 {
102 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
102 if (event->mimeData()->hasFormat(MIME_TYPE_TIME_RANGE)) {
103 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
103 auto mimeData = event->mimeData()->data(MIME_TYPE_TIME_RANGE);
104 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
104 auto timeRange = TimeController::timeRangeForMimeData(mimeData);
105
105
106 setTimeRange(timeRange);
106 setTimeRange(timeRange);
107 }
107 }
108 else {
108 else {
109 event->ignore();
109 event->ignore();
110 }
110 }
111
111
112 setStyleSheet(QString{});
112 setStyleSheet(QString{});
113 }
113 }
114
114
115
115
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
116 void TimeWidget::mousePressEvent(QMouseEvent *event)
117 {
117 {
118 if (event->button() == Qt::LeftButton) {
118 if (event->button() == Qt::LeftButton) {
119 impl->m_DragStartPosition = event->pos();
119 impl->m_DragStartPosition = event->pos();
120 }
120 }
121
121
122 QWidget::mousePressEvent(event);
122 QWidget::mousePressEvent(event);
123 }
123 }
124
124
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
125 void TimeWidget::mouseMoveEvent(QMouseEvent *event)
126 {
126 {
127 if (!(event->buttons() & Qt::LeftButton)) {
127 if (!(event->buttons() & Qt::LeftButton)) {
128 return;
128 return;
129 }
129 }
130
130
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
131 if ((event->pos() - impl->m_DragStartPosition).manhattanLength()
132 < QApplication::startDragDistance()) {
132 < QApplication::startDragDistance()) {
133 return;
133 return;
134 }
134 }
135
135
136 // Note: The management of the drag object is done by Qt
136 // Note: The management of the drag object is done by Qt
137 auto drag = new QDrag{this};
137 auto drag = new QDrag{this};
138
138
139 auto mimeData = new QMimeData;
139 auto mimeData = new QMimeData;
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
140 auto timeData = TimeController::mimeDataForTimeRange(timeRange());
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
141 mimeData->setData(MIME_TYPE_TIME_RANGE, timeData);
142
142
143 drag->setMimeData(mimeData);
143 drag->setMimeData(mimeData);
144
144
145 auto pixmap = QPixmap{":/icones/time.png"};
145 auto pixmap = QPixmap{":/icones/time.png"};
146 drag->setPixmap(pixmap.scaledToWidth(22));
146 drag->setPixmap(pixmap.scaledToWidth(22));
147
147
148 sqpApp->dragDropHelper().resetDragAndDrop();
148 sqpApp->dragDropGuiController().resetDragAndDrop();
149
149
150 // Note: The exec() is blocking on windows but not on linux and macOS
150 // Note: The exec() is blocking on windows but not on linux and macOS
151 drag->exec(Qt::MoveAction | Qt::CopyAction);
151 drag->exec(Qt::MoveAction | Qt::CopyAction);
152
152
153 QWidget::mouseMoveEvent(event);
153 QWidget::mouseMoveEvent(event);
154 }
154 }
@@ -1,15 +1,15
1 #include "Variable/VariableInspectorTableView.h"
1 #include "Variable/VariableInspectorTableView.h"
2
2
3 #include "DragAndDrop/DragDropHelper.h"
3 #include "DragAndDrop/DragDropGuiController.h"
4 #include "SqpApplication.h"
4 #include "SqpApplication.h"
5
5
6 VariableInspectorTableView::VariableInspectorTableView(QWidget *parent) : QTableView(parent)
6 VariableInspectorTableView::VariableInspectorTableView(QWidget *parent) : QTableView(parent)
7 {
7 {
8 }
8 }
9
9
10 void VariableInspectorTableView::startDrag(Qt::DropActions supportedActions)
10 void VariableInspectorTableView::startDrag(Qt::DropActions supportedActions)
11 {
11 {
12 // Resets the drag&drop operations before it's starting
12 // Resets the drag&drop operations before it's starting
13 sqpApp->dragDropHelper().resetDragAndDrop();
13 sqpApp->dragDropGuiController().resetDragAndDrop();
14 QTableView::startDrag(supportedActions);
14 QTableView::startDrag(supportedActions);
15 }
15 }
@@ -1,240 +1,240
1 #include <Variable/RenameVariableDialog.h>
1 #include <Variable/RenameVariableDialog.h>
2 #include <Variable/Variable.h>
2 #include <Variable/Variable.h>
3 #include <Variable/VariableController.h>
3 #include <Variable/VariableController.h>
4 #include <Variable/VariableInspectorWidget.h>
4 #include <Variable/VariableInspectorWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
5 #include <Variable/VariableMenuHeaderWidget.h>
6 #include <Variable/VariableModel.h>
6 #include <Variable/VariableModel.h>
7
7
8 #include <ui_VariableInspectorWidget.h>
8 #include <ui_VariableInspectorWidget.h>
9
9
10 #include <QMouseEvent>
10 #include <QMouseEvent>
11 #include <QSortFilterProxyModel>
11 #include <QSortFilterProxyModel>
12 #include <QStyledItemDelegate>
12 #include <QStyledItemDelegate>
13 #include <QWidgetAction>
13 #include <QWidgetAction>
14
14
15 #include <DragAndDrop/DragDropHelper.h>
15 #include <DragAndDrop/DragDropGuiController.h>
16 #include <SqpApplication.h>
16 #include <SqpApplication.h>
17
17
18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
19
19
20
20
21 class QProgressBarItemDelegate : public QStyledItemDelegate {
21 class QProgressBarItemDelegate : public QStyledItemDelegate {
22
22
23 public:
23 public:
24 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
24 QProgressBarItemDelegate(QObject *parent) : QStyledItemDelegate{parent} {}
25
25
26 void paint(QPainter *painter, const QStyleOptionViewItem &option,
26 void paint(QPainter *painter, const QStyleOptionViewItem &option,
27 const QModelIndex &index) const
27 const QModelIndex &index) const
28 {
28 {
29 auto data = index.data(Qt::DisplayRole);
29 auto data = index.data(Qt::DisplayRole);
30 auto progressData = index.data(VariableRoles::ProgressRole);
30 auto progressData = index.data(VariableRoles::ProgressRole);
31 if (data.isValid() && progressData.isValid()) {
31 if (data.isValid() && progressData.isValid()) {
32 auto name = data.value<QString>();
32 auto name = data.value<QString>();
33 auto progress = progressData.value<double>();
33 auto progress = progressData.value<double>();
34 if (progress > 0) {
34 if (progress > 0) {
35 auto cancelButtonWidth = 20;
35 auto cancelButtonWidth = 20;
36 auto progressBarOption = QStyleOptionProgressBar{};
36 auto progressBarOption = QStyleOptionProgressBar{};
37 auto progressRect = option.rect;
37 auto progressRect = option.rect;
38 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
38 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
39 progressBarOption.rect = progressRect;
39 progressBarOption.rect = progressRect;
40 progressBarOption.minimum = 0;
40 progressBarOption.minimum = 0;
41 progressBarOption.maximum = 100;
41 progressBarOption.maximum = 100;
42 progressBarOption.progress = progress;
42 progressBarOption.progress = progress;
43 progressBarOption.text
43 progressBarOption.text
44 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
44 = QString("%1 %2").arg(name).arg(QString::number(progress, 'f', 2) + "%");
45 progressBarOption.textVisible = true;
45 progressBarOption.textVisible = true;
46 progressBarOption.textAlignment = Qt::AlignCenter;
46 progressBarOption.textAlignment = Qt::AlignCenter;
47
47
48
48
49 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
49 QApplication::style()->drawControl(QStyle::CE_ProgressBar, &progressBarOption,
50 painter);
50 painter);
51
51
52 // Cancel button
52 // Cancel button
53 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
53 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
54 option.rect.height());
54 option.rect.height());
55 auto buttonOption = QStyleOptionButton{};
55 auto buttonOption = QStyleOptionButton{};
56 buttonOption.rect = buttonRect;
56 buttonOption.rect = buttonRect;
57 buttonOption.text = "X";
57 buttonOption.text = "X";
58
58
59 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
59 QApplication::style()->drawControl(QStyle::CE_PushButton, &buttonOption, painter);
60 }
60 }
61 else {
61 else {
62 QStyledItemDelegate::paint(painter, option, index);
62 QStyledItemDelegate::paint(painter, option, index);
63 }
63 }
64 }
64 }
65 else {
65 else {
66 QStyledItemDelegate::paint(painter, option, index);
66 QStyledItemDelegate::paint(painter, option, index);
67 }
67 }
68 }
68 }
69
69
70 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
70 bool editorEvent(QEvent *event, QAbstractItemModel *model, const QStyleOptionViewItem &option,
71 const QModelIndex &index)
71 const QModelIndex &index)
72 {
72 {
73 if (event->type() == QEvent::MouseButtonRelease) {
73 if (event->type() == QEvent::MouseButtonRelease) {
74 auto data = index.data(Qt::DisplayRole);
74 auto data = index.data(Qt::DisplayRole);
75 auto progressData = index.data(VariableRoles::ProgressRole);
75 auto progressData = index.data(VariableRoles::ProgressRole);
76 if (data.isValid() && progressData.isValid()) {
76 if (data.isValid() && progressData.isValid()) {
77 auto cancelButtonWidth = 20;
77 auto cancelButtonWidth = 20;
78 auto progressRect = option.rect;
78 auto progressRect = option.rect;
79 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
79 progressRect.setWidth(progressRect.width() - cancelButtonWidth);
80 // Cancel button
80 // Cancel button
81 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
81 auto buttonRect = QRect(progressRect.right(), option.rect.top(), cancelButtonWidth,
82 option.rect.height());
82 option.rect.height());
83
83
84 auto e = (QMouseEvent *)event;
84 auto e = (QMouseEvent *)event;
85 auto clickX = e->x();
85 auto clickX = e->x();
86 auto clickY = e->y();
86 auto clickY = e->y();
87
87
88 auto x = buttonRect.left(); // the X coordinate
88 auto x = buttonRect.left(); // the X coordinate
89 auto y = buttonRect.top(); // the Y coordinate
89 auto y = buttonRect.top(); // the Y coordinate
90 auto w = buttonRect.width(); // button width
90 auto w = buttonRect.width(); // button width
91 auto h = buttonRect.height(); // button height
91 auto h = buttonRect.height(); // button height
92
92
93 if (clickX > x && clickX < x + w) {
93 if (clickX > x && clickX < x + w) {
94 if (clickY > y && clickY < y + h) {
94 if (clickY > y && clickY < y + h) {
95 auto variableModel = sqpApp->variableController().variableModel();
95 auto variableModel = sqpApp->variableController().variableModel();
96 variableModel->abortProgress(index);
96 variableModel->abortProgress(index);
97 }
97 }
98 return true;
98 return true;
99 }
99 }
100 else {
100 else {
101 return QStyledItemDelegate::editorEvent(event, model, option, index);
101 return QStyledItemDelegate::editorEvent(event, model, option, index);
102 }
102 }
103 }
103 }
104 else {
104 else {
105 return QStyledItemDelegate::editorEvent(event, model, option, index);
105 return QStyledItemDelegate::editorEvent(event, model, option, index);
106 }
106 }
107 }
107 }
108 else {
108 else {
109 return QStyledItemDelegate::editorEvent(event, model, option, index);
109 return QStyledItemDelegate::editorEvent(event, model, option, index);
110 }
110 }
111
111
112
112
113 return QStyledItemDelegate::editorEvent(event, model, option, index);
113 return QStyledItemDelegate::editorEvent(event, model, option, index);
114 }
114 }
115 };
115 };
116
116
117 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
117 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
118 : QWidget{parent},
118 : QWidget{parent},
119 ui{new Ui::VariableInspectorWidget},
119 ui{new Ui::VariableInspectorWidget},
120 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
120 m_ProgressBarItemDelegate{new QProgressBarItemDelegate{this}}
121 {
121 {
122 ui->setupUi(this);
122 ui->setupUi(this);
123
123
124 // Sets model for table
124 // Sets model for table
125 // auto sortFilterModel = new QSortFilterProxyModel{this};
125 // auto sortFilterModel = new QSortFilterProxyModel{this};
126 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
126 // sortFilterModel->setSourceModel(sqpApp->variableController().variableModel());
127
127
128 auto variableModel = sqpApp->variableController().variableModel();
128 auto variableModel = sqpApp->variableController().variableModel();
129 ui->tableView->setModel(variableModel);
129 ui->tableView->setModel(variableModel);
130
130
131 // Adds extra signal/slot between view and model, so the view can be updated instantly when
131 // Adds extra signal/slot between view and model, so the view can be updated instantly when
132 // there is a change of data in the model
132 // there is a change of data in the model
133 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
133 connect(variableModel, SIGNAL(dataChanged(const QModelIndex &, const QModelIndex &)), this,
134 SLOT(refresh()));
134 SLOT(refresh()));
135
135
136 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
136 ui->tableView->setSelectionModel(sqpApp->variableController().variableSelectionModel());
137 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
137 ui->tableView->setItemDelegateForColumn(0, m_ProgressBarItemDelegate);
138
138
139 // Fixes column sizes
139 // Fixes column sizes
140 auto model = ui->tableView->model();
140 auto model = ui->tableView->model();
141 const auto count = model->columnCount();
141 const auto count = model->columnCount();
142 for (auto i = 0; i < count; ++i) {
142 for (auto i = 0; i < count; ++i) {
143 ui->tableView->setColumnWidth(
143 ui->tableView->setColumnWidth(
144 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
144 i, model->headerData(i, Qt::Horizontal, Qt::SizeHintRole).toSize().width());
145 }
145 }
146
146
147 // Sets selection options
147 // Sets selection options
148 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
148 ui->tableView->setSelectionBehavior(QTableView::SelectRows);
149 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
149 ui->tableView->setSelectionMode(QTableView::ExtendedSelection);
150
150
151 // Connection to show a menu when right clicking on the tree
151 // Connection to show a menu when right clicking on the tree
152 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
152 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
153 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
153 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
154 &VariableInspectorWidget::onTableMenuRequested);
154 &VariableInspectorWidget::onTableMenuRequested);
155 }
155 }
156
156
157 VariableInspectorWidget::~VariableInspectorWidget()
157 VariableInspectorWidget::~VariableInspectorWidget()
158 {
158 {
159 delete ui;
159 delete ui;
160 }
160 }
161
161
162 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
162 void VariableInspectorWidget::onTableMenuRequested(const QPoint &pos) noexcept
163 {
163 {
164 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
164 auto selectedRows = ui->tableView->selectionModel()->selectedRows();
165
165
166 // Gets the model to retrieve the underlying selected variables
166 // Gets the model to retrieve the underlying selected variables
167 auto model = sqpApp->variableController().variableModel();
167 auto model = sqpApp->variableController().variableModel();
168 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
168 auto selectedVariables = QVector<std::shared_ptr<Variable> >{};
169 for (const auto &selectedRow : qAsConst(selectedRows)) {
169 for (const auto &selectedRow : qAsConst(selectedRows)) {
170 if (auto selectedVariable = model->variable(selectedRow.row())) {
170 if (auto selectedVariable = model->variable(selectedRow.row())) {
171 selectedVariables.push_back(selectedVariable);
171 selectedVariables.push_back(selectedVariable);
172 }
172 }
173 }
173 }
174
174
175 QMenu tableMenu{};
175 QMenu tableMenu{};
176
176
177 // Emits a signal so that potential receivers can populate the menu before displaying it
177 // Emits a signal so that potential receivers can populate the menu before displaying it
178 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
178 emit tableMenuAboutToBeDisplayed(&tableMenu, selectedVariables);
179
179
180 // Adds menu-specific actions
180 // Adds menu-specific actions
181 if (!selectedVariables.isEmpty()) {
181 if (!selectedVariables.isEmpty()) {
182 tableMenu.addSeparator();
182 tableMenu.addSeparator();
183
183
184 // 'Rename' and 'Duplicate' actions (only if one variable selected)
184 // 'Rename' and 'Duplicate' actions (only if one variable selected)
185 if (selectedVariables.size() == 1) {
185 if (selectedVariables.size() == 1) {
186 auto selectedVariable = selectedVariables.front();
186 auto selectedVariable = selectedVariables.front();
187
187
188 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
188 auto duplicateFun = [varW = std::weak_ptr<Variable>(selectedVariable)]()
189 {
189 {
190 if (auto var = varW.lock()) {
190 if (auto var = varW.lock()) {
191 sqpApp->variableController().cloneVariable(var);
191 sqpApp->variableController().cloneVariable(var);
192 }
192 }
193 };
193 };
194
194
195 tableMenu.addAction(tr("Duplicate"), duplicateFun);
195 tableMenu.addAction(tr("Duplicate"), duplicateFun);
196
196
197 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]()
197 auto renameFun = [ varW = std::weak_ptr<Variable>(selectedVariable), &model, this ]()
198 {
198 {
199 if (auto var = varW.lock()) {
199 if (auto var = varW.lock()) {
200 // Generates forbidden names (names associated to existing variables)
200 // Generates forbidden names (names associated to existing variables)
201 auto allVariables = model->variables();
201 auto allVariables = model->variables();
202 auto forbiddenNames = QVector<QString>(allVariables.size());
202 auto forbiddenNames = QVector<QString>(allVariables.size());
203 std::transform(allVariables.cbegin(), allVariables.cend(),
203 std::transform(allVariables.cbegin(), allVariables.cend(),
204 forbiddenNames.begin(),
204 forbiddenNames.begin(),
205 [](const auto &variable) { return variable->name(); });
205 [](const auto &variable) { return variable->name(); });
206
206
207 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
207 RenameVariableDialog dialog{var->name(), forbiddenNames, this};
208 if (dialog.exec() == QDialog::Accepted) {
208 if (dialog.exec() == QDialog::Accepted) {
209 var->setName(dialog.name());
209 var->setName(dialog.name());
210 }
210 }
211 }
211 }
212 };
212 };
213
213
214 tableMenu.addAction(tr("Rename..."), renameFun);
214 tableMenu.addAction(tr("Rename..."), renameFun);
215 }
215 }
216
216
217 // 'Delete' action
217 // 'Delete' action
218 auto deleteFun = [&selectedVariables]() {
218 auto deleteFun = [&selectedVariables]() {
219 sqpApp->variableController().deleteVariables(selectedVariables);
219 sqpApp->variableController().deleteVariables(selectedVariables);
220 };
220 };
221
221
222 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
222 tableMenu.addAction(QIcon{":/icones/delete.png"}, tr("Delete"), deleteFun);
223 }
223 }
224
224
225 if (!tableMenu.isEmpty()) {
225 if (!tableMenu.isEmpty()) {
226 // Generates menu header (inserted before first action)
226 // Generates menu header (inserted before first action)
227 auto firstAction = tableMenu.actions().first();
227 auto firstAction = tableMenu.actions().first();
228 auto headerAction = new QWidgetAction{&tableMenu};
228 auto headerAction = new QWidgetAction{&tableMenu};
229 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
229 headerAction->setDefaultWidget(new VariableMenuHeaderWidget{selectedVariables, &tableMenu});
230 tableMenu.insertAction(firstAction, headerAction);
230 tableMenu.insertAction(firstAction, headerAction);
231
231
232 // Displays menu
232 // Displays menu
233 tableMenu.exec(QCursor::pos());
233 tableMenu.exec(QCursor::pos());
234 }
234 }
235 }
235 }
236
236
237 void VariableInspectorWidget::refresh() noexcept
237 void VariableInspectorWidget::refresh() noexcept
238 {
238 {
239 ui->tableView->viewport()->update();
239 ui->tableView->viewport()->update();
240 }
240 }
@@ -1,499 +1,500
1 #include "Visualization/VisualizationDragDropContainer.h"
1 #include "Visualization/VisualizationDragDropContainer.h"
2 #include "DragAndDrop/DragDropHelper.h"
2 #include "DragAndDrop/DragDropGuiController.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 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
17 auto DRAGGED_MINIATURE_WIDTH = 200; // in pixels
18
18
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
19 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
20
20
21 QVBoxLayout *m_Layout;
21 QVBoxLayout *m_Layout;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
22 QHash<QString, VisualizationDragDropContainer::DropBehavior> m_AcceptedMimeTypes;
23 QString m_PlaceHolderText;
23 QString m_PlaceHolderText;
24 DragDropHelper::PlaceHolderType m_PlaceHolderType;
24 DragDropGuiController::PlaceHolderType m_PlaceHolderType;
25
25
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
26 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
27 = [](auto mimeData) { return true; };
27 = [](auto mimeData) { return true; };
28 VisualizationDragDropContainer::AcceptDragWidgetFunction m_AcceptDragWidgetFun
28 VisualizationDragDropContainer::AcceptDragWidgetFunction m_AcceptDragWidgetFun
29 = [](auto dragWidget, auto mimeData) { return true; };
29 = [](auto dragWidget, auto mimeData) { return true; };
30
30
31 int m_MinContainerHeight = 0;
31 int m_MinContainerHeight = 0;
32
32
33 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
33 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
34 : m_PlaceHolderType(DragDropHelper::PlaceHolderType::Graph)
34 : m_PlaceHolderType(DragDropGuiController::PlaceHolderType::Graph)
35 {
35 {
36 m_Layout = new QVBoxLayout(widget);
36 m_Layout = new QVBoxLayout(widget);
37 m_Layout->setContentsMargins(0, 0, 0, 0);
37 m_Layout->setContentsMargins(0, 0, 0, 0);
38 }
38 }
39
39
40 bool acceptMimeData(const QMimeData *data) const
40 bool acceptMimeData(const QMimeData *data) const
41 {
41 {
42 auto accepted = false;
42 auto accepted = false;
43 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
43 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
44 ++it) {
44 ++it) {
45 const auto &type = it.key();
45 const auto &type = it.key();
46 const auto &behavior = it.value();
46 const auto &behavior = it.value();
47
47
48 if (data->hasFormat(type)) {
48 if (data->hasFormat(type)) {
49 if (behavior != DropBehavior::Forbidden) {
49 if (behavior != DropBehavior::Forbidden) {
50 accepted = true;
50 accepted = true;
51 }
51 }
52 else {
52 else {
53 accepted = false;
53 accepted = false;
54 break;
54 break;
55 }
55 }
56 }
56 }
57 }
57 }
58
58
59 if (accepted) {
59 if (accepted) {
60 accepted = m_AcceptMimeDataFun(data);
60 accepted = m_AcceptMimeDataFun(data);
61 }
61 }
62
62
63 return accepted;
63 return accepted;
64 }
64 }
65
65
66 bool allowMergeForMimeData(const QMimeData *data) const
66 bool allowMergeForMimeData(const QMimeData *data) const
67 {
67 {
68 auto result = false;
68 auto result = false;
69 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
69 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
70 ++it) {
70 ++it) {
71
71
72 if (data->hasFormat(it.key())
72 if (data->hasFormat(it.key())
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
73 && (it.value() == VisualizationDragDropContainer::DropBehavior::Merged
74 || it.value()
74 || it.value()
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
75 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
76 result = true;
76 result = true;
77 }
77 }
78 else if (data->hasFormat(it.key())
78 else if (data->hasFormat(it.key())
79 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
79 && it.value() == VisualizationDragDropContainer::DropBehavior::Inserted) {
80 // Merge is forbidden if the mime data contain an acceptable type which cannot be
80 // Merge is forbidden if the mime data contain an acceptable type which cannot be
81 // merged
81 // merged
82 result = false;
82 result = false;
83 break;
83 break;
84 }
84 }
85 }
85 }
86
86
87 return result;
87 return result;
88 }
88 }
89
89
90 bool allowInsertForMimeData(const QMimeData *data) const
90 bool allowInsertForMimeData(const QMimeData *data) const
91 {
91 {
92 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
92 for (auto it = m_AcceptedMimeTypes.constBegin(); it != m_AcceptedMimeTypes.constEnd();
93 ++it) {
93 ++it) {
94 if (data->hasFormat(it.key())
94 if (data->hasFormat(it.key())
95 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
95 && (it.value() == VisualizationDragDropContainer::DropBehavior::Inserted
96 || it.value()
96 || it.value()
97 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
97 == VisualizationDragDropContainer::DropBehavior::InsertedAndMerged)) {
98 return true;
98 return true;
99 }
99 }
100 }
100 }
101
101
102 return false;
102 return false;
103 }
103 }
104
104
105 bool hasPlaceHolder() const
105 bool hasPlaceHolder() const
106 {
106 {
107 return sqpApp->dragDropHelper().placeHolder().parentWidget() == m_Layout->parentWidget();
107 return sqpApp->dragDropGuiController().placeHolder().parentWidget()
108 == m_Layout->parentWidget();
108 }
109 }
109
110
110 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
111 VisualizationDragWidget *getChildDragWidgetAt(const QWidget *parent, const QPoint &pos) const
111 {
112 {
112 VisualizationDragWidget *dragWidget = nullptr;
113 VisualizationDragWidget *dragWidget = nullptr;
113
114
114 for (auto child : parent->children()) {
115 for (auto child : parent->children()) {
115 auto widget = qobject_cast<VisualizationDragWidget *>(child);
116 auto widget = qobject_cast<VisualizationDragWidget *>(child);
116 if (widget && widget->isVisible()) {
117 if (widget && widget->isVisible()) {
117 if (widget->frameGeometry().contains(pos)) {
118 if (widget->frameGeometry().contains(pos)) {
118 dragWidget = widget;
119 dragWidget = widget;
119 break;
120 break;
120 }
121 }
121 }
122 }
122 }
123 }
123
124
124 return dragWidget;
125 return dragWidget;
125 }
126 }
126
127
127 bool cursorIsInContainer(QWidget *container) const
128 bool cursorIsInContainer(QWidget *container) const
128 {
129 {
129 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
130 auto widgetUnderMouse = sqpApp->widgetAt(QCursor::pos());
130 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
131 return container->isAncestorOf(widgetUnderMouse) && widgetUnderMouse != container
131 && sqpApp->dragDropHelper().placeHolder().isAncestorOf(widgetUnderMouse);
132 && sqpApp->dragDropGuiController().placeHolder().isAncestorOf(widgetUnderMouse);
132 }
133 }
133
134
134 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
135 int countDragWidget(const QWidget *parent, bool onlyVisible = false) const
135 {
136 {
136 auto nbGraph = 0;
137 auto nbGraph = 0;
137 for (auto child : parent->children()) {
138 for (auto child : parent->children()) {
138 if (qobject_cast<VisualizationDragWidget *>(child)) {
139 if (qobject_cast<VisualizationDragWidget *>(child)) {
139 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
140 if (!onlyVisible || qobject_cast<VisualizationDragWidget *>(child)->isVisible()) {
140 nbGraph += 1;
141 nbGraph += 1;
141 }
142 }
142 }
143 }
143 }
144 }
144
145
145 return nbGraph;
146 return nbGraph;
146 }
147 }
147
148
148 bool findPlaceHolderPosition(const QPoint &pos, const QMimeData *mimeData, bool canInsert,
149 bool findPlaceHolderPosition(const QPoint &pos, const QMimeData *mimeData, bool canInsert,
149 bool canMerge, const VisualizationDragDropContainer *container);
150 bool canMerge, const VisualizationDragDropContainer *container);
150 };
151 };
151
152
152 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
153 VisualizationDragDropContainer::VisualizationDragDropContainer(QWidget *parent)
153 : QFrame{parent},
154 : QFrame{parent},
154 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
155 impl{spimpl::make_unique_impl<VisualizationDragDropContainerPrivate>(this)}
155 {
156 {
156 setAcceptDrops(true);
157 setAcceptDrops(true);
157 }
158 }
158
159
159 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
160 void VisualizationDragDropContainer::addDragWidget(VisualizationDragWidget *dragWidget)
160 {
161 {
161 impl->m_Layout->addWidget(dragWidget);
162 impl->m_Layout->addWidget(dragWidget);
162 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
163 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
163 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
164 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
164 &VisualizationDragDropContainer::startDrag);
165 &VisualizationDragDropContainer::startDrag);
165 }
166 }
166
167
167 void VisualizationDragDropContainer::insertDragWidget(int index,
168 void VisualizationDragDropContainer::insertDragWidget(int index,
168 VisualizationDragWidget *dragWidget)
169 VisualizationDragWidget *dragWidget)
169 {
170 {
170 impl->m_Layout->insertWidget(index, dragWidget);
171 impl->m_Layout->insertWidget(index, dragWidget);
171 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
172 disconnect(dragWidget, &VisualizationDragWidget::dragDetected, nullptr, nullptr);
172 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
173 connect(dragWidget, &VisualizationDragWidget::dragDetected, this,
173 &VisualizationDragDropContainer::startDrag);
174 &VisualizationDragDropContainer::startDrag);
174 }
175 }
175
176
176 void VisualizationDragDropContainer::setMimeType(
177 void VisualizationDragDropContainer::setMimeType(
177 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
178 const QString &mimeType, VisualizationDragDropContainer::DropBehavior behavior)
178 {
179 {
179 impl->m_AcceptedMimeTypes[mimeType] = behavior;
180 impl->m_AcceptedMimeTypes[mimeType] = behavior;
180 }
181 }
181
182
182 int VisualizationDragDropContainer::countDragWidget() const
183 int VisualizationDragDropContainer::countDragWidget() const
183 {
184 {
184 return impl->countDragWidget(this);
185 return impl->countDragWidget(this);
185 }
186 }
186
187
187 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
188 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
188 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
189 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
189 {
190 {
190 impl->m_AcceptMimeDataFun = fun;
191 impl->m_AcceptMimeDataFun = fun;
191 }
192 }
192
193
193 void VisualizationDragDropContainer::setAcceptDragWidgetFunction(
194 void VisualizationDragDropContainer::setAcceptDragWidgetFunction(
194 VisualizationDragDropContainer::AcceptDragWidgetFunction fun)
195 VisualizationDragDropContainer::AcceptDragWidgetFunction fun)
195 {
196 {
196 impl->m_AcceptDragWidgetFun = fun;
197 impl->m_AcceptDragWidgetFun = fun;
197 }
198 }
198
199
199 void VisualizationDragDropContainer::setPlaceHolderType(DragDropHelper::PlaceHolderType type,
200 void VisualizationDragDropContainer::setPlaceHolderType(DragDropGuiController::PlaceHolderType type,
200 const QString &placeHolderText)
201 const QString &placeHolderText)
201 {
202 {
202 impl->m_PlaceHolderType = type;
203 impl->m_PlaceHolderType = type;
203 impl->m_PlaceHolderText = placeHolderText;
204 impl->m_PlaceHolderText = placeHolderText;
204 }
205 }
205
206
206 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
207 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
207 const QPoint &dragPosition)
208 const QPoint &dragPosition)
208 {
209 {
209 auto &helper = sqpApp->dragDropHelper();
210 auto &helper = sqpApp->dragDropGuiController();
210 helper.resetDragAndDrop();
211 helper.resetDragAndDrop();
211
212
212 // Note: The management of the drag object is done by Qt
213 // Note: The management of the drag object is done by Qt
213 auto drag = new QDrag{dragWidget};
214 auto drag = new QDrag{dragWidget};
214
215
215 auto mimeData = dragWidget->mimeData(dragPosition);
216 auto mimeData = dragWidget->mimeData(dragPosition);
216 drag->setMimeData(mimeData);
217 drag->setMimeData(mimeData);
217
218
218 auto pixmap = dragWidget->customDragPixmap(dragPosition);
219 auto pixmap = dragWidget->customDragPixmap(dragPosition);
219 if (pixmap.isNull()) {
220 if (pixmap.isNull()) {
220 pixmap = QPixmap{dragWidget->size()};
221 pixmap = QPixmap{dragWidget->size()};
221 dragWidget->render(&pixmap);
222 dragWidget->render(&pixmap);
222 }
223 }
223
224
224 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
225 drag->setPixmap(pixmap.scaled(DRAGGED_MINIATURE_WIDTH, DRAGGED_MINIATURE_WIDTH,
225 Qt::KeepAspectRatio, Qt::SmoothTransformation));
226 Qt::KeepAspectRatio, Qt::SmoothTransformation));
226
227
227 auto image = pixmap.toImage();
228 auto image = pixmap.toImage();
228 mimeData->setImageData(image);
229 mimeData->setImageData(image);
229 mimeData->setUrls({helper.imageTemporaryUrl(image)});
230 mimeData->setUrls({helper.imageTemporaryUrl(image)});
230
231
231 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
232 if (impl->m_Layout->indexOf(dragWidget) >= 0) {
232
233
233 if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) {
234 if (impl->acceptMimeData(mimeData) && impl->allowInsertForMimeData(mimeData)) {
234 helper.setCurrentDragWidget(dragWidget);
235 helper.setCurrentDragWidget(dragWidget);
235
236
236 if (impl->cursorIsInContainer(this)) {
237 if (impl->cursorIsInContainer(this)) {
237 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
238 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
238 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
239 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex, impl->m_PlaceHolderType,
239 impl->m_PlaceHolderText);
240 impl->m_PlaceHolderText);
240 dragWidget->setVisible(false);
241 dragWidget->setVisible(false);
241 }
242 }
242 else {
243 else {
243 // The drag starts directly outside the drop zone
244 // The drag starts directly outside the drop zone
244 // do not add the placeHolder
245 // do not add the placeHolder
245 }
246 }
246 }
247 }
247
248
248 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
249 drag->exec(Qt::MoveAction | Qt::CopyAction, Qt::MoveAction);
249
250
250 helper.doCloseWidgets();
251 helper.doCloseWidgets();
251 }
252 }
252 else {
253 else {
253 qCWarning(LOG_VisualizationDragDropContainer())
254 qCWarning(LOG_VisualizationDragDropContainer())
254 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
255 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
255 "VisualizationDragWidget is not found in this container.");
256 "VisualizationDragWidget is not found in this container.");
256 }
257 }
257 }
258 }
258
259
259 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
260 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
260 {
261 {
261 if (impl->acceptMimeData(event->mimeData())) {
262 if (impl->acceptMimeData(event->mimeData())) {
262 event->acceptProposedAction();
263 event->acceptProposedAction();
263
264
264 auto &helper = sqpApp->dragDropHelper();
265 auto &helper = sqpApp->dragDropGuiController();
265
266
266 if (!impl->hasPlaceHolder()) {
267 if (!impl->hasPlaceHolder()) {
267 auto dragWidget = helper.getCurrentDragWidget();
268 auto dragWidget = helper.getCurrentDragWidget();
268
269
269 if (dragWidget) {
270 if (dragWidget) {
270 // If the drag&drop is internal to the visualization, entering the container hide
271 // If the drag&drop is internal to the visualization, entering the container hide
271 // the dragWidget which was made visible by the dragLeaveEvent
272 // the dragWidget which was made visible by the dragLeaveEvent
272 auto parentWidget
273 auto parentWidget
273 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
274 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
274 if (parentWidget) {
275 if (parentWidget) {
275 dragWidget->setVisible(false);
276 dragWidget->setVisible(false);
276 }
277 }
277 }
278 }
278
279
279 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
280 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
280 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
281 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
281 if (!impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge,
282 if (!impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge,
282 this)) {
283 this)) {
283 event->ignore();
284 event->ignore();
284 }
285 }
285 }
286 }
286 else {
287 else {
287 // do nothing
288 // do nothing
288 }
289 }
289 }
290 }
290 else {
291 else {
291 event->ignore();
292 event->ignore();
292 }
293 }
293
294
294 QWidget::dragEnterEvent(event);
295 QWidget::dragEnterEvent(event);
295 }
296 }
296
297
297 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
298 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
298 {
299 {
299 Q_UNUSED(event);
300 Q_UNUSED(event);
300
301
301 auto &helper = sqpApp->dragDropHelper();
302 auto &helper = sqpApp->dragDropGuiController();
302
303
303 if (!impl->cursorIsInContainer(this)) {
304 if (!impl->cursorIsInContainer(this)) {
304 helper.removePlaceHolder();
305 helper.removePlaceHolder();
305 helper.setHightlightedDragWidget(nullptr);
306 helper.setHightlightedDragWidget(nullptr);
306 impl->m_MinContainerHeight = 0;
307 impl->m_MinContainerHeight = 0;
307
308
308 auto dragWidget = helper.getCurrentDragWidget();
309 auto dragWidget = helper.getCurrentDragWidget();
309 if (dragWidget) {
310 if (dragWidget) {
310 // dragWidget has a value only if the drag is started from the visualization
311 // dragWidget has a value only if the drag is started from the visualization
311 // In that case, shows the drag widget at its original place
312 // In that case, shows the drag widget at its original place
312 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
313 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
313 // drop zone (It is not possible to catch a drop event outside of the application)
314 // drop zone (It is not possible to catch a drop event outside of the application)
314
315
315 if (dragWidget) {
316 if (dragWidget) {
316 dragWidget->setVisible(true);
317 dragWidget->setVisible(true);
317 }
318 }
318 }
319 }
319 }
320 }
320 else {
321 else {
321 // Leave event probably received for a child widget.
322 // Leave event probably received for a child widget.
322 // Do nothing.
323 // Do nothing.
323 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
324 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
324 }
325 }
325
326
326 QWidget::dragLeaveEvent(event);
327 QWidget::dragLeaveEvent(event);
327 }
328 }
328
329
329 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
330 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
330 {
331 {
331 if (impl->acceptMimeData(event->mimeData())) {
332 if (impl->acceptMimeData(event->mimeData())) {
332 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
333 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
333 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
334 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
334 impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, this);
335 impl->findPlaceHolderPosition(event->pos(), event->mimeData(), canInsert, canMerge, this);
335 }
336 }
336 else {
337 else {
337 event->ignore();
338 event->ignore();
338 }
339 }
339
340
340 QWidget::dragMoveEvent(event);
341 QWidget::dragMoveEvent(event);
341 }
342 }
342
343
343 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
344 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
344 {
345 {
345 auto &helper = sqpApp->dragDropHelper();
346 auto &helper = sqpApp->dragDropGuiController();
346
347
347 if (impl->acceptMimeData(event->mimeData())) {
348 if (impl->acceptMimeData(event->mimeData())) {
348 auto dragWidget = helper.getCurrentDragWidget();
349 auto dragWidget = helper.getCurrentDragWidget();
349 if (impl->hasPlaceHolder()) {
350 if (impl->hasPlaceHolder()) {
350 // drop where the placeHolder is located
351 // drop where the placeHolder is located
351
352
352 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
353 auto canInsert = impl->allowInsertForMimeData(event->mimeData());
353 if (canInsert) {
354 if (canInsert) {
354 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
355 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
355
356
356 if (dragWidget) {
357 if (dragWidget) {
357 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
358 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
358 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
359 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
359 // Correction of the index if the drop occurs in the same container
360 // Correction of the index if the drop occurs in the same container
360 // and if the drag is started from the visualization (in that case, the
361 // and if the drag is started from the visualization (in that case, the
361 // dragWidget is hidden)
362 // dragWidget is hidden)
362 droppedIndex -= 1;
363 droppedIndex -= 1;
363 }
364 }
364
365
365 dragWidget->setVisible(true);
366 dragWidget->setVisible(true);
366 }
367 }
367
368
368 event->acceptProposedAction();
369 event->acceptProposedAction();
369
370
370 helper.removePlaceHolder();
371 helper.removePlaceHolder();
371
372
372 emit dropOccuredInContainer(droppedIndex, event->mimeData());
373 emit dropOccuredInContainer(droppedIndex, event->mimeData());
373 }
374 }
374 else {
375 else {
375 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
376 qCWarning(LOG_VisualizationDragDropContainer()) << tr(
376 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
377 "VisualizationDragDropContainer::dropEvent, dropping on the placeHolder, but "
377 "the insertion is forbidden.");
378 "the insertion is forbidden.");
378 Q_ASSERT(false);
379 Q_ASSERT(false);
379 }
380 }
380 }
381 }
381 else if (helper.getHightlightedDragWidget()) {
382 else if (helper.getHightlightedDragWidget()) {
382 // drop on the highlighted widget
383 // drop on the highlighted widget
383
384
384 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
385 auto canMerge = impl->allowMergeForMimeData(event->mimeData());
385 if (canMerge) {
386 if (canMerge) {
386 event->acceptProposedAction();
387 event->acceptProposedAction();
387 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
388 emit dropOccuredOnWidget(helper.getHightlightedDragWidget(), event->mimeData());
388 }
389 }
389 else {
390 else {
390 qCWarning(LOG_VisualizationDragDropContainer())
391 qCWarning(LOG_VisualizationDragDropContainer())
391 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
392 << tr("VisualizationDragDropContainer::dropEvent, dropping on a widget, but "
392 "the merge is forbidden.");
393 "the merge is forbidden.");
393 Q_ASSERT(false);
394 Q_ASSERT(false);
394 }
395 }
395 }
396 }
396 }
397 }
397 else {
398 else {
398 event->ignore();
399 event->ignore();
399 }
400 }
400
401
401 sqpApp->dragDropHelper().setHightlightedDragWidget(nullptr);
402 sqpApp->dragDropGuiController().setHightlightedDragWidget(nullptr);
402 impl->m_MinContainerHeight = 0;
403 impl->m_MinContainerHeight = 0;
403
404
404 QWidget::dropEvent(event);
405 QWidget::dropEvent(event);
405 }
406 }
406
407
407
408
408 bool VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
409 bool VisualizationDragDropContainer::VisualizationDragDropContainerPrivate::findPlaceHolderPosition(
409 const QPoint &pos, const QMimeData *mimeData, bool canInsert, bool canMerge,
410 const QPoint &pos, const QMimeData *mimeData, bool canInsert, bool canMerge,
410 const VisualizationDragDropContainer *container)
411 const VisualizationDragDropContainer *container)
411 {
412 {
412 auto &helper = sqpApp->dragDropHelper();
413 auto &helper = sqpApp->dragDropGuiController();
413
414
414 auto absPos = container->mapToGlobal(pos);
415 auto absPos = container->mapToGlobal(pos);
415 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
416 auto isOnPlaceHolder = helper.placeHolder().isAncestorOf(sqpApp->widgetAt(absPos));
416
417
417 if (countDragWidget(container, true) == 0) {
418 if (countDragWidget(container, true) == 0) {
418 // Drop on an empty container, just add the placeHolder at the top
419 // Drop on an empty container, just add the placeHolder at the top
419 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
420 helper.insertPlaceHolder(m_Layout, 0, m_PlaceHolderType, m_PlaceHolderText);
420 }
421 }
421 else if (!isOnPlaceHolder) {
422 else if (!isOnPlaceHolder) {
422 auto nbDragWidget = countDragWidget(container);
423 auto nbDragWidget = countDragWidget(container);
423 if (nbDragWidget > 0) {
424 if (nbDragWidget > 0) {
424
425
425 if (m_MinContainerHeight == 0) {
426 if (m_MinContainerHeight == 0) {
426 m_MinContainerHeight = container->size().height();
427 m_MinContainerHeight = container->size().height();
427 }
428 }
428
429
429 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
430 m_MinContainerHeight = qMin(m_MinContainerHeight, container->size().height());
430 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
431 auto graphHeight = qMax(m_MinContainerHeight / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
431
432
432 auto posY = pos.y();
433 auto posY = pos.y();
433 auto dropIndex = floor(posY / graphHeight);
434 auto dropIndex = floor(posY / graphHeight);
434 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
435 auto zoneSize = qMin(graphHeight / 4.0, 75.0);
435
436
436
437
437 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
438 auto isOnTop = posY < dropIndex * graphHeight + zoneSize;
438 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
439 auto isOnBottom = posY > (dropIndex + 1) * graphHeight - zoneSize;
439
440
440 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
441 auto placeHolderIndex = m_Layout->indexOf(&(helper.placeHolder()));
441
442
442 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
443 auto dragWidgetHovered = getChildDragWidgetAt(container, pos);
443
444
444 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
445 if (canInsert && (isOnTop || isOnBottom || !canMerge)) {
445 if (isOnBottom) {
446 if (isOnBottom) {
446 dropIndex += 1;
447 dropIndex += 1;
447 }
448 }
448
449
449 if (helper.getCurrentDragWidget()) {
450 if (helper.getCurrentDragWidget()) {
450 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
451 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
451 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
452 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
452 // Correction of the index if the drop occurs in the same container
453 // Correction of the index if the drop occurs in the same container
453 // and if the drag is started from the visualization (in that case, the
454 // and if the drag is started from the visualization (in that case, the
454 // dragWidget is hidden)
455 // dragWidget is hidden)
455 dropIndex += 1;
456 dropIndex += 1;
456 }
457 }
457 }
458 }
458
459
459 if (dropIndex != placeHolderIndex) {
460 if (dropIndex != placeHolderIndex) {
460 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
461 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
461 m_PlaceHolderText);
462 m_PlaceHolderText);
462 }
463 }
463
464
464 helper.setHightlightedDragWidget(nullptr);
465 helper.setHightlightedDragWidget(nullptr);
465 }
466 }
466 else if (canMerge && dragWidgetHovered) {
467 else if (canMerge && dragWidgetHovered) {
467 // drop on the middle -> merge
468 // drop on the middle -> merge
468 if (hasPlaceHolder()) {
469 if (hasPlaceHolder()) {
469 helper.removePlaceHolder();
470 helper.removePlaceHolder();
470 }
471 }
471
472
472 if (m_AcceptDragWidgetFun(dragWidgetHovered, mimeData)) {
473 if (m_AcceptDragWidgetFun(dragWidgetHovered, mimeData)) {
473 helper.setHightlightedDragWidget(dragWidgetHovered);
474 helper.setHightlightedDragWidget(dragWidgetHovered);
474 return true;
475 return true;
475 }
476 }
476 else {
477 else {
477 return false;
478 return false;
478 }
479 }
479 }
480 }
480 else {
481 else {
481 qCWarning(LOG_VisualizationDragDropContainer())
482 qCWarning(LOG_VisualizationDragDropContainer())
482 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
483 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
483 "action.");
484 "action.");
484 }
485 }
485 }
486 }
486 else {
487 else {
487 qCWarning(LOG_VisualizationDragDropContainer())
488 qCWarning(LOG_VisualizationDragDropContainer())
488 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
489 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
489 "found in the "
490 "found in the "
490 "container");
491 "container");
491 }
492 }
492 }
493 }
493 else {
494 else {
494 // the mouse is hover the placeHolder
495 // the mouse is hover the placeHolder
495 // Do nothing
496 // Do nothing
496 }
497 }
497
498
498 return true;
499 return true;
499 }
500 }
@@ -1,876 +1,876
1 #include "Visualization/VisualizationGraphWidget.h"
1 #include "Visualization/VisualizationGraphWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationCursorItem.h"
3 #include "Visualization/VisualizationCursorItem.h"
4 #include "Visualization/VisualizationDefs.h"
4 #include "Visualization/VisualizationDefs.h"
5 #include "Visualization/VisualizationGraphHelper.h"
5 #include "Visualization/VisualizationGraphHelper.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
6 #include "Visualization/VisualizationGraphRenderingDelegate.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationSelectionZoneManager.h"
8 #include "Visualization/VisualizationSelectionZoneManager.h"
9 #include "Visualization/VisualizationWidget.h"
9 #include "Visualization/VisualizationWidget.h"
10 #include "Visualization/VisualizationZoneWidget.h"
10 #include "Visualization/VisualizationZoneWidget.h"
11 #include "ui_VisualizationGraphWidget.h"
11 #include "ui_VisualizationGraphWidget.h"
12
12
13 #include <Common/MimeTypesDef.h>
13 #include <Common/MimeTypesDef.h>
14 #include <Data/ArrayData.h>
14 #include <Data/ArrayData.h>
15 #include <Data/IDataSeries.h>
15 #include <Data/IDataSeries.h>
16 #include <Data/SpectrogramSeries.h>
16 #include <Data/SpectrogramSeries.h>
17 #include <DragAndDrop/DragDropHelper.h>
17 #include <DragAndDrop/DragDropGuiController.h>
18 #include <Settings/SqpSettingsDefs.h>
18 #include <Settings/SqpSettingsDefs.h>
19 #include <SqpApplication.h>
19 #include <SqpApplication.h>
20 #include <Time/TimeController.h>
20 #include <Time/TimeController.h>
21 #include <Variable/Variable.h>
21 #include <Variable/Variable.h>
22 #include <Variable/VariableController.h>
22 #include <Variable/VariableController.h>
23
23
24 #include <unordered_map>
24 #include <unordered_map>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
27
27
28 namespace {
28 namespace {
29
29
30 /// Key pressed to enable drag&drop in all modes
30 /// Key pressed to enable drag&drop in all modes
31 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
31 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
32
32
33 /// Key pressed to enable zoom on horizontal axis
33 /// Key pressed to enable zoom on horizontal axis
34 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
34 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
35
35
36 /// Key pressed to enable zoom on vertical axis
36 /// Key pressed to enable zoom on vertical axis
37 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
37 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
38
38
39 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
39 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
40 const auto PAN_SPEED = 5;
40 const auto PAN_SPEED = 5;
41
41
42 /// Key pressed to enable a calibration pan
42 /// Key pressed to enable a calibration pan
43 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
43 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
44
44
45 /// Key pressed to enable multi selection of selection zones
45 /// Key pressed to enable multi selection of selection zones
46 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
46 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
47
47
48 /// Minimum size for the zoom box, in percentage of the axis range
48 /// Minimum size for the zoom box, in percentage of the axis range
49 const auto ZOOM_BOX_MIN_SIZE = 0.8;
49 const auto ZOOM_BOX_MIN_SIZE = 0.8;
50
50
51 /// Format of the dates appearing in the label of a cursor
51 /// Format of the dates appearing in the label of a cursor
52 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
52 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
53
53
54 } // namespace
54 } // namespace
55
55
56 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
56 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
57
57
58 explicit VisualizationGraphWidgetPrivate(const QString &name)
58 explicit VisualizationGraphWidgetPrivate(const QString &name)
59 : m_Name{name},
59 : m_Name{name},
60 m_DoAcquisition{true},
60 m_DoAcquisition{true},
61 m_IsCalibration{false},
61 m_IsCalibration{false},
62 m_RenderingDelegate{nullptr}
62 m_RenderingDelegate{nullptr}
63 {
63 {
64 }
64 }
65
65
66 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
66 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
67 const SqpRange &range)
67 const SqpRange &range)
68 {
68 {
69 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
69 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
70
70
71 // Prevents that data has changed to update rendering
71 // Prevents that data has changed to update rendering
72 m_RenderingDelegate->onPlotUpdated();
72 m_RenderingDelegate->onPlotUpdated();
73 }
73 }
74
74
75 QString m_Name;
75 QString m_Name;
76 // 1 variable -> n qcpplot
76 // 1 variable -> n qcpplot
77 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
77 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
78 bool m_DoAcquisition;
78 bool m_DoAcquisition;
79 bool m_IsCalibration;
79 bool m_IsCalibration;
80 /// Delegate used to attach rendering features to the plot
80 /// Delegate used to attach rendering features to the plot
81 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
81 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
82
82
83 QCPItemRect *m_DrawingZoomRect = nullptr;
83 QCPItemRect *m_DrawingZoomRect = nullptr;
84 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
84 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
85
85
86 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
86 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
87 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
87 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
88
88
89 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
89 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
90 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
90 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
91 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
91 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
92
92
93 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
93 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
94
94
95 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
95 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
96 {
96 {
97 removeDrawingRect(plot);
97 removeDrawingRect(plot);
98
98
99 auto axisPos = posToAxisPos(pos, plot);
99 auto axisPos = posToAxisPos(pos, plot);
100
100
101 m_DrawingZoomRect = new QCPItemRect{&plot};
101 m_DrawingZoomRect = new QCPItemRect{&plot};
102 QPen p;
102 QPen p;
103 p.setWidth(2);
103 p.setWidth(2);
104 m_DrawingZoomRect->setPen(p);
104 m_DrawingZoomRect->setPen(p);
105
105
106 m_DrawingZoomRect->topLeft->setCoords(axisPos);
106 m_DrawingZoomRect->topLeft->setCoords(axisPos);
107 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
107 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
108 }
108 }
109
109
110 void removeDrawingRect(QCustomPlot &plot)
110 void removeDrawingRect(QCustomPlot &plot)
111 {
111 {
112 if (m_DrawingZoomRect) {
112 if (m_DrawingZoomRect) {
113 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
113 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
114 m_DrawingZoomRect = nullptr;
114 m_DrawingZoomRect = nullptr;
115 plot.replot(QCustomPlot::rpQueuedReplot);
115 plot.replot(QCustomPlot::rpQueuedReplot);
116 }
116 }
117 }
117 }
118
118
119 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
119 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
120 {
120 {
121 endDrawingZone(graph);
121 endDrawingZone(graph);
122
122
123 auto axisPos = posToAxisPos(pos, graph->plot());
123 auto axisPos = posToAxisPos(pos, graph->plot());
124
124
125 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
125 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
126 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
126 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
127 m_DrawingZone->setEditionEnabled(false);
127 m_DrawingZone->setEditionEnabled(false);
128 }
128 }
129
129
130 void endDrawingZone(VisualizationGraphWidget *graph)
130 void endDrawingZone(VisualizationGraphWidget *graph)
131 {
131 {
132 if (m_DrawingZone) {
132 if (m_DrawingZone) {
133 auto drawingZoneRange = m_DrawingZone->range();
133 auto drawingZoneRange = m_DrawingZone->range();
134 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
134 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
135 m_DrawingZone->setEditionEnabled(true);
135 m_DrawingZone->setEditionEnabled(true);
136 addSelectionZone(m_DrawingZone);
136 addSelectionZone(m_DrawingZone);
137 }
137 }
138 else {
138 else {
139 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
139 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
140 }
140 }
141
141
142 graph->plot().replot(QCustomPlot::rpQueuedReplot);
142 graph->plot().replot(QCustomPlot::rpQueuedReplot);
143 m_DrawingZone = nullptr;
143 m_DrawingZone = nullptr;
144 }
144 }
145 }
145 }
146
146
147 void setSelectionZonesEditionEnabled(bool value)
147 void setSelectionZonesEditionEnabled(bool value)
148 {
148 {
149 for (auto s : m_SelectionZones) {
149 for (auto s : m_SelectionZones) {
150 s->setEditionEnabled(value);
150 s->setEditionEnabled(value);
151 }
151 }
152 }
152 }
153
153
154 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
154 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
155
155
156 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
156 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
157 const QCustomPlot &plot) const
157 const QCustomPlot &plot) const
158 {
158 {
159 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
159 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
160 auto minDistanceToZone = -1;
160 auto minDistanceToZone = -1;
161 for (auto zone : m_SelectionZones) {
161 for (auto zone : m_SelectionZones) {
162 auto distanceToZone = zone->selectTest(pos, false);
162 auto distanceToZone = zone->selectTest(pos, false);
163 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
163 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
164 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
164 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
165 selectionZoneItemUnderCursor = zone;
165 selectionZoneItemUnderCursor = zone;
166 }
166 }
167 }
167 }
168
168
169 return selectionZoneItemUnderCursor;
169 return selectionZoneItemUnderCursor;
170 }
170 }
171
171
172 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
172 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
173 {
173 {
174 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
174 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
175 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
175 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
176 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
176 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
177 }
177 }
178
178
179 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
179 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
180 {
180 {
181 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
181 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
182 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
182 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
183 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
183 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
184 }
184 }
185 };
185 };
186
186
187 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
187 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
188 : VisualizationDragWidget{parent},
188 : VisualizationDragWidget{parent},
189 ui{new Ui::VisualizationGraphWidget},
189 ui{new Ui::VisualizationGraphWidget},
190 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
190 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
191 {
191 {
192 ui->setupUi(this);
192 ui->setupUi(this);
193
193
194 // 'Close' options : widget is deleted when closed
194 // 'Close' options : widget is deleted when closed
195 setAttribute(Qt::WA_DeleteOnClose);
195 setAttribute(Qt::WA_DeleteOnClose);
196
196
197 // Set qcpplot properties :
197 // Set qcpplot properties :
198 // - zoom is enabled
198 // - zoom is enabled
199 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
199 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
200 ui->widget->setInteractions(QCP::iRangeZoom);
200 ui->widget->setInteractions(QCP::iRangeZoom);
201 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
201 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
202
202
203 // The delegate must be initialized after the ui as it uses the plot
203 // The delegate must be initialized after the ui as it uses the plot
204 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
204 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
205
205
206 // Init the cursors
206 // Init the cursors
207 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
207 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
208 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
208 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
209 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
209 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
210 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
210 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
211
211
212 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
212 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
213 connect(ui->widget, &QCustomPlot::mouseRelease, this,
213 connect(ui->widget, &QCustomPlot::mouseRelease, this,
214 &VisualizationGraphWidget::onMouseRelease);
214 &VisualizationGraphWidget::onMouseRelease);
215 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
215 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
216 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
216 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
217 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
217 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
218 &VisualizationGraphWidget::onMouseDoubleClick);
218 &VisualizationGraphWidget::onMouseDoubleClick);
219 connect(
219 connect(
220 ui->widget->xAxis,
220 ui->widget->xAxis,
221 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
221 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
222 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
222 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
223
223
224 // Activates menu when right clicking on the graph
224 // Activates menu when right clicking on the graph
225 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
225 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
226 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
226 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
227 &VisualizationGraphWidget::onGraphMenuRequested);
227 &VisualizationGraphWidget::onGraphMenuRequested);
228
228
229 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
229 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
230 &VariableController::onRequestDataLoading);
230 &VariableController::onRequestDataLoading);
231
231
232 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
232 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
233 &VisualizationGraphWidget::onUpdateVarDisplaying);
233 &VisualizationGraphWidget::onUpdateVarDisplaying);
234
234
235 #ifdef Q_OS_MAC
235 #ifdef Q_OS_MAC
236 plot().setPlottingHint(QCP::phFastPolylines, true);
236 plot().setPlottingHint(QCP::phFastPolylines, true);
237 #endif
237 #endif
238 }
238 }
239
239
240
240
241 VisualizationGraphWidget::~VisualizationGraphWidget()
241 VisualizationGraphWidget::~VisualizationGraphWidget()
242 {
242 {
243 delete ui;
243 delete ui;
244 }
244 }
245
245
246 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
246 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
247 {
247 {
248 auto parent = parentWidget();
248 auto parent = parentWidget();
249 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
249 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
250 parent = parent->parentWidget();
250 parent = parent->parentWidget();
251 }
251 }
252
252
253 return qobject_cast<VisualizationZoneWidget *>(parent);
253 return qobject_cast<VisualizationZoneWidget *>(parent);
254 }
254 }
255
255
256 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
256 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
257 {
257 {
258 auto parent = parentWidget();
258 auto parent = parentWidget();
259 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
259 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
260 parent = parent->parentWidget();
260 parent = parent->parentWidget();
261 }
261 }
262
262
263 return qobject_cast<VisualizationWidget *>(parent);
263 return qobject_cast<VisualizationWidget *>(parent);
264 }
264 }
265
265
266 void VisualizationGraphWidget::enableAcquisition(bool enable)
266 void VisualizationGraphWidget::enableAcquisition(bool enable)
267 {
267 {
268 impl->m_DoAcquisition = enable;
268 impl->m_DoAcquisition = enable;
269 }
269 }
270
270
271 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
271 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
272 {
272 {
273 // Uses delegate to create the qcpplot components according to the variable
273 // Uses delegate to create the qcpplot components according to the variable
274 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
274 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
275
275
276 if (auto dataSeries = variable->dataSeries()) {
276 if (auto dataSeries = variable->dataSeries()) {
277 // Set axes properties according to the units of the data series
277 // Set axes properties according to the units of the data series
278 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
278 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
279
279
280 // Sets rendering properties for the new plottables
280 // Sets rendering properties for the new plottables
281 // Warning: this method must be called after setAxesProperties(), as it can access to some
281 // Warning: this method must be called after setAxesProperties(), as it can access to some
282 // axes properties that have to be initialized
282 // axes properties that have to be initialized
283 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
283 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
284 }
284 }
285
285
286 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
286 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
287
287
288 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
288 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
289
289
290 this->enableAcquisition(false);
290 this->enableAcquisition(false);
291 this->setGraphRange(range);
291 this->setGraphRange(range);
292 this->enableAcquisition(true);
292 this->enableAcquisition(true);
293
293
294 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
294 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
295
295
296 emit variableAdded(variable);
296 emit variableAdded(variable);
297 }
297 }
298
298
299 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
299 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
300 {
300 {
301 // Each component associated to the variable :
301 // Each component associated to the variable :
302 // - is removed from qcpplot (which deletes it)
302 // - is removed from qcpplot (which deletes it)
303 // - is no longer referenced in the map
303 // - is no longer referenced in the map
304 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
304 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
305 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
305 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
306 emit variableAboutToBeRemoved(variable);
306 emit variableAboutToBeRemoved(variable);
307
307
308 auto &plottablesMap = variableIt->second;
308 auto &plottablesMap = variableIt->second;
309
309
310 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
310 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
311 plottableIt != plottableEnd;) {
311 plottableIt != plottableEnd;) {
312 ui->widget->removePlottable(plottableIt->second);
312 ui->widget->removePlottable(plottableIt->second);
313 plottableIt = plottablesMap.erase(plottableIt);
313 plottableIt = plottablesMap.erase(plottableIt);
314 }
314 }
315
315
316 impl->m_VariableToPlotMultiMap.erase(variableIt);
316 impl->m_VariableToPlotMultiMap.erase(variableIt);
317 }
317 }
318
318
319 // Updates graph
319 // Updates graph
320 ui->widget->replot();
320 ui->widget->replot();
321 }
321 }
322
322
323 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
323 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
324 {
324 {
325 auto variables = QList<std::shared_ptr<Variable> >{};
325 auto variables = QList<std::shared_ptr<Variable> >{};
326 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
326 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
327 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
327 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
328 variables << it->first;
328 variables << it->first;
329 }
329 }
330
330
331 return variables;
331 return variables;
332 }
332 }
333
333
334 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
334 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
335 {
335 {
336 if (!variable) {
336 if (!variable) {
337 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
337 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
338 return;
338 return;
339 }
339 }
340
340
341 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
341 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
342 }
342 }
343
343
344 SqpRange VisualizationGraphWidget::graphRange() const noexcept
344 SqpRange VisualizationGraphWidget::graphRange() const noexcept
345 {
345 {
346 auto graphRange = ui->widget->xAxis->range();
346 auto graphRange = ui->widget->xAxis->range();
347 return SqpRange{graphRange.lower, graphRange.upper};
347 return SqpRange{graphRange.lower, graphRange.upper};
348 }
348 }
349
349
350 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
350 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
351 {
351 {
352 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
352 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
353 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
353 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
354 ui->widget->replot();
354 ui->widget->replot();
355 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
355 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
356 }
356 }
357
357
358 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
358 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
359 {
359 {
360 QVector<SqpRange> ranges;
360 QVector<SqpRange> ranges;
361 for (auto zone : impl->m_SelectionZones) {
361 for (auto zone : impl->m_SelectionZones) {
362 ranges << zone->range();
362 ranges << zone->range();
363 }
363 }
364
364
365 return ranges;
365 return ranges;
366 }
366 }
367
367
368 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
368 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
369 {
369 {
370 for (const auto &range : ranges) {
370 for (const auto &range : ranges) {
371 // note: ownership is transfered to QCustomPlot
371 // note: ownership is transfered to QCustomPlot
372 auto zone = new VisualizationSelectionZoneItem(&plot());
372 auto zone = new VisualizationSelectionZoneItem(&plot());
373 zone->setRange(range.m_TStart, range.m_TEnd);
373 zone->setRange(range.m_TStart, range.m_TEnd);
374 impl->addSelectionZone(zone);
374 impl->addSelectionZone(zone);
375 }
375 }
376
376
377 plot().replot(QCustomPlot::rpQueuedReplot);
377 plot().replot(QCustomPlot::rpQueuedReplot);
378 }
378 }
379
379
380 void VisualizationGraphWidget::undoZoom()
380 void VisualizationGraphWidget::undoZoom()
381 {
381 {
382 auto zoom = impl->m_ZoomStack.pop();
382 auto zoom = impl->m_ZoomStack.pop();
383 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
383 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
384 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
384 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
385
385
386 axisX->setRange(zoom.first);
386 axisX->setRange(zoom.first);
387 axisY->setRange(zoom.second);
387 axisY->setRange(zoom.second);
388
388
389 plot().replot(QCustomPlot::rpQueuedReplot);
389 plot().replot(QCustomPlot::rpQueuedReplot);
390 }
390 }
391
391
392 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
392 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
393 {
393 {
394 if (visitor) {
394 if (visitor) {
395 visitor->visit(this);
395 visitor->visit(this);
396 }
396 }
397 else {
397 else {
398 qCCritical(LOG_VisualizationGraphWidget())
398 qCCritical(LOG_VisualizationGraphWidget())
399 << tr("Can't visit widget : the visitor is null");
399 << tr("Can't visit widget : the visitor is null");
400 }
400 }
401 }
401 }
402
402
403 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
403 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
404 {
404 {
405 auto isSpectrogram = [](const auto &variable) {
405 auto isSpectrogram = [](const auto &variable) {
406 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
406 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
407 };
407 };
408
408
409 // - A spectrogram series can't be dropped on graph with existing plottables
409 // - A spectrogram series can't be dropped on graph with existing plottables
410 // - No data series can be dropped on graph with existing spectrogram series
410 // - No data series can be dropped on graph with existing spectrogram series
411 return isSpectrogram(variable)
411 return isSpectrogram(variable)
412 ? impl->m_VariableToPlotMultiMap.empty()
412 ? impl->m_VariableToPlotMultiMap.empty()
413 : std::none_of(
413 : std::none_of(
414 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
414 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
415 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
415 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
416 }
416 }
417
417
418 bool VisualizationGraphWidget::contains(const Variable &variable) const
418 bool VisualizationGraphWidget::contains(const Variable &variable) const
419 {
419 {
420 // Finds the variable among the keys of the map
420 // Finds the variable among the keys of the map
421 auto variablePtr = &variable;
421 auto variablePtr = &variable;
422 auto findVariable
422 auto findVariable
423 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
423 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
424
424
425 auto end = impl->m_VariableToPlotMultiMap.cend();
425 auto end = impl->m_VariableToPlotMultiMap.cend();
426 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
426 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
427 return it != end;
427 return it != end;
428 }
428 }
429
429
430 QString VisualizationGraphWidget::name() const
430 QString VisualizationGraphWidget::name() const
431 {
431 {
432 return impl->m_Name;
432 return impl->m_Name;
433 }
433 }
434
434
435 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
435 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
436 {
436 {
437 auto mimeData = new QMimeData;
437 auto mimeData = new QMimeData;
438
438
439 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
439 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
440 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
440 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
441 && selectionZoneItemUnderCursor) {
441 && selectionZoneItemUnderCursor) {
442 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
442 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
443 selectionZoneItemUnderCursor->range()));
443 selectionZoneItemUnderCursor->range()));
444 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
444 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
445 selectionZoneItemUnderCursor->range()));
445 selectionZoneItemUnderCursor->range()));
446 }
446 }
447 else {
447 else {
448 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
448 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
449
449
450 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
450 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
451 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
451 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
452 }
452 }
453
453
454 return mimeData;
454 return mimeData;
455 }
455 }
456
456
457 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
457 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
458 {
458 {
459 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
459 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
460 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
460 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
461 && selectionZoneItemUnderCursor) {
461 && selectionZoneItemUnderCursor) {
462
462
463 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
463 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
464 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
464 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
465
465
466 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
466 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
467 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
467 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
468 .toSize();
468 .toSize();
469
469
470 auto pixmap = QPixmap(zoneSize);
470 auto pixmap = QPixmap(zoneSize);
471 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
471 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
472
472
473 return pixmap;
473 return pixmap;
474 }
474 }
475
475
476 return QPixmap();
476 return QPixmap();
477 }
477 }
478
478
479 bool VisualizationGraphWidget::isDragAllowed() const
479 bool VisualizationGraphWidget::isDragAllowed() const
480 {
480 {
481 return true;
481 return true;
482 }
482 }
483
483
484 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
484 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
485 {
485 {
486 if (highlighted) {
486 if (highlighted) {
487 plot().setBackground(QBrush(QColor("#BBD5EE")));
487 plot().setBackground(QBrush(QColor("#BBD5EE")));
488 }
488 }
489 else {
489 else {
490 plot().setBackground(QBrush(Qt::white));
490 plot().setBackground(QBrush(Qt::white));
491 }
491 }
492
492
493 plot().update();
493 plot().update();
494 }
494 }
495
495
496 void VisualizationGraphWidget::addVerticalCursor(double time)
496 void VisualizationGraphWidget::addVerticalCursor(double time)
497 {
497 {
498 impl->m_VerticalCursor->setPosition(time);
498 impl->m_VerticalCursor->setPosition(time);
499 impl->m_VerticalCursor->setVisible(true);
499 impl->m_VerticalCursor->setVisible(true);
500
500
501 auto text
501 auto text
502 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
502 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
503 impl->m_VerticalCursor->setLabelText(text);
503 impl->m_VerticalCursor->setLabelText(text);
504 }
504 }
505
505
506 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
506 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
507 {
507 {
508 impl->m_VerticalCursor->setAbsolutePosition(position);
508 impl->m_VerticalCursor->setAbsolutePosition(position);
509 impl->m_VerticalCursor->setVisible(true);
509 impl->m_VerticalCursor->setVisible(true);
510
510
511 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
511 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
512 auto text
512 auto text
513 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
513 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
514 impl->m_VerticalCursor->setLabelText(text);
514 impl->m_VerticalCursor->setLabelText(text);
515 }
515 }
516
516
517 void VisualizationGraphWidget::removeVerticalCursor()
517 void VisualizationGraphWidget::removeVerticalCursor()
518 {
518 {
519 impl->m_VerticalCursor->setVisible(false);
519 impl->m_VerticalCursor->setVisible(false);
520 plot().replot(QCustomPlot::rpQueuedReplot);
520 plot().replot(QCustomPlot::rpQueuedReplot);
521 }
521 }
522
522
523 void VisualizationGraphWidget::addHorizontalCursor(double value)
523 void VisualizationGraphWidget::addHorizontalCursor(double value)
524 {
524 {
525 impl->m_HorizontalCursor->setPosition(value);
525 impl->m_HorizontalCursor->setPosition(value);
526 impl->m_HorizontalCursor->setVisible(true);
526 impl->m_HorizontalCursor->setVisible(true);
527 impl->m_HorizontalCursor->setLabelText(QString::number(value));
527 impl->m_HorizontalCursor->setLabelText(QString::number(value));
528 }
528 }
529
529
530 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
530 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
531 {
531 {
532 impl->m_HorizontalCursor->setAbsolutePosition(position);
532 impl->m_HorizontalCursor->setAbsolutePosition(position);
533 impl->m_HorizontalCursor->setVisible(true);
533 impl->m_HorizontalCursor->setVisible(true);
534
534
535 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
535 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
536 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
536 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
537 }
537 }
538
538
539 void VisualizationGraphWidget::removeHorizontalCursor()
539 void VisualizationGraphWidget::removeHorizontalCursor()
540 {
540 {
541 impl->m_HorizontalCursor->setVisible(false);
541 impl->m_HorizontalCursor->setVisible(false);
542 plot().replot(QCustomPlot::rpQueuedReplot);
542 plot().replot(QCustomPlot::rpQueuedReplot);
543 }
543 }
544
544
545 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
545 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
546 {
546 {
547 Q_UNUSED(event);
547 Q_UNUSED(event);
548
548
549 // Prevents that all variables will be removed from graph when it will be closed
549 // Prevents that all variables will be removed from graph when it will be closed
550 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
550 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
551 emit variableAboutToBeRemoved(variableEntry.first);
551 emit variableAboutToBeRemoved(variableEntry.first);
552 }
552 }
553 }
553 }
554
554
555 void VisualizationGraphWidget::enterEvent(QEvent *event)
555 void VisualizationGraphWidget::enterEvent(QEvent *event)
556 {
556 {
557 Q_UNUSED(event);
557 Q_UNUSED(event);
558 impl->m_RenderingDelegate->showGraphOverlay(true);
558 impl->m_RenderingDelegate->showGraphOverlay(true);
559 }
559 }
560
560
561 void VisualizationGraphWidget::leaveEvent(QEvent *event)
561 void VisualizationGraphWidget::leaveEvent(QEvent *event)
562 {
562 {
563 Q_UNUSED(event);
563 Q_UNUSED(event);
564 impl->m_RenderingDelegate->showGraphOverlay(false);
564 impl->m_RenderingDelegate->showGraphOverlay(false);
565
565
566 if (auto parentZone = parentZoneWidget()) {
566 if (auto parentZone = parentZoneWidget()) {
567 parentZone->notifyMouseLeaveGraph(this);
567 parentZone->notifyMouseLeaveGraph(this);
568 }
568 }
569 else {
569 else {
570 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
570 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
571 }
571 }
572
572
573 if (impl->m_HoveredZone) {
573 if (impl->m_HoveredZone) {
574 impl->m_HoveredZone->setHovered(false);
574 impl->m_HoveredZone->setHovered(false);
575 impl->m_HoveredZone = nullptr;
575 impl->m_HoveredZone = nullptr;
576 }
576 }
577 }
577 }
578
578
579 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
579 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
580 {
580 {
581 return *ui->widget;
581 return *ui->widget;
582 }
582 }
583
583
584 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
584 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
585 {
585 {
586 QMenu graphMenu{};
586 QMenu graphMenu{};
587
587
588 // Iterates on variables (unique keys)
588 // Iterates on variables (unique keys)
589 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
589 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
590 end = impl->m_VariableToPlotMultiMap.cend();
590 end = impl->m_VariableToPlotMultiMap.cend();
591 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
591 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
592 // 'Remove variable' action
592 // 'Remove variable' action
593 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
593 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
594 [ this, var = it->first ]() { removeVariable(var); });
594 [ this, var = it->first ]() { removeVariable(var); });
595 }
595 }
596
596
597 if (!impl->m_ZoomStack.isEmpty()) {
597 if (!impl->m_ZoomStack.isEmpty()) {
598 if (!graphMenu.isEmpty()) {
598 if (!graphMenu.isEmpty()) {
599 graphMenu.addSeparator();
599 graphMenu.addSeparator();
600 }
600 }
601
601
602 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
602 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
603 }
603 }
604
604
605 if (!graphMenu.isEmpty()) {
605 if (!graphMenu.isEmpty()) {
606 graphMenu.exec(QCursor::pos());
606 graphMenu.exec(QCursor::pos());
607 }
607 }
608 }
608 }
609
609
610 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
610 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
611 {
611 {
612 qCDebug(LOG_VisualizationGraphWidget())
612 qCDebug(LOG_VisualizationGraphWidget())
613 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
613 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
614 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
614 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
615
615
616 auto graphRange = SqpRange{t1.lower, t1.upper};
616 auto graphRange = SqpRange{t1.lower, t1.upper};
617 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
617 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
618
618
619 if (impl->m_DoAcquisition) {
619 if (impl->m_DoAcquisition) {
620 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
620 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
621
621
622 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
622 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
623 end = impl->m_VariableToPlotMultiMap.end();
623 end = impl->m_VariableToPlotMultiMap.end();
624 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
624 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
625 variableUnderGraphVector.push_back(it->first);
625 variableUnderGraphVector.push_back(it->first);
626 }
626 }
627 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
627 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
628 !impl->m_IsCalibration);
628 !impl->m_IsCalibration);
629
629
630 if (!impl->m_IsCalibration) {
630 if (!impl->m_IsCalibration) {
631 qCDebug(LOG_VisualizationGraphWidget())
631 qCDebug(LOG_VisualizationGraphWidget())
632 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
632 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
633 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
633 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
634 emit synchronize(graphRange, oldGraphRange);
634 emit synchronize(graphRange, oldGraphRange);
635 }
635 }
636 }
636 }
637
637
638 auto pos = mapFromGlobal(QCursor::pos());
638 auto pos = mapFromGlobal(QCursor::pos());
639 auto axisPos = impl->posToAxisPos(pos, plot());
639 auto axisPos = impl->posToAxisPos(pos, plot());
640 if (auto parentZone = parentZoneWidget()) {
640 if (auto parentZone = parentZoneWidget()) {
641 if (impl->pointIsInAxisRect(axisPos, plot())) {
641 if (impl->pointIsInAxisRect(axisPos, plot())) {
642 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
642 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
643 }
643 }
644 else {
644 else {
645 parentZone->notifyMouseLeaveGraph(this);
645 parentZone->notifyMouseLeaveGraph(this);
646 }
646 }
647 }
647 }
648 else {
648 else {
649 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
649 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
650 }
650 }
651 }
651 }
652
652
653 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
653 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
654 {
654 {
655 impl->m_RenderingDelegate->onMouseDoubleClick(event);
655 impl->m_RenderingDelegate->onMouseDoubleClick(event);
656 }
656 }
657
657
658 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
658 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
659 {
659 {
660 // Handles plot rendering when mouse is moving
660 // Handles plot rendering when mouse is moving
661 impl->m_RenderingDelegate->onMouseMove(event);
661 impl->m_RenderingDelegate->onMouseMove(event);
662
662
663 auto axisPos = impl->posToAxisPos(event->pos(), plot());
663 auto axisPos = impl->posToAxisPos(event->pos(), plot());
664
664
665 // Zoom box and zone drawing
665 // Zoom box and zone drawing
666 if (impl->m_DrawingZoomRect) {
666 if (impl->m_DrawingZoomRect) {
667 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
667 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
668 }
668 }
669 else if (impl->m_DrawingZone) {
669 else if (impl->m_DrawingZone) {
670 impl->m_DrawingZone->setEnd(axisPos.x());
670 impl->m_DrawingZone->setEnd(axisPos.x());
671 }
671 }
672
672
673 // Cursor
673 // Cursor
674 if (auto parentZone = parentZoneWidget()) {
674 if (auto parentZone = parentZoneWidget()) {
675 if (impl->pointIsInAxisRect(axisPos, plot())) {
675 if (impl->pointIsInAxisRect(axisPos, plot())) {
676 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
676 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
677 }
677 }
678 else {
678 else {
679 parentZone->notifyMouseLeaveGraph(this);
679 parentZone->notifyMouseLeaveGraph(this);
680 }
680 }
681 }
681 }
682 else {
682 else {
683 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
683 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
684 }
684 }
685
685
686 // Search for the selection zone under the mouse
686 // Search for the selection zone under the mouse
687 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
687 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
688 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
688 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
689 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
689 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
690
690
691 // Sets the appropriate cursor shape
691 // Sets the appropriate cursor shape
692 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
692 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
693 setCursor(cursorShape);
693 setCursor(cursorShape);
694
694
695 // Manages the hovered zone
695 // Manages the hovered zone
696 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
696 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
697 if (impl->m_HoveredZone) {
697 if (impl->m_HoveredZone) {
698 impl->m_HoveredZone->setHovered(false);
698 impl->m_HoveredZone->setHovered(false);
699 }
699 }
700 selectionZoneItemUnderCursor->setHovered(true);
700 selectionZoneItemUnderCursor->setHovered(true);
701 impl->m_HoveredZone = selectionZoneItemUnderCursor;
701 impl->m_HoveredZone = selectionZoneItemUnderCursor;
702 plot().replot(QCustomPlot::rpQueuedReplot);
702 plot().replot(QCustomPlot::rpQueuedReplot);
703 }
703 }
704 }
704 }
705 else {
705 else {
706 // There is no zone under the mouse or the interaction mode is not "selection zones"
706 // There is no zone under the mouse or the interaction mode is not "selection zones"
707 if (impl->m_HoveredZone) {
707 if (impl->m_HoveredZone) {
708 impl->m_HoveredZone->setHovered(false);
708 impl->m_HoveredZone->setHovered(false);
709 impl->m_HoveredZone = nullptr;
709 impl->m_HoveredZone = nullptr;
710 }
710 }
711
711
712 setCursor(Qt::ArrowCursor);
712 setCursor(Qt::ArrowCursor);
713 }
713 }
714
714
715 impl->m_HasMovedMouse = true;
715 impl->m_HasMovedMouse = true;
716 VisualizationDragWidget::mouseMoveEvent(event);
716 VisualizationDragWidget::mouseMoveEvent(event);
717 }
717 }
718
718
719 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
719 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
720 {
720 {
721 auto value = event->angleDelta().x() + event->angleDelta().y();
721 auto value = event->angleDelta().x() + event->angleDelta().y();
722 if (value != 0) {
722 if (value != 0) {
723
723
724 auto direction = value > 0 ? 1.0 : -1.0;
724 auto direction = value > 0 ? 1.0 : -1.0;
725 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
725 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
726 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
726 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
727 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
727 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
728
728
729 auto zoomOrientations = QFlags<Qt::Orientation>{};
729 auto zoomOrientations = QFlags<Qt::Orientation>{};
730 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
730 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
731 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
731 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
732
732
733 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
733 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
734
734
735 if (!isZoomX && !isZoomY) {
735 if (!isZoomX && !isZoomY) {
736 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
736 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
737 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
737 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
738
738
739 axis->setRange(axis->range() + diff);
739 axis->setRange(axis->range() + diff);
740
740
741 if (plot().noAntialiasingOnDrag()) {
741 if (plot().noAntialiasingOnDrag()) {
742 plot().setNotAntialiasedElements(QCP::aeAll);
742 plot().setNotAntialiasedElements(QCP::aeAll);
743 }
743 }
744
744
745 plot().replot(QCustomPlot::rpQueuedReplot);
745 plot().replot(QCustomPlot::rpQueuedReplot);
746 }
746 }
747 }
747 }
748 }
748 }
749
749
750 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
750 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
751 {
751 {
752 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
752 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
753 auto isSelectionZoneMode
753 auto isSelectionZoneMode
754 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
754 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
755 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
755 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
756
756
757 if (!isDragDropClick && isLeftClick) {
757 if (!isDragDropClick && isLeftClick) {
758 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
758 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
759 // Starts a zoom box
759 // Starts a zoom box
760 impl->startDrawingRect(event->pos(), plot());
760 impl->startDrawingRect(event->pos(), plot());
761 }
761 }
762 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
762 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
763 // Starts a new selection zone
763 // Starts a new selection zone
764 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
764 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
765 if (!zoneAtPos) {
765 if (!zoneAtPos) {
766 impl->startDrawingZone(event->pos(), this);
766 impl->startDrawingZone(event->pos(), this);
767 }
767 }
768 }
768 }
769 }
769 }
770
770
771 // Allows mouse panning only in default mode
771 // Allows mouse panning only in default mode
772 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
772 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
773 == SqpApplication::PlotsInteractionMode::None
773 == SqpApplication::PlotsInteractionMode::None
774 && !isDragDropClick);
774 && !isDragDropClick);
775
775
776 // Allows zone edition only in selection zone mode without drag&drop
776 // Allows zone edition only in selection zone mode without drag&drop
777 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
777 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
778
778
779 // Selection / Deselection
779 // Selection / Deselection
780 if (isSelectionZoneMode) {
780 if (isSelectionZoneMode) {
781 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
781 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
782 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
782 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
783 if (selectionZoneItemUnderCursor && isLeftClick) {
783 if (selectionZoneItemUnderCursor && isLeftClick) {
784 selectionZoneItemUnderCursor->setAssociatedEditedZones(
784 selectionZoneItemUnderCursor->setAssociatedEditedZones(
785 parentVisualizationWidget()->selectionZoneManager().selectedItems());
785 parentVisualizationWidget()->selectionZoneManager().selectedItems());
786 }
786 }
787 else if (!isMultiSelectionClick && isLeftClick) {
787 else if (!isMultiSelectionClick && isLeftClick) {
788 parentVisualizationWidget()->selectionZoneManager().clearSelection();
788 parentVisualizationWidget()->selectionZoneManager().clearSelection();
789 }
789 }
790 else {
790 else {
791 // No selection change
791 // No selection change
792 }
792 }
793 }
793 }
794
794
795
795
796 impl->m_HasMovedMouse = false;
796 impl->m_HasMovedMouse = false;
797 VisualizationDragWidget::mousePressEvent(event);
797 VisualizationDragWidget::mousePressEvent(event);
798 }
798 }
799
799
800 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
800 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
801 {
801 {
802 if (impl->m_DrawingZoomRect) {
802 if (impl->m_DrawingZoomRect) {
803
803
804 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
804 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
805 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
805 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
806
806
807 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
807 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
808 impl->m_DrawingZoomRect->bottomRight->coords().x()};
808 impl->m_DrawingZoomRect->bottomRight->coords().x()};
809
809
810 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
810 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
811 impl->m_DrawingZoomRect->bottomRight->coords().y()};
811 impl->m_DrawingZoomRect->bottomRight->coords().y()};
812
812
813 impl->removeDrawingRect(plot());
813 impl->removeDrawingRect(plot());
814
814
815 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
815 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
816 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
816 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
817 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
817 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
818 axisX->setRange(newAxisXRange);
818 axisX->setRange(newAxisXRange);
819 axisY->setRange(newAxisYRange);
819 axisY->setRange(newAxisYRange);
820
820
821 plot().replot(QCustomPlot::rpQueuedReplot);
821 plot().replot(QCustomPlot::rpQueuedReplot);
822 }
822 }
823 }
823 }
824
824
825 impl->endDrawingZone(this);
825 impl->endDrawingZone(this);
826
826
827 impl->m_IsCalibration = false;
827 impl->m_IsCalibration = false;
828
828
829 // Selection / Deselection
829 // Selection / Deselection
830 auto isSelectionZoneMode
830 auto isSelectionZoneMode
831 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
831 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
832 if (isSelectionZoneMode) {
832 if (isSelectionZoneMode) {
833 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
833 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
834 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
834 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
835 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) {
835 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) {
836 if (!isMultiSelectionClick && !impl->m_HasMovedMouse) {
836 if (!isMultiSelectionClick && !impl->m_HasMovedMouse) {
837 parentVisualizationWidget()->selectionZoneManager().select(
837 parentVisualizationWidget()->selectionZoneManager().select(
838 {selectionZoneItemUnderCursor});
838 {selectionZoneItemUnderCursor});
839 }
839 }
840 else if (!impl->m_HasMovedMouse) {
840 else if (!impl->m_HasMovedMouse) {
841 parentVisualizationWidget()->selectionZoneManager().setSelected(
841 parentVisualizationWidget()->selectionZoneManager().setSelected(
842 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
842 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
843 || event->button() == Qt::RightButton);
843 || event->button() == Qt::RightButton);
844 }
844 }
845 }
845 }
846 else {
846 else {
847 // No selection change
847 // No selection change
848 }
848 }
849 }
849 }
850 }
850 }
851
851
852 void VisualizationGraphWidget::onDataCacheVariableUpdated()
852 void VisualizationGraphWidget::onDataCacheVariableUpdated()
853 {
853 {
854 auto graphRange = ui->widget->xAxis->range();
854 auto graphRange = ui->widget->xAxis->range();
855 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
855 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
856
856
857 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
857 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
858 auto variable = variableEntry.first;
858 auto variable = variableEntry.first;
859 qCDebug(LOG_VisualizationGraphWidget())
859 qCDebug(LOG_VisualizationGraphWidget())
860 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
860 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
861 qCDebug(LOG_VisualizationGraphWidget())
861 qCDebug(LOG_VisualizationGraphWidget())
862 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
862 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
863 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
863 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
864 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
864 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
865 }
865 }
866 }
866 }
867 }
867 }
868
868
869 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
869 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
870 const SqpRange &range)
870 const SqpRange &range)
871 {
871 {
872 auto it = impl->m_VariableToPlotMultiMap.find(variable);
872 auto it = impl->m_VariableToPlotMultiMap.find(variable);
873 if (it != impl->m_VariableToPlotMultiMap.end()) {
873 if (it != impl->m_VariableToPlotMultiMap.end()) {
874 impl->updateData(it->second, variable->dataSeries(), range);
874 impl->updateData(it->second, variable->dataSeries(), range);
875 }
875 }
876 }
876 }
@@ -1,329 +1,329
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 "Visualization/MacScrollBarStyle.h"
8 #include "Visualization/MacScrollBarStyle.h"
9
9
10 #include "Variable/VariableController.h"
10 #include "Variable/VariableController.h"
11
11
12 #include "Common/MimeTypesDef.h"
12 #include "Common/MimeTypesDef.h"
13
13
14 #include "DragAndDrop/DragDropHelper.h"
14 #include "DragAndDrop/DragDropGuiController.h"
15 #include "SqpApplication.h"
15 #include "SqpApplication.h"
16
16
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
17 Q_LOGGING_CATEGORY(LOG_VisualizationTabWidget, "VisualizationTabWidget")
18
18
19 namespace {
19 namespace {
20
20
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
21 /// Generates a default name for a new zone, according to the number of zones already displayed in
22 /// the tab
22 /// the tab
23 QString defaultZoneName(const QLayout &layout)
23 QString defaultZoneName(const QLayout &layout)
24 {
24 {
25 auto count = 0;
25 auto count = 0;
26 for (auto i = 0; i < layout.count(); ++i) {
26 for (auto i = 0; i < layout.count(); ++i) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
27 if (dynamic_cast<VisualizationZoneWidget *>(layout.itemAt(i)->widget())) {
28 count++;
28 count++;
29 }
29 }
30 }
30 }
31
31
32 return QObject::tr("Zone %1").arg(count + 1);
32 return QObject::tr("Zone %1").arg(count + 1);
33 }
33 }
34
34
35 /**
35 /**
36 * Applies a function to all zones of the tab represented by its layout
36 * Applies a function to all zones of the tab represented by its layout
37 * @param layout the layout that contains zones
37 * @param layout the layout that contains zones
38 * @param fun the function to apply to each zone
38 * @param fun the function to apply to each zone
39 */
39 */
40 template <typename Fun>
40 template <typename Fun>
41 void processZones(QLayout &layout, Fun fun)
41 void processZones(QLayout &layout, Fun fun)
42 {
42 {
43 for (auto i = 0; i < layout.count(); ++i) {
43 for (auto i = 0; i < layout.count(); ++i) {
44 if (auto item = layout.itemAt(i)) {
44 if (auto item = layout.itemAt(i)) {
45 if (auto visualizationZoneWidget
45 if (auto visualizationZoneWidget
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
46 = dynamic_cast<VisualizationZoneWidget *>(item->widget())) {
47 fun(*visualizationZoneWidget);
47 fun(*visualizationZoneWidget);
48 }
48 }
49 }
49 }
50 }
50 }
51 }
51 }
52
52
53 } // namespace
53 } // namespace
54
54
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
55 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
56 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
57
57
58 QString m_Name;
58 QString m_Name;
59
59
60 #ifdef Q_OS_MAC
60 #ifdef Q_OS_MAC
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
61 std::unique_ptr<MacScrollBarStyle> m_MacScrollBarStyle = std::make_unique<MacScrollBarStyle>();
62 #endif
62 #endif
63
63
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
64 void dropGraph(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
65 void dropZone(int index, VisualizationTabWidget *tabWidget);
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
66 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
67 VisualizationTabWidget *tabWidget);
67 VisualizationTabWidget *tabWidget);
68 };
68 };
69
69
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
70 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
71 : QWidget{parent},
71 : QWidget{parent},
72 ui{new Ui::VisualizationTabWidget},
72 ui{new Ui::VisualizationTabWidget},
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
73 impl{spimpl::make_unique_impl<VisualizationTabWidgetPrivate>(name)}
74 {
74 {
75 ui->setupUi(this);
75 ui->setupUi(this);
76
76
77 #ifdef Q_OS_MAC
77 #ifdef Q_OS_MAC
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
78 impl->m_MacScrollBarStyle->selfInstallOn(ui->scrollArea, true);
79 #endif
79 #endif
80
80
81 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Zone, "Zone");
81 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Zone, "Zone");
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
82 ui->dragDropContainer->layout()->setContentsMargins(0, 0, 0, 12);
83 ui->dragDropContainer->layout()->setSpacing(0);
83 ui->dragDropContainer->layout()->setSpacing(0);
84 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
84 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
85 VisualizationDragDropContainer::DropBehavior::Inserted);
85 VisualizationDragDropContainer::DropBehavior::Inserted);
86 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
86 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
87 VisualizationDragDropContainer::DropBehavior::Inserted);
87 VisualizationDragDropContainer::DropBehavior::Inserted);
88 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
88 ui->dragDropContainer->setMimeType(MIME_TYPE_VARIABLE_LIST,
89 VisualizationDragDropContainer::DropBehavior::Inserted);
89 VisualizationDragDropContainer::DropBehavior::Inserted);
90
90
91 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
91 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
92 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
92 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
93 ui->dragDropContainer);
93 ui->dragDropContainer);
94 });
94 });
95
95
96 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
96 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
97 &VisualizationTabWidget::dropMimeData);
97 &VisualizationTabWidget::dropMimeData);
98
98
99 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
99 sqpApp->dragDropGuiController().addDragDropScrollArea(ui->scrollArea);
100
100
101 // Widget is deleted when closed
101 // Widget is deleted when closed
102 setAttribute(Qt::WA_DeleteOnClose);
102 setAttribute(Qt::WA_DeleteOnClose);
103 }
103 }
104
104
105 VisualizationTabWidget::~VisualizationTabWidget()
105 VisualizationTabWidget::~VisualizationTabWidget()
106 {
106 {
107 sqpApp->dragDropHelper().removeDragDropScrollArea(ui->scrollArea);
107 sqpApp->dragDropGuiController().removeDragDropScrollArea(ui->scrollArea);
108 delete ui;
108 delete ui;
109 }
109 }
110
110
111 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
111 void VisualizationTabWidget::addZone(VisualizationZoneWidget *zoneWidget)
112 {
112 {
113 ui->dragDropContainer->addDragWidget(zoneWidget);
113 ui->dragDropContainer->addDragWidget(zoneWidget);
114 }
114 }
115
115
116 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
116 void VisualizationTabWidget::insertZone(int index, VisualizationZoneWidget *zoneWidget)
117 {
117 {
118 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
118 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
119 }
119 }
120
120
121 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
121 VisualizationZoneWidget *VisualizationTabWidget::createZone(std::shared_ptr<Variable> variable)
122 {
122 {
123 return createZone({variable}, -1);
123 return createZone({variable}, -1);
124 }
124 }
125
125
126 VisualizationZoneWidget *
126 VisualizationZoneWidget *
127 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
127 VisualizationTabWidget::createZone(const QList<std::shared_ptr<Variable> > &variables, int index)
128 {
128 {
129 auto zoneWidget = createEmptyZone(index);
129 auto zoneWidget = createEmptyZone(index);
130
130
131 // Creates a new graph into the zone
131 // Creates a new graph into the zone
132 zoneWidget->createGraph(variables, index);
132 zoneWidget->createGraph(variables, index);
133
133
134 return zoneWidget;
134 return zoneWidget;
135 }
135 }
136
136
137 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
137 VisualizationZoneWidget *VisualizationTabWidget::createEmptyZone(int index)
138 {
138 {
139 auto zoneWidget
139 auto zoneWidget
140 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
140 = new VisualizationZoneWidget{defaultZoneName(*ui->dragDropContainer->layout()), this};
141 this->insertZone(index, zoneWidget);
141 this->insertZone(index, zoneWidget);
142
142
143 return zoneWidget;
143 return zoneWidget;
144 }
144 }
145
145
146 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
146 void VisualizationTabWidget::accept(IVisualizationWidgetVisitor *visitor)
147 {
147 {
148 if (visitor) {
148 if (visitor) {
149 visitor->visitEnter(this);
149 visitor->visitEnter(this);
150
150
151 // Apply visitor to zone children: widgets different from zones are not visited (no action)
151 // Apply visitor to zone children: widgets different from zones are not visited (no action)
152 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
152 processZones(tabLayout(), [visitor](VisualizationZoneWidget &zoneWidget) {
153 zoneWidget.accept(visitor);
153 zoneWidget.accept(visitor);
154 });
154 });
155
155
156 visitor->visitLeave(this);
156 visitor->visitLeave(this);
157 }
157 }
158 else {
158 else {
159 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
159 qCCritical(LOG_VisualizationTabWidget()) << tr("Can't visit widget : the visitor is null");
160 }
160 }
161 }
161 }
162
162
163 bool VisualizationTabWidget::canDrop(const Variable &variable) const
163 bool VisualizationTabWidget::canDrop(const Variable &variable) const
164 {
164 {
165 // A tab can always accomodate a variable
165 // A tab can always accomodate a variable
166 Q_UNUSED(variable);
166 Q_UNUSED(variable);
167 return true;
167 return true;
168 }
168 }
169
169
170 bool VisualizationTabWidget::contains(const Variable &variable) const
170 bool VisualizationTabWidget::contains(const Variable &variable) const
171 {
171 {
172 Q_UNUSED(variable);
172 Q_UNUSED(variable);
173 return false;
173 return false;
174 }
174 }
175
175
176 QString VisualizationTabWidget::name() const
176 QString VisualizationTabWidget::name() const
177 {
177 {
178 return impl->m_Name;
178 return impl->m_Name;
179 }
179 }
180
180
181 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
181 void VisualizationTabWidget::closeEvent(QCloseEvent *event)
182 {
182 {
183 // Closes zones in the tab
183 // Closes zones in the tab
184 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
184 processZones(tabLayout(), [](VisualizationZoneWidget &zoneWidget) { zoneWidget.close(); });
185
185
186 QWidget::closeEvent(event);
186 QWidget::closeEvent(event);
187 }
187 }
188
188
189 QLayout &VisualizationTabWidget::tabLayout() const noexcept
189 QLayout &VisualizationTabWidget::tabLayout() const noexcept
190 {
190 {
191 return *ui->dragDropContainer->layout();
191 return *ui->dragDropContainer->layout();
192 }
192 }
193
193
194 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
194 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
195 {
195 {
196 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
196 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
197 impl->dropGraph(index, this);
197 impl->dropGraph(index, this);
198 }
198 }
199 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
199 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
200 impl->dropZone(index, this);
200 impl->dropZone(index, this);
201 }
201 }
202 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
202 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
203 auto variables = sqpApp->variableController().variablesForMimeData(
203 auto variables = sqpApp->variableController().variablesForMimeData(
204 mimeData->data(MIME_TYPE_VARIABLE_LIST));
204 mimeData->data(MIME_TYPE_VARIABLE_LIST));
205 impl->dropVariables(variables, index, this);
205 impl->dropVariables(variables, index, this);
206 }
206 }
207 else {
207 else {
208 qCWarning(LOG_VisualizationZoneWidget())
208 qCWarning(LOG_VisualizationZoneWidget())
209 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
209 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
210 }
210 }
211 }
211 }
212
212
213 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
213 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
214 int index, VisualizationTabWidget *tabWidget)
214 int index, VisualizationTabWidget *tabWidget)
215 {
215 {
216 auto &helper = sqpApp->dragDropHelper();
216 auto &helper = sqpApp->dragDropGuiController();
217
217
218 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
218 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
219 if (!graphWidget) {
219 if (!graphWidget) {
220 qCWarning(LOG_VisualizationZoneWidget())
220 qCWarning(LOG_VisualizationZoneWidget())
221 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
221 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
222 "found or invalid.");
222 "found or invalid.");
223 Q_ASSERT(false);
223 Q_ASSERT(false);
224 return;
224 return;
225 }
225 }
226
226
227 auto parentDragDropContainer
227 auto parentDragDropContainer
228 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
228 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
229 if (!parentDragDropContainer) {
229 if (!parentDragDropContainer) {
230 qCWarning(LOG_VisualizationZoneWidget())
230 qCWarning(LOG_VisualizationZoneWidget())
231 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
231 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
232 "the dropped graph is not found.");
232 "the dropped graph is not found.");
233 Q_ASSERT(false);
233 Q_ASSERT(false);
234 return;
234 return;
235 }
235 }
236
236
237 auto nbGraph = parentDragDropContainer->countDragWidget();
237 auto nbGraph = parentDragDropContainer->countDragWidget();
238
238
239 const auto &variables = graphWidget->variables();
239 const auto &variables = graphWidget->variables();
240
240
241 if (!variables.isEmpty()) {
241 if (!variables.isEmpty()) {
242 // Abort the requests for the variables (if any)
242 // Abort the requests for the variables (if any)
243 // Commented, because it's not sure if it's needed or not
243 // Commented, because it's not sure if it's needed or not
244 // for (const auto& var : variables)
244 // for (const auto& var : variables)
245 //{
245 //{
246 // sqpApp->variableController().onAbortProgressRequested(var);
246 // sqpApp->variableController().onAbortProgressRequested(var);
247 //}
247 //}
248
248
249 if (nbGraph == 1) {
249 if (nbGraph == 1) {
250 // This is the only graph in the previous zone, close the zone
250 // This is the only graph in the previous zone, close the zone
251 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
251 helper.delayedCloseWidget(graphWidget->parentZoneWidget());
252 }
252 }
253 else {
253 else {
254 // Close the graph
254 // Close the graph
255 helper.delayedCloseWidget(graphWidget);
255 helper.delayedCloseWidget(graphWidget);
256 }
256 }
257
257
258 auto zoneWidget = tabWidget->createZone(variables, index);
258 auto zoneWidget = tabWidget->createZone(variables, index);
259 auto firstGraph = zoneWidget->firstGraph();
259 auto firstGraph = zoneWidget->firstGraph();
260 if (firstGraph) {
260 if (firstGraph) {
261 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
261 firstGraph->addSelectionZones(graphWidget->selectionZoneRanges());
262 }
262 }
263 else {
263 else {
264 qCWarning(LOG_VisualizationZoneWidget())
264 qCWarning(LOG_VisualizationZoneWidget())
265 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
265 << tr("VisualizationTabWidget::dropGraph, no graph added in the widget.");
266 Q_ASSERT(false);
266 Q_ASSERT(false);
267 }
267 }
268 }
268 }
269 else {
269 else {
270 // The graph is empty, create an empty zone and move the graph inside
270 // The graph is empty, create an empty zone and move the graph inside
271
271
272 auto parentZoneWidget = graphWidget->parentZoneWidget();
272 auto parentZoneWidget = graphWidget->parentZoneWidget();
273
273
274 parentDragDropContainer->layout()->removeWidget(graphWidget);
274 parentDragDropContainer->layout()->removeWidget(graphWidget);
275
275
276 auto zoneWidget = tabWidget->createEmptyZone(index);
276 auto zoneWidget = tabWidget->createEmptyZone(index);
277 zoneWidget->addGraph(graphWidget);
277 zoneWidget->addGraph(graphWidget);
278
278
279 // Close the old zone if it was the only graph inside
279 // Close the old zone if it was the only graph inside
280 if (nbGraph == 1) {
280 if (nbGraph == 1) {
281 helper.delayedCloseWidget(parentZoneWidget);
281 helper.delayedCloseWidget(parentZoneWidget);
282 }
282 }
283 }
283 }
284 }
284 }
285
285
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
287 int index, VisualizationTabWidget *tabWidget)
287 int index, VisualizationTabWidget *tabWidget)
288 {
288 {
289 auto &helper = sqpApp->dragDropHelper();
289 auto &helper = sqpApp->dragDropGuiController();
290
290
291 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
291 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
292 if (!zoneWidget) {
292 if (!zoneWidget) {
293 qCWarning(LOG_VisualizationZoneWidget())
293 qCWarning(LOG_VisualizationZoneWidget())
294 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
294 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
295 "found or invalid.");
295 "found or invalid.");
296 Q_ASSERT(false);
296 Q_ASSERT(false);
297 return;
297 return;
298 }
298 }
299
299
300 auto parentDragDropContainer
300 auto parentDragDropContainer
301 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
301 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
302 if (!parentDragDropContainer) {
302 if (!parentDragDropContainer) {
303 qCWarning(LOG_VisualizationZoneWidget())
303 qCWarning(LOG_VisualizationZoneWidget())
304 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
304 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
305 "the dropped zone is not found.");
305 "the dropped zone is not found.");
306 Q_ASSERT(false);
306 Q_ASSERT(false);
307 return;
307 return;
308 }
308 }
309
309
310 // Simple move of the zone, no variable operation associated
310 // Simple move of the zone, no variable operation associated
311 parentDragDropContainer->layout()->removeWidget(zoneWidget);
311 parentDragDropContainer->layout()->removeWidget(zoneWidget);
312 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
312 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
313 }
313 }
314
314
315 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
315 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
316 const QList<std::shared_ptr<Variable> > &variables, int index,
316 const QList<std::shared_ptr<Variable> > &variables, int index,
317 VisualizationTabWidget *tabWidget)
317 VisualizationTabWidget *tabWidget)
318 {
318 {
319 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
319 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
320 // compatible variable here
320 // compatible variable here
321 if (variables.count() > 1) {
321 if (variables.count() > 1) {
322 qCWarning(LOG_VisualizationZoneWidget())
322 qCWarning(LOG_VisualizationZoneWidget())
323 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
323 << tr("VisualizationTabWidget::dropVariables, dropping multiple variables, operation "
324 "aborted.");
324 "aborted.");
325 return;
325 return;
326 }
326 }
327
327
328 tabWidget->createZone(variables, index);
328 tabWidget->createZone(variables, index);
329 }
329 }
@@ -1,197 +1,197
1 #include "Visualization/VisualizationWidget.h"
1 #include "Visualization/VisualizationWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationSelectionZoneManager.h"
4 #include "Visualization/VisualizationSelectionZoneManager.h"
5 #include "Visualization/VisualizationTabWidget.h"
5 #include "Visualization/VisualizationTabWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "Visualization/operations/FindVariableOperation.h"
7 #include "Visualization/operations/FindVariableOperation.h"
8 #include "Visualization/operations/GenerateVariableMenuOperation.h"
8 #include "Visualization/operations/GenerateVariableMenuOperation.h"
9 #include "Visualization/operations/RemoveVariableOperation.h"
9 #include "Visualization/operations/RemoveVariableOperation.h"
10 #include "Visualization/operations/RescaleAxeOperation.h"
10 #include "Visualization/operations/RescaleAxeOperation.h"
11 #include "Visualization/qcustomplot.h"
11 #include "Visualization/qcustomplot.h"
12
12
13 #include "ui_VisualizationWidget.h"
13 #include "ui_VisualizationWidget.h"
14
14
15 #include "DragAndDrop/DragDropHelper.h"
15 #include "DragAndDrop/DragDropGuiController.h"
16 #include "SqpApplication.h"
16 #include "SqpApplication.h"
17
17
18 #include <QToolButton>
18 #include <QToolButton>
19
19
20 #include <memory>
20 #include <memory>
21
21
22 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
22 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
23
23
24 struct VisualizationWidget::VisualizationWidgetPrivate {
24 struct VisualizationWidget::VisualizationWidgetPrivate {
25 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
25 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
26
26
27 VisualizationWidgetPrivate()
27 VisualizationWidgetPrivate()
28 : m_ZoneSelectionManager(std::make_unique<VisualizationSelectionZoneManager>())
28 : m_ZoneSelectionManager(std::make_unique<VisualizationSelectionZoneManager>())
29 {
29 {
30 }
30 }
31 };
31 };
32
32
33 VisualizationWidget::VisualizationWidget(QWidget *parent)
33 VisualizationWidget::VisualizationWidget(QWidget *parent)
34 : QWidget{parent},
34 : QWidget{parent},
35 ui{new Ui::VisualizationWidget},
35 ui{new Ui::VisualizationWidget},
36 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
36 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
37 {
37 {
38 ui->setupUi(this);
38 ui->setupUi(this);
39
39
40 auto addTabViewButton = new QToolButton{ui->tabWidget};
40 auto addTabViewButton = new QToolButton{ui->tabWidget};
41 addTabViewButton->setText(tr("Add View"));
41 addTabViewButton->setText(tr("Add View"));
42 addTabViewButton->setCursor(Qt::ArrowCursor);
42 addTabViewButton->setCursor(Qt::ArrowCursor);
43 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
43 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
44
44
45 auto enableMinimumCornerWidgetSize = [this](bool enable) {
45 auto enableMinimumCornerWidgetSize = [this](bool enable) {
46
46
47 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
47 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
48 auto width = enable ? tabViewCornerWidget->width() : 0;
48 auto width = enable ? tabViewCornerWidget->width() : 0;
49 auto height = enable ? tabViewCornerWidget->height() : 0;
49 auto height = enable ? tabViewCornerWidget->height() : 0;
50 tabViewCornerWidget->setMinimumHeight(height);
50 tabViewCornerWidget->setMinimumHeight(height);
51 tabViewCornerWidget->setMinimumWidth(width);
51 tabViewCornerWidget->setMinimumWidth(width);
52 ui->tabWidget->setMinimumHeight(height);
52 ui->tabWidget->setMinimumHeight(height);
53 ui->tabWidget->setMinimumWidth(width);
53 ui->tabWidget->setMinimumWidth(width);
54 };
54 };
55
55
56 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
56 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
57 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
57 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
58 ui->tabWidget};
58 ui->tabWidget};
59 auto index = ui->tabWidget->addTab(widget, widget->name());
59 auto index = ui->tabWidget->addTab(widget, widget->name());
60 if (ui->tabWidget->count() > 0) {
60 if (ui->tabWidget->count() > 0) {
61 enableMinimumCornerWidgetSize(false);
61 enableMinimumCornerWidgetSize(false);
62 }
62 }
63 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
63 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
64 };
64 };
65
65
66 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
66 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
67 if (ui->tabWidget->count() == 1) {
67 if (ui->tabWidget->count() == 1) {
68 enableMinimumCornerWidgetSize(true);
68 enableMinimumCornerWidgetSize(true);
69 }
69 }
70
70
71 // Removes widget from tab and closes it
71 // Removes widget from tab and closes it
72 auto widget = ui->tabWidget->widget(index);
72 auto widget = ui->tabWidget->widget(index);
73 ui->tabWidget->removeTab(index);
73 ui->tabWidget->removeTab(index);
74 if (widget) {
74 if (widget) {
75 widget->close();
75 widget->close();
76 }
76 }
77
77
78 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
78 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
79
79
80 };
80 };
81
81
82 ui->tabWidget->setTabsClosable(true);
82 ui->tabWidget->setTabsClosable(true);
83
83
84 connect(addTabViewButton, &QToolButton::clicked, addTabView);
84 connect(addTabViewButton, &QToolButton::clicked, addTabView);
85 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
85 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
86
86
87 sqpApp->dragDropHelper().addDragDropTabBar(ui->tabWidget->tabBar());
87 sqpApp->dragDropGuiController().addDragDropTabBar(ui->tabWidget->tabBar());
88
88
89 // Adds default tab
89 // Adds default tab
90 addTabView();
90 addTabView();
91 }
91 }
92
92
93 VisualizationWidget::~VisualizationWidget()
93 VisualizationWidget::~VisualizationWidget()
94 {
94 {
95 sqpApp->dragDropHelper().removeDragDropTabBar(ui->tabWidget->tabBar());
95 sqpApp->dragDropGuiController().removeDragDropTabBar(ui->tabWidget->tabBar());
96 delete ui;
96 delete ui;
97 }
97 }
98
98
99 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
99 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
100 {
100 {
101 return *impl->m_ZoneSelectionManager.get();
101 return *impl->m_ZoneSelectionManager.get();
102 }
102 }
103
103
104 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
104 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
105 {
105 {
106 if (visitor) {
106 if (visitor) {
107 visitor->visitEnter(this);
107 visitor->visitEnter(this);
108
108
109 // Apply visitor for tab children
109 // Apply visitor for tab children
110 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
110 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
111 // Widgets different from tabs are not visited (no action)
111 // Widgets different from tabs are not visited (no action)
112 if (auto visualizationTabWidget
112 if (auto visualizationTabWidget
113 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
113 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
114 visualizationTabWidget->accept(visitor);
114 visualizationTabWidget->accept(visitor);
115 }
115 }
116 }
116 }
117
117
118 visitor->visitLeave(this);
118 visitor->visitLeave(this);
119 }
119 }
120 else {
120 else {
121 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
121 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
122 }
122 }
123 }
123 }
124
124
125 bool VisualizationWidget::canDrop(const Variable &variable) const
125 bool VisualizationWidget::canDrop(const Variable &variable) const
126 {
126 {
127 // The main widget can never accomodate a variable
127 // The main widget can never accomodate a variable
128 Q_UNUSED(variable);
128 Q_UNUSED(variable);
129 return false;
129 return false;
130 }
130 }
131
131
132 bool VisualizationWidget::contains(const Variable &variable) const
132 bool VisualizationWidget::contains(const Variable &variable) const
133 {
133 {
134 Q_UNUSED(variable);
134 Q_UNUSED(variable);
135 return false;
135 return false;
136 }
136 }
137
137
138 QString VisualizationWidget::name() const
138 QString VisualizationWidget::name() const
139 {
139 {
140 return QStringLiteral("MainView");
140 return QStringLiteral("MainView");
141 }
141 }
142
142
143 void VisualizationWidget::attachVariableMenu(
143 void VisualizationWidget::attachVariableMenu(
144 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
144 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
145 {
145 {
146 // Menu is generated only if there is a single variable
146 // Menu is generated only if there is a single variable
147 if (variables.size() == 1) {
147 if (variables.size() == 1) {
148 if (auto variable = variables.first()) {
148 if (auto variable = variables.first()) {
149 // Gets the containers of the variable
149 // Gets the containers of the variable
150 FindVariableOperation findVariableOperation{variable};
150 FindVariableOperation findVariableOperation{variable};
151 accept(&findVariableOperation);
151 accept(&findVariableOperation);
152 auto variableContainers = findVariableOperation.result();
152 auto variableContainers = findVariableOperation.result();
153
153
154 // Generates the actions that make it possible to visualize the variable
154 // Generates the actions that make it possible to visualize the variable
155 GenerateVariableMenuOperation generateVariableMenuOperation{
155 GenerateVariableMenuOperation generateVariableMenuOperation{
156 menu, variable, std::move(variableContainers)};
156 menu, variable, std::move(variableContainers)};
157 accept(&generateVariableMenuOperation);
157 accept(&generateVariableMenuOperation);
158 }
158 }
159 else {
159 else {
160 qCCritical(LOG_VisualizationWidget()) << tr(
160 qCCritical(LOG_VisualizationWidget()) << tr(
161 "Can't generate the menu relative to the visualization: the variable is null");
161 "Can't generate the menu relative to the visualization: the variable is null");
162 }
162 }
163 }
163 }
164 else {
164 else {
165 qCDebug(LOG_VisualizationWidget())
165 qCDebug(LOG_VisualizationWidget())
166 << tr("No generation of the menu related to the visualization: several variables are "
166 << tr("No generation of the menu related to the visualization: several variables are "
167 "selected");
167 "selected");
168 }
168 }
169 }
169 }
170
170
171 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
171 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
172 {
172 {
173 // Calls the operation of removing all references to the variable in the visualization
173 // Calls the operation of removing all references to the variable in the visualization
174 auto removeVariableOperation = RemoveVariableOperation{variable};
174 auto removeVariableOperation = RemoveVariableOperation{variable};
175 accept(&removeVariableOperation);
175 accept(&removeVariableOperation);
176 }
176 }
177
177
178 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
178 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
179 const SqpRange &range) noexcept
179 const SqpRange &range) noexcept
180 {
180 {
181 // Calls the operation of rescaling all graph that contrains variable in the visualization
181 // Calls the operation of rescaling all graph that contrains variable in the visualization
182 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
182 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
183 accept(&rescaleVariableOperation);
183 accept(&rescaleVariableOperation);
184 }
184 }
185
185
186 void VisualizationWidget::closeEvent(QCloseEvent *event)
186 void VisualizationWidget::closeEvent(QCloseEvent *event)
187 {
187 {
188 // Closes tabs in the widget
188 // Closes tabs in the widget
189 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
189 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
190 if (auto visualizationTabWidget
190 if (auto visualizationTabWidget
191 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
191 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
192 visualizationTabWidget->close();
192 visualizationTabWidget->close();
193 }
193 }
194 }
194 }
195
195
196 QWidget::closeEvent(event);
196 QWidget::closeEvent(event);
197 }
197 }
@@ -1,587 +1,587
1 #include "Visualization/VisualizationZoneWidget.h"
1 #include "Visualization/VisualizationZoneWidget.h"
2
2
3 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/IVisualizationWidgetVisitor.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
4 #include "Visualization/QCustomPlotSynchronizer.h"
5 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationGraphWidget.h"
6 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/VisualizationWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
8
8
9 #include "Common/MimeTypesDef.h"
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
10 #include "Common/VisualizationDef.h"
11
11
12 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14 #include <Variable/Variable.h>
14 #include <Variable/Variable.h>
15 #include <Variable/VariableController.h>
15 #include <Variable/VariableController.h>
16
16
17 #include <Visualization/operations/FindVariableOperation.h>
17 #include <Visualization/operations/FindVariableOperation.h>
18
18
19 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropGuiController.h>
20 #include <QUuid>
20 #include <QUuid>
21 #include <SqpApplication.h>
21 #include <SqpApplication.h>
22 #include <cmath>
22 #include <cmath>
23
23
24 #include <QLayout>
24 #include <QLayout>
25
25
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
26 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
27
27
28 namespace {
28 namespace {
29
29
30
30
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
31 /// Generates a default name for a new graph, according to the number of graphs already displayed in
32 /// the zone
32 /// the zone
33 QString defaultGraphName(const QLayout &layout)
33 QString defaultGraphName(const QLayout &layout)
34 {
34 {
35 auto count = 0;
35 auto count = 0;
36 for (auto i = 0; i < layout.count(); ++i) {
36 for (auto i = 0; i < layout.count(); ++i) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
37 if (dynamic_cast<VisualizationGraphWidget *>(layout.itemAt(i)->widget())) {
38 count++;
38 count++;
39 }
39 }
40 }
40 }
41
41
42 return QObject::tr("Graph %1").arg(count + 1);
42 return QObject::tr("Graph %1").arg(count + 1);
43 }
43 }
44
44
45 /**
45 /**
46 * Applies a function to all graphs of the zone represented by its layout
46 * Applies a function to all graphs of the zone represented by its layout
47 * @param layout the layout that contains graphs
47 * @param layout the layout that contains graphs
48 * @param fun the function to apply to each graph
48 * @param fun the function to apply to each graph
49 */
49 */
50 template <typename Fun>
50 template <typename Fun>
51 void processGraphs(QLayout &layout, Fun fun)
51 void processGraphs(QLayout &layout, Fun fun)
52 {
52 {
53 for (auto i = 0; i < layout.count(); ++i) {
53 for (auto i = 0; i < layout.count(); ++i) {
54 if (auto item = layout.itemAt(i)) {
54 if (auto item = layout.itemAt(i)) {
55 if (auto visualizationGraphWidget
55 if (auto visualizationGraphWidget
56 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
56 = qobject_cast<VisualizationGraphWidget *>(item->widget())) {
57 fun(*visualizationGraphWidget);
57 fun(*visualizationGraphWidget);
58 }
58 }
59 }
59 }
60 }
60 }
61 }
61 }
62
62
63 } // namespace
63 } // namespace
64
64
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
65 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66
66
67 explicit VisualizationZoneWidgetPrivate()
67 explicit VisualizationZoneWidgetPrivate()
68 : m_SynchronisationGroupId{QUuid::createUuid()},
68 : m_SynchronisationGroupId{QUuid::createUuid()},
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
69 m_Synchronizer{std::make_unique<QCustomPlotSynchronizer>()}
70 {
70 {
71 }
71 }
72 QUuid m_SynchronisationGroupId;
72 QUuid m_SynchronisationGroupId;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
74
74
75 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
76 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
77 VisualizationZoneWidget *zoneWidget);
77 VisualizationZoneWidget *zoneWidget);
78 };
78 };
79
79
80 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
80 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
81 : VisualizationDragWidget{parent},
81 : VisualizationDragWidget{parent},
82 ui{new Ui::VisualizationZoneWidget},
82 ui{new Ui::VisualizationZoneWidget},
83 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
83 impl{spimpl::make_unique_impl<VisualizationZoneWidgetPrivate>()}
84 {
84 {
85 ui->setupUi(this);
85 ui->setupUi(this);
86
86
87 ui->zoneNameLabel->setText(name);
87 ui->zoneNameLabel->setText(name);
88
88
89 ui->dragDropContainer->setPlaceHolderType(DragDropHelper::PlaceHolderType::Graph);
89 ui->dragDropContainer->setPlaceHolderType(DragDropGuiController::PlaceHolderType::Graph);
90 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
90 ui->dragDropContainer->setMimeType(MIME_TYPE_GRAPH,
91 VisualizationDragDropContainer::DropBehavior::Inserted);
91 VisualizationDragDropContainer::DropBehavior::Inserted);
92 ui->dragDropContainer->setMimeType(
92 ui->dragDropContainer->setMimeType(
93 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
93 MIME_TYPE_VARIABLE_LIST, VisualizationDragDropContainer::DropBehavior::InsertedAndMerged);
94 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
94 ui->dragDropContainer->setMimeType(MIME_TYPE_TIME_RANGE,
95 VisualizationDragDropContainer::DropBehavior::Merged);
95 VisualizationDragDropContainer::DropBehavior::Merged);
96 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
96 ui->dragDropContainer->setMimeType(MIME_TYPE_ZONE,
97 VisualizationDragDropContainer::DropBehavior::Forbidden);
97 VisualizationDragDropContainer::DropBehavior::Forbidden);
98 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
98 ui->dragDropContainer->setMimeType(MIME_TYPE_SELECTION_ZONE,
99 VisualizationDragDropContainer::DropBehavior::Forbidden);
99 VisualizationDragDropContainer::DropBehavior::Forbidden);
100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
100 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
101 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
101 return sqpApp->dragDropGuiController().checkMimeDataForVisualization(mimeData,
102 ui->dragDropContainer);
102 ui->dragDropContainer);
103 });
103 });
104
104
105 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
105 auto acceptDragWidgetFun = [](auto dragWidget, auto mimeData) {
106 if (!mimeData) {
106 if (!mimeData) {
107 return false;
107 return false;
108 }
108 }
109
109
110 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
110 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
111 auto variables = sqpApp->variableController().variablesForMimeData(
111 auto variables = sqpApp->variableController().variablesForMimeData(
112 mimeData->data(MIME_TYPE_VARIABLE_LIST));
112 mimeData->data(MIME_TYPE_VARIABLE_LIST));
113
113
114 if (variables.count() != 1) {
114 if (variables.count() != 1) {
115 return false;
115 return false;
116 }
116 }
117 auto variable = variables.first();
117 auto variable = variables.first();
118
118
119 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
119 if (auto graphWidget = dynamic_cast<const VisualizationGraphWidget *>(dragWidget)) {
120 return graphWidget->canDrop(*variable);
120 return graphWidget->canDrop(*variable);
121 }
121 }
122 }
122 }
123
123
124 return true;
124 return true;
125 };
125 };
126 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
126 ui->dragDropContainer->setAcceptDragWidgetFunction(acceptDragWidgetFun);
127
127
128 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
128 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredInContainer, this,
129 &VisualizationZoneWidget::dropMimeData);
129 &VisualizationZoneWidget::dropMimeData);
130 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
130 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccuredOnWidget, this,
131 &VisualizationZoneWidget::dropMimeDataOnGraph);
131 &VisualizationZoneWidget::dropMimeDataOnGraph);
132
132
133 // 'Close' options : widget is deleted when closed
133 // 'Close' options : widget is deleted when closed
134 setAttribute(Qt::WA_DeleteOnClose);
134 setAttribute(Qt::WA_DeleteOnClose);
135 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
135 connect(ui->closeButton, &QToolButton::clicked, this, &VisualizationZoneWidget::close);
136 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
136 ui->closeButton->setIcon(sqpApp->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
137
137
138 // Synchronisation id
138 // Synchronisation id
139 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
139 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronizationGroupId",
140 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
140 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
141 }
141 }
142
142
143 VisualizationZoneWidget::~VisualizationZoneWidget()
143 VisualizationZoneWidget::~VisualizationZoneWidget()
144 {
144 {
145 delete ui;
145 delete ui;
146 }
146 }
147
147
148 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
148 void VisualizationZoneWidget::addGraph(VisualizationGraphWidget *graphWidget)
149 {
149 {
150 // Synchronize new graph with others in the zone
150 // Synchronize new graph with others in the zone
151 impl->m_Synchronizer->addGraph(*graphWidget);
151 impl->m_Synchronizer->addGraph(*graphWidget);
152
152
153 ui->dragDropContainer->addDragWidget(graphWidget);
153 ui->dragDropContainer->addDragWidget(graphWidget);
154 }
154 }
155
155
156 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
156 void VisualizationZoneWidget::insertGraph(int index, VisualizationGraphWidget *graphWidget)
157 {
157 {
158 // Synchronize new graph with others in the zone
158 // Synchronize new graph with others in the zone
159 impl->m_Synchronizer->addGraph(*graphWidget);
159 impl->m_Synchronizer->addGraph(*graphWidget);
160
160
161 ui->dragDropContainer->insertDragWidget(index, graphWidget);
161 ui->dragDropContainer->insertDragWidget(index, graphWidget);
162 }
162 }
163
163
164 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
164 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable)
165 {
165 {
166 return createGraph(variable, -1);
166 return createGraph(variable, -1);
167 }
167 }
168
168
169 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
169 VisualizationGraphWidget *VisualizationZoneWidget::createGraph(std::shared_ptr<Variable> variable,
170 int index)
170 int index)
171 {
171 {
172 auto graphWidget
172 auto graphWidget
173 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
173 = new VisualizationGraphWidget{defaultGraphName(*ui->dragDropContainer->layout()), this};
174
174
175
175
176 // Set graph properties
176 // Set graph properties
177 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
177 graphWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
178 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
178 graphWidget->setMinimumHeight(GRAPH_MINIMUM_HEIGHT);
179
179
180
180
181 // Lambda to synchronize zone widget
181 // Lambda to synchronize zone widget
182 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
182 auto synchronizeZoneWidget = [this, graphWidget](const SqpRange &graphRange,
183 const SqpRange &oldGraphRange) {
183 const SqpRange &oldGraphRange) {
184
184
185 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
185 auto zoomType = VariableController::getZoomType(graphRange, oldGraphRange);
186 auto frameLayout = ui->dragDropContainer->layout();
186 auto frameLayout = ui->dragDropContainer->layout();
187 for (auto i = 0; i < frameLayout->count(); ++i) {
187 for (auto i = 0; i < frameLayout->count(); ++i) {
188 auto graphChild
188 auto graphChild
189 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
189 = dynamic_cast<VisualizationGraphWidget *>(frameLayout->itemAt(i)->widget());
190 if (graphChild && (graphChild != graphWidget)) {
190 if (graphChild && (graphChild != graphWidget)) {
191
191
192 auto graphChildRange = graphChild->graphRange();
192 auto graphChildRange = graphChild->graphRange();
193 switch (zoomType) {
193 switch (zoomType) {
194 case AcquisitionZoomType::ZoomIn: {
194 case AcquisitionZoomType::ZoomIn: {
195 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
195 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
196 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
196 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
197 graphChildRange.m_TStart += deltaLeft;
197 graphChildRange.m_TStart += deltaLeft;
198 graphChildRange.m_TEnd -= deltaRight;
198 graphChildRange.m_TEnd -= deltaRight;
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
199 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomIn");
200 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
200 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
201 << deltaLeft;
201 << deltaLeft;
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
202 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
203 << deltaRight;
203 << deltaRight;
204 qCDebug(LOG_VisualizationZoneWidget())
204 qCDebug(LOG_VisualizationZoneWidget())
205 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
205 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
206
206
207 break;
207 break;
208 }
208 }
209
209
210 case AcquisitionZoomType::ZoomOut: {
210 case AcquisitionZoomType::ZoomOut: {
211 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
211 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: ZoomOut");
212 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
212 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
213 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
213 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
214 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaLeft")
215 << deltaLeft;
215 << deltaLeft;
216 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
216 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: deltaRight")
217 << deltaRight;
217 << deltaRight;
218 qCDebug(LOG_VisualizationZoneWidget())
218 qCDebug(LOG_VisualizationZoneWidget())
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
219 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
220 graphChildRange.m_TStart -= deltaLeft;
220 graphChildRange.m_TStart -= deltaLeft;
221 graphChildRange.m_TEnd += deltaRight;
221 graphChildRange.m_TEnd += deltaRight;
222 break;
222 break;
223 }
223 }
224 case AcquisitionZoomType::PanRight: {
224 case AcquisitionZoomType::PanRight: {
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
225 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanRight");
226 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
226 auto deltaLeft = graphRange.m_TStart - oldGraphRange.m_TStart;
227 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
227 auto deltaRight = graphRange.m_TEnd - oldGraphRange.m_TEnd;
228 graphChildRange.m_TStart += deltaLeft;
228 graphChildRange.m_TStart += deltaLeft;
229 graphChildRange.m_TEnd += deltaRight;
229 graphChildRange.m_TEnd += deltaRight;
230 qCDebug(LOG_VisualizationZoneWidget())
230 qCDebug(LOG_VisualizationZoneWidget())
231 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
231 << tr("TORM: dt") << graphRange.m_TEnd - graphRange.m_TStart;
232 break;
232 break;
233 }
233 }
234 case AcquisitionZoomType::PanLeft: {
234 case AcquisitionZoomType::PanLeft: {
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
235 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: PanLeft");
236 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
236 auto deltaLeft = oldGraphRange.m_TStart - graphRange.m_TStart;
237 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
237 auto deltaRight = oldGraphRange.m_TEnd - graphRange.m_TEnd;
238 graphChildRange.m_TStart -= deltaLeft;
238 graphChildRange.m_TStart -= deltaLeft;
239 graphChildRange.m_TEnd -= deltaRight;
239 graphChildRange.m_TEnd -= deltaRight;
240 break;
240 break;
241 }
241 }
242 case AcquisitionZoomType::Unknown: {
242 case AcquisitionZoomType::Unknown: {
243 qCDebug(LOG_VisualizationZoneWidget())
243 qCDebug(LOG_VisualizationZoneWidget())
244 << tr("Impossible to synchronize: zoom type unknown");
244 << tr("Impossible to synchronize: zoom type unknown");
245 break;
245 break;
246 }
246 }
247 default:
247 default:
248 qCCritical(LOG_VisualizationZoneWidget())
248 qCCritical(LOG_VisualizationZoneWidget())
249 << tr("Impossible to synchronize: zoom type not take into account");
249 << tr("Impossible to synchronize: zoom type not take into account");
250 // No action
250 // No action
251 break;
251 break;
252 }
252 }
253 graphChild->enableAcquisition(false);
253 graphChild->enableAcquisition(false);
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
254 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range before: ")
255 << graphChild->graphRange();
255 << graphChild->graphRange();
256 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
256 qCDebug(LOG_VisualizationZoneWidget()) << tr("TORM: Range after : ")
257 << graphChildRange;
257 << graphChildRange;
258 qCDebug(LOG_VisualizationZoneWidget())
258 qCDebug(LOG_VisualizationZoneWidget())
259 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
259 << tr("TORM: child dt") << graphChildRange.m_TEnd - graphChildRange.m_TStart;
260 graphChild->setGraphRange(graphChildRange);
260 graphChild->setGraphRange(graphChildRange);
261 graphChild->enableAcquisition(true);
261 graphChild->enableAcquisition(true);
262 }
262 }
263 }
263 }
264 };
264 };
265
265
266 // connection for synchronization
266 // connection for synchronization
267 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
267 connect(graphWidget, &VisualizationGraphWidget::synchronize, synchronizeZoneWidget);
268 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
268 connect(graphWidget, &VisualizationGraphWidget::variableAdded, this,
269 &VisualizationZoneWidget::onVariableAdded);
269 &VisualizationZoneWidget::onVariableAdded);
270 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
270 connect(graphWidget, &VisualizationGraphWidget::variableAboutToBeRemoved, this,
271 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
271 &VisualizationZoneWidget::onVariableAboutToBeRemoved);
272
272
273 auto range = SqpRange{};
273 auto range = SqpRange{};
274 if (auto firstGraph = this->firstGraph()) {
274 if (auto firstGraph = this->firstGraph()) {
275 // Case of a new graph in a existant zone
275 // Case of a new graph in a existant zone
276 range = firstGraph->graphRange();
276 range = firstGraph->graphRange();
277 }
277 }
278 else {
278 else {
279 // Case of a new graph as the first of the zone
279 // Case of a new graph as the first of the zone
280 range = variable->range();
280 range = variable->range();
281 }
281 }
282
282
283 this->insertGraph(index, graphWidget);
283 this->insertGraph(index, graphWidget);
284
284
285 graphWidget->addVariable(variable, range);
285 graphWidget->addVariable(variable, range);
286 graphWidget->setYRange(variable);
286 graphWidget->setYRange(variable);
287
287
288 return graphWidget;
288 return graphWidget;
289 }
289 }
290
290
291 VisualizationGraphWidget *
291 VisualizationGraphWidget *
292 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
292 VisualizationZoneWidget::createGraph(const QList<std::shared_ptr<Variable> > variables, int index)
293 {
293 {
294 if (variables.isEmpty()) {
294 if (variables.isEmpty()) {
295 return nullptr;
295 return nullptr;
296 }
296 }
297
297
298 auto graphWidget = createGraph(variables.first(), index);
298 auto graphWidget = createGraph(variables.first(), index);
299 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
299 for (auto variableIt = variables.cbegin() + 1; variableIt != variables.cend(); ++variableIt) {
300 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
300 graphWidget->addVariable(*variableIt, graphWidget->graphRange());
301 }
301 }
302
302
303 return graphWidget;
303 return graphWidget;
304 }
304 }
305
305
306 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
306 VisualizationGraphWidget *VisualizationZoneWidget::firstGraph() const
307 {
307 {
308 VisualizationGraphWidget *firstGraph = nullptr;
308 VisualizationGraphWidget *firstGraph = nullptr;
309 auto layout = ui->dragDropContainer->layout();
309 auto layout = ui->dragDropContainer->layout();
310 if (layout->count() > 0) {
310 if (layout->count() > 0) {
311 if (auto visualizationGraphWidget
311 if (auto visualizationGraphWidget
312 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
312 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
313 firstGraph = visualizationGraphWidget;
313 firstGraph = visualizationGraphWidget;
314 }
314 }
315 }
315 }
316
316
317 return firstGraph;
317 return firstGraph;
318 }
318 }
319
319
320 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
320 void VisualizationZoneWidget::accept(IVisualizationWidgetVisitor *visitor)
321 {
321 {
322 if (visitor) {
322 if (visitor) {
323 visitor->visitEnter(this);
323 visitor->visitEnter(this);
324
324
325 // Apply visitor to graph children: widgets different from graphs are not visited (no
325 // Apply visitor to graph children: widgets different from graphs are not visited (no
326 // action)
326 // action)
327 processGraphs(
327 processGraphs(
328 *ui->dragDropContainer->layout(),
328 *ui->dragDropContainer->layout(),
329 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
329 [visitor](VisualizationGraphWidget &graphWidget) { graphWidget.accept(visitor); });
330
330
331 visitor->visitLeave(this);
331 visitor->visitLeave(this);
332 }
332 }
333 else {
333 else {
334 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
334 qCCritical(LOG_VisualizationZoneWidget()) << tr("Can't visit widget : the visitor is null");
335 }
335 }
336 }
336 }
337
337
338 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
338 bool VisualizationZoneWidget::canDrop(const Variable &variable) const
339 {
339 {
340 // A tab can always accomodate a variable
340 // A tab can always accomodate a variable
341 Q_UNUSED(variable);
341 Q_UNUSED(variable);
342 return true;
342 return true;
343 }
343 }
344
344
345 bool VisualizationZoneWidget::contains(const Variable &variable) const
345 bool VisualizationZoneWidget::contains(const Variable &variable) const
346 {
346 {
347 Q_UNUSED(variable);
347 Q_UNUSED(variable);
348 return false;
348 return false;
349 }
349 }
350
350
351 QString VisualizationZoneWidget::name() const
351 QString VisualizationZoneWidget::name() const
352 {
352 {
353 return ui->zoneNameLabel->text();
353 return ui->zoneNameLabel->text();
354 }
354 }
355
355
356 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
356 QMimeData *VisualizationZoneWidget::mimeData(const QPoint &position) const
357 {
357 {
358 Q_UNUSED(position);
358 Q_UNUSED(position);
359
359
360 auto mimeData = new QMimeData;
360 auto mimeData = new QMimeData;
361 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
361 mimeData->setData(MIME_TYPE_ZONE, QByteArray{});
362
362
363 if (auto firstGraph = this->firstGraph()) {
363 if (auto firstGraph = this->firstGraph()) {
364 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
364 auto timeRangeData = TimeController::mimeDataForTimeRange(firstGraph->graphRange());
365 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
365 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
366 }
366 }
367
367
368 return mimeData;
368 return mimeData;
369 }
369 }
370
370
371 bool VisualizationZoneWidget::isDragAllowed() const
371 bool VisualizationZoneWidget::isDragAllowed() const
372 {
372 {
373 return true;
373 return true;
374 }
374 }
375
375
376 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
376 void VisualizationZoneWidget::notifyMouseMoveInGraph(const QPointF &graphPosition,
377 const QPointF &plotPosition,
377 const QPointF &plotPosition,
378 VisualizationGraphWidget *graphWidget)
378 VisualizationGraphWidget *graphWidget)
379 {
379 {
380 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
380 processGraphs(*ui->dragDropContainer->layout(), [&graphPosition, &plotPosition, &graphWidget](
381 VisualizationGraphWidget &processedGraph) {
381 VisualizationGraphWidget &processedGraph) {
382
382
383 switch (sqpApp->plotsCursorMode()) {
383 switch (sqpApp->plotsCursorMode()) {
384 case SqpApplication::PlotsCursorMode::Vertical:
384 case SqpApplication::PlotsCursorMode::Vertical:
385 processedGraph.removeHorizontalCursor();
385 processedGraph.removeHorizontalCursor();
386 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
386 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
387 break;
387 break;
388 case SqpApplication::PlotsCursorMode::Temporal:
388 case SqpApplication::PlotsCursorMode::Temporal:
389 processedGraph.addVerticalCursor(plotPosition.x());
389 processedGraph.addVerticalCursor(plotPosition.x());
390 processedGraph.removeHorizontalCursor();
390 processedGraph.removeHorizontalCursor();
391 break;
391 break;
392 case SqpApplication::PlotsCursorMode::Horizontal:
392 case SqpApplication::PlotsCursorMode::Horizontal:
393 processedGraph.removeVerticalCursor();
393 processedGraph.removeVerticalCursor();
394 if (&processedGraph == graphWidget) {
394 if (&processedGraph == graphWidget) {
395 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
395 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
396 }
396 }
397 else {
397 else {
398 processedGraph.removeHorizontalCursor();
398 processedGraph.removeHorizontalCursor();
399 }
399 }
400 break;
400 break;
401 case SqpApplication::PlotsCursorMode::Cross:
401 case SqpApplication::PlotsCursorMode::Cross:
402 if (&processedGraph == graphWidget) {
402 if (&processedGraph == graphWidget) {
403 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
403 processedGraph.addVerticalCursorAtViewportPosition(graphPosition.x());
404 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
404 processedGraph.addHorizontalCursorAtViewportPosition(graphPosition.y());
405 }
405 }
406 else {
406 else {
407 processedGraph.removeHorizontalCursor();
407 processedGraph.removeHorizontalCursor();
408 processedGraph.removeVerticalCursor();
408 processedGraph.removeVerticalCursor();
409 }
409 }
410 break;
410 break;
411 case SqpApplication::PlotsCursorMode::NoCursor:
411 case SqpApplication::PlotsCursorMode::NoCursor:
412 processedGraph.removeHorizontalCursor();
412 processedGraph.removeHorizontalCursor();
413 processedGraph.removeVerticalCursor();
413 processedGraph.removeVerticalCursor();
414 break;
414 break;
415 }
415 }
416
416
417
417
418 });
418 });
419 }
419 }
420
420
421 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
421 void VisualizationZoneWidget::notifyMouseLeaveGraph(VisualizationGraphWidget *graphWidget)
422 {
422 {
423 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
423 processGraphs(*ui->dragDropContainer->layout(), [](VisualizationGraphWidget &processedGraph) {
424 processedGraph.removeHorizontalCursor();
424 processedGraph.removeHorizontalCursor();
425 processedGraph.removeVerticalCursor();
425 processedGraph.removeVerticalCursor();
426 });
426 });
427 }
427 }
428
428
429 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
429 void VisualizationZoneWidget::closeEvent(QCloseEvent *event)
430 {
430 {
431 // Closes graphs in the zone
431 // Closes graphs in the zone
432 processGraphs(*ui->dragDropContainer->layout(),
432 processGraphs(*ui->dragDropContainer->layout(),
433 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
433 [](VisualizationGraphWidget &graphWidget) { graphWidget.close(); });
434
434
435 // Delete synchronization group from variable controller
435 // Delete synchronization group from variable controller
436 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
436 QMetaObject::invokeMethod(&sqpApp->variableController(), "onRemoveSynchronizationGroupId",
437 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
437 Qt::QueuedConnection, Q_ARG(QUuid, impl->m_SynchronisationGroupId));
438
438
439 QWidget::closeEvent(event);
439 QWidget::closeEvent(event);
440 }
440 }
441
441
442 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
442 void VisualizationZoneWidget::onVariableAdded(std::shared_ptr<Variable> variable)
443 {
443 {
444 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
444 QMetaObject::invokeMethod(&sqpApp->variableController(), "onAddSynchronized",
445 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
445 Qt::QueuedConnection, Q_ARG(std::shared_ptr<Variable>, variable),
446 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
446 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
447 }
447 }
448
448
449 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
449 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variable> variable)
450 {
450 {
451 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
451 QMetaObject::invokeMethod(&sqpApp->variableController(), "desynchronize", Qt::QueuedConnection,
452 Q_ARG(std::shared_ptr<Variable>, variable),
452 Q_ARG(std::shared_ptr<Variable>, variable),
453 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
453 Q_ARG(QUuid, impl->m_SynchronisationGroupId));
454 }
454 }
455
455
456 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
456 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
457 {
457 {
458 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
458 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
459 impl->dropGraph(index, this);
459 impl->dropGraph(index, this);
460 }
460 }
461 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
461 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
462 auto variables = sqpApp->variableController().variablesForMimeData(
462 auto variables = sqpApp->variableController().variablesForMimeData(
463 mimeData->data(MIME_TYPE_VARIABLE_LIST));
463 mimeData->data(MIME_TYPE_VARIABLE_LIST));
464 impl->dropVariables(variables, index, this);
464 impl->dropVariables(variables, index, this);
465 }
465 }
466 else {
466 else {
467 qCWarning(LOG_VisualizationZoneWidget())
467 qCWarning(LOG_VisualizationZoneWidget())
468 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
468 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
469 }
469 }
470 }
470 }
471
471
472 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
472 void VisualizationZoneWidget::dropMimeDataOnGraph(VisualizationDragWidget *dragWidget,
473 const QMimeData *mimeData)
473 const QMimeData *mimeData)
474 {
474 {
475 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
475 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(dragWidget);
476 if (!graphWidget) {
476 if (!graphWidget) {
477 qCWarning(LOG_VisualizationZoneWidget())
477 qCWarning(LOG_VisualizationZoneWidget())
478 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
478 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, dropping in an unknown widget, "
479 "drop aborted");
479 "drop aborted");
480 Q_ASSERT(false);
480 Q_ASSERT(false);
481 return;
481 return;
482 }
482 }
483
483
484 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
484 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
485 auto variables = sqpApp->variableController().variablesForMimeData(
485 auto variables = sqpApp->variableController().variablesForMimeData(
486 mimeData->data(MIME_TYPE_VARIABLE_LIST));
486 mimeData->data(MIME_TYPE_VARIABLE_LIST));
487 for (const auto &var : variables) {
487 for (const auto &var : variables) {
488 graphWidget->addVariable(var, graphWidget->graphRange());
488 graphWidget->addVariable(var, graphWidget->graphRange());
489 }
489 }
490 }
490 }
491 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
491 else if (mimeData->hasFormat(MIME_TYPE_TIME_RANGE)) {
492 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
492 auto range = TimeController::timeRangeForMimeData(mimeData->data(MIME_TYPE_TIME_RANGE));
493 graphWidget->setGraphRange(range);
493 graphWidget->setGraphRange(range);
494 }
494 }
495 else {
495 else {
496 qCWarning(LOG_VisualizationZoneWidget())
496 qCWarning(LOG_VisualizationZoneWidget())
497 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
497 << tr("VisualizationZoneWidget::dropMimeDataOnGraph, unknown MIME data received.");
498 }
498 }
499 }
499 }
500
500
501 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
501 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
502 int index, VisualizationZoneWidget *zoneWidget)
502 int index, VisualizationZoneWidget *zoneWidget)
503 {
503 {
504 auto &helper = sqpApp->dragDropHelper();
504 auto &helper = sqpApp->dragDropGuiController();
505
505
506 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
506 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
507 if (!graphWidget) {
507 if (!graphWidget) {
508 qCWarning(LOG_VisualizationZoneWidget())
508 qCWarning(LOG_VisualizationZoneWidget())
509 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
509 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
510 "found or invalid.");
510 "found or invalid.");
511 Q_ASSERT(false);
511 Q_ASSERT(false);
512 return;
512 return;
513 }
513 }
514
514
515 auto parentDragDropContainer
515 auto parentDragDropContainer
516 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
516 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
517 if (!parentDragDropContainer) {
517 if (!parentDragDropContainer) {
518 qCWarning(LOG_VisualizationZoneWidget())
518 qCWarning(LOG_VisualizationZoneWidget())
519 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
519 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
520 "the dropped graph is not found.");
520 "the dropped graph is not found.");
521 Q_ASSERT(false);
521 Q_ASSERT(false);
522 return;
522 return;
523 }
523 }
524
524
525 const auto &variables = graphWidget->variables();
525 const auto &variables = graphWidget->variables();
526
526
527 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
527 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
528 // The drop didn't occur in the same zone
528 // The drop didn't occur in the same zone
529
529
530 // Abort the requests for the variables (if any)
530 // Abort the requests for the variables (if any)
531 // Commented, because it's not sure if it's needed or not
531 // Commented, because it's not sure if it's needed or not
532 // for (const auto& var : variables)
532 // for (const auto& var : variables)
533 //{
533 //{
534 // sqpApp->variableController().onAbortProgressRequested(var);
534 // sqpApp->variableController().onAbortProgressRequested(var);
535 //}
535 //}
536
536
537 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
537 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
538 auto nbGraph = parentDragDropContainer->countDragWidget();
538 auto nbGraph = parentDragDropContainer->countDragWidget();
539 if (nbGraph == 1) {
539 if (nbGraph == 1) {
540 // This is the only graph in the previous zone, close the zone
540 // This is the only graph in the previous zone, close the zone
541 helper.delayedCloseWidget(previousParentZoneWidget);
541 helper.delayedCloseWidget(previousParentZoneWidget);
542 }
542 }
543 else {
543 else {
544 // Close the graph
544 // Close the graph
545 helper.delayedCloseWidget(graphWidget);
545 helper.delayedCloseWidget(graphWidget);
546 }
546 }
547
547
548 // Creates the new graph in the zone
548 // Creates the new graph in the zone
549 auto newGraphWidget = zoneWidget->createGraph(variables, index);
549 auto newGraphWidget = zoneWidget->createGraph(variables, index);
550 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
550 newGraphWidget->addSelectionZones(graphWidget->selectionZoneRanges());
551 }
551 }
552 else {
552 else {
553 // The drop occurred in the same zone or the graph is empty
553 // The drop occurred in the same zone or the graph is empty
554 // Simple move of the graph, no variable operation associated
554 // Simple move of the graph, no variable operation associated
555 parentDragDropContainer->layout()->removeWidget(graphWidget);
555 parentDragDropContainer->layout()->removeWidget(graphWidget);
556
556
557 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
557 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
558 // The graph is empty and dropped in a different zone.
558 // The graph is empty and dropped in a different zone.
559 // Take the range of the first graph in the zone (if existing).
559 // Take the range of the first graph in the zone (if existing).
560 auto layout = zoneWidget->ui->dragDropContainer->layout();
560 auto layout = zoneWidget->ui->dragDropContainer->layout();
561 if (layout->count() > 0) {
561 if (layout->count() > 0) {
562 if (auto visualizationGraphWidget
562 if (auto visualizationGraphWidget
563 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
563 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
564 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
564 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
565 }
565 }
566 }
566 }
567 }
567 }
568
568
569 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
569 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
570 }
570 }
571 }
571 }
572
572
573 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
573 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
574 const QList<std::shared_ptr<Variable> > &variables, int index,
574 const QList<std::shared_ptr<Variable> > &variables, int index,
575 VisualizationZoneWidget *zoneWidget)
575 VisualizationZoneWidget *zoneWidget)
576 {
576 {
577 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
577 // Note: the AcceptMimeDataFunction (set on the drop container) ensure there is a single and
578 // compatible variable here
578 // compatible variable here
579 if (variables.count() > 1) {
579 if (variables.count() > 1) {
580 qCWarning(LOG_VisualizationZoneWidget())
580 qCWarning(LOG_VisualizationZoneWidget())
581 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
581 << tr("VisualizationZoneWidget::dropVariables, dropping multiple variables, operation "
582 "aborted.");
582 "aborted.");
583 return;
583 return;
584 }
584 }
585
585
586 zoneWidget->createGraph(variables, index);
586 zoneWidget->createGraph(variables, index);
587 }
587 }
General Comments 4
Under Review
author

Auto status change to "Under Review"

Approved

Status change > Approved

Approved

Status change > Approved

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