##// END OF EJS Templates
Merge pull request 382 from SciQLop-fork develop...
trabillard -
r1108:0b3fbaa8bda5 merge
parent child
Show More
@@ -0,0 +1,27
1 #ifndef SCIQLOP_ACTIONSGUICONTROLLER_H
2 #define SCIQLOP_ACTIONSGUICONTROLLER_H
3
4 #include <Actions/SelectionZoneAction.h>
5 #include <Common/spimpl.h>
6
7 #include <memory>
8
9 class ActionsGuiController {
10 public:
11 ActionsGuiController();
12
13 std::shared_ptr<SelectionZoneAction>
14 addSectionZoneAction(const QString &name, SelectionZoneAction::ExecuteFunction function);
15
16 std::shared_ptr<SelectionZoneAction>
17 addSectionZoneAction(const QStringList &subMenuList, const QString &name,
18 SelectionZoneAction::ExecuteFunction function);
19
20 QVector<std::shared_ptr<SelectionZoneAction> > selectionZoneActions() const;
21
22 private:
23 class ActionsGuiControllerPrivate;
24 spimpl::unique_impl_ptr<ActionsGuiControllerPrivate> impl;
25 };
26
27 #endif // SCIQLOP_ACTIONSGUICONTROLLER_H
@@ -0,0 +1,75
1 #ifndef SCIQLOP_SELECTIONZONEACTION_H
2 #define SCIQLOP_SELECTIONZONEACTION_H
3
4 #include <Common/spimpl.h>
5
6 #include <QLoggingCategory>
7 #include <QObject>
8
9 #include <functional>
10
11 class VisualizationSelectionZoneItem;
12
13 Q_DECLARE_LOGGING_CATEGORY(LOG_SelectionZoneAction)
14
15 /**
16 * @brief The SelectionZoneAction class represents an action on a selection zone in the
17 * visualization.
18 *
19 * The action is a function that will be executed when the slot execute() is called.
20 */
21 class SelectionZoneAction : public QObject {
22
23 Q_OBJECT
24
25 public:
26 /// Signature of the function associated to the action
27 using ExecuteFunction
28 = std::function<void(const QVector<VisualizationSelectionZoneItem *> &item)>;
29
30 using EnableFunction
31 = std::function<bool(const QVector<VisualizationSelectionZoneItem *> &item)>;
32
33 /**
34 * @param name the name of the action, displayed to the user
35 * @param fun the function that will be called when the action is executed
36 * @sa execute()
37 */
38 explicit SelectionZoneAction(const QString &name, ExecuteFunction fun);
39
40 /**
41 * @param name the name of the action, displayed to the user
42 * @param subMenusList the list of sub menus where the action should be inserted
43 * @param fun the function that will be called when the action is executed
44 * @sa execute()
45 */
46 explicit SelectionZoneAction(const QStringList &subMenuList, const QString &name,
47 ExecuteFunction fun);
48
49 /// Sets the function which determine if the action should be enabled or disabled
50 void setEnableFunction(EnableFunction fun);
51
52 /// Sets the shortcut displayed by the action.
53 /// Note: The shortcut is only displayed and not active because it is not permanently stored
54 void setDisplayedShortcut(const QKeySequence &shortcut);
55 QKeySequence displayedShortcut() const;
56
57 /// The name of the action
58 QString name() const noexcept;
59
60 /// The path in the sub menus, if any
61 QStringList subMenuList() const noexcept;
62
63 public slots:
64 /// Executes the action
65 void execute(const QVector<VisualizationSelectionZoneItem *> &item);
66
67 /// Returns true if the action is enabled
68 bool isEnabled(const QVector<VisualizationSelectionZoneItem *> &item);
69
70 private:
71 class SelectionZoneActionPrivate;
72 spimpl::unique_impl_ptr<SelectionZoneActionPrivate> impl;
73 };
74
75 #endif // SCIQLOP_SELECTIONZONEACTION_H
@@ -0,0 +1,12
1 #ifndef SCIQLOP_VISUALIZATIONACTIONMANAGER_H
2 #define SCIQLOP_VISUALIZATIONACTIONMANAGER_H
3
4
5 class VisualizationActionManager {
6 public:
7 VisualizationActionManager();
8
9 void installSelectionZoneActions();
10 };
11
12 #endif // SCIQLOP_VISUALIZATIONACTIONMANAGER_H
@@ -0,0 +1,30
1 #ifndef SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H
2 #define SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H
3
4 #include <Common/spimpl.h>
5 #include <QDialog>
6
7 namespace Ui {
8 class VisualizationMultiZoneSelectionDialog;
9 }
10
11 class VisualizationSelectionZoneItem;
12
13 class VisualizationMultiZoneSelectionDialog : public QDialog {
14 Q_OBJECT
15
16 public:
17 explicit VisualizationMultiZoneSelectionDialog(QWidget *parent = 0);
18 ~VisualizationMultiZoneSelectionDialog();
19
20 void setZones(const QVector<VisualizationSelectionZoneItem *> &zones);
21 QMap<VisualizationSelectionZoneItem *, bool> selectedZones() const;
22
23 private:
24 Ui::VisualizationMultiZoneSelectionDialog *ui;
25
26 class VisualizationMultiZoneSelectionDialogPrivate;
27 spimpl::unique_impl_ptr<VisualizationMultiZoneSelectionDialogPrivate> impl;
28 };
29
30 #endif // SCIQLOP_VISUALIZATIONMULTIZONESELECTIONDIALOG_H
@@ -0,0 +1,36
1 #include "Actions/ActionsGuiController.h"
2
3 struct ActionsGuiController::ActionsGuiControllerPrivate {
4
5 QVector<std::shared_ptr<SelectionZoneAction> > m_SelectionZoneActions;
6 };
7
8 ActionsGuiController::ActionsGuiController()
9 : impl{spimpl::make_unique_impl<ActionsGuiControllerPrivate>()}
10 {
11 }
12
13 std::shared_ptr<SelectionZoneAction>
14 ActionsGuiController::addSectionZoneAction(const QString &name,
15 SelectionZoneAction::ExecuteFunction function)
16 {
17 auto action = std::make_shared<SelectionZoneAction>(name, function);
18 impl->m_SelectionZoneActions.push_back(action);
19
20 return action;
21 }
22
23 std::shared_ptr<SelectionZoneAction>
24 ActionsGuiController::addSectionZoneAction(const QStringList &subMenuList, const QString &name,
25 SelectionZoneAction::ExecuteFunction function)
26 {
27 auto action = std::make_shared<SelectionZoneAction>(subMenuList, name, function);
28 impl->m_SelectionZoneActions.push_back(action);
29
30 return action;
31 }
32
33 QVector<std::shared_ptr<SelectionZoneAction> > ActionsGuiController::selectionZoneActions() const
34 {
35 return impl->m_SelectionZoneActions;
36 }
@@ -0,0 +1,66
1 #include <Actions/SelectionZoneAction.h>
2 #include <Visualization/VisualizationSelectionZoneItem.h>
3
4 Q_LOGGING_CATEGORY(LOG_SelectionZoneAction, "SelectionZoneAction")
5
6 struct SelectionZoneAction::SelectionZoneActionPrivate {
7 explicit SelectionZoneActionPrivate(const QString &name, const QStringList &subMenuList,
8 SelectionZoneAction::ExecuteFunction fun)
9 : m_Name{name}, m_SubMenuList{subMenuList}, m_Fun{std::move(fun)}
10 {
11 }
12
13 QString m_Name;
14 QStringList m_SubMenuList;
15 QKeySequence m_DisplayedShortcut;
16 SelectionZoneAction::ExecuteFunction m_Fun;
17 SelectionZoneAction::EnableFunction m_EnableFun = [](auto zones) { return true; };
18 };
19
20 SelectionZoneAction::SelectionZoneAction(const QString &name, ExecuteFunction fun)
21 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, QStringList{},
22 std::move(fun))}
23 {
24 }
25
26 SelectionZoneAction::SelectionZoneAction(const QStringList &subMenuList, const QString &name,
27 SelectionZoneAction::ExecuteFunction fun)
28 : impl{spimpl::make_unique_impl<SelectionZoneActionPrivate>(name, subMenuList,
29 std::move(fun))}
30 {
31 }
32
33 void SelectionZoneAction::setEnableFunction(EnableFunction fun)
34 {
35 impl->m_EnableFun = std::move(fun);
36 }
37
38 void SelectionZoneAction::setDisplayedShortcut(const QKeySequence &shortcut)
39 {
40 impl->m_DisplayedShortcut = shortcut;
41 }
42
43 QKeySequence SelectionZoneAction::displayedShortcut() const
44 {
45 return impl->m_DisplayedShortcut;
46 }
47
48 QString SelectionZoneAction::name() const noexcept
49 {
50 return impl->m_Name;
51 }
52
53 QStringList SelectionZoneAction::subMenuList() const noexcept
54 {
55 return impl->m_SubMenuList;
56 }
57
58 void SelectionZoneAction::execute(const QVector<VisualizationSelectionZoneItem *> &item)
59 {
60 impl->m_Fun(item);
61 }
62
63 bool SelectionZoneAction::isEnabled(const QVector<VisualizationSelectionZoneItem *> &item)
64 {
65 return impl->m_EnableFun(item);
66 }
@@ -0,0 +1,109
1 #include "Visualization/VisualizationActionManager.h"
2 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationSelectionZoneItem.h"
4
5 #include <Actions/ActionsGuiController.h>
6 #include <SqpApplication.h>
7
8 VisualizationActionManager::VisualizationActionManager() {}
9
10 void VisualizationActionManager::installSelectionZoneActions()
11 {
12 auto &actionController = sqpApp->actionsGuiController();
13
14 auto removeZonesAction
15 = actionController.addSectionZoneAction("Remove Selected Zone(s)", [](auto zones) {
16 for (auto selectionZone : zones) {
17 if (auto graph = selectionZone->parentGraphWidget()) {
18 graph->removeSelectionZone(selectionZone);
19 }
20 }
21 });
22 removeZonesAction->setDisplayedShortcut(QKeySequence::Delete);
23
24 auto alignEnableFuntion = [](auto items) { return items.count() > 1; };
25
26 // Vertical alignment actions
27 auto alignLeftAction = actionController.addSectionZoneAction(
28 QStringList{"Align Vertically"}, "Left", [](auto zones) {
29 Q_ASSERT(zones.count() > 1);
30 auto ref = zones.takeFirst();
31 ref->alignZonesVerticallyOnLeft(zones, false);
32 });
33 alignLeftAction->setEnableFunction(alignEnableFuntion);
34
35 auto alignLeftBorderAction = actionController.addSectionZoneAction(
36 QStringList{"Align Vertically"}, "Left Borders", [](auto zones) {
37 Q_ASSERT(zones.count() > 1);
38 auto ref = zones.takeFirst();
39 ref->alignZonesVerticallyOnLeft(zones, true);
40 });
41 alignLeftBorderAction->setEnableFunction(alignEnableFuntion);
42
43 auto alignRightAction = actionController.addSectionZoneAction(
44 QStringList{"Align Vertically"}, "Right", [](auto zones) {
45 Q_ASSERT(zones.count() > 1);
46 auto ref = zones.takeFirst();
47 ref->alignZonesVerticallyOnRight(zones, false);
48 });
49 alignRightAction->setEnableFunction(alignEnableFuntion);
50
51 auto alignRightBorderAction = actionController.addSectionZoneAction(
52 QStringList{"Align Vertically"}, "Right Borders", [](auto zones) {
53 Q_ASSERT(zones.count() > 1);
54 auto ref = zones.takeFirst();
55 ref->alignZonesVerticallyOnRight(zones, true);
56 });
57 alignRightBorderAction->setEnableFunction(alignEnableFuntion);
58
59 auto alignLeftAndRightAction = actionController.addSectionZoneAction(
60 QStringList{"Align Vertically"}, "Left and Right", [](auto zones) {
61 Q_ASSERT(zones.count() > 1);
62 auto ref = zones.takeFirst();
63 ref->alignZonesVerticallyOnLeft(zones, false);
64 ref->alignZonesVerticallyOnRight(zones, true);
65 });
66 alignLeftAndRightAction->setEnableFunction(alignEnableFuntion);
67
68 // Temporal alignment actions
69 auto alignLeftTemporallyAction = actionController.addSectionZoneAction(
70 QStringList{"Align Temporally"}, "Left", [](auto zones) {
71 Q_ASSERT(zones.count() > 1);
72 auto ref = zones.takeFirst();
73 ref->alignZonesTemporallyOnLeft(zones, false);
74 });
75 alignLeftTemporallyAction->setEnableFunction(alignEnableFuntion);
76
77 auto alignLeftBorderTemporallyAction = actionController.addSectionZoneAction(
78 QStringList{"Align Temporally"}, "Left Borders", [](auto zones) {
79 Q_ASSERT(zones.count() > 1);
80 auto ref = zones.takeFirst();
81 ref->alignZonesTemporallyOnLeft(zones, true);
82 });
83 alignLeftBorderTemporallyAction->setEnableFunction(alignEnableFuntion);
84
85 auto alignRightTemporallyAction = actionController.addSectionZoneAction(
86 QStringList{"Align Temporally"}, "Right", [](auto zones) {
87 Q_ASSERT(zones.count() > 1);
88 auto ref = zones.takeFirst();
89 ref->alignZonesTemporallyOnRight(zones, false);
90 });
91 alignRightTemporallyAction->setEnableFunction(alignEnableFuntion);
92
93 auto alignRightBorderTemporallyAction = actionController.addSectionZoneAction(
94 QStringList{"Align Temporally"}, "Right Borders", [](auto zones) {
95 Q_ASSERT(zones.count() > 1);
96 auto ref = zones.takeFirst();
97 ref->alignZonesTemporallyOnRight(zones, true);
98 });
99 alignRightBorderTemporallyAction->setEnableFunction(alignEnableFuntion);
100
101 auto alignLeftAndRightTemporallyAction = actionController.addSectionZoneAction(
102 QStringList{"Align Temporally"}, "Left and Right", [](auto zones) {
103 Q_ASSERT(zones.count() > 1);
104 auto ref = zones.takeFirst();
105 ref->alignZonesTemporallyOnLeft(zones, false);
106 ref->alignZonesTemporallyOnRight(zones, true);
107 });
108 alignLeftAndRightTemporallyAction->setEnableFunction(alignEnableFuntion);
109 }
@@ -0,0 +1,69
1 #include "Visualization/VisualizationMultiZoneSelectionDialog.h"
2 #include "ui_VisualizationMultiZoneSelectionDialog.h"
3
4 #include "Common/DateUtils.h"
5 #include "Visualization/VisualizationSelectionZoneItem.h"
6
7 const auto DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd hh:mm:ss");
8
9 struct VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialogPrivate {
10 QVector<VisualizationSelectionZoneItem *> m_Zones;
11 };
12
13 VisualizationMultiZoneSelectionDialog::VisualizationMultiZoneSelectionDialog(QWidget *parent)
14 : QDialog(parent, Qt::Tool),
15 ui(new Ui::VisualizationMultiZoneSelectionDialog),
16 impl{spimpl::make_unique_impl<VisualizationMultiZoneSelectionDialogPrivate>()}
17 {
18 ui->setupUi(this);
19
20 connect(ui->buttonBox, &QDialogButtonBox::accepted, this,
21 &VisualizationMultiZoneSelectionDialog::accept);
22 connect(ui->buttonBox, &QDialogButtonBox::rejected, this,
23 &VisualizationMultiZoneSelectionDialog::reject);
24 }
25
26 VisualizationMultiZoneSelectionDialog::~VisualizationMultiZoneSelectionDialog()
27 {
28 delete ui;
29 }
30
31 void VisualizationMultiZoneSelectionDialog::setZones(
32 const QVector<VisualizationSelectionZoneItem *> &zones)
33 {
34 impl->m_Zones = zones;
35
36 // Sorts the zones to display them in temporal order
37 std::sort(impl->m_Zones.begin(), impl->m_Zones.end(), [](auto zone1, auto zone2) {
38 return zone1->range().m_TStart < zone2->range().m_TStart;
39 });
40
41 // Adds the zones in the listwidget
42 for (auto zone : impl->m_Zones) {
43 auto name = zone->name();
44 if (!name.isEmpty()) {
45 name += tr(": ");
46 }
47
48 auto range = zone->range();
49 name += DateUtils::dateTime(range.m_TStart).toString(DATETIME_FORMAT);
50 name += " - ";
51 name += DateUtils::dateTime(range.m_TEnd).toString(DATETIME_FORMAT);
52
53 auto item = new QListWidgetItem(name, ui->listWidget);
54 item->setSelected(zone->selected());
55 }
56 }
57
58 QMap<VisualizationSelectionZoneItem *, bool>
59 VisualizationMultiZoneSelectionDialog::selectedZones() const
60 {
61 QMap<VisualizationSelectionZoneItem *, bool> selectedZones;
62
63 for (auto i = 0; i < ui->listWidget->count(); ++i) {
64 auto item = ui->listWidget->item(i);
65 selectedZones[impl->m_Zones[i]] = item->isSelected();
66 }
67
68 return selectedZones;
69 }
@@ -0,0 +1,50
1 <?xml version="1.0" encoding="UTF-8"?>
2 <ui version="4.0">
3 <class>VisualizationMultiZoneSelectionDialog</class>
4 <widget class="QDialog" name="VisualizationMultiZoneSelectionDialog">
5 <property name="geometry">
6 <rect>
7 <x>0</x>
8 <y>0</y>
9 <width>303</width>
10 <height>139</height>
11 </rect>
12 </property>
13 <property name="windowTitle">
14 <string>Select...</string>
15 </property>
16 <layout class="QVBoxLayout" name="verticalLayout">
17 <property name="spacing">
18 <number>6</number>
19 </property>
20 <property name="leftMargin">
21 <number>0</number>
22 </property>
23 <property name="topMargin">
24 <number>0</number>
25 </property>
26 <property name="rightMargin">
27 <number>0</number>
28 </property>
29 <property name="bottomMargin">
30 <number>0</number>
31 </property>
32 <item>
33 <widget class="QListWidget" name="listWidget">
34 <property name="selectionMode">
35 <enum>QAbstractItemView::ExtendedSelection</enum>
36 </property>
37 </widget>
38 </item>
39 <item>
40 <widget class="QDialogButtonBox" name="buttonBox">
41 <property name="standardButtons">
42 <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
43 </property>
44 </widget>
45 </item>
46 </layout>
47 </widget>
48 <resources/>
49 <connections/>
50 </ui>
@@ -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,69
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 class ActionsGuiController;
24
25
25 /**
26 /**
26 * @brief The SqpApplication class aims to make the link between SciQlop
27 * @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
28 * 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
29 * 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
30 * a plugin specified by its metadata name (JSON plugin source) then others specifics
30 * method will be able to access it.
31 * method will be able to access it.
31 * You can load a data source driver plugin then create a data source.
32 * You can load a data source driver plugin then create a data source.
32 */
33 */
33
34
34 class SqpApplication : public QApplication {
35 class SqpApplication : public QApplication {
35 Q_OBJECT
36 Q_OBJECT
36 public:
37 public:
37 explicit SqpApplication(int &argc, char **argv);
38 explicit SqpApplication(int &argc, char **argv);
38 virtual ~SqpApplication();
39 virtual ~SqpApplication();
39 void initialize();
40 void initialize();
40
41
41 /// Accessors for the differents sciqlop controllers
42 /// Accessors for the differents sciqlop controllers
42 DataSourceController &dataSourceController() noexcept;
43 DataSourceController &dataSourceController() noexcept;
43 NetworkController &networkController() noexcept;
44 NetworkController &networkController() noexcept;
44 TimeController &timeController() noexcept;
45 TimeController &timeController() noexcept;
45 VariableController &variableController() noexcept;
46 VariableController &variableController() noexcept;
46 VisualizationController &visualizationController() noexcept;
47 VisualizationController &visualizationController() noexcept;
47
48
48 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
49 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
49 /// doesn't live in a thread and access gui
50 /// doesn't live in a thread and access gui
50 DragDropHelper &dragDropHelper() noexcept;
51 DragDropGuiController &dragDropGuiController() noexcept;
52 ActionsGuiController &actionsGuiController() noexcept;
51
53
52 enum class PlotsInteractionMode { None, ZoomBox, DragAndDrop, SelectionZones };
54 enum class PlotsInteractionMode { None, ZoomBox, DragAndDrop, SelectionZones };
53
55
54 enum class PlotsCursorMode { NoCursor, Vertical, Temporal, Horizontal, Cross };
56 enum class PlotsCursorMode { NoCursor, Vertical, Temporal, Horizontal, Cross };
55
57
56 PlotsInteractionMode plotsInteractionMode() const;
58 PlotsInteractionMode plotsInteractionMode() const;
57 void setPlotsInteractionMode(PlotsInteractionMode mode);
59 void setPlotsInteractionMode(PlotsInteractionMode mode);
58
60
59 PlotsCursorMode plotsCursorMode() const;
61 PlotsCursorMode plotsCursorMode() const;
60 void setPlotsCursorMode(PlotsCursorMode mode);
62 void setPlotsCursorMode(PlotsCursorMode mode);
61
63
62 private:
64 private:
63 class SqpApplicationPrivate;
65 class SqpApplicationPrivate;
64 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
66 spimpl::unique_impl_ptr<SqpApplicationPrivate> impl;
65 };
67 };
66
68
67 #endif // SCIQLOP_SQPAPPLICATION_H
69 #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,138 +1,141
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
1 #ifndef SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
2 #define SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
3
3
4 #include "Visualization/IVisualizationWidget.h"
4 #include "Visualization/IVisualizationWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationDragWidget.h"
6
6
7 #include <QLoggingCategory>
7 #include <QLoggingCategory>
8 #include <QWidget>
8 #include <QWidget>
9
9
10 #include <memory>
10 #include <memory>
11
11
12 #include <Common/spimpl.h>
12 #include <Common/spimpl.h>
13
13
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
14 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationGraphWidget)
15
15
16 class QCPRange;
16 class QCPRange;
17 class QCustomPlot;
17 class QCustomPlot;
18 class SqpRange;
18 class SqpRange;
19 class Variable;
19 class Variable;
20 class VisualizationWidget;
20 class VisualizationWidget;
21 class VisualizationZoneWidget;
21 class VisualizationZoneWidget;
22 class VisualizationSelectionZoneItem;
22
23
23 namespace Ui {
24 namespace Ui {
24 class VisualizationGraphWidget;
25 class VisualizationGraphWidget;
25 } // namespace Ui
26 } // namespace Ui
26
27
27 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
28 class VisualizationGraphWidget : public VisualizationDragWidget, public IVisualizationWidget {
28 Q_OBJECT
29 Q_OBJECT
29
30
30 friend class QCustomPlotSynchronizer;
31 friend class QCustomPlotSynchronizer;
31 friend class VisualizationGraphRenderingDelegate;
32 friend class VisualizationGraphRenderingDelegate;
32
33
33 public:
34 public:
34 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
35 explicit VisualizationGraphWidget(const QString &name = {}, QWidget *parent = 0);
35 virtual ~VisualizationGraphWidget();
36 virtual ~VisualizationGraphWidget();
36
37
37 /// Returns the VisualizationZoneWidget which contains the graph or nullptr
38 /// Returns the VisualizationZoneWidget which contains the graph or nullptr
38 VisualizationZoneWidget *parentZoneWidget() const noexcept;
39 VisualizationZoneWidget *parentZoneWidget() const noexcept;
39
40
40 /// Returns the main VisualizationWidget which contains the graph or nullptr
41 /// Returns the main VisualizationWidget which contains the graph or nullptr
41 VisualizationWidget *parentVisualizationWidget() const;
42 VisualizationWidget *parentVisualizationWidget() const;
42
43
43 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
44 /// If acquisition isn't enable, requestDataLoading signal cannot be emit
44 void enableAcquisition(bool enable);
45 void enableAcquisition(bool enable);
45
46
46 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
47 void addVariable(std::shared_ptr<Variable> variable, SqpRange range);
47
48
48 /// Removes a variable from the graph
49 /// Removes a variable from the graph
49 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
50 void removeVariable(std::shared_ptr<Variable> variable) noexcept;
50
51
51 /// Returns the list of all variables used in the graph
52 /// Returns the list of all variables used in the graph
52 QList<std::shared_ptr<Variable> > variables() const;
53 QList<std::shared_ptr<Variable> > variables() const;
53
54
54 /// Sets the y-axis range based on the data of a variable
55 /// Sets the y-axis range based on the data of a variable
55 void setYRange(std::shared_ptr<Variable> variable);
56 void setYRange(std::shared_ptr<Variable> variable);
56 SqpRange graphRange() const noexcept;
57 SqpRange graphRange() const noexcept;
57 void setGraphRange(const SqpRange &range);
58 void setGraphRange(const SqpRange &range);
58
59
60 // Zones
59 /// Returns the ranges of all the selection zones on the graph
61 /// Returns the ranges of all the selection zones on the graph
60 QVector<SqpRange> selectionZoneRanges() const;
62 QVector<SqpRange> selectionZoneRanges() const;
61
62 /// Adds new selection zones in the graph
63 /// Adds new selection zones in the graph
63 void addSelectionZones(const QVector<SqpRange> &ranges);
64 void addSelectionZones(const QVector<SqpRange> &ranges);
65 /// Removes the specified selection zone
66 void removeSelectionZone(VisualizationSelectionZoneItem *selectionZone);
64
67
65 /// Undo the last zoom done with a zoom box
68 /// Undo the last zoom done with a zoom box
66 void undoZoom();
69 void undoZoom();
67
70
68 // IVisualizationWidget interface
71 // IVisualizationWidget interface
69 void accept(IVisualizationWidgetVisitor *visitor) override;
72 void accept(IVisualizationWidgetVisitor *visitor) override;
70 bool canDrop(const Variable &variable) const override;
73 bool canDrop(const Variable &variable) const override;
71 bool contains(const Variable &variable) const override;
74 bool contains(const Variable &variable) const override;
72 QString name() const override;
75 QString name() const override;
73
76
74 // VisualisationDragWidget
77 // VisualisationDragWidget
75 QMimeData *mimeData(const QPoint &position) const override;
78 QMimeData *mimeData(const QPoint &position) const override;
76 QPixmap customDragPixmap(const QPoint &dragPosition) override;
79 QPixmap customDragPixmap(const QPoint &dragPosition) override;
77 bool isDragAllowed() const override;
80 bool isDragAllowed() const override;
78 void highlightForMerge(bool highlighted) override;
81 void highlightForMerge(bool highlighted) override;
79
82
80 // Cursors
83 // Cursors
81 /// Adds or moves the vertical cursor at the specified value on the x-axis
84 /// Adds or moves the vertical cursor at the specified value on the x-axis
82 void addVerticalCursor(double time);
85 void addVerticalCursor(double time);
83 /// Adds or moves the vertical cursor at the specified value on the x-axis
86 /// Adds or moves the vertical cursor at the specified value on the x-axis
84 void addVerticalCursorAtViewportPosition(double position);
87 void addVerticalCursorAtViewportPosition(double position);
85 void removeVerticalCursor();
88 void removeVerticalCursor();
86 /// Adds or moves the vertical cursor at the specified value on the y-axis
89 /// Adds or moves the vertical cursor at the specified value on the y-axis
87 void addHorizontalCursor(double value);
90 void addHorizontalCursor(double value);
88 /// Adds or moves the vertical cursor at the specified value on the y-axis
91 /// Adds or moves the vertical cursor at the specified value on the y-axis
89 void addHorizontalCursorAtViewportPosition(double position);
92 void addHorizontalCursorAtViewportPosition(double position);
90 void removeHorizontalCursor();
93 void removeHorizontalCursor();
91
94
92 signals:
95 signals:
93 void synchronize(const SqpRange &range, const SqpRange &oldRange);
96 void synchronize(const SqpRange &range, const SqpRange &oldRange);
94 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
97 void requestDataLoading(QVector<std::shared_ptr<Variable> > variable, const SqpRange &range,
95 bool synchronise);
98 bool synchronise);
96
99
97 /// Signal emitted when the variable is about to be removed from the graph
100 /// Signal emitted when the variable is about to be removed from the graph
98 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
101 void variableAboutToBeRemoved(std::shared_ptr<Variable> var);
99 /// Signal emitted when the variable has been added to the graph
102 /// Signal emitted when the variable has been added to the graph
100 void variableAdded(std::shared_ptr<Variable> var);
103 void variableAdded(std::shared_ptr<Variable> var);
101
104
102 protected:
105 protected:
103 void closeEvent(QCloseEvent *event) override;
106 void closeEvent(QCloseEvent *event) override;
104 void enterEvent(QEvent *event) override;
107 void enterEvent(QEvent *event) override;
105 void leaveEvent(QEvent *event) override;
108 void leaveEvent(QEvent *event) override;
106
109
107 QCustomPlot &plot() const noexcept;
110 QCustomPlot &plot() const noexcept;
108
111
109 private:
112 private:
110 Ui::VisualizationGraphWidget *ui;
113 Ui::VisualizationGraphWidget *ui;
111
114
112 class VisualizationGraphWidgetPrivate;
115 class VisualizationGraphWidgetPrivate;
113 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
116 spimpl::unique_impl_ptr<VisualizationGraphWidgetPrivate> impl;
114
117
115 private slots:
118 private slots:
116 /// Slot called when right clicking on the graph (displays a menu)
119 /// Slot called when right clicking on the graph (displays a menu)
117 void onGraphMenuRequested(const QPoint &pos) noexcept;
120 void onGraphMenuRequested(const QPoint &pos) noexcept;
118
121
119 /// Rescale the X axe to range parameter
122 /// Rescale the X axe to range parameter
120 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
123 void onRangeChanged(const QCPRange &t1, const QCPRange &t2);
121
124
122 /// Slot called when a mouse double click was made
125 /// Slot called when a mouse double click was made
123 void onMouseDoubleClick(QMouseEvent *event) noexcept;
126 void onMouseDoubleClick(QMouseEvent *event) noexcept;
124 /// Slot called when a mouse move was made
127 /// Slot called when a mouse move was made
125 void onMouseMove(QMouseEvent *event) noexcept;
128 void onMouseMove(QMouseEvent *event) noexcept;
126 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
129 /// Slot called when a mouse wheel was made, to perform some processing before the zoom is done
127 void onMouseWheel(QWheelEvent *event) noexcept;
130 void onMouseWheel(QWheelEvent *event) noexcept;
128 /// Slot called when a mouse press was made, to activate the calibration of a graph
131 /// Slot called when a mouse press was made, to activate the calibration of a graph
129 void onMousePress(QMouseEvent *event) noexcept;
132 void onMousePress(QMouseEvent *event) noexcept;
130 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
133 /// Slot called when a mouse release was made, to deactivate the calibration of a graph
131 void onMouseRelease(QMouseEvent *event) noexcept;
134 void onMouseRelease(QMouseEvent *event) noexcept;
132
135
133 void onDataCacheVariableUpdated();
136 void onDataCacheVariableUpdated();
134
137
135 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
138 void onUpdateVarDisplaying(std::shared_ptr<Variable> variable, const SqpRange &range);
136 };
139 };
137
140
138 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
141 #endif // SCIQLOP_VISUALIZATIONGRAPHWIDGET_H
@@ -1,47 +1,68
1 #ifndef SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
1 #ifndef SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
2 #define SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
2 #define SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <Data/SqpRange.h>
5 #include <Data/SqpRange.h>
6 #include <Visualization/qcustomplot.h>
6 #include <Visualization/qcustomplot.h>
7
7
8 class VisualizationGraphWidget;
9
8 class VisualizationSelectionZoneItem : public QCPItemRect {
10 class VisualizationSelectionZoneItem : public QCPItemRect {
9
11
10 public:
12 public:
11 VisualizationSelectionZoneItem(QCustomPlot *plot);
13 VisualizationSelectionZoneItem(QCustomPlot *plot);
12 virtual ~VisualizationSelectionZoneItem();
14 virtual ~VisualizationSelectionZoneItem();
13
15
16 VisualizationGraphWidget *parentGraphWidget() const noexcept;
17
14 void setName(const QString &name);
18 void setName(const QString &name);
15 QString name() const;
19 QString name() const;
16
20
17 SqpRange range() const;
21 SqpRange range() const;
18 void setRange(double tstart, double tend);
22 void setRange(double tstart, double tend);
19 void setStart(double tstart);
23 void setStart(double tstart);
20 void setEnd(double tend);
24 void setEnd(double tend);
21
25
22 void setColor(const QColor &color);
26 void setColor(const QColor &color);
23
27
24 void setEditionEnabled(bool value);
28 void setEditionEnabled(bool value);
25 bool isEditionEnabled() const;
29 bool isEditionEnabled() const;
26
30
31 /// Moves the item at the top of its QCPLayer. It will then receive the mouse events if multiple
32 /// items are stacked on top of each others.
33 void moveToTop();
34
27 Qt::CursorShape curshorShapeForPosition(const QPoint &position) const;
35 Qt::CursorShape curshorShapeForPosition(const QPoint &position) const;
28 void setHovered(bool value);
36 void setHovered(bool value);
29
37
38 /// Sets the zones which should be moved or reisized together with this zone
30 void setAssociatedEditedZones(const QVector<VisualizationSelectionZoneItem *> &associatedZones);
39 void setAssociatedEditedZones(const QVector<VisualizationSelectionZoneItem *> &associatedZones);
31
40
41 /// Align the specified zones with this one, vertically with the left border
42 bool alignZonesVerticallyOnLeft(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
43 bool allowResize);
44 /// Align the specified zones with this one, vertically with the right border
45 bool alignZonesVerticallyOnRight(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
46 bool allowResize);
47 /// Align the specified zones with this one, temporally with the left border
48 bool alignZonesTemporallyOnLeft(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
49 bool allowResize);
50 /// Align the specified zones with this one, temporally with the right border
51 bool alignZonesTemporallyOnRight(const QVector<VisualizationSelectionZoneItem *> &zonesToAlign,
52 bool allowResize);
53
32 protected:
54 protected:
33 void mousePressEvent(QMouseEvent *event, const QVariant &details) override;
55 void mousePressEvent(QMouseEvent *event, const QVariant &details) override;
34 void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) override;
56 void mouseMoveEvent(QMouseEvent *event, const QPointF &startPos) override;
35 void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) override;
57 void mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos) override;
36
58
37 void resizeLeft(double pixelDiff);
59 void resizeLeft(double pixelDiff);
38 void resizeRight(double pixelDiff);
60 void resizeRight(double pixelDiff);
39 void move(double pixelDiff);
61 void move(double pixelDiff);
40
62
41
42 private:
63 private:
43 class VisualizationSelectionZoneItemPrivate;
64 class VisualizationSelectionZoneItemPrivate;
44 spimpl::unique_impl_ptr<VisualizationSelectionZoneItemPrivate> impl;
65 spimpl::unique_impl_ptr<VisualizationSelectionZoneItemPrivate> impl;
45 };
66 };
46
67
47 #endif // SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
68 #endif // SCIQLOP_VISUALIZATIONSELECTIONZONEITEM_H
@@ -1,103 +1,110
1
1
2 gui_moc_headers = [
2 gui_moc_headers = [
3 'include/DataSource/DataSourceWidget.h',
3 'include/DataSource/DataSourceWidget.h',
4 'include/Settings/SqpSettingsDialog.h',
4 'include/Settings/SqpSettingsDialog.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
5 'include/Settings/SqpSettingsGeneralWidget.h',
6 'include/SidePane/SqpSidePane.h',
6 'include/SidePane/SqpSidePane.h',
7 'include/SqpApplication.h',
7 'include/SqpApplication.h',
8 'include/DragAndDrop/DragDropScroller.h',
8 'include/DragAndDrop/DragDropScroller.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
9 'include/DragAndDrop/DragDropTabSwitcher.h',
10 'include/TimeWidget/TimeWidget.h',
10 'include/TimeWidget/TimeWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
11 'include/Variable/VariableInspectorWidget.h',
12 'include/Variable/RenameVariableDialog.h',
12 'include/Variable/RenameVariableDialog.h',
13 'include/Visualization/qcustomplot.h',
13 'include/Visualization/qcustomplot.h',
14 'include/Visualization/VisualizationGraphWidget.h',
14 'include/Visualization/VisualizationGraphWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
15 'include/Visualization/VisualizationTabWidget.h',
16 'include/Visualization/VisualizationWidget.h',
16 'include/Visualization/VisualizationWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
17 'include/Visualization/VisualizationZoneWidget.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
18 'include/Visualization/VisualizationDragDropContainer.h',
19 'include/Visualization/VisualizationDragWidget.h',
19 'include/Visualization/VisualizationDragWidget.h',
20 'include/Visualization/ColorScaleEditor.h'
20 'include/Visualization/ColorScaleEditor.h',
21 'include/Actions/SelectionZoneAction.h',
22 'include/Visualization/VisualizationMultiZoneSelectionDialog.h'
21 ]
23 ]
22
24
23 gui_ui_files = [
25 gui_ui_files = [
24 'ui/DataSource/DataSourceWidget.ui',
26 'ui/DataSource/DataSourceWidget.ui',
25 'ui/Settings/SqpSettingsDialog.ui',
27 'ui/Settings/SqpSettingsDialog.ui',
26 'ui/Settings/SqpSettingsGeneralWidget.ui',
28 'ui/Settings/SqpSettingsGeneralWidget.ui',
27 'ui/SidePane/SqpSidePane.ui',
29 'ui/SidePane/SqpSidePane.ui',
28 'ui/TimeWidget/TimeWidget.ui',
30 'ui/TimeWidget/TimeWidget.ui',
29 'ui/Variable/VariableInspectorWidget.ui',
31 'ui/Variable/VariableInspectorWidget.ui',
30 'ui/Variable/RenameVariableDialog.ui',
32 'ui/Variable/RenameVariableDialog.ui',
31 'ui/Variable/VariableMenuHeaderWidget.ui',
33 'ui/Variable/VariableMenuHeaderWidget.ui',
32 'ui/Visualization/VisualizationGraphWidget.ui',
34 'ui/Visualization/VisualizationGraphWidget.ui',
33 'ui/Visualization/VisualizationTabWidget.ui',
35 'ui/Visualization/VisualizationTabWidget.ui',
34 'ui/Visualization/VisualizationWidget.ui',
36 'ui/Visualization/VisualizationWidget.ui',
35 'ui/Visualization/VisualizationZoneWidget.ui',
37 'ui/Visualization/VisualizationZoneWidget.ui',
36 'ui/Visualization/ColorScaleEditor.ui'
38 'ui/Visualization/ColorScaleEditor.ui',
39 'ui/Visualization/VisualizationMultiZoneSelectionDialog.ui'
37 ]
40 ]
38
41
39 gui_qresources = ['resources/sqpguiresources.qrc']
42 gui_qresources = ['resources/sqpguiresources.qrc']
40
43
41 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
44 gui_moc_files = qt5.preprocess(moc_headers : gui_moc_headers,
42 ui_files : gui_ui_files,
45 ui_files : gui_ui_files,
43 qresources : gui_qresources)
46 qresources : gui_qresources)
44
47
45 gui_sources = [
48 gui_sources = [
46 'src/SqpApplication.cpp',
49 'src/SqpApplication.cpp',
47 'src/DragAndDrop/DragDropHelper.cpp',
50 'src/DragAndDrop/DragDropGuiController.cpp',
48 'src/DragAndDrop/DragDropScroller.cpp',
51 'src/DragAndDrop/DragDropScroller.cpp',
49 'src/DragAndDrop/DragDropTabSwitcher.cpp',
52 'src/DragAndDrop/DragDropTabSwitcher.cpp',
50 'src/Common/ColorUtils.cpp',
53 'src/Common/ColorUtils.cpp',
51 'src/Common/VisualizationDef.cpp',
54 'src/Common/VisualizationDef.cpp',
52 'src/DataSource/DataSourceTreeWidgetItem.cpp',
55 'src/DataSource/DataSourceTreeWidgetItem.cpp',
53 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
56 'src/DataSource/DataSourceTreeWidgetHelper.cpp',
54 'src/DataSource/DataSourceWidget.cpp',
57 'src/DataSource/DataSourceWidget.cpp',
55 'src/DataSource/DataSourceTreeWidget.cpp',
58 'src/DataSource/DataSourceTreeWidget.cpp',
56 'src/Settings/SqpSettingsDialog.cpp',
59 'src/Settings/SqpSettingsDialog.cpp',
57 'src/Settings/SqpSettingsGeneralWidget.cpp',
60 'src/Settings/SqpSettingsGeneralWidget.cpp',
58 'src/SidePane/SqpSidePane.cpp',
61 'src/SidePane/SqpSidePane.cpp',
59 'src/TimeWidget/TimeWidget.cpp',
62 'src/TimeWidget/TimeWidget.cpp',
60 'src/Variable/VariableInspectorWidget.cpp',
63 'src/Variable/VariableInspectorWidget.cpp',
61 'src/Variable/VariableInspectorTableView.cpp',
64 'src/Variable/VariableInspectorTableView.cpp',
62 'src/Variable/VariableMenuHeaderWidget.cpp',
65 'src/Variable/VariableMenuHeaderWidget.cpp',
63 'src/Variable/RenameVariableDialog.cpp',
66 'src/Variable/RenameVariableDialog.cpp',
64 'src/Visualization/VisualizationGraphHelper.cpp',
67 'src/Visualization/VisualizationGraphHelper.cpp',
65 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
68 'src/Visualization/VisualizationGraphRenderingDelegate.cpp',
66 'src/Visualization/VisualizationGraphWidget.cpp',
69 'src/Visualization/VisualizationGraphWidget.cpp',
67 'src/Visualization/VisualizationTabWidget.cpp',
70 'src/Visualization/VisualizationTabWidget.cpp',
68 'src/Visualization/VisualizationWidget.cpp',
71 'src/Visualization/VisualizationWidget.cpp',
69 'src/Visualization/VisualizationZoneWidget.cpp',
72 'src/Visualization/VisualizationZoneWidget.cpp',
70 'src/Visualization/qcustomplot.cpp',
73 'src/Visualization/qcustomplot.cpp',
71 'src/Visualization/QCustomPlotSynchronizer.cpp',
74 'src/Visualization/QCustomPlotSynchronizer.cpp',
72 'src/Visualization/operations/FindVariableOperation.cpp',
75 'src/Visualization/operations/FindVariableOperation.cpp',
73 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
76 'src/Visualization/operations/GenerateVariableMenuOperation.cpp',
74 'src/Visualization/operations/MenuBuilder.cpp',
77 'src/Visualization/operations/MenuBuilder.cpp',
75 'src/Visualization/operations/RemoveVariableOperation.cpp',
78 'src/Visualization/operations/RemoveVariableOperation.cpp',
76 'src/Visualization/operations/RescaleAxeOperation.cpp',
79 'src/Visualization/operations/RescaleAxeOperation.cpp',
77 'src/Visualization/VisualizationDragDropContainer.cpp',
80 'src/Visualization/VisualizationDragDropContainer.cpp',
78 'src/Visualization/VisualizationDragWidget.cpp',
81 'src/Visualization/VisualizationDragWidget.cpp',
79 'src/Visualization/AxisRenderingUtils.cpp',
82 'src/Visualization/AxisRenderingUtils.cpp',
80 'src/Visualization/PlottablesRenderingUtils.cpp',
83 'src/Visualization/PlottablesRenderingUtils.cpp',
81 'src/Visualization/MacScrollBarStyle.cpp',
84 'src/Visualization/MacScrollBarStyle.cpp',
82 'src/Visualization/VisualizationCursorItem.cpp',
85 'src/Visualization/VisualizationCursorItem.cpp',
83 'src/Visualization/ColorScaleEditor.cpp',
86 'src/Visualization/ColorScaleEditor.cpp',
84 'src/Visualization/SqpColorScale.cpp',
87 'src/Visualization/SqpColorScale.cpp',
85 'src/Visualization/QCPColorMapIterator.cpp',
88 'src/Visualization/QCPColorMapIterator.cpp',
86 'src/Visualization/VisualizationSelectionZoneItem.cpp',
89 'src/Visualization/VisualizationSelectionZoneItem.cpp',
87 'src/Visualization/VisualizationSelectionZoneManager.cpp'
90 'src/Visualization/VisualizationSelectionZoneManager.cpp',
91 'src/Actions/SelectionZoneAction.cpp',
92 'src/Actions/ActionsGuiController.cpp',
93 'src/Visualization/VisualizationActionManager.cpp',
94 'src/Visualization/VisualizationMultiZoneSelectionDialog.cpp'
88 ]
95 ]
89
96
90 gui_inc = include_directories(['include'])
97 gui_inc = include_directories(['include'])
91
98
92 sciqlop_gui_lib = library('sciqlopgui',
99 sciqlop_gui_lib = library('sciqlopgui',
93 gui_sources,
100 gui_sources,
94 gui_moc_files,
101 gui_moc_files,
95 include_directories : [gui_inc],
102 include_directories : [gui_inc],
96 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
103 dependencies : [ qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core],
97 install : true
104 install : true
98 )
105 )
99
106
100 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
107 sciqlop_gui = declare_dependency(link_with : sciqlop_gui_lib,
101 include_directories : gui_inc,
108 include_directories : gui_inc,
102 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
109 dependencies : [qt5printsupport, qt5gui, qt5widgets, qt5svg, sciqlop_core])
103
110
@@ -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,212
1 #include "SqpApplication.h"
1 #include "SqpApplication.h"
2
2
3 #include <Actions/ActionsGuiController.h>
3 #include <Catalogue/CatalogueController.h>
4 #include <Catalogue/CatalogueController.h>
4 #include <Data/IDataProvider.h>
5 #include <Data/IDataProvider.h>
5 #include <DataSource/DataSourceController.h>
6 #include <DataSource/DataSourceController.h>
6 #include <DragAndDrop/DragDropHelper.h>
7 #include <DragAndDrop/DragDropGuiController.h>
7 #include <Network/NetworkController.h>
8 #include <Network/NetworkController.h>
8 #include <QThread>
9 #include <QThread>
9 #include <Time/TimeController.h>
10 #include <Time/TimeController.h>
10 #include <Variable/Variable.h>
11 #include <Variable/Variable.h>
11 #include <Variable/VariableController.h>
12 #include <Variable/VariableController.h>
12 #include <Variable/VariableModel.h>
13 #include <Variable/VariableModel.h>
13 #include <Visualization/VisualizationController.h>
14 #include <Visualization/VisualizationController.h>
14
15
15 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
16 Q_LOGGING_CATEGORY(LOG_SqpApplication, "SqpApplication")
16
17
17 class SqpApplication::SqpApplicationPrivate {
18 class SqpApplication::SqpApplicationPrivate {
18 public:
19 public:
19 SqpApplicationPrivate()
20 SqpApplicationPrivate()
20 : m_DataSourceController{std::make_unique<DataSourceController>()},
21 : m_DataSourceController{std::make_unique<DataSourceController>()},
21 m_VariableController{std::make_unique<VariableController>()},
22 m_VariableController{std::make_unique<VariableController>()},
22 m_TimeController{std::make_unique<TimeController>()},
23 m_TimeController{std::make_unique<TimeController>()},
23 m_NetworkController{std::make_unique<NetworkController>()},
24 m_NetworkController{std::make_unique<NetworkController>()},
24 m_VisualizationController{std::make_unique<VisualizationController>()},
25 m_VisualizationController{std::make_unique<VisualizationController>()},
25 m_DragDropHelper{std::make_unique<DragDropHelper>()},
26 m_DragDropGuiController{std::make_unique<DragDropGuiController>()},
26 m_CatalogueController{std::make_unique<CatalogueController>()},
27 m_CatalogueController{std::make_unique<CatalogueController>()},
28 m_ActionsGuiController{std::make_unique<ActionsGuiController>()},
27 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
29 m_PlotInterractionMode(SqpApplication::PlotsInteractionMode::None),
28 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
30 m_PlotCursorMode(SqpApplication::PlotsCursorMode::NoCursor)
29 {
31 {
30 // /////////////////////////////// //
32 // /////////////////////////////// //
31 // Connections between controllers //
33 // Connections between controllers //
32 // /////////////////////////////// //
34 // /////////////////////////////// //
33
35
34 // VariableController <-> DataSourceController
36 // VariableController <-> DataSourceController
35 connect(m_DataSourceController.get(),
37 connect(m_DataSourceController.get(),
36 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
38 SIGNAL(variableCreationRequested(const QString &, const QVariantHash &,
37 std::shared_ptr<IDataProvider>)),
39 std::shared_ptr<IDataProvider>)),
38 m_VariableController.get(),
40 m_VariableController.get(),
39 SLOT(createVariable(const QString &, const QVariantHash &,
41 SLOT(createVariable(const QString &, const QVariantHash &,
40 std::shared_ptr<IDataProvider>)));
42 std::shared_ptr<IDataProvider>)));
41
43
42 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
44 connect(m_VariableController->variableModel(), &VariableModel::requestVariable,
43 m_DataSourceController.get(), &DataSourceController::requestVariable);
45 m_DataSourceController.get(), &DataSourceController::requestVariable);
44
46
45 // VariableController <-> VisualizationController
47 // VariableController <-> VisualizationController
46 connect(m_VariableController.get(),
48 connect(m_VariableController.get(),
47 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
49 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)),
48 m_VisualizationController.get(),
50 m_VisualizationController.get(),
49 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
51 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
50
52
51 connect(m_VariableController.get(),
53 connect(m_VariableController.get(),
52 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
54 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)),
53 m_VisualizationController.get(),
55 m_VisualizationController.get(),
54 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
56 SIGNAL(rangeChanged(std::shared_ptr<Variable>, const SqpRange &)));
55
57
56
58
57 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
59 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
58 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
60 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
59 m_NetworkController->moveToThread(&m_NetworkControllerThread);
61 m_NetworkController->moveToThread(&m_NetworkControllerThread);
60 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
62 m_NetworkControllerThread.setObjectName("NetworkControllerThread");
61 m_VariableController->moveToThread(&m_VariableControllerThread);
63 m_VariableController->moveToThread(&m_VariableControllerThread);
62 m_VariableControllerThread.setObjectName("VariableControllerThread");
64 m_VariableControllerThread.setObjectName("VariableControllerThread");
63 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
65 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
64 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
66 m_VisualizationControllerThread.setObjectName("VsualizationControllerThread");
65 m_CatalogueController->moveToThread(&m_CatalogueControllerThread);
67 m_CatalogueController->moveToThread(&m_CatalogueControllerThread);
66 m_CatalogueControllerThread.setObjectName("CatalogueControllerThread");
68 m_CatalogueControllerThread.setObjectName("CatalogueControllerThread");
67
69
68
70
69 // Additionnal init
71 // Additionnal init
70 m_VariableController->setTimeController(m_TimeController.get());
72 m_VariableController->setTimeController(m_TimeController.get());
71 }
73 }
72
74
73 virtual ~SqpApplicationPrivate()
75 virtual ~SqpApplicationPrivate()
74 {
76 {
75 m_DataSourceControllerThread.quit();
77 m_DataSourceControllerThread.quit();
76 m_DataSourceControllerThread.wait();
78 m_DataSourceControllerThread.wait();
77
79
78 m_NetworkControllerThread.quit();
80 m_NetworkControllerThread.quit();
79 m_NetworkControllerThread.wait();
81 m_NetworkControllerThread.wait();
80
82
81 m_VariableControllerThread.quit();
83 m_VariableControllerThread.quit();
82 m_VariableControllerThread.wait();
84 m_VariableControllerThread.wait();
83
85
84 m_VisualizationControllerThread.quit();
86 m_VisualizationControllerThread.quit();
85 m_VisualizationControllerThread.wait();
87 m_VisualizationControllerThread.wait();
86
88
87 m_CatalogueControllerThread.quit();
89 m_CatalogueControllerThread.quit();
88 m_CatalogueControllerThread.wait();
90 m_CatalogueControllerThread.wait();
89 }
91 }
90
92
91 std::unique_ptr<DataSourceController> m_DataSourceController;
93 std::unique_ptr<DataSourceController> m_DataSourceController;
92 std::unique_ptr<VariableController> m_VariableController;
94 std::unique_ptr<VariableController> m_VariableController;
93 std::unique_ptr<TimeController> m_TimeController;
95 std::unique_ptr<TimeController> m_TimeController;
94 std::unique_ptr<NetworkController> m_NetworkController;
96 std::unique_ptr<NetworkController> m_NetworkController;
95 std::unique_ptr<VisualizationController> m_VisualizationController;
97 std::unique_ptr<VisualizationController> m_VisualizationController;
96 std::unique_ptr<CatalogueController> m_CatalogueController;
98 std::unique_ptr<CatalogueController> m_CatalogueController;
99
97 QThread m_DataSourceControllerThread;
100 QThread m_DataSourceControllerThread;
98 QThread m_NetworkControllerThread;
101 QThread m_NetworkControllerThread;
99 QThread m_VariableControllerThread;
102 QThread m_VariableControllerThread;
100 QThread m_VisualizationControllerThread;
103 QThread m_VisualizationControllerThread;
101 QThread m_CatalogueControllerThread;
104 QThread m_CatalogueControllerThread;
102
105
103 std::unique_ptr<DragDropHelper> m_DragDropHelper;
106 std::unique_ptr<DragDropGuiController> m_DragDropGuiController;
107 std::unique_ptr<ActionsGuiController> m_ActionsGuiController;
104
108
105 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
109 SqpApplication::PlotsInteractionMode m_PlotInterractionMode;
106 SqpApplication::PlotsCursorMode m_PlotCursorMode;
110 SqpApplication::PlotsCursorMode m_PlotCursorMode;
107 };
111 };
108
112
109
113
110 SqpApplication::SqpApplication(int &argc, char **argv)
114 SqpApplication::SqpApplication(int &argc, char **argv)
111 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
115 : QApplication{argc, argv}, impl{spimpl::make_unique_impl<SqpApplicationPrivate>()}
112 {
116 {
113 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
117 qCDebug(LOG_SqpApplication()) << tr("SqpApplication construction") << QThread::currentThread();
114
118
115 connect(&impl->m_DataSourceControllerThread, &QThread::started,
119 connect(&impl->m_DataSourceControllerThread, &QThread::started,
116 impl->m_DataSourceController.get(), &DataSourceController::initialize);
120 impl->m_DataSourceController.get(), &DataSourceController::initialize);
117 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
121 connect(&impl->m_DataSourceControllerThread, &QThread::finished,
118 impl->m_DataSourceController.get(), &DataSourceController::finalize);
122 impl->m_DataSourceController.get(), &DataSourceController::finalize);
119
123
120 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
124 connect(&impl->m_NetworkControllerThread, &QThread::started, impl->m_NetworkController.get(),
121 &NetworkController::initialize);
125 &NetworkController::initialize);
122 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
126 connect(&impl->m_NetworkControllerThread, &QThread::finished, impl->m_NetworkController.get(),
123 &NetworkController::finalize);
127 &NetworkController::finalize);
124
128
125 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
129 connect(&impl->m_VariableControllerThread, &QThread::started, impl->m_VariableController.get(),
126 &VariableController::initialize);
130 &VariableController::initialize);
127 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
131 connect(&impl->m_VariableControllerThread, &QThread::finished, impl->m_VariableController.get(),
128 &VariableController::finalize);
132 &VariableController::finalize);
129
133
130 connect(&impl->m_VisualizationControllerThread, &QThread::started,
134 connect(&impl->m_VisualizationControllerThread, &QThread::started,
131 impl->m_VisualizationController.get(), &VisualizationController::initialize);
135 impl->m_VisualizationController.get(), &VisualizationController::initialize);
132 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
136 connect(&impl->m_VisualizationControllerThread, &QThread::finished,
133 impl->m_VisualizationController.get(), &VisualizationController::finalize);
137 impl->m_VisualizationController.get(), &VisualizationController::finalize);
134
138
135 connect(&impl->m_CatalogueControllerThread, &QThread::started,
139 connect(&impl->m_CatalogueControllerThread, &QThread::started,
136 impl->m_CatalogueController.get(), &CatalogueController::initialize);
140 impl->m_CatalogueController.get(), &CatalogueController::initialize);
137 connect(&impl->m_CatalogueControllerThread, &QThread::finished,
141 connect(&impl->m_CatalogueControllerThread, &QThread::finished,
138 impl->m_CatalogueController.get(), &CatalogueController::finalize);
142 impl->m_CatalogueController.get(), &CatalogueController::finalize);
139
143
140 impl->m_DataSourceControllerThread.start();
144 impl->m_DataSourceControllerThread.start();
141 impl->m_NetworkControllerThread.start();
145 impl->m_NetworkControllerThread.start();
142 impl->m_VariableControllerThread.start();
146 impl->m_VariableControllerThread.start();
143 impl->m_VisualizationControllerThread.start();
147 impl->m_VisualizationControllerThread.start();
144 impl->m_CatalogueControllerThread.start();
148 impl->m_CatalogueControllerThread.start();
145 }
149 }
146
150
147 SqpApplication::~SqpApplication()
151 SqpApplication::~SqpApplication()
148 {
152 {
149 }
153 }
150
154
151 void SqpApplication::initialize()
155 void SqpApplication::initialize()
152 {
156 {
153 }
157 }
154
158
155 DataSourceController &SqpApplication::dataSourceController() noexcept
159 DataSourceController &SqpApplication::dataSourceController() noexcept
156 {
160 {
157 return *impl->m_DataSourceController;
161 return *impl->m_DataSourceController;
158 }
162 }
159
163
160 NetworkController &SqpApplication::networkController() noexcept
164 NetworkController &SqpApplication::networkController() noexcept
161 {
165 {
162 return *impl->m_NetworkController;
166 return *impl->m_NetworkController;
163 }
167 }
164
168
165 TimeController &SqpApplication::timeController() noexcept
169 TimeController &SqpApplication::timeController() noexcept
166 {
170 {
167 return *impl->m_TimeController;
171 return *impl->m_TimeController;
168 }
172 }
169
173
170 VariableController &SqpApplication::variableController() noexcept
174 VariableController &SqpApplication::variableController() noexcept
171 {
175 {
172 return *impl->m_VariableController;
176 return *impl->m_VariableController;
173 }
177 }
174
178
175 VisualizationController &SqpApplication::visualizationController() noexcept
179 VisualizationController &SqpApplication::visualizationController() noexcept
176 {
180 {
177 return *impl->m_VisualizationController;
181 return *impl->m_VisualizationController;
178 }
182 }
179
183
180 DragDropHelper &SqpApplication::dragDropHelper() noexcept
184 DragDropGuiController &SqpApplication::dragDropGuiController() noexcept
185 {
186 return *impl->m_DragDropGuiController;
187 }
188
189 ActionsGuiController &SqpApplication::actionsGuiController() noexcept
181 {
190 {
182 return *impl->m_DragDropHelper;
191 return *impl->m_ActionsGuiController;
183 }
192 }
184
193
185 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
194 SqpApplication::PlotsInteractionMode SqpApplication::plotsInteractionMode() const
186 {
195 {
187 return impl->m_PlotInterractionMode;
196 return impl->m_PlotInterractionMode;
188 }
197 }
189
198
190 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
199 void SqpApplication::setPlotsInteractionMode(SqpApplication::PlotsInteractionMode mode)
191 {
200 {
192 impl->m_PlotInterractionMode = mode;
201 impl->m_PlotInterractionMode = mode;
193 }
202 }
194
203
195 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
204 SqpApplication::PlotsCursorMode SqpApplication::plotsCursorMode() const
196 {
205 {
197 return impl->m_PlotCursorMode;
206 return impl->m_PlotCursorMode;
198 }
207 }
199
208
200 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
209 void SqpApplication::setPlotsCursorMode(SqpApplication::PlotsCursorMode mode)
201 {
210 {
202 impl->m_PlotCursorMode = mode;
211 impl->m_PlotCursorMode = mode;
203 }
212 }
@@ -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,496
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 = graphHeight / 4.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 auto acceptMerge = m_AcceptDragWidgetFun(dragWidgetHovered, mimeData);
445 if (isOnBottom) {
446
447 if (canInsert && (isOnTop || isOnBottom || !canMerge || !acceptMerge)) {
448 if (posY > (dropIndex + 1) * graphHeight - graphHeight / 2.0) {
446 dropIndex += 1;
449 dropIndex += 1;
447 }
450 }
448
451
449 if (helper.getCurrentDragWidget()) {
452 if (helper.getCurrentDragWidget()) {
450 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
453 auto dragWidgetIndex = m_Layout->indexOf(helper.getCurrentDragWidget());
451 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
454 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
452 // Correction of the index if the drop occurs in the same container
455 // 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
456 // and if the drag is started from the visualization (in that case, the
454 // dragWidget is hidden)
457 // dragWidget is hidden)
455 dropIndex += 1;
458 dropIndex += 1;
456 }
459 }
457 }
460 }
458
461
459 if (dropIndex != placeHolderIndex) {
462 if (dropIndex != placeHolderIndex) {
460 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
463 helper.insertPlaceHolder(m_Layout, dropIndex, m_PlaceHolderType,
461 m_PlaceHolderText);
464 m_PlaceHolderText);
462 }
465 }
463
466
464 helper.setHightlightedDragWidget(nullptr);
467 helper.setHightlightedDragWidget(nullptr);
465 }
468 }
466 else if (canMerge && dragWidgetHovered) {
469 else if (canMerge && dragWidgetHovered) {
467 // drop on the middle -> merge
470 // drop on the middle -> merge
468 if (hasPlaceHolder()) {
471 if (hasPlaceHolder()) {
469 helper.removePlaceHolder();
472 helper.removePlaceHolder();
470 }
473 }
471
474
472 if (m_AcceptDragWidgetFun(dragWidgetHovered, mimeData)) {
475 helper.setHightlightedDragWidget(dragWidgetHovered);
473 helper.setHightlightedDragWidget(dragWidgetHovered);
474 return true;
475 }
476 else {
477 return false;
478 }
479 }
476 }
480 else {
477 else {
481 qCWarning(LOG_VisualizationDragDropContainer())
478 qCWarning(LOG_VisualizationDragDropContainer())
482 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
479 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no valid drop "
483 "action.");
480 "action.");
484 }
481 }
485 }
482 }
486 else {
483 else {
487 qCWarning(LOG_VisualizationDragDropContainer())
484 qCInfo(LOG_VisualizationDragDropContainer())
488 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
485 << tr("VisualizationDragDropContainer::findPlaceHolderPosition, no widget "
489 "found in the "
486 "found in the "
490 "container");
487 "container");
491 }
488 }
492 }
489 }
493 else {
490 else {
494 // the mouse is hover the placeHolder
491 // the mouse is hover the placeHolder
495 // Do nothing
492 // Do nothing
496 }
493 }
497
494
498 return true;
495 return true;
499 }
496 }
@@ -1,876 +1,1004
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/VisualizationMultiZoneSelectionDialog.h"
7 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationSelectionZoneItem.h"
8 #include "Visualization/VisualizationSelectionZoneManager.h"
9 #include "Visualization/VisualizationSelectionZoneManager.h"
9 #include "Visualization/VisualizationWidget.h"
10 #include "Visualization/VisualizationWidget.h"
10 #include "Visualization/VisualizationZoneWidget.h"
11 #include "Visualization/VisualizationZoneWidget.h"
11 #include "ui_VisualizationGraphWidget.h"
12 #include "ui_VisualizationGraphWidget.h"
12
13
14 #include <Actions/ActionsGuiController.h>
13 #include <Common/MimeTypesDef.h>
15 #include <Common/MimeTypesDef.h>
14 #include <Data/ArrayData.h>
16 #include <Data/ArrayData.h>
15 #include <Data/IDataSeries.h>
17 #include <Data/IDataSeries.h>
16 #include <Data/SpectrogramSeries.h>
18 #include <Data/SpectrogramSeries.h>
17 #include <DragAndDrop/DragDropHelper.h>
19 #include <DragAndDrop/DragDropGuiController.h>
18 #include <Settings/SqpSettingsDefs.h>
20 #include <Settings/SqpSettingsDefs.h>
19 #include <SqpApplication.h>
21 #include <SqpApplication.h>
20 #include <Time/TimeController.h>
22 #include <Time/TimeController.h>
21 #include <Variable/Variable.h>
23 #include <Variable/Variable.h>
22 #include <Variable/VariableController.h>
24 #include <Variable/VariableController.h>
23
25
24 #include <unordered_map>
26 #include <unordered_map>
25
27
26 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
28 Q_LOGGING_CATEGORY(LOG_VisualizationGraphWidget, "VisualizationGraphWidget")
27
29
28 namespace {
30 namespace {
29
31
30 /// Key pressed to enable drag&drop in all modes
32 /// Key pressed to enable drag&drop in all modes
31 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
33 const auto DRAG_DROP_MODIFIER = Qt::AltModifier;
32
34
33 /// Key pressed to enable zoom on horizontal axis
35 /// Key pressed to enable zoom on horizontal axis
34 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
36 const auto HORIZONTAL_ZOOM_MODIFIER = Qt::ControlModifier;
35
37
36 /// Key pressed to enable zoom on vertical axis
38 /// Key pressed to enable zoom on vertical axis
37 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
39 const auto VERTICAL_ZOOM_MODIFIER = Qt::ShiftModifier;
38
40
39 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
41 /// Speed of a step of a wheel event for a pan, in percentage of the axis range
40 const auto PAN_SPEED = 5;
42 const auto PAN_SPEED = 5;
41
43
42 /// Key pressed to enable a calibration pan
44 /// Key pressed to enable a calibration pan
43 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
45 const auto VERTICAL_PAN_MODIFIER = Qt::AltModifier;
44
46
45 /// Key pressed to enable multi selection of selection zones
47 /// Key pressed to enable multi selection of selection zones
46 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
48 const auto MULTI_ZONE_SELECTION_MODIFIER = Qt::ControlModifier;
47
49
48 /// Minimum size for the zoom box, in percentage of the axis range
50 /// Minimum size for the zoom box, in percentage of the axis range
49 const auto ZOOM_BOX_MIN_SIZE = 0.8;
51 const auto ZOOM_BOX_MIN_SIZE = 0.8;
50
52
51 /// Format of the dates appearing in the label of a cursor
53 /// 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");
54 const auto CURSOR_LABELS_DATETIME_FORMAT = QStringLiteral("yyyy/MM/dd\nhh:mm:ss:zzz");
53
55
54 } // namespace
56 } // namespace
55
57
56 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
58 struct VisualizationGraphWidget::VisualizationGraphWidgetPrivate {
57
59
58 explicit VisualizationGraphWidgetPrivate(const QString &name)
60 explicit VisualizationGraphWidgetPrivate(const QString &name)
59 : m_Name{name},
61 : m_Name{name},
60 m_DoAcquisition{true},
62 m_DoAcquisition{true},
61 m_IsCalibration{false},
63 m_IsCalibration{false},
62 m_RenderingDelegate{nullptr}
64 m_RenderingDelegate{nullptr}
63 {
65 {
64 }
66 }
65
67
66 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
68 void updateData(PlottablesMap &plottables, std::shared_ptr<IDataSeries> dataSeries,
67 const SqpRange &range)
69 const SqpRange &range)
68 {
70 {
69 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
71 VisualizationGraphHelper::updateData(plottables, dataSeries, range);
70
72
71 // Prevents that data has changed to update rendering
73 // Prevents that data has changed to update rendering
72 m_RenderingDelegate->onPlotUpdated();
74 m_RenderingDelegate->onPlotUpdated();
73 }
75 }
74
76
75 QString m_Name;
77 QString m_Name;
76 // 1 variable -> n qcpplot
78 // 1 variable -> n qcpplot
77 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
79 std::map<std::shared_ptr<Variable>, PlottablesMap> m_VariableToPlotMultiMap;
78 bool m_DoAcquisition;
80 bool m_DoAcquisition;
79 bool m_IsCalibration;
81 bool m_IsCalibration;
80 /// Delegate used to attach rendering features to the plot
82 /// Delegate used to attach rendering features to the plot
81 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
83 std::unique_ptr<VisualizationGraphRenderingDelegate> m_RenderingDelegate;
82
84
83 QCPItemRect *m_DrawingZoomRect = nullptr;
85 QCPItemRect *m_DrawingZoomRect = nullptr;
84 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
86 QStack<QPair<QCPRange, QCPRange> > m_ZoomStack;
85
87
86 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
88 std::unique_ptr<VisualizationCursorItem> m_HorizontalCursor = nullptr;
87 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
89 std::unique_ptr<VisualizationCursorItem> m_VerticalCursor = nullptr;
88
90
89 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
91 VisualizationSelectionZoneItem *m_DrawingZone = nullptr;
90 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
92 VisualizationSelectionZoneItem *m_HoveredZone = nullptr;
91 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
93 QVector<VisualizationSelectionZoneItem *> m_SelectionZones;
92
94
93 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
95 bool m_HasMovedMouse = false; // Indicates if the mouse moved in a releaseMouse even
94
96
95 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
97 void startDrawingRect(const QPoint &pos, QCustomPlot &plot)
96 {
98 {
97 removeDrawingRect(plot);
99 removeDrawingRect(plot);
98
100
99 auto axisPos = posToAxisPos(pos, plot);
101 auto axisPos = posToAxisPos(pos, plot);
100
102
101 m_DrawingZoomRect = new QCPItemRect{&plot};
103 m_DrawingZoomRect = new QCPItemRect{&plot};
102 QPen p;
104 QPen p;
103 p.setWidth(2);
105 p.setWidth(2);
104 m_DrawingZoomRect->setPen(p);
106 m_DrawingZoomRect->setPen(p);
105
107
106 m_DrawingZoomRect->topLeft->setCoords(axisPos);
108 m_DrawingZoomRect->topLeft->setCoords(axisPos);
107 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
109 m_DrawingZoomRect->bottomRight->setCoords(axisPos);
108 }
110 }
109
111
110 void removeDrawingRect(QCustomPlot &plot)
112 void removeDrawingRect(QCustomPlot &plot)
111 {
113 {
112 if (m_DrawingZoomRect) {
114 if (m_DrawingZoomRect) {
113 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
115 plot.removeItem(m_DrawingZoomRect); // the item is deleted by QCustomPlot
114 m_DrawingZoomRect = nullptr;
116 m_DrawingZoomRect = nullptr;
115 plot.replot(QCustomPlot::rpQueuedReplot);
117 plot.replot(QCustomPlot::rpQueuedReplot);
116 }
118 }
117 }
119 }
118
120
119 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
121 void startDrawingZone(const QPoint &pos, VisualizationGraphWidget *graph)
120 {
122 {
121 endDrawingZone(graph);
123 endDrawingZone(graph);
122
124
123 auto axisPos = posToAxisPos(pos, graph->plot());
125 auto axisPos = posToAxisPos(pos, graph->plot());
124
126
125 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
127 m_DrawingZone = new VisualizationSelectionZoneItem{&graph->plot()};
126 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
128 m_DrawingZone->setRange(axisPos.x(), axisPos.x());
127 m_DrawingZone->setEditionEnabled(false);
129 m_DrawingZone->setEditionEnabled(false);
128 }
130 }
129
131
130 void endDrawingZone(VisualizationGraphWidget *graph)
132 void endDrawingZone(VisualizationGraphWidget *graph)
131 {
133 {
132 if (m_DrawingZone) {
134 if (m_DrawingZone) {
133 auto drawingZoneRange = m_DrawingZone->range();
135 auto drawingZoneRange = m_DrawingZone->range();
134 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
136 if (qAbs(drawingZoneRange.m_TEnd - drawingZoneRange.m_TStart) > 0) {
135 m_DrawingZone->setEditionEnabled(true);
137 m_DrawingZone->setEditionEnabled(true);
136 addSelectionZone(m_DrawingZone);
138 addSelectionZone(m_DrawingZone);
137 }
139 }
138 else {
140 else {
139 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
141 graph->plot().removeItem(m_DrawingZone); // the item is deleted by QCustomPlot
140 }
142 }
141
143
142 graph->plot().replot(QCustomPlot::rpQueuedReplot);
144 graph->plot().replot(QCustomPlot::rpQueuedReplot);
143 m_DrawingZone = nullptr;
145 m_DrawingZone = nullptr;
144 }
146 }
145 }
147 }
146
148
147 void setSelectionZonesEditionEnabled(bool value)
149 void setSelectionZonesEditionEnabled(bool value)
148 {
150 {
149 for (auto s : m_SelectionZones) {
151 for (auto s : m_SelectionZones) {
150 s->setEditionEnabled(value);
152 s->setEditionEnabled(value);
151 }
153 }
152 }
154 }
153
155
154 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
156 void addSelectionZone(VisualizationSelectionZoneItem *zone) { m_SelectionZones << zone; }
155
157
156 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
158 VisualizationSelectionZoneItem *selectionZoneAt(const QPoint &pos,
157 const QCustomPlot &plot) const
159 const QCustomPlot &plot) const
158 {
160 {
159 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
161 VisualizationSelectionZoneItem *selectionZoneItemUnderCursor = nullptr;
160 auto minDistanceToZone = -1;
162 auto minDistanceToZone = -1;
161 for (auto zone : m_SelectionZones) {
163 for (auto zone : m_SelectionZones) {
162 auto distanceToZone = zone->selectTest(pos, false);
164 auto distanceToZone = zone->selectTest(pos, false);
163 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
165 if ((minDistanceToZone < 0 || distanceToZone <= minDistanceToZone)
164 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
166 && distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
165 selectionZoneItemUnderCursor = zone;
167 selectionZoneItemUnderCursor = zone;
166 }
168 }
167 }
169 }
168
170
169 return selectionZoneItemUnderCursor;
171 return selectionZoneItemUnderCursor;
170 }
172 }
171
173
174 QVector<VisualizationSelectionZoneItem *> selectionZonesAt(const QPoint &pos,
175 const QCustomPlot &plot) const
176 {
177 QVector<VisualizationSelectionZoneItem *> zones;
178 for (auto zone : m_SelectionZones) {
179 auto distanceToZone = zone->selectTest(pos, false);
180 if (distanceToZone >= 0 && distanceToZone < plot.selectionTolerance()) {
181 zones << zone;
182 }
183 }
184
185 return zones;
186 }
187
188 void moveSelectionZoneOnTop(VisualizationSelectionZoneItem *zone, QCustomPlot &plot)
189 {
190 if (!m_SelectionZones.isEmpty() && m_SelectionZones.last() != zone) {
191 zone->moveToTop();
192 m_SelectionZones.removeAll(zone);
193 m_SelectionZones.append(zone);
194 }
195 }
196
172 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
197 QPointF posToAxisPos(const QPoint &pos, QCustomPlot &plot) const
173 {
198 {
174 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
199 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
175 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
200 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
176 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
201 return QPointF{axisX->pixelToCoord(pos.x()), axisY->pixelToCoord(pos.y())};
177 }
202 }
178
203
179 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
204 bool pointIsInAxisRect(const QPointF &axisPoint, QCustomPlot &plot) const
180 {
205 {
181 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
206 auto axisX = plot.axisRect()->axis(QCPAxis::atBottom);
182 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
207 auto axisY = plot.axisRect()->axis(QCPAxis::atLeft);
183 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
208 return axisX->range().contains(axisPoint.x()) && axisY->range().contains(axisPoint.y());
184 }
209 }
185 };
210 };
186
211
187 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
212 VisualizationGraphWidget::VisualizationGraphWidget(const QString &name, QWidget *parent)
188 : VisualizationDragWidget{parent},
213 : VisualizationDragWidget{parent},
189 ui{new Ui::VisualizationGraphWidget},
214 ui{new Ui::VisualizationGraphWidget},
190 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
215 impl{spimpl::make_unique_impl<VisualizationGraphWidgetPrivate>(name)}
191 {
216 {
192 ui->setupUi(this);
217 ui->setupUi(this);
193
218
194 // 'Close' options : widget is deleted when closed
219 // 'Close' options : widget is deleted when closed
195 setAttribute(Qt::WA_DeleteOnClose);
220 setAttribute(Qt::WA_DeleteOnClose);
196
221
197 // Set qcpplot properties :
222 // Set qcpplot properties :
198 // - zoom is enabled
223 // - zoom is enabled
199 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
224 // - Mouse wheel on qcpplot is intercepted to determine the zoom orientation
200 ui->widget->setInteractions(QCP::iRangeZoom);
225 ui->widget->setInteractions(QCP::iRangeZoom);
201 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
226 ui->widget->axisRect()->setRangeDrag(Qt::Horizontal | Qt::Vertical);
202
227
203 // The delegate must be initialized after the ui as it uses the plot
228 // The delegate must be initialized after the ui as it uses the plot
204 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
229 impl->m_RenderingDelegate = std::make_unique<VisualizationGraphRenderingDelegate>(*this);
205
230
206 // Init the cursors
231 // Init the cursors
207 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
232 impl->m_HorizontalCursor = std::make_unique<VisualizationCursorItem>(&plot());
208 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
233 impl->m_HorizontalCursor->setOrientation(Qt::Horizontal);
209 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
234 impl->m_VerticalCursor = std::make_unique<VisualizationCursorItem>(&plot());
210 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
235 impl->m_VerticalCursor->setOrientation(Qt::Vertical);
211
236
212 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
237 connect(ui->widget, &QCustomPlot::mousePress, this, &VisualizationGraphWidget::onMousePress);
213 connect(ui->widget, &QCustomPlot::mouseRelease, this,
238 connect(ui->widget, &QCustomPlot::mouseRelease, this,
214 &VisualizationGraphWidget::onMouseRelease);
239 &VisualizationGraphWidget::onMouseRelease);
215 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
240 connect(ui->widget, &QCustomPlot::mouseMove, this, &VisualizationGraphWidget::onMouseMove);
216 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
241 connect(ui->widget, &QCustomPlot::mouseWheel, this, &VisualizationGraphWidget::onMouseWheel);
217 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
242 connect(ui->widget, &QCustomPlot::mouseDoubleClick, this,
218 &VisualizationGraphWidget::onMouseDoubleClick);
243 &VisualizationGraphWidget::onMouseDoubleClick);
219 connect(
244 connect(
220 ui->widget->xAxis,
245 ui->widget->xAxis,
221 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
246 static_cast<void (QCPAxis::*)(const QCPRange &, const QCPRange &)>(&QCPAxis::rangeChanged),
222 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
247 this, &VisualizationGraphWidget::onRangeChanged, Qt::DirectConnection);
223
248
224 // Activates menu when right clicking on the graph
249 // Activates menu when right clicking on the graph
225 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
250 ui->widget->setContextMenuPolicy(Qt::CustomContextMenu);
226 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
251 connect(ui->widget, &QCustomPlot::customContextMenuRequested, this,
227 &VisualizationGraphWidget::onGraphMenuRequested);
252 &VisualizationGraphWidget::onGraphMenuRequested);
228
253
229 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
254 connect(this, &VisualizationGraphWidget::requestDataLoading, &sqpApp->variableController(),
230 &VariableController::onRequestDataLoading);
255 &VariableController::onRequestDataLoading);
231
256
232 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
257 connect(&sqpApp->variableController(), &VariableController::updateVarDisplaying, this,
233 &VisualizationGraphWidget::onUpdateVarDisplaying);
258 &VisualizationGraphWidget::onUpdateVarDisplaying);
234
259
235 #ifdef Q_OS_MAC
260 #ifdef Q_OS_MAC
236 plot().setPlottingHint(QCP::phFastPolylines, true);
261 plot().setPlottingHint(QCP::phFastPolylines, true);
237 #endif
262 #endif
238 }
263 }
239
264
240
265
241 VisualizationGraphWidget::~VisualizationGraphWidget()
266 VisualizationGraphWidget::~VisualizationGraphWidget()
242 {
267 {
243 delete ui;
268 delete ui;
244 }
269 }
245
270
246 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
271 VisualizationZoneWidget *VisualizationGraphWidget::parentZoneWidget() const noexcept
247 {
272 {
248 auto parent = parentWidget();
273 auto parent = parentWidget();
249 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
274 while (parent != nullptr && !qobject_cast<VisualizationZoneWidget *>(parent)) {
250 parent = parent->parentWidget();
275 parent = parent->parentWidget();
251 }
276 }
252
277
253 return qobject_cast<VisualizationZoneWidget *>(parent);
278 return qobject_cast<VisualizationZoneWidget *>(parent);
254 }
279 }
255
280
256 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
281 VisualizationWidget *VisualizationGraphWidget::parentVisualizationWidget() const
257 {
282 {
258 auto parent = parentWidget();
283 auto parent = parentWidget();
259 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
284 while (parent != nullptr && !qobject_cast<VisualizationWidget *>(parent)) {
260 parent = parent->parentWidget();
285 parent = parent->parentWidget();
261 }
286 }
262
287
263 return qobject_cast<VisualizationWidget *>(parent);
288 return qobject_cast<VisualizationWidget *>(parent);
264 }
289 }
265
290
266 void VisualizationGraphWidget::enableAcquisition(bool enable)
291 void VisualizationGraphWidget::enableAcquisition(bool enable)
267 {
292 {
268 impl->m_DoAcquisition = enable;
293 impl->m_DoAcquisition = enable;
269 }
294 }
270
295
271 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
296 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable, SqpRange range)
272 {
297 {
273 // Uses delegate to create the qcpplot components according to the variable
298 // Uses delegate to create the qcpplot components according to the variable
274 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
299 auto createdPlottables = VisualizationGraphHelper::create(variable, *ui->widget);
275
300
276 if (auto dataSeries = variable->dataSeries()) {
301 if (auto dataSeries = variable->dataSeries()) {
277 // Set axes properties according to the units of the data series
302 // Set axes properties according to the units of the data series
278 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
303 impl->m_RenderingDelegate->setAxesProperties(dataSeries);
279
304
280 // Sets rendering properties for the new plottables
305 // Sets rendering properties for the new plottables
281 // Warning: this method must be called after setAxesProperties(), as it can access to some
306 // Warning: this method must be called after setAxesProperties(), as it can access to some
282 // axes properties that have to be initialized
307 // axes properties that have to be initialized
283 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
308 impl->m_RenderingDelegate->setPlottablesProperties(dataSeries, createdPlottables);
284 }
309 }
285
310
286 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
311 impl->m_VariableToPlotMultiMap.insert({variable, std::move(createdPlottables)});
287
312
288 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
313 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
289
314
290 this->enableAcquisition(false);
315 this->enableAcquisition(false);
291 this->setGraphRange(range);
316 this->setGraphRange(range);
292 this->enableAcquisition(true);
317 this->enableAcquisition(true);
293
318
294 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
319 emit requestDataLoading(QVector<std::shared_ptr<Variable> >() << variable, range, false);
295
320
296 emit variableAdded(variable);
321 emit variableAdded(variable);
297 }
322 }
298
323
299 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
324 void VisualizationGraphWidget::removeVariable(std::shared_ptr<Variable> variable) noexcept
300 {
325 {
301 // Each component associated to the variable :
326 // Each component associated to the variable :
302 // - is removed from qcpplot (which deletes it)
327 // - is removed from qcpplot (which deletes it)
303 // - is no longer referenced in the map
328 // - is no longer referenced in the map
304 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
329 auto variableIt = impl->m_VariableToPlotMultiMap.find(variable);
305 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
330 if (variableIt != impl->m_VariableToPlotMultiMap.cend()) {
306 emit variableAboutToBeRemoved(variable);
331 emit variableAboutToBeRemoved(variable);
307
332
308 auto &plottablesMap = variableIt->second;
333 auto &plottablesMap = variableIt->second;
309
334
310 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
335 for (auto plottableIt = plottablesMap.cbegin(), plottableEnd = plottablesMap.cend();
311 plottableIt != plottableEnd;) {
336 plottableIt != plottableEnd;) {
312 ui->widget->removePlottable(plottableIt->second);
337 ui->widget->removePlottable(plottableIt->second);
313 plottableIt = plottablesMap.erase(plottableIt);
338 plottableIt = plottablesMap.erase(plottableIt);
314 }
339 }
315
340
316 impl->m_VariableToPlotMultiMap.erase(variableIt);
341 impl->m_VariableToPlotMultiMap.erase(variableIt);
317 }
342 }
318
343
319 // Updates graph
344 // Updates graph
320 ui->widget->replot();
345 ui->widget->replot();
321 }
346 }
322
347
323 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
348 QList<std::shared_ptr<Variable> > VisualizationGraphWidget::variables() const
324 {
349 {
325 auto variables = QList<std::shared_ptr<Variable> >{};
350 auto variables = QList<std::shared_ptr<Variable> >{};
326 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
351 for (auto it = std::cbegin(impl->m_VariableToPlotMultiMap);
327 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
352 it != std::cend(impl->m_VariableToPlotMultiMap); ++it) {
328 variables << it->first;
353 variables << it->first;
329 }
354 }
330
355
331 return variables;
356 return variables;
332 }
357 }
333
358
334 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
359 void VisualizationGraphWidget::setYRange(std::shared_ptr<Variable> variable)
335 {
360 {
336 if (!variable) {
361 if (!variable) {
337 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
362 qCCritical(LOG_VisualizationGraphWidget()) << "Can't set y-axis range: variable is null";
338 return;
363 return;
339 }
364 }
340
365
341 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
366 VisualizationGraphHelper::setYAxisRange(variable, *ui->widget);
342 }
367 }
343
368
344 SqpRange VisualizationGraphWidget::graphRange() const noexcept
369 SqpRange VisualizationGraphWidget::graphRange() const noexcept
345 {
370 {
346 auto graphRange = ui->widget->xAxis->range();
371 auto graphRange = ui->widget->xAxis->range();
347 return SqpRange{graphRange.lower, graphRange.upper};
372 return SqpRange{graphRange.lower, graphRange.upper};
348 }
373 }
349
374
350 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
375 void VisualizationGraphWidget::setGraphRange(const SqpRange &range)
351 {
376 {
352 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
377 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange START");
353 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
378 ui->widget->xAxis->setRange(range.m_TStart, range.m_TEnd);
354 ui->widget->replot();
379 ui->widget->replot();
355 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
380 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::setGraphRange END");
356 }
381 }
357
382
358 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
383 QVector<SqpRange> VisualizationGraphWidget::selectionZoneRanges() const
359 {
384 {
360 QVector<SqpRange> ranges;
385 QVector<SqpRange> ranges;
361 for (auto zone : impl->m_SelectionZones) {
386 for (auto zone : impl->m_SelectionZones) {
362 ranges << zone->range();
387 ranges << zone->range();
363 }
388 }
364
389
365 return ranges;
390 return ranges;
366 }
391 }
367
392
368 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
393 void VisualizationGraphWidget::addSelectionZones(const QVector<SqpRange> &ranges)
369 {
394 {
370 for (const auto &range : ranges) {
395 for (const auto &range : ranges) {
371 // note: ownership is transfered to QCustomPlot
396 // note: ownership is transfered to QCustomPlot
372 auto zone = new VisualizationSelectionZoneItem(&plot());
397 auto zone = new VisualizationSelectionZoneItem(&plot());
373 zone->setRange(range.m_TStart, range.m_TEnd);
398 zone->setRange(range.m_TStart, range.m_TEnd);
374 impl->addSelectionZone(zone);
399 impl->addSelectionZone(zone);
375 }
400 }
376
401
377 plot().replot(QCustomPlot::rpQueuedReplot);
402 plot().replot(QCustomPlot::rpQueuedReplot);
378 }
403 }
379
404
405 void VisualizationGraphWidget::removeSelectionZone(VisualizationSelectionZoneItem *selectionZone)
406 {
407 parentVisualizationWidget()->selectionZoneManager().setSelected(selectionZone, false);
408
409 if (impl->m_HoveredZone == selectionZone) {
410 impl->m_HoveredZone = nullptr;
411 setCursor(Qt::ArrowCursor);
412 }
413
414 impl->m_SelectionZones.removeAll(selectionZone);
415 plot().removeItem(selectionZone);
416 plot().replot(QCustomPlot::rpQueuedReplot);
417 }
418
380 void VisualizationGraphWidget::undoZoom()
419 void VisualizationGraphWidget::undoZoom()
381 {
420 {
382 auto zoom = impl->m_ZoomStack.pop();
421 auto zoom = impl->m_ZoomStack.pop();
383 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
422 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
384 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
423 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
385
424
386 axisX->setRange(zoom.first);
425 axisX->setRange(zoom.first);
387 axisY->setRange(zoom.second);
426 axisY->setRange(zoom.second);
388
427
389 plot().replot(QCustomPlot::rpQueuedReplot);
428 plot().replot(QCustomPlot::rpQueuedReplot);
390 }
429 }
391
430
392 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
431 void VisualizationGraphWidget::accept(IVisualizationWidgetVisitor *visitor)
393 {
432 {
394 if (visitor) {
433 if (visitor) {
395 visitor->visit(this);
434 visitor->visit(this);
396 }
435 }
397 else {
436 else {
398 qCCritical(LOG_VisualizationGraphWidget())
437 qCCritical(LOG_VisualizationGraphWidget())
399 << tr("Can't visit widget : the visitor is null");
438 << tr("Can't visit widget : the visitor is null");
400 }
439 }
401 }
440 }
402
441
403 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
442 bool VisualizationGraphWidget::canDrop(const Variable &variable) const
404 {
443 {
405 auto isSpectrogram = [](const auto &variable) {
444 auto isSpectrogram = [](const auto &variable) {
406 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
445 return std::dynamic_pointer_cast<SpectrogramSeries>(variable.dataSeries()) != nullptr;
407 };
446 };
408
447
409 // - A spectrogram series can't be dropped on graph with existing plottables
448 // - 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
449 // - No data series can be dropped on graph with existing spectrogram series
411 return isSpectrogram(variable)
450 return isSpectrogram(variable)
412 ? impl->m_VariableToPlotMultiMap.empty()
451 ? impl->m_VariableToPlotMultiMap.empty()
413 : std::none_of(
452 : std::none_of(
414 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
453 impl->m_VariableToPlotMultiMap.cbegin(), impl->m_VariableToPlotMultiMap.cend(),
415 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
454 [isSpectrogram](const auto &entry) { return isSpectrogram(*entry.first); });
416 }
455 }
417
456
418 bool VisualizationGraphWidget::contains(const Variable &variable) const
457 bool VisualizationGraphWidget::contains(const Variable &variable) const
419 {
458 {
420 // Finds the variable among the keys of the map
459 // Finds the variable among the keys of the map
421 auto variablePtr = &variable;
460 auto variablePtr = &variable;
422 auto findVariable
461 auto findVariable
423 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
462 = [variablePtr](const auto &entry) { return variablePtr == entry.first.get(); };
424
463
425 auto end = impl->m_VariableToPlotMultiMap.cend();
464 auto end = impl->m_VariableToPlotMultiMap.cend();
426 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
465 auto it = std::find_if(impl->m_VariableToPlotMultiMap.cbegin(), end, findVariable);
427 return it != end;
466 return it != end;
428 }
467 }
429
468
430 QString VisualizationGraphWidget::name() const
469 QString VisualizationGraphWidget::name() const
431 {
470 {
432 return impl->m_Name;
471 return impl->m_Name;
433 }
472 }
434
473
435 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
474 QMimeData *VisualizationGraphWidget::mimeData(const QPoint &position) const
436 {
475 {
437 auto mimeData = new QMimeData;
476 auto mimeData = new QMimeData;
438
477
439 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
478 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(position, plot());
440 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
479 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
441 && selectionZoneItemUnderCursor) {
480 && selectionZoneItemUnderCursor) {
442 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
481 mimeData->setData(MIME_TYPE_TIME_RANGE, TimeController::mimeDataForTimeRange(
443 selectionZoneItemUnderCursor->range()));
482 selectionZoneItemUnderCursor->range()));
444 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
483 mimeData->setData(MIME_TYPE_SELECTION_ZONE, TimeController::mimeDataForTimeRange(
445 selectionZoneItemUnderCursor->range()));
484 selectionZoneItemUnderCursor->range()));
446 }
485 }
447 else {
486 else {
448 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
487 mimeData->setData(MIME_TYPE_GRAPH, QByteArray{});
449
488
450 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
489 auto timeRangeData = TimeController::mimeDataForTimeRange(graphRange());
451 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
490 mimeData->setData(MIME_TYPE_TIME_RANGE, timeRangeData);
452 }
491 }
453
492
454 return mimeData;
493 return mimeData;
455 }
494 }
456
495
457 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
496 QPixmap VisualizationGraphWidget::customDragPixmap(const QPoint &dragPosition)
458 {
497 {
459 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
498 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(dragPosition, plot());
460 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
499 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones
461 && selectionZoneItemUnderCursor) {
500 && selectionZoneItemUnderCursor) {
462
501
463 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
502 auto zoneTopLeft = selectionZoneItemUnderCursor->topLeft->pixelPosition();
464 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
503 auto zoneBottomRight = selectionZoneItemUnderCursor->bottomRight->pixelPosition();
465
504
466 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
505 auto zoneSize = QSizeF{qAbs(zoneBottomRight.x() - zoneTopLeft.x()),
467 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
506 qAbs(zoneBottomRight.y() - zoneTopLeft.y())}
468 .toSize();
507 .toSize();
469
508
470 auto pixmap = QPixmap(zoneSize);
509 auto pixmap = QPixmap(zoneSize);
471 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
510 render(&pixmap, QPoint(), QRegion{QRect{zoneTopLeft.toPoint(), zoneSize}});
472
511
473 return pixmap;
512 return pixmap;
474 }
513 }
475
514
476 return QPixmap();
515 return QPixmap();
477 }
516 }
478
517
479 bool VisualizationGraphWidget::isDragAllowed() const
518 bool VisualizationGraphWidget::isDragAllowed() const
480 {
519 {
481 return true;
520 return true;
482 }
521 }
483
522
484 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
523 void VisualizationGraphWidget::highlightForMerge(bool highlighted)
485 {
524 {
486 if (highlighted) {
525 if (highlighted) {
487 plot().setBackground(QBrush(QColor("#BBD5EE")));
526 plot().setBackground(QBrush(QColor("#BBD5EE")));
488 }
527 }
489 else {
528 else {
490 plot().setBackground(QBrush(Qt::white));
529 plot().setBackground(QBrush(Qt::white));
491 }
530 }
492
531
493 plot().update();
532 plot().update();
494 }
533 }
495
534
496 void VisualizationGraphWidget::addVerticalCursor(double time)
535 void VisualizationGraphWidget::addVerticalCursor(double time)
497 {
536 {
498 impl->m_VerticalCursor->setPosition(time);
537 impl->m_VerticalCursor->setPosition(time);
499 impl->m_VerticalCursor->setVisible(true);
538 impl->m_VerticalCursor->setVisible(true);
500
539
501 auto text
540 auto text
502 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
541 = DateUtils::dateTime(time).toString(CURSOR_LABELS_DATETIME_FORMAT).replace(' ', '\n');
503 impl->m_VerticalCursor->setLabelText(text);
542 impl->m_VerticalCursor->setLabelText(text);
504 }
543 }
505
544
506 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
545 void VisualizationGraphWidget::addVerticalCursorAtViewportPosition(double position)
507 {
546 {
508 impl->m_VerticalCursor->setAbsolutePosition(position);
547 impl->m_VerticalCursor->setAbsolutePosition(position);
509 impl->m_VerticalCursor->setVisible(true);
548 impl->m_VerticalCursor->setVisible(true);
510
549
511 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
550 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
512 auto text
551 auto text
513 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
552 = DateUtils::dateTime(axis->pixelToCoord(position)).toString(CURSOR_LABELS_DATETIME_FORMAT);
514 impl->m_VerticalCursor->setLabelText(text);
553 impl->m_VerticalCursor->setLabelText(text);
515 }
554 }
516
555
517 void VisualizationGraphWidget::removeVerticalCursor()
556 void VisualizationGraphWidget::removeVerticalCursor()
518 {
557 {
519 impl->m_VerticalCursor->setVisible(false);
558 impl->m_VerticalCursor->setVisible(false);
520 plot().replot(QCustomPlot::rpQueuedReplot);
559 plot().replot(QCustomPlot::rpQueuedReplot);
521 }
560 }
522
561
523 void VisualizationGraphWidget::addHorizontalCursor(double value)
562 void VisualizationGraphWidget::addHorizontalCursor(double value)
524 {
563 {
525 impl->m_HorizontalCursor->setPosition(value);
564 impl->m_HorizontalCursor->setPosition(value);
526 impl->m_HorizontalCursor->setVisible(true);
565 impl->m_HorizontalCursor->setVisible(true);
527 impl->m_HorizontalCursor->setLabelText(QString::number(value));
566 impl->m_HorizontalCursor->setLabelText(QString::number(value));
528 }
567 }
529
568
530 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
569 void VisualizationGraphWidget::addHorizontalCursorAtViewportPosition(double position)
531 {
570 {
532 impl->m_HorizontalCursor->setAbsolutePosition(position);
571 impl->m_HorizontalCursor->setAbsolutePosition(position);
533 impl->m_HorizontalCursor->setVisible(true);
572 impl->m_HorizontalCursor->setVisible(true);
534
573
535 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
574 auto axis = plot().axisRect()->axis(QCPAxis::atLeft);
536 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
575 impl->m_HorizontalCursor->setLabelText(QString::number(axis->pixelToCoord(position)));
537 }
576 }
538
577
539 void VisualizationGraphWidget::removeHorizontalCursor()
578 void VisualizationGraphWidget::removeHorizontalCursor()
540 {
579 {
541 impl->m_HorizontalCursor->setVisible(false);
580 impl->m_HorizontalCursor->setVisible(false);
542 plot().replot(QCustomPlot::rpQueuedReplot);
581 plot().replot(QCustomPlot::rpQueuedReplot);
543 }
582 }
544
583
545 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
584 void VisualizationGraphWidget::closeEvent(QCloseEvent *event)
546 {
585 {
547 Q_UNUSED(event);
586 Q_UNUSED(event);
548
587
549 // Prevents that all variables will be removed from graph when it will be closed
588 // Prevents that all variables will be removed from graph when it will be closed
550 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
589 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
551 emit variableAboutToBeRemoved(variableEntry.first);
590 emit variableAboutToBeRemoved(variableEntry.first);
552 }
591 }
553 }
592 }
554
593
555 void VisualizationGraphWidget::enterEvent(QEvent *event)
594 void VisualizationGraphWidget::enterEvent(QEvent *event)
556 {
595 {
557 Q_UNUSED(event);
596 Q_UNUSED(event);
558 impl->m_RenderingDelegate->showGraphOverlay(true);
597 impl->m_RenderingDelegate->showGraphOverlay(true);
559 }
598 }
560
599
561 void VisualizationGraphWidget::leaveEvent(QEvent *event)
600 void VisualizationGraphWidget::leaveEvent(QEvent *event)
562 {
601 {
563 Q_UNUSED(event);
602 Q_UNUSED(event);
564 impl->m_RenderingDelegate->showGraphOverlay(false);
603 impl->m_RenderingDelegate->showGraphOverlay(false);
565
604
566 if (auto parentZone = parentZoneWidget()) {
605 if (auto parentZone = parentZoneWidget()) {
567 parentZone->notifyMouseLeaveGraph(this);
606 parentZone->notifyMouseLeaveGraph(this);
568 }
607 }
569 else {
608 else {
570 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
609 qCWarning(LOG_VisualizationGraphWidget()) << "leaveEvent: No parent zone widget";
571 }
610 }
572
611
573 if (impl->m_HoveredZone) {
612 if (impl->m_HoveredZone) {
574 impl->m_HoveredZone->setHovered(false);
613 impl->m_HoveredZone->setHovered(false);
575 impl->m_HoveredZone = nullptr;
614 impl->m_HoveredZone = nullptr;
576 }
615 }
577 }
616 }
578
617
579 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
618 QCustomPlot &VisualizationGraphWidget::plot() const noexcept
580 {
619 {
581 return *ui->widget;
620 return *ui->widget;
582 }
621 }
583
622
584 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
623 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
585 {
624 {
586 QMenu graphMenu{};
625 QMenu graphMenu{};
587
626
588 // Iterates on variables (unique keys)
627 // Iterates on variables (unique keys)
589 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
628 for (auto it = impl->m_VariableToPlotMultiMap.cbegin(),
590 end = impl->m_VariableToPlotMultiMap.cend();
629 end = impl->m_VariableToPlotMultiMap.cend();
591 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
630 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
592 // 'Remove variable' action
631 // 'Remove variable' action
593 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
632 graphMenu.addAction(tr("Remove variable %1").arg(it->first->name()),
594 [ this, var = it->first ]() { removeVariable(var); });
633 [ this, var = it->first ]() { removeVariable(var); });
595 }
634 }
596
635
597 if (!impl->m_ZoomStack.isEmpty()) {
636 if (!impl->m_ZoomStack.isEmpty()) {
598 if (!graphMenu.isEmpty()) {
637 if (!graphMenu.isEmpty()) {
599 graphMenu.addSeparator();
638 graphMenu.addSeparator();
600 }
639 }
601
640
602 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
641 graphMenu.addAction(tr("Undo Zoom"), [this]() { undoZoom(); });
603 }
642 }
604
643
644 // Selection Zone Actions
645 auto selectionZoneItem = impl->selectionZoneAt(pos, plot());
646 if (selectionZoneItem) {
647 auto selectedItems = parentVisualizationWidget()->selectionZoneManager().selectedItems();
648 selectedItems.removeAll(selectionZoneItem);
649 selectedItems.prepend(selectionZoneItem); // Put the current selection zone first
650
651 auto zoneActions = sqpApp->actionsGuiController().selectionZoneActions();
652 if (!zoneActions.isEmpty() && !graphMenu.isEmpty()) {
653 graphMenu.addSeparator();
654 }
655
656 QHash<QString, QMenu *> subMenus;
657 QHash<QString, bool> subMenusEnabled;
658
659 for (auto zoneAction : zoneActions) {
660
661 auto isEnabled = zoneAction->isEnabled(selectedItems);
662
663 auto menu = &graphMenu;
664 for (auto subMenuName : zoneAction->subMenuList()) {
665 if (!subMenus.contains(subMenuName)) {
666 menu = menu->addMenu(subMenuName);
667 subMenus[subMenuName] = menu;
668 subMenusEnabled[subMenuName] = isEnabled;
669 }
670 else {
671 menu = subMenus.value(subMenuName);
672 if (isEnabled) {
673 // The sub menu is enabled if at least one of its actions is enabled
674 subMenusEnabled[subMenuName] = true;
675 }
676 }
677 }
678
679 auto action = menu->addAction(zoneAction->name());
680 action->setEnabled(isEnabled);
681 action->setShortcut(zoneAction->displayedShortcut());
682 QObject::connect(action, &QAction::triggered,
683 [zoneAction, selectedItems]() { zoneAction->execute(selectedItems); });
684 }
685
686 for (auto it = subMenus.cbegin(); it != subMenus.cend(); ++it) {
687 it.value()->setEnabled(subMenusEnabled[it.key()]);
688 }
689 }
690
605 if (!graphMenu.isEmpty()) {
691 if (!graphMenu.isEmpty()) {
606 graphMenu.exec(QCursor::pos());
692 graphMenu.exec(QCursor::pos());
607 }
693 }
608 }
694 }
609
695
610 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
696 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1, const QCPRange &t2)
611 {
697 {
612 qCDebug(LOG_VisualizationGraphWidget())
698 qCDebug(LOG_VisualizationGraphWidget())
613 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
699 << tr("TORM: VisualizationGraphWidget::onRangeChanged")
614 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
700 << QThread::currentThread()->objectName() << "DoAcqui" << impl->m_DoAcquisition;
615
701
616 auto graphRange = SqpRange{t1.lower, t1.upper};
702 auto graphRange = SqpRange{t1.lower, t1.upper};
617 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
703 auto oldGraphRange = SqpRange{t2.lower, t2.upper};
618
704
619 if (impl->m_DoAcquisition) {
705 if (impl->m_DoAcquisition) {
620 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
706 QVector<std::shared_ptr<Variable> > variableUnderGraphVector;
621
707
622 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
708 for (auto it = impl->m_VariableToPlotMultiMap.begin(),
623 end = impl->m_VariableToPlotMultiMap.end();
709 end = impl->m_VariableToPlotMultiMap.end();
624 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
710 it != end; it = impl->m_VariableToPlotMultiMap.upper_bound(it->first)) {
625 variableUnderGraphVector.push_back(it->first);
711 variableUnderGraphVector.push_back(it->first);
626 }
712 }
627 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
713 emit requestDataLoading(std::move(variableUnderGraphVector), graphRange,
628 !impl->m_IsCalibration);
714 !impl->m_IsCalibration);
629
715
630 if (!impl->m_IsCalibration) {
716 if (!impl->m_IsCalibration) {
631 qCDebug(LOG_VisualizationGraphWidget())
717 qCDebug(LOG_VisualizationGraphWidget())
632 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
718 << tr("TORM: VisualizationGraphWidget::Synchronize notify !!")
633 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
719 << QThread::currentThread()->objectName() << graphRange << oldGraphRange;
634 emit synchronize(graphRange, oldGraphRange);
720 emit synchronize(graphRange, oldGraphRange);
635 }
721 }
636 }
722 }
637
723
638 auto pos = mapFromGlobal(QCursor::pos());
724 auto pos = mapFromGlobal(QCursor::pos());
639 auto axisPos = impl->posToAxisPos(pos, plot());
725 auto axisPos = impl->posToAxisPos(pos, plot());
640 if (auto parentZone = parentZoneWidget()) {
726 if (auto parentZone = parentZoneWidget()) {
641 if (impl->pointIsInAxisRect(axisPos, plot())) {
727 if (impl->pointIsInAxisRect(axisPos, plot())) {
642 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
728 parentZone->notifyMouseMoveInGraph(pos, axisPos, this);
643 }
729 }
644 else {
730 else {
645 parentZone->notifyMouseLeaveGraph(this);
731 parentZone->notifyMouseLeaveGraph(this);
646 }
732 }
647 }
733 }
648 else {
734 else {
649 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
735 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
650 }
736 }
651 }
737 }
652
738
653 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
739 void VisualizationGraphWidget::onMouseDoubleClick(QMouseEvent *event) noexcept
654 {
740 {
655 impl->m_RenderingDelegate->onMouseDoubleClick(event);
741 impl->m_RenderingDelegate->onMouseDoubleClick(event);
656 }
742 }
657
743
658 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
744 void VisualizationGraphWidget::onMouseMove(QMouseEvent *event) noexcept
659 {
745 {
660 // Handles plot rendering when mouse is moving
746 // Handles plot rendering when mouse is moving
661 impl->m_RenderingDelegate->onMouseMove(event);
747 impl->m_RenderingDelegate->onMouseMove(event);
662
748
663 auto axisPos = impl->posToAxisPos(event->pos(), plot());
749 auto axisPos = impl->posToAxisPos(event->pos(), plot());
664
750
665 // Zoom box and zone drawing
751 // Zoom box and zone drawing
666 if (impl->m_DrawingZoomRect) {
752 if (impl->m_DrawingZoomRect) {
667 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
753 impl->m_DrawingZoomRect->bottomRight->setCoords(axisPos);
668 }
754 }
669 else if (impl->m_DrawingZone) {
755 else if (impl->m_DrawingZone) {
670 impl->m_DrawingZone->setEnd(axisPos.x());
756 impl->m_DrawingZone->setEnd(axisPos.x());
671 }
757 }
672
758
673 // Cursor
759 // Cursor
674 if (auto parentZone = parentZoneWidget()) {
760 if (auto parentZone = parentZoneWidget()) {
675 if (impl->pointIsInAxisRect(axisPos, plot())) {
761 if (impl->pointIsInAxisRect(axisPos, plot())) {
676 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
762 parentZone->notifyMouseMoveInGraph(event->pos(), axisPos, this);
677 }
763 }
678 else {
764 else {
679 parentZone->notifyMouseLeaveGraph(this);
765 parentZone->notifyMouseLeaveGraph(this);
680 }
766 }
681 }
767 }
682 else {
768 else {
683 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
769 qCWarning(LOG_VisualizationGraphWidget()) << "onMouseMove: No parent zone widget";
684 }
770 }
685
771
686 // Search for the selection zone under the mouse
772 // Search for the selection zone under the mouse
687 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
773 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
688 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
774 if (selectionZoneItemUnderCursor && !impl->m_DrawingZone
689 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
775 && sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones) {
690
776
691 // Sets the appropriate cursor shape
777 // Sets the appropriate cursor shape
692 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
778 auto cursorShape = selectionZoneItemUnderCursor->curshorShapeForPosition(event->pos());
693 setCursor(cursorShape);
779 setCursor(cursorShape);
694
780
695 // Manages the hovered zone
781 // Manages the hovered zone
696 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
782 if (selectionZoneItemUnderCursor != impl->m_HoveredZone) {
697 if (impl->m_HoveredZone) {
783 if (impl->m_HoveredZone) {
698 impl->m_HoveredZone->setHovered(false);
784 impl->m_HoveredZone->setHovered(false);
699 }
785 }
700 selectionZoneItemUnderCursor->setHovered(true);
786 selectionZoneItemUnderCursor->setHovered(true);
701 impl->m_HoveredZone = selectionZoneItemUnderCursor;
787 impl->m_HoveredZone = selectionZoneItemUnderCursor;
702 plot().replot(QCustomPlot::rpQueuedReplot);
788 plot().replot(QCustomPlot::rpQueuedReplot);
703 }
789 }
704 }
790 }
705 else {
791 else {
706 // There is no zone under the mouse or the interaction mode is not "selection zones"
792 // There is no zone under the mouse or the interaction mode is not "selection zones"
707 if (impl->m_HoveredZone) {
793 if (impl->m_HoveredZone) {
708 impl->m_HoveredZone->setHovered(false);
794 impl->m_HoveredZone->setHovered(false);
709 impl->m_HoveredZone = nullptr;
795 impl->m_HoveredZone = nullptr;
710 }
796 }
711
797
712 setCursor(Qt::ArrowCursor);
798 setCursor(Qt::ArrowCursor);
713 }
799 }
714
800
715 impl->m_HasMovedMouse = true;
801 impl->m_HasMovedMouse = true;
716 VisualizationDragWidget::mouseMoveEvent(event);
802 VisualizationDragWidget::mouseMoveEvent(event);
717 }
803 }
718
804
719 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
805 void VisualizationGraphWidget::onMouseWheel(QWheelEvent *event) noexcept
720 {
806 {
721 auto value = event->angleDelta().x() + event->angleDelta().y();
807 auto value = event->angleDelta().x() + event->angleDelta().y();
722 if (value != 0) {
808 if (value != 0) {
723
809
724 auto direction = value > 0 ? 1.0 : -1.0;
810 auto direction = value > 0 ? 1.0 : -1.0;
725 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
811 auto isZoomX = event->modifiers().testFlag(HORIZONTAL_ZOOM_MODIFIER);
726 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
812 auto isZoomY = event->modifiers().testFlag(VERTICAL_ZOOM_MODIFIER);
727 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
813 impl->m_IsCalibration = event->modifiers().testFlag(VERTICAL_PAN_MODIFIER);
728
814
729 auto zoomOrientations = QFlags<Qt::Orientation>{};
815 auto zoomOrientations = QFlags<Qt::Orientation>{};
730 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
816 zoomOrientations.setFlag(Qt::Horizontal, isZoomX);
731 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
817 zoomOrientations.setFlag(Qt::Vertical, isZoomY);
732
818
733 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
819 ui->widget->axisRect()->setRangeZoom(zoomOrientations);
734
820
735 if (!isZoomX && !isZoomY) {
821 if (!isZoomX && !isZoomY) {
736 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
822 auto axis = plot().axisRect()->axis(QCPAxis::atBottom);
737 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
823 auto diff = direction * (axis->range().size() * (PAN_SPEED / 100.0));
738
824
739 axis->setRange(axis->range() + diff);
825 axis->setRange(axis->range() + diff);
740
826
741 if (plot().noAntialiasingOnDrag()) {
827 if (plot().noAntialiasingOnDrag()) {
742 plot().setNotAntialiasedElements(QCP::aeAll);
828 plot().setNotAntialiasedElements(QCP::aeAll);
743 }
829 }
744
830
745 plot().replot(QCustomPlot::rpQueuedReplot);
831 plot().replot(QCustomPlot::rpQueuedReplot);
746 }
832 }
747 }
833 }
748 }
834 }
749
835
750 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
836 void VisualizationGraphWidget::onMousePress(QMouseEvent *event) noexcept
751 {
837 {
752 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
838 auto isDragDropClick = event->modifiers().testFlag(DRAG_DROP_MODIFIER);
753 auto isSelectionZoneMode
839 auto isSelectionZoneMode
754 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
840 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
755 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
841 auto isLeftClick = event->buttons().testFlag(Qt::LeftButton);
756
842
757 if (!isDragDropClick && isLeftClick) {
843 if (!isDragDropClick && isLeftClick) {
758 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
844 if (sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::ZoomBox) {
759 // Starts a zoom box
845 // Starts a zoom box
760 impl->startDrawingRect(event->pos(), plot());
846 impl->startDrawingRect(event->pos(), plot());
761 }
847 }
762 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
848 else if (isSelectionZoneMode && impl->m_DrawingZone == nullptr) {
763 // Starts a new selection zone
849 // Starts a new selection zone
764 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
850 auto zoneAtPos = impl->selectionZoneAt(event->pos(), plot());
765 if (!zoneAtPos) {
851 if (!zoneAtPos) {
766 impl->startDrawingZone(event->pos(), this);
852 impl->startDrawingZone(event->pos(), this);
767 }
853 }
768 }
854 }
769 }
855 }
770
856
771 // Allows mouse panning only in default mode
857 // Allows mouse panning only in default mode
772 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
858 plot().setInteraction(QCP::iRangeDrag, sqpApp->plotsInteractionMode()
773 == SqpApplication::PlotsInteractionMode::None
859 == SqpApplication::PlotsInteractionMode::None
774 && !isDragDropClick);
860 && !isDragDropClick);
775
861
776 // Allows zone edition only in selection zone mode without drag&drop
862 // Allows zone edition only in selection zone mode without drag&drop
777 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
863 impl->setSelectionZonesEditionEnabled(isSelectionZoneMode && !isDragDropClick);
778
864
779 // Selection / Deselection
865 // Selection / Deselection
780 if (isSelectionZoneMode) {
866 if (isSelectionZoneMode) {
781 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
867 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
782 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
868 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
783 if (selectionZoneItemUnderCursor && isLeftClick) {
869
784 selectionZoneItemUnderCursor->setAssociatedEditedZones(
870
785 parentVisualizationWidget()->selectionZoneManager().selectedItems());
871 if (selectionZoneItemUnderCursor && !selectionZoneItemUnderCursor->selected()
872 && !isMultiSelectionClick) {
873 parentVisualizationWidget()->selectionZoneManager().select(
874 {selectionZoneItemUnderCursor});
786 }
875 }
787 else if (!isMultiSelectionClick && isLeftClick) {
876 else if (!selectionZoneItemUnderCursor && !isMultiSelectionClick && isLeftClick) {
788 parentVisualizationWidget()->selectionZoneManager().clearSelection();
877 parentVisualizationWidget()->selectionZoneManager().clearSelection();
789 }
878 }
790 else {
879 else {
791 // No selection change
880 // No selection change
792 }
881 }
882
883 if (selectionZoneItemUnderCursor && isLeftClick) {
884 selectionZoneItemUnderCursor->setAssociatedEditedZones(
885 parentVisualizationWidget()->selectionZoneManager().selectedItems());
886 }
793 }
887 }
794
888
795
889
796 impl->m_HasMovedMouse = false;
890 impl->m_HasMovedMouse = false;
797 VisualizationDragWidget::mousePressEvent(event);
891 VisualizationDragWidget::mousePressEvent(event);
798 }
892 }
799
893
800 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
894 void VisualizationGraphWidget::onMouseRelease(QMouseEvent *event) noexcept
801 {
895 {
802 if (impl->m_DrawingZoomRect) {
896 if (impl->m_DrawingZoomRect) {
803
897
804 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
898 auto axisX = plot().axisRect()->axis(QCPAxis::atBottom);
805 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
899 auto axisY = plot().axisRect()->axis(QCPAxis::atLeft);
806
900
807 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
901 auto newAxisXRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().x(),
808 impl->m_DrawingZoomRect->bottomRight->coords().x()};
902 impl->m_DrawingZoomRect->bottomRight->coords().x()};
809
903
810 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
904 auto newAxisYRange = QCPRange{impl->m_DrawingZoomRect->topLeft->coords().y(),
811 impl->m_DrawingZoomRect->bottomRight->coords().y()};
905 impl->m_DrawingZoomRect->bottomRight->coords().y()};
812
906
813 impl->removeDrawingRect(plot());
907 impl->removeDrawingRect(plot());
814
908
815 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
909 if (newAxisXRange.size() > axisX->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)
816 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
910 && newAxisYRange.size() > axisY->range().size() * (ZOOM_BOX_MIN_SIZE / 100.0)) {
817 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
911 impl->m_ZoomStack.push(qMakePair(axisX->range(), axisY->range()));
818 axisX->setRange(newAxisXRange);
912 axisX->setRange(newAxisXRange);
819 axisY->setRange(newAxisYRange);
913 axisY->setRange(newAxisYRange);
820
914
821 plot().replot(QCustomPlot::rpQueuedReplot);
915 plot().replot(QCustomPlot::rpQueuedReplot);
822 }
916 }
823 }
917 }
824
918
825 impl->endDrawingZone(this);
919 impl->endDrawingZone(this);
826
920
827 impl->m_IsCalibration = false;
921 impl->m_IsCalibration = false;
828
922
829 // Selection / Deselection
923 // Selection / Deselection
830 auto isSelectionZoneMode
924 auto isSelectionZoneMode
831 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
925 = sqpApp->plotsInteractionMode() == SqpApplication::PlotsInteractionMode::SelectionZones;
832 if (isSelectionZoneMode) {
926 if (isSelectionZoneMode) {
833 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
927 auto isMultiSelectionClick = event->modifiers().testFlag(MULTI_ZONE_SELECTION_MODIFIER);
834 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
928 auto selectionZoneItemUnderCursor = impl->selectionZoneAt(event->pos(), plot());
835 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton) {
929 if (selectionZoneItemUnderCursor && event->button() == Qt::LeftButton
836 if (!isMultiSelectionClick && !impl->m_HasMovedMouse) {
930 && !impl->m_HasMovedMouse) {
837 parentVisualizationWidget()->selectionZoneManager().select(
931
838 {selectionZoneItemUnderCursor});
932 auto zonesUnderCursor = impl->selectionZonesAt(event->pos(), plot());
933 if (zonesUnderCursor.count() > 1) {
934 // There are multiple zones under the mouse.
935 // Performs the selection with a selection dialog.
936 VisualizationMultiZoneSelectionDialog dialog{this};
937 dialog.setZones(zonesUnderCursor);
938 dialog.move(mapToGlobal(event->pos() - QPoint(dialog.width() / 2, 20)));
939 dialog.activateWindow();
940 dialog.raise();
941 if (dialog.exec() == QDialog::Accepted) {
942 auto selection = dialog.selectedZones();
943
944 if (!isMultiSelectionClick) {
945 parentVisualizationWidget()->selectionZoneManager().clearSelection();
946 }
947
948 for (auto it = selection.cbegin(); it != selection.cend(); ++it) {
949 auto zone = it.key();
950 auto isSelected = it.value();
951 parentVisualizationWidget()->selectionZoneManager().setSelected(zone,
952 isSelected);
953
954 if (isSelected) {
955 // Puts the zone on top of the stack so it can be moved or resized
956 impl->moveSelectionZoneOnTop(zone, plot());
957 }
958 }
959 }
839 }
960 }
840 else if (!impl->m_HasMovedMouse) {
961 else {
841 parentVisualizationWidget()->selectionZoneManager().setSelected(
962 if (!isMultiSelectionClick) {
842 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
963 parentVisualizationWidget()->selectionZoneManager().select(
843 || event->button() == Qt::RightButton);
964 {selectionZoneItemUnderCursor});
965 impl->moveSelectionZoneOnTop(selectionZoneItemUnderCursor, plot());
966 }
967 else {
968 parentVisualizationWidget()->selectionZoneManager().setSelected(
969 selectionZoneItemUnderCursor, !selectionZoneItemUnderCursor->selected()
970 || event->button() == Qt::RightButton);
971 }
844 }
972 }
845 }
973 }
846 else {
974 else {
847 // No selection change
975 // No selection change
848 }
976 }
849 }
977 }
850 }
978 }
851
979
852 void VisualizationGraphWidget::onDataCacheVariableUpdated()
980 void VisualizationGraphWidget::onDataCacheVariableUpdated()
853 {
981 {
854 auto graphRange = ui->widget->xAxis->range();
982 auto graphRange = ui->widget->xAxis->range();
855 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
983 auto dateTime = SqpRange{graphRange.lower, graphRange.upper};
856
984
857 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
985 for (auto &variableEntry : impl->m_VariableToPlotMultiMap) {
858 auto variable = variableEntry.first;
986 auto variable = variableEntry.first;
859 qCDebug(LOG_VisualizationGraphWidget())
987 qCDebug(LOG_VisualizationGraphWidget())
860 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
988 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated S" << variable->range();
861 qCDebug(LOG_VisualizationGraphWidget())
989 qCDebug(LOG_VisualizationGraphWidget())
862 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
990 << "TORM: VisualizationGraphWidget::onDataCacheVariableUpdated E" << dateTime;
863 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
991 if (dateTime.contains(variable->range()) || dateTime.intersect(variable->range())) {
864 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
992 impl->updateData(variableEntry.second, variable->dataSeries(), variable->range());
865 }
993 }
866 }
994 }
867 }
995 }
868
996
869 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
997 void VisualizationGraphWidget::onUpdateVarDisplaying(std::shared_ptr<Variable> variable,
870 const SqpRange &range)
998 const SqpRange &range)
871 {
999 {
872 auto it = impl->m_VariableToPlotMultiMap.find(variable);
1000 auto it = impl->m_VariableToPlotMultiMap.find(variable);
873 if (it != impl->m_VariableToPlotMultiMap.end()) {
1001 if (it != impl->m_VariableToPlotMultiMap.end()) {
874 impl->updateData(it->second, variable->dataSeries(), range);
1002 impl->updateData(it->second, variable->dataSeries(), range);
875 }
1003 }
876 }
1004 }
@@ -1,343 +1,440
1 #include "Visualization/VisualizationSelectionZoneItem.h"
1 #include "Visualization/VisualizationSelectionZoneItem.h"
2 #include "Visualization/VisualizationGraphWidget.h"
3 #include "Visualization/VisualizationSelectionZoneManager.h"
4 #include "Visualization/VisualizationWidget.h"
2
5
3 const QString &DEFAULT_COLOR = QStringLiteral("#E79D41");
6 const QString &DEFAULT_COLOR = QStringLiteral("#E79D41");
4
7
5 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
8 struct VisualizationSelectionZoneItem::VisualizationSelectionZoneItemPrivate {
6
9
7 QCustomPlot *m_Plot;
10 QCustomPlot *m_Plot;
8 double m_T1 = 0;
11 double m_T1 = 0;
9 double m_T2 = 0;
12 double m_T2 = 0;
10 QColor m_Color;
13 QColor m_Color;
11
14
12 bool m_IsEditionEnabled = true;
15 bool m_IsEditionEnabled = true;
13 double m_MovedOrinalT1 = 0;
16 double m_MovedOrinalT1 = 0;
14 double m_MovedOrinalT2 = 0;
17 double m_MovedOrinalT2 = 0;
15
18
16 QCPItemStraightLine *m_LeftLine;
19 QCPItemStraightLine *m_LeftLine;
17 QCPItemStraightLine *m_RightLine;
20 QCPItemStraightLine *m_RightLine;
18 QCPItemText *m_NameLabelItem = nullptr;
21 QCPItemText *m_NameLabelItem = nullptr;
19
22
20 enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move };
23 enum class EditionMode { NoEdition, ResizeLeft, ResizeRight, Move };
21 EditionMode m_CurrentEditionMode;
24 EditionMode m_CurrentEditionMode;
22
25
23 QVector<VisualizationSelectionZoneItem *> m_AssociatedEditedZones;
26 QVector<VisualizationSelectionZoneItem *> m_AssociatedEditedZones;
24
27
25 VisualizationSelectionZoneItemPrivate(QCustomPlot *plot)
28 VisualizationSelectionZoneItemPrivate(QCustomPlot *plot)
26 : m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition)
29 : m_Plot(plot), m_Color(Qt::blue), m_CurrentEditionMode(EditionMode::NoEdition)
27 {
30 {
28 }
31 }
29
32
30 void updatePosition(VisualizationSelectionZoneItem *item)
33 void updatePosition(VisualizationSelectionZoneItem *item)
31 {
34 {
32 item->topLeft->setCoords(m_T1, 0);
35 item->topLeft->setCoords(m_T1, 0);
33 item->bottomRight->setCoords(m_T2, 1);
36 item->bottomRight->setCoords(m_T2, 1);
34 }
37 }
35
38
36 EditionMode getEditionMode(const QPoint &pos, const VisualizationSelectionZoneItem *zoneItem)
39 EditionMode getEditionMode(const QPoint &pos, const VisualizationSelectionZoneItem *zoneItem)
37 {
40 {
38 auto distanceLeft = m_LeftLine->selectTest(pos, false);
41 auto distanceLeft = m_LeftLine->selectTest(pos, false);
39 auto distanceRight = m_RightLine->selectTest(pos, false);
42 auto distanceRight = m_RightLine->selectTest(pos, false);
40 auto distance = zoneItem->selectTest(pos, false);
43 auto distance = zoneItem->selectTest(pos, false);
41
44
42 if (distanceRight <= distance) {
45 if (distanceRight <= distance) {
43 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
46 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight;
44 }
47 }
45 else if (distanceLeft <= distance) {
48 else if (distanceLeft <= distance) {
46 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft;
49 return VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft;
47 }
50 }
48
51
49 return VisualizationSelectionZoneItemPrivate::EditionMode::Move;
52 return VisualizationSelectionZoneItemPrivate::EditionMode::Move;
50 }
53 }
51
54
52 double pixelSizeToAxisXSize(double pixels)
55 double pixelSizeToAxisXSize(double pixels)
53 {
56 {
54 auto axis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
57 auto axis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
55 return axis->pixelToCoord(pixels) - axis->pixelToCoord(0);
58 return axis->pixelToCoord(pixels) - axis->pixelToCoord(0);
56 }
59 }
60
61 bool alignZones(VisualizationSelectionZoneItem *referenceZone,
62 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool alignOnLeft,
63 bool allowResize, bool vertically)
64 {
65 auto result = false;
66
67 auto referenceTime
68 = alignOnLeft ? referenceZone->range().m_TStart : referenceZone->range().m_TEnd;
69
70 auto referenceBottomAxis = m_Plot->axisRect()->axis(QCPAxis::atBottom);
71 auto referenceVerticalPosition = referenceBottomAxis->coordToPixel(referenceTime);
72
73 for (auto otherZone : zonesToAlign) {
74
75 auto otherZoneRange = otherZone->range();
76 auto newZoneStart = otherZoneRange.m_TStart;
77 auto newZoneEnd = otherZoneRange.m_TEnd;
78
79 auto alignedTime = referenceTime;
80 if (vertically) {
81 auto otherZoneAxis = otherZone->parentPlot()->axisRect()->axis(QCPAxis::atBottom);
82 alignedTime = otherZoneAxis->pixelToCoord(referenceVerticalPosition);
83 }
84
85 if (alignOnLeft) {
86 newZoneStart = alignedTime;
87 if (!allowResize) {
88 newZoneEnd = alignedTime + (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
89 }
90 }
91 else { // align on right
92 newZoneEnd = alignedTime;
93 if (!allowResize) {
94 newZoneStart = alignedTime - (otherZoneRange.m_TEnd - otherZoneRange.m_TStart);
95 }
96 }
97
98 if (newZoneStart < newZoneEnd) {
99 result = true;
100 otherZone->setRange(newZoneStart, newZoneEnd);
101 otherZone->parentPlot()->replot();
102 }
103 }
104
105 return result;
106 }
57 };
107 };
58
108
59 VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot)
109 VisualizationSelectionZoneItem::VisualizationSelectionZoneItem(QCustomPlot *plot)
60 : QCPItemRect(plot),
110 : QCPItemRect(plot),
61 impl{spimpl::make_unique_impl<VisualizationSelectionZoneItemPrivate>(plot)}
111 impl{spimpl::make_unique_impl<VisualizationSelectionZoneItemPrivate>(plot)}
62 {
112 {
63 topLeft->setTypeX(QCPItemPosition::ptPlotCoords);
113 topLeft->setTypeX(QCPItemPosition::ptPlotCoords);
64 topLeft->setTypeY(QCPItemPosition::ptAxisRectRatio);
114 topLeft->setTypeY(QCPItemPosition::ptAxisRectRatio);
65 bottomRight->setTypeX(QCPItemPosition::ptPlotCoords);
115 bottomRight->setTypeX(QCPItemPosition::ptPlotCoords);
66 bottomRight->setTypeY(QCPItemPosition::ptAxisRectRatio);
116 bottomRight->setTypeY(QCPItemPosition::ptAxisRectRatio);
67 setSelectable(false);
117 setSelectable(false);
68
118
69 impl->m_RightLine = new QCPItemStraightLine(plot);
119 impl->m_RightLine = new QCPItemStraightLine(plot);
70 impl->m_RightLine->point1->setParentAnchor(topRight);
120 impl->m_RightLine->point1->setParentAnchor(topRight);
71 impl->m_RightLine->point2->setParentAnchor(bottomRight);
121 impl->m_RightLine->point2->setParentAnchor(bottomRight);
72 impl->m_RightLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
122 impl->m_RightLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
73 impl->m_RightLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
123 impl->m_RightLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
74 impl->m_RightLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
124 impl->m_RightLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
75 impl->m_RightLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
125 impl->m_RightLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
76 impl->m_RightLine->setSelectable(false);
126 impl->m_RightLine->setSelectable(false);
77
127
78 impl->m_LeftLine = new QCPItemStraightLine(plot);
128 impl->m_LeftLine = new QCPItemStraightLine(plot);
79 impl->m_LeftLine->point1->setParentAnchor(topLeft);
129 impl->m_LeftLine->point1->setParentAnchor(topLeft);
80 impl->m_LeftLine->point2->setParentAnchor(bottomLeft);
130 impl->m_LeftLine->point2->setParentAnchor(bottomLeft);
81 impl->m_LeftLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
131 impl->m_LeftLine->point1->setTypeX(QCPItemPosition::ptAbsolute);
82 impl->m_LeftLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
132 impl->m_LeftLine->point1->setTypeY(QCPItemPosition::ptAbsolute);
83 impl->m_LeftLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
133 impl->m_LeftLine->point2->setTypeX(QCPItemPosition::ptAbsolute);
84 impl->m_LeftLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
134 impl->m_LeftLine->point2->setTypeY(QCPItemPosition::ptAbsolute);
85 impl->m_LeftLine->setSelectable(false);
135 impl->m_LeftLine->setSelectable(false);
86
136
87 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_RightLine,
137 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_RightLine,
88 &QCPItemStraightLine::setSelected);
138 &QCPItemStraightLine::setSelected);
89 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_LeftLine,
139 connect(this, &VisualizationSelectionZoneItem::selectionChanged, impl->m_LeftLine,
90 &QCPItemStraightLine::setSelected);
140 &QCPItemStraightLine::setSelected);
91
141
92 setColor(QColor(DEFAULT_COLOR));
142 setColor(QColor(DEFAULT_COLOR));
93 }
143 }
94
144
95 VisualizationSelectionZoneItem::~VisualizationSelectionZoneItem()
145 VisualizationSelectionZoneItem::~VisualizationSelectionZoneItem()
96 {
146 {
97 impl->m_Plot->removeItem(impl->m_RightLine);
147 }
98 impl->m_Plot->removeItem(impl->m_LeftLine);
148
149 VisualizationGraphWidget *VisualizationSelectionZoneItem::parentGraphWidget() const noexcept
150 {
151 auto parent = impl->m_Plot->parentWidget();
152 while (parent != nullptr && !qobject_cast<VisualizationGraphWidget *>(parent)) {
153 parent = parent->parentWidget();
154 }
155
156 return qobject_cast<VisualizationGraphWidget *>(parent);
99 }
157 }
100
158
101 void VisualizationSelectionZoneItem::setName(const QString &name)
159 void VisualizationSelectionZoneItem::setName(const QString &name)
102 {
160 {
103 if (name.isEmpty() && impl->m_NameLabelItem) {
161 if (name.isEmpty() && impl->m_NameLabelItem) {
104 impl->m_Plot->removeItem(impl->m_NameLabelItem);
162 impl->m_Plot->removeItem(impl->m_NameLabelItem);
105 impl->m_NameLabelItem = nullptr;
163 impl->m_NameLabelItem = nullptr;
106 }
164 }
107 else if (!impl->m_NameLabelItem) {
165 else if (!impl->m_NameLabelItem) {
108 impl->m_NameLabelItem = new QCPItemText(impl->m_Plot);
166 impl->m_NameLabelItem = new QCPItemText(impl->m_Plot);
109 impl->m_NameLabelItem->setText(name);
167 impl->m_NameLabelItem->setText(name);
110 impl->m_NameLabelItem->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);
168 impl->m_NameLabelItem->setPositionAlignment(Qt::AlignHCenter | Qt::AlignTop);
111 impl->m_NameLabelItem->setColor(impl->m_Color);
169 impl->m_NameLabelItem->setColor(impl->m_Color);
112 impl->m_NameLabelItem->position->setParentAnchor(top);
170 impl->m_NameLabelItem->position->setParentAnchor(top);
113 }
171 }
114 }
172 }
115
173
116 QString VisualizationSelectionZoneItem::name() const
174 QString VisualizationSelectionZoneItem::name() const
117 {
175 {
118 if (!impl->m_NameLabelItem) {
176 if (!impl->m_NameLabelItem) {
119 return QString();
177 return QString();
120 }
178 }
121
179
122 return impl->m_NameLabelItem->text();
180 return impl->m_NameLabelItem->text();
123 }
181 }
124
182
125 SqpRange VisualizationSelectionZoneItem::range() const
183 SqpRange VisualizationSelectionZoneItem::range() const
126 {
184 {
127 SqpRange range;
185 SqpRange range;
128 range.m_TStart = impl->m_T1 <= impl->m_T2 ? impl->m_T1 : impl->m_T2;
186 range.m_TStart = impl->m_T1 <= impl->m_T2 ? impl->m_T1 : impl->m_T2;
129 range.m_TEnd = impl->m_T1 > impl->m_T2 ? impl->m_T1 : impl->m_T2;
187 range.m_TEnd = impl->m_T1 > impl->m_T2 ? impl->m_T1 : impl->m_T2;
130 return range;
188 return range;
131 }
189 }
132
190
133 void VisualizationSelectionZoneItem::setRange(double tstart, double tend)
191 void VisualizationSelectionZoneItem::setRange(double tstart, double tend)
134 {
192 {
135 impl->m_T1 = tstart;
193 impl->m_T1 = tstart;
136 impl->m_T2 = tend;
194 impl->m_T2 = tend;
137 impl->updatePosition(this);
195 impl->updatePosition(this);
138 }
196 }
139
197
140 void VisualizationSelectionZoneItem::setStart(double tstart)
198 void VisualizationSelectionZoneItem::setStart(double tstart)
141 {
199 {
142 impl->m_T1 = tstart;
200 impl->m_T1 = tstart;
143 impl->updatePosition(this);
201 impl->updatePosition(this);
144 }
202 }
145
203
146 void VisualizationSelectionZoneItem::setEnd(double tend)
204 void VisualizationSelectionZoneItem::setEnd(double tend)
147 {
205 {
148 impl->m_T2 = tend;
206 impl->m_T2 = tend;
149 impl->updatePosition(this);
207 impl->updatePosition(this);
150 }
208 }
151
209
152 void VisualizationSelectionZoneItem::setColor(const QColor &color)
210 void VisualizationSelectionZoneItem::setColor(const QColor &color)
153 {
211 {
154 impl->m_Color = color;
212 impl->m_Color = color;
155
213
156 auto brushColor = color;
214 auto brushColor = color;
157 brushColor.setAlpha(80);
215 brushColor.setAlpha(80);
158 setBrush(QBrush(brushColor));
216 setBrush(QBrush(brushColor));
159 setPen(QPen(Qt::NoPen));
217 setPen(QPen(Qt::NoPen));
160
218
161 auto selectedBrushColor = brushColor;
219 auto selectedBrushColor = brushColor;
162 selectedBrushColor.setAlpha(150);
220 selectedBrushColor.setAlpha(150);
163 setSelectedBrush(QBrush(selectedBrushColor));
221 setSelectedBrush(QBrush(selectedBrushColor));
164 setSelectedPen(QPen(Qt::NoPen));
222 setSelectedPen(QPen(Qt::NoPen));
165
223
166 auto linePen = QPen(color);
224 auto linePen = QPen(color);
167 linePen.setStyle(Qt::SolidLine);
225 linePen.setStyle(Qt::SolidLine);
168 linePen.setWidth(4);
226 linePen.setWidth(4);
169
227
170 auto selectedLinePen = linePen;
228 auto selectedLinePen = linePen;
171 selectedLinePen.setColor(color.darker(120));
229 selectedLinePen.setColor(color.darker(120));
172 selectedLinePen.setWidth(4);
230 selectedLinePen.setWidth(4);
173
231
174 impl->m_LeftLine->setPen(linePen);
232 impl->m_LeftLine->setPen(linePen);
175 impl->m_RightLine->setPen(linePen);
233 impl->m_RightLine->setPen(linePen);
176
234
177 impl->m_LeftLine->setSelectedPen(selectedLinePen);
235 impl->m_LeftLine->setSelectedPen(selectedLinePen);
178 impl->m_RightLine->setSelectedPen(selectedLinePen);
236 impl->m_RightLine->setSelectedPen(selectedLinePen);
179 }
237 }
180
238
181 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
239 void VisualizationSelectionZoneItem::setEditionEnabled(bool value)
182 {
240 {
183 impl->m_IsEditionEnabled = value;
241 impl->m_IsEditionEnabled = value;
184 setSelectable(value);
242 setSelectable(value);
185 if (!value) {
243 if (!value) {
186 setSelected(false);
244 setSelected(false);
187 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
245 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
188 }
246 }
189 }
247 }
190
248
191 bool VisualizationSelectionZoneItem::isEditionEnabled() const
249 bool VisualizationSelectionZoneItem::isEditionEnabled() const
192 {
250 {
193 return impl->m_IsEditionEnabled;
251 return impl->m_IsEditionEnabled;
194 }
252 }
195
253
254 void VisualizationSelectionZoneItem::moveToTop()
255 {
256 moveToLayer(layer(), false);
257 }
258
196 Qt::CursorShape
259 Qt::CursorShape
197 VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const
260 VisualizationSelectionZoneItem::curshorShapeForPosition(const QPoint &position) const
198 {
261 {
199 auto mode = impl->m_CurrentEditionMode
262 auto mode = impl->m_CurrentEditionMode
200 == VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition
263 == VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition
201 ? impl->getEditionMode(position, this)
264 ? impl->getEditionMode(position, this)
202 : impl->m_CurrentEditionMode;
265 : impl->m_CurrentEditionMode;
203 switch (mode) {
266 switch (mode) {
204 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
267 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
205 return Qt::SizeAllCursor;
268 return Qt::SizeAllCursor;
206 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
269 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
207 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: // fallthrough
270 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight: // fallthrough
208 return Qt::SizeHorCursor;
271 return Qt::SizeHorCursor;
209 default:
272 default:
210 return Qt::ArrowCursor;
273 return Qt::ArrowCursor;
211 }
274 }
212 }
275 }
213
276
214 void VisualizationSelectionZoneItem::setHovered(bool value)
277 void VisualizationSelectionZoneItem::setHovered(bool value)
215 {
278 {
216 if (value) {
279 if (value) {
217 auto linePen = impl->m_LeftLine->pen();
280 auto linePen = impl->m_LeftLine->pen();
218 linePen.setStyle(Qt::DotLine);
281 linePen.setStyle(Qt::DotLine);
219 linePen.setWidth(3);
282 linePen.setWidth(3);
220
283
221 auto selectedLinePen = impl->m_LeftLine->selectedPen();
284 auto selectedLinePen = impl->m_LeftLine->selectedPen();
222 ;
285 ;
223 selectedLinePen.setStyle(Qt::DotLine);
286 selectedLinePen.setStyle(Qt::DotLine);
224 selectedLinePen.setWidth(3);
287 selectedLinePen.setWidth(3);
225
288
226 impl->m_LeftLine->setPen(linePen);
289 impl->m_LeftLine->setPen(linePen);
227 impl->m_RightLine->setPen(linePen);
290 impl->m_RightLine->setPen(linePen);
228
291
229 impl->m_LeftLine->setSelectedPen(selectedLinePen);
292 impl->m_LeftLine->setSelectedPen(selectedLinePen);
230 impl->m_RightLine->setSelectedPen(selectedLinePen);
293 impl->m_RightLine->setSelectedPen(selectedLinePen);
231 }
294 }
232 else {
295 else {
233 setColor(impl->m_Color);
296 setColor(impl->m_Color);
234 }
297 }
235 }
298 }
236
299
237 void VisualizationSelectionZoneItem::setAssociatedEditedZones(
300 void VisualizationSelectionZoneItem::setAssociatedEditedZones(
238 const QVector<VisualizationSelectionZoneItem *> &associatedZones)
301 const QVector<VisualizationSelectionZoneItem *> &associatedZones)
239 {
302 {
240 impl->m_AssociatedEditedZones = associatedZones;
303 impl->m_AssociatedEditedZones = associatedZones;
241 impl->m_AssociatedEditedZones.removeAll(this);
304 impl->m_AssociatedEditedZones.removeAll(this);
242 }
305 }
243
306
307 bool VisualizationSelectionZoneItem::alignZonesVerticallyOnLeft(
308 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
309 {
310 return impl->alignZones(this, zonesToAlign, true, allowResize, true);
311 }
312
313 bool VisualizationSelectionZoneItem::alignZonesVerticallyOnRight(
314 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
315 {
316 return impl->alignZones(this, zonesToAlign, false, allowResize, true);
317 }
318
319 bool VisualizationSelectionZoneItem::alignZonesTemporallyOnLeft(
320 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
321 {
322 return impl->alignZones(this, zonesToAlign, true, allowResize, false);
323 }
324
325 bool VisualizationSelectionZoneItem::alignZonesTemporallyOnRight(
326 const QVector<VisualizationSelectionZoneItem *> &zonesToAlign, bool allowResize)
327 {
328 return impl->alignZones(this, zonesToAlign, false, allowResize, false);
329 }
330
244 void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details)
331 void VisualizationSelectionZoneItem::mousePressEvent(QMouseEvent *event, const QVariant &details)
245 {
332 {
333 Q_UNUSED(details);
334
246 if (isEditionEnabled() && event->button() == Qt::LeftButton) {
335 if (isEditionEnabled() && event->button() == Qt::LeftButton) {
247 impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this);
336 impl->m_CurrentEditionMode = impl->getEditionMode(event->pos(), this);
248
337
249 impl->m_MovedOrinalT1 = impl->m_T1;
338 impl->m_MovedOrinalT1 = impl->m_T1;
250 impl->m_MovedOrinalT2 = impl->m_T2;
339 impl->m_MovedOrinalT2 = impl->m_T2;
251 for (auto associatedZone : impl->m_AssociatedEditedZones) {
340 for (auto associatedZone : impl->m_AssociatedEditedZones) {
252 associatedZone->impl->m_MovedOrinalT1 = associatedZone->impl->m_T1;
341 associatedZone->impl->m_MovedOrinalT1 = associatedZone->impl->m_T1;
253 associatedZone->impl->m_MovedOrinalT2 = associatedZone->impl->m_T2;
342 associatedZone->impl->m_MovedOrinalT2 = associatedZone->impl->m_T2;
254 }
343 }
255 }
344 }
256 else {
345 else {
257 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
346 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
258 event->ignore();
347 event->ignore();
259 }
348 }
260 }
349 }
261
350
262 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
351 void VisualizationSelectionZoneItem::mouseMoveEvent(QMouseEvent *event, const QPointF &startPos)
263 {
352 {
264 if (isEditionEnabled()) {
353 if (isEditionEnabled()) {
354 if (!selected()) {
355 // Force the item to be selected during the edition
356 parentGraphWidget()->parentVisualizationWidget()->selectionZoneManager().setSelected(
357 this, true);
358 }
359
265 auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom);
360 auto axis = impl->m_Plot->axisRect()->axis(QCPAxis::atBottom);
266 auto pixelDiff = event->pos().x() - startPos.x();
361 auto pixelDiff = event->pos().x() - startPos.x();
267 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
362 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
268
363
269 switch (impl->m_CurrentEditionMode) {
364 switch (impl->m_CurrentEditionMode) {
270 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
365 case VisualizationSelectionZoneItemPrivate::EditionMode::Move:
271 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
366 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
272 for (auto associatedZone : impl->m_AssociatedEditedZones) {
367 for (auto associatedZone : impl->m_AssociatedEditedZones) {
273 associatedZone->move(pixelDiff);
368 associatedZone->move(pixelDiff);
274 }
369 }
275 break;
370 break;
276 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
371 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeLeft:
277 setStart(impl->m_MovedOrinalT1 + diff);
372 setStart(impl->m_MovedOrinalT1 + diff);
278 for (auto associatedZone : impl->m_AssociatedEditedZones) {
373 for (auto associatedZone : impl->m_AssociatedEditedZones) {
279 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
374 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
280 ? associatedZone->resizeLeft(pixelDiff)
375 ? associatedZone->resizeLeft(pixelDiff)
281 : associatedZone->resizeRight(pixelDiff);
376 : associatedZone->resizeRight(pixelDiff);
282 }
377 }
283 break;
378 break;
284 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight:
379 case VisualizationSelectionZoneItemPrivate::EditionMode::ResizeRight:
285 setEnd(impl->m_MovedOrinalT2 + diff);
380 setEnd(impl->m_MovedOrinalT2 + diff);
286 for (auto associatedZone : impl->m_AssociatedEditedZones) {
381 for (auto associatedZone : impl->m_AssociatedEditedZones) {
287 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
382 impl->m_MovedOrinalT1 < impl->m_MovedOrinalT2
288 ? associatedZone->resizeRight(pixelDiff)
383 ? associatedZone->resizeRight(pixelDiff)
289 : associatedZone->resizeLeft(pixelDiff);
384 : associatedZone->resizeLeft(pixelDiff);
290 }
385 }
291 break;
386 break;
292 default:
387 default:
293 break;
388 break;
294 }
389 }
295
390
296 for (auto associatedZone : impl->m_AssociatedEditedZones) {
391 for (auto associatedZone : impl->m_AssociatedEditedZones) {
297 associatedZone->parentPlot()->replot();
392 associatedZone->parentPlot()->replot();
298 }
393 }
299 }
394 }
300 else {
395 else {
301 event->ignore();
396 event->ignore();
302 }
397 }
303 }
398 }
304
399
305 void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
400 void VisualizationSelectionZoneItem::mouseReleaseEvent(QMouseEvent *event, const QPointF &startPos)
306 {
401 {
402 Q_UNUSED(startPos);
403
307 if (isEditionEnabled()) {
404 if (isEditionEnabled()) {
308 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
405 impl->m_CurrentEditionMode = VisualizationSelectionZoneItemPrivate::EditionMode::NoEdition;
309 }
406 }
310 else {
407 else {
311 event->ignore();
408 event->ignore();
312 }
409 }
313
410
314 impl->m_AssociatedEditedZones.clear();
411 impl->m_AssociatedEditedZones.clear();
315 }
412 }
316
413
317 void VisualizationSelectionZoneItem::resizeLeft(double pixelDiff)
414 void VisualizationSelectionZoneItem::resizeLeft(double pixelDiff)
318 {
415 {
319 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
416 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
320 if (impl->m_MovedOrinalT1 <= impl->m_MovedOrinalT2) {
417 if (impl->m_MovedOrinalT1 <= impl->m_MovedOrinalT2) {
321 setStart(impl->m_MovedOrinalT1 + diff);
418 setStart(impl->m_MovedOrinalT1 + diff);
322 }
419 }
323 else {
420 else {
324 setEnd(impl->m_MovedOrinalT2 + diff);
421 setEnd(impl->m_MovedOrinalT2 + diff);
325 }
422 }
326 }
423 }
327
424
328 void VisualizationSelectionZoneItem::resizeRight(double pixelDiff)
425 void VisualizationSelectionZoneItem::resizeRight(double pixelDiff)
329 {
426 {
330 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
427 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
331 if (impl->m_MovedOrinalT1 > impl->m_MovedOrinalT2) {
428 if (impl->m_MovedOrinalT1 > impl->m_MovedOrinalT2) {
332 setStart(impl->m_MovedOrinalT1 + diff);
429 setStart(impl->m_MovedOrinalT1 + diff);
333 }
430 }
334 else {
431 else {
335 setEnd(impl->m_MovedOrinalT2 + diff);
432 setEnd(impl->m_MovedOrinalT2 + diff);
336 }
433 }
337 }
434 }
338
435
339 void VisualizationSelectionZoneItem::move(double pixelDiff)
436 void VisualizationSelectionZoneItem::move(double pixelDiff)
340 {
437 {
341 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
438 auto diff = impl->pixelSizeToAxisXSize(pixelDiff);
342 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
439 setRange(impl->m_MovedOrinalT1 + diff, impl->m_MovedOrinalT2 + diff);
343 }
440 }
@@ -1,51 +1,51
1 #include "Visualization/VisualizationSelectionZoneManager.h"
1 #include "Visualization/VisualizationSelectionZoneManager.h"
2 #include "Visualization/VisualizationSelectionZoneItem.h"
2 #include "Visualization/VisualizationSelectionZoneItem.h"
3
3
4 struct VisualizationSelectionZoneManager::VisualizationSelectionZoneManagerPrivate {
4 struct VisualizationSelectionZoneManager::VisualizationSelectionZoneManagerPrivate {
5 QVector<VisualizationSelectionZoneItem *> m_SelectedItems;
5 QVector<VisualizationSelectionZoneItem *> m_SelectedItems;
6 };
6 };
7
7
8 VisualizationSelectionZoneManager::VisualizationSelectionZoneManager()
8 VisualizationSelectionZoneManager::VisualizationSelectionZoneManager()
9 : impl{spimpl::make_unique_impl<VisualizationSelectionZoneManagerPrivate>()}
9 : impl{spimpl::make_unique_impl<VisualizationSelectionZoneManagerPrivate>()}
10 {
10 {
11 }
11 }
12
12
13 void VisualizationSelectionZoneManager::select(
13 void VisualizationSelectionZoneManager::select(
14 const QVector<VisualizationSelectionZoneItem *> &items)
14 const QVector<VisualizationSelectionZoneItem *> &items)
15 {
15 {
16 clearSelection();
16 clearSelection();
17 for (auto item : items) {
17 for (auto item : items) {
18 setSelected(item, true);
18 setSelected(item, true);
19 }
19 }
20 }
20 }
21
21
22 void VisualizationSelectionZoneManager::setSelected(VisualizationSelectionZoneItem *item,
22 void VisualizationSelectionZoneManager::setSelected(VisualizationSelectionZoneItem *item,
23 bool value)
23 bool value)
24 {
24 {
25 if (value != item->selected()) {
25 if (value != item->selected()) {
26 item->setSelected(value);
26 item->setSelected(value);
27 item->parentPlot()->replot();
27 item->parentPlot()->replot(QCustomPlot::rpQueuedReplot);
28 }
28 }
29
29
30 if (!value && impl->m_SelectedItems.contains(item)) {
30 if (!value && impl->m_SelectedItems.contains(item)) {
31 impl->m_SelectedItems.removeAll(item);
31 impl->m_SelectedItems.removeAll(item);
32 }
32 }
33 else if (value) {
33 else if (value) {
34 impl->m_SelectedItems << item;
34 impl->m_SelectedItems << item;
35 }
35 }
36 }
36 }
37
37
38 void VisualizationSelectionZoneManager::clearSelection()
38 void VisualizationSelectionZoneManager::clearSelection()
39 {
39 {
40 for (auto item : impl->m_SelectedItems) {
40 for (auto item : impl->m_SelectedItems) {
41 item->setSelected(false);
41 item->setSelected(false);
42 item->parentPlot()->replot();
42 item->parentPlot()->replot(QCustomPlot::rpQueuedReplot);
43 }
43 }
44
44
45 impl->m_SelectedItems.clear();
45 impl->m_SelectedItems.clear();
46 }
46 }
47
47
48 QVector<VisualizationSelectionZoneItem *> VisualizationSelectionZoneManager::selectedItems() const
48 QVector<VisualizationSelectionZoneItem *> VisualizationSelectionZoneManager::selectedItems() const
49 {
49 {
50 return impl->m_SelectedItems;
50 return impl->m_SelectedItems;
51 }
51 }
@@ -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,215
1 #include "Visualization/VisualizationWidget.h"
1 #include "Visualization/VisualizationWidget.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
2 #include "Visualization/IVisualizationWidgetVisitor.h"
3 #include "Visualization/VisualizationActionManager.h"
3 #include "Visualization/VisualizationGraphWidget.h"
4 #include "Visualization/VisualizationGraphWidget.h"
5 #include "Visualization/VisualizationSelectionZoneItem.h"
4 #include "Visualization/VisualizationSelectionZoneManager.h"
6 #include "Visualization/VisualizationSelectionZoneManager.h"
5 #include "Visualization/VisualizationTabWidget.h"
7 #include "Visualization/VisualizationTabWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
8 #include "Visualization/VisualizationZoneWidget.h"
7 #include "Visualization/operations/FindVariableOperation.h"
9 #include "Visualization/operations/FindVariableOperation.h"
8 #include "Visualization/operations/GenerateVariableMenuOperation.h"
10 #include "Visualization/operations/GenerateVariableMenuOperation.h"
9 #include "Visualization/operations/RemoveVariableOperation.h"
11 #include "Visualization/operations/RemoveVariableOperation.h"
10 #include "Visualization/operations/RescaleAxeOperation.h"
12 #include "Visualization/operations/RescaleAxeOperation.h"
11 #include "Visualization/qcustomplot.h"
13 #include "Visualization/qcustomplot.h"
12
14
13 #include "ui_VisualizationWidget.h"
15 #include "ui_VisualizationWidget.h"
14
16
15 #include "DragAndDrop/DragDropHelper.h"
17 #include "DragAndDrop/DragDropGuiController.h"
16 #include "SqpApplication.h"
18 #include "SqpApplication.h"
17
19
18 #include <QToolButton>
20 #include <QToolButton>
19
21
20 #include <memory>
22 #include <memory>
21
23
22 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
24 Q_LOGGING_CATEGORY(LOG_VisualizationWidget, "VisualizationWidget")
23
25
24 struct VisualizationWidget::VisualizationWidgetPrivate {
26 struct VisualizationWidget::VisualizationWidgetPrivate {
25 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
27 std::unique_ptr<VisualizationSelectionZoneManager> m_ZoneSelectionManager = nullptr;
28 VisualizationActionManager m_ActionManager;
26
29
27 VisualizationWidgetPrivate()
30 VisualizationWidgetPrivate()
28 : m_ZoneSelectionManager(std::make_unique<VisualizationSelectionZoneManager>())
31 : m_ZoneSelectionManager(std::make_unique<VisualizationSelectionZoneManager>())
29 {
32 {
30 }
33 }
31 };
34 };
32
35
33 VisualizationWidget::VisualizationWidget(QWidget *parent)
36 VisualizationWidget::VisualizationWidget(QWidget *parent)
34 : QWidget{parent},
37 : QWidget{parent},
35 ui{new Ui::VisualizationWidget},
38 ui{new Ui::VisualizationWidget},
36 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
39 impl{spimpl::make_unique_impl<VisualizationWidgetPrivate>()}
37 {
40 {
38 ui->setupUi(this);
41 ui->setupUi(this);
39
42
40 auto addTabViewButton = new QToolButton{ui->tabWidget};
43 auto addTabViewButton = new QToolButton{ui->tabWidget};
41 addTabViewButton->setText(tr("Add View"));
44 addTabViewButton->setText(tr("Add View"));
42 addTabViewButton->setCursor(Qt::ArrowCursor);
45 addTabViewButton->setCursor(Qt::ArrowCursor);
43 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
46 ui->tabWidget->setCornerWidget(addTabViewButton, Qt::TopRightCorner);
44
47
45 auto enableMinimumCornerWidgetSize = [this](bool enable) {
48 auto enableMinimumCornerWidgetSize = [this](bool enable) {
46
49
47 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
50 auto tabViewCornerWidget = ui->tabWidget->cornerWidget();
48 auto width = enable ? tabViewCornerWidget->width() : 0;
51 auto width = enable ? tabViewCornerWidget->width() : 0;
49 auto height = enable ? tabViewCornerWidget->height() : 0;
52 auto height = enable ? tabViewCornerWidget->height() : 0;
50 tabViewCornerWidget->setMinimumHeight(height);
53 tabViewCornerWidget->setMinimumHeight(height);
51 tabViewCornerWidget->setMinimumWidth(width);
54 tabViewCornerWidget->setMinimumWidth(width);
52 ui->tabWidget->setMinimumHeight(height);
55 ui->tabWidget->setMinimumHeight(height);
53 ui->tabWidget->setMinimumWidth(width);
56 ui->tabWidget->setMinimumWidth(width);
54 };
57 };
55
58
56 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
59 auto addTabView = [this, enableMinimumCornerWidgetSize]() {
57 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
60 auto widget = new VisualizationTabWidget{QString{"View %1"}.arg(ui->tabWidget->count() + 1),
58 ui->tabWidget};
61 ui->tabWidget};
59 auto index = ui->tabWidget->addTab(widget, widget->name());
62 auto index = ui->tabWidget->addTab(widget, widget->name());
60 if (ui->tabWidget->count() > 0) {
63 if (ui->tabWidget->count() > 0) {
61 enableMinimumCornerWidgetSize(false);
64 enableMinimumCornerWidgetSize(false);
62 }
65 }
63 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
66 qCInfo(LOG_VisualizationWidget()) << tr("add the tab of index %1").arg(index);
64 };
67 };
65
68
66 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
69 auto removeTabView = [this, enableMinimumCornerWidgetSize](int index) {
67 if (ui->tabWidget->count() == 1) {
70 if (ui->tabWidget->count() == 1) {
68 enableMinimumCornerWidgetSize(true);
71 enableMinimumCornerWidgetSize(true);
69 }
72 }
70
73
71 // Removes widget from tab and closes it
74 // Removes widget from tab and closes it
72 auto widget = ui->tabWidget->widget(index);
75 auto widget = ui->tabWidget->widget(index);
73 ui->tabWidget->removeTab(index);
76 ui->tabWidget->removeTab(index);
74 if (widget) {
77 if (widget) {
75 widget->close();
78 widget->close();
76 }
79 }
77
80
78 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
81 qCInfo(LOG_VisualizationWidget()) << tr("remove the tab of index %1").arg(index);
79
82
80 };
83 };
81
84
82 ui->tabWidget->setTabsClosable(true);
85 ui->tabWidget->setTabsClosable(true);
83
86
84 connect(addTabViewButton, &QToolButton::clicked, addTabView);
87 connect(addTabViewButton, &QToolButton::clicked, addTabView);
85 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
88 connect(ui->tabWidget, &QTabWidget::tabCloseRequested, removeTabView);
86
89
87 sqpApp->dragDropHelper().addDragDropTabBar(ui->tabWidget->tabBar());
90 sqpApp->dragDropGuiController().addDragDropTabBar(ui->tabWidget->tabBar());
91
92 // Actions
93 impl->m_ActionManager.installSelectionZoneActions();
94
95 auto removeZoneAction = new QAction("Remove selected zone(s)");
96 removeZoneAction->setShortcut(QKeySequence::Delete);
97 connect(removeZoneAction, &QAction::triggered, [this]() {
98 auto selection = impl->m_ZoneSelectionManager->selectedItems();
99 for (auto selectionZone : selection) {
100 if (auto graph = selectionZone->parentGraphWidget()) {
101 graph->removeSelectionZone(selectionZone);
102 }
103 }
104 });
105 addAction(removeZoneAction);
88
106
89 // Adds default tab
107 // Adds default tab
90 addTabView();
108 addTabView();
91 }
109 }
92
110
93 VisualizationWidget::~VisualizationWidget()
111 VisualizationWidget::~VisualizationWidget()
94 {
112 {
95 sqpApp->dragDropHelper().removeDragDropTabBar(ui->tabWidget->tabBar());
113 sqpApp->dragDropGuiController().removeDragDropTabBar(ui->tabWidget->tabBar());
96 delete ui;
114 delete ui;
97 }
115 }
98
116
99 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
117 VisualizationSelectionZoneManager &VisualizationWidget::selectionZoneManager() const
100 {
118 {
101 return *impl->m_ZoneSelectionManager.get();
119 return *impl->m_ZoneSelectionManager.get();
102 }
120 }
103
121
104 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
122 void VisualizationWidget::accept(IVisualizationWidgetVisitor *visitor)
105 {
123 {
106 if (visitor) {
124 if (visitor) {
107 visitor->visitEnter(this);
125 visitor->visitEnter(this);
108
126
109 // Apply visitor for tab children
127 // Apply visitor for tab children
110 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
128 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
111 // Widgets different from tabs are not visited (no action)
129 // Widgets different from tabs are not visited (no action)
112 if (auto visualizationTabWidget
130 if (auto visualizationTabWidget
113 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
131 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
114 visualizationTabWidget->accept(visitor);
132 visualizationTabWidget->accept(visitor);
115 }
133 }
116 }
134 }
117
135
118 visitor->visitLeave(this);
136 visitor->visitLeave(this);
119 }
137 }
120 else {
138 else {
121 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
139 qCCritical(LOG_VisualizationWidget()) << tr("Can't visit widget : the visitor is null");
122 }
140 }
123 }
141 }
124
142
125 bool VisualizationWidget::canDrop(const Variable &variable) const
143 bool VisualizationWidget::canDrop(const Variable &variable) const
126 {
144 {
127 // The main widget can never accomodate a variable
145 // The main widget can never accomodate a variable
128 Q_UNUSED(variable);
146 Q_UNUSED(variable);
129 return false;
147 return false;
130 }
148 }
131
149
132 bool VisualizationWidget::contains(const Variable &variable) const
150 bool VisualizationWidget::contains(const Variable &variable) const
133 {
151 {
134 Q_UNUSED(variable);
152 Q_UNUSED(variable);
135 return false;
153 return false;
136 }
154 }
137
155
138 QString VisualizationWidget::name() const
156 QString VisualizationWidget::name() const
139 {
157 {
140 return QStringLiteral("MainView");
158 return QStringLiteral("MainView");
141 }
159 }
142
160
143 void VisualizationWidget::attachVariableMenu(
161 void VisualizationWidget::attachVariableMenu(
144 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
162 QMenu *menu, const QVector<std::shared_ptr<Variable> > &variables) noexcept
145 {
163 {
146 // Menu is generated only if there is a single variable
164 // Menu is generated only if there is a single variable
147 if (variables.size() == 1) {
165 if (variables.size() == 1) {
148 if (auto variable = variables.first()) {
166 if (auto variable = variables.first()) {
149 // Gets the containers of the variable
167 // Gets the containers of the variable
150 FindVariableOperation findVariableOperation{variable};
168 FindVariableOperation findVariableOperation{variable};
151 accept(&findVariableOperation);
169 accept(&findVariableOperation);
152 auto variableContainers = findVariableOperation.result();
170 auto variableContainers = findVariableOperation.result();
153
171
154 // Generates the actions that make it possible to visualize the variable
172 // Generates the actions that make it possible to visualize the variable
155 GenerateVariableMenuOperation generateVariableMenuOperation{
173 GenerateVariableMenuOperation generateVariableMenuOperation{
156 menu, variable, std::move(variableContainers)};
174 menu, variable, std::move(variableContainers)};
157 accept(&generateVariableMenuOperation);
175 accept(&generateVariableMenuOperation);
158 }
176 }
159 else {
177 else {
160 qCCritical(LOG_VisualizationWidget()) << tr(
178 qCCritical(LOG_VisualizationWidget()) << tr(
161 "Can't generate the menu relative to the visualization: the variable is null");
179 "Can't generate the menu relative to the visualization: the variable is null");
162 }
180 }
163 }
181 }
164 else {
182 else {
165 qCDebug(LOG_VisualizationWidget())
183 qCDebug(LOG_VisualizationWidget())
166 << tr("No generation of the menu related to the visualization: several variables are "
184 << tr("No generation of the menu related to the visualization: several variables are "
167 "selected");
185 "selected");
168 }
186 }
169 }
187 }
170
188
171 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
189 void VisualizationWidget::onVariableAboutToBeDeleted(std::shared_ptr<Variable> variable) noexcept
172 {
190 {
173 // Calls the operation of removing all references to the variable in the visualization
191 // Calls the operation of removing all references to the variable in the visualization
174 auto removeVariableOperation = RemoveVariableOperation{variable};
192 auto removeVariableOperation = RemoveVariableOperation{variable};
175 accept(&removeVariableOperation);
193 accept(&removeVariableOperation);
176 }
194 }
177
195
178 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
196 void VisualizationWidget::onRangeChanged(std::shared_ptr<Variable> variable,
179 const SqpRange &range) noexcept
197 const SqpRange &range) noexcept
180 {
198 {
181 // Calls the operation of rescaling all graph that contrains variable in the visualization
199 // Calls the operation of rescaling all graph that contrains variable in the visualization
182 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
200 auto rescaleVariableOperation = RescaleAxeOperation{variable, range};
183 accept(&rescaleVariableOperation);
201 accept(&rescaleVariableOperation);
184 }
202 }
185
203
186 void VisualizationWidget::closeEvent(QCloseEvent *event)
204 void VisualizationWidget::closeEvent(QCloseEvent *event)
187 {
205 {
188 // Closes tabs in the widget
206 // Closes tabs in the widget
189 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
207 for (auto i = 0; i < ui->tabWidget->count(); ++i) {
190 if (auto visualizationTabWidget
208 if (auto visualizationTabWidget
191 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
209 = dynamic_cast<VisualizationTabWidget *>(ui->tabWidget->widget(i))) {
192 visualizationTabWidget->close();
210 visualizationTabWidget->close();
193 }
211 }
194 }
212 }
195
213
196 QWidget::closeEvent(event);
214 QWidget::closeEvent(event);
197 }
215 }
@@ -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 0
You need to be logged in to leave comments. Login now