##// END OF EJS Templates
Merge branch 'feature/DragVariables' into develop
trabillard -
r854:552d1389af00 merge
parent child
Show More
@@ -0,0 +1,18
1 #ifndef SCIQLOP_MIMETYPESDEF_H
2 #define SCIQLOP_MIMETYPESDEF_H
3
4 #include "CoreGlobal.h"
5
6 #include <QString>
7
8 // ////////////////// //
9 // SciQlop Mime Types //
10 // ////////////////// //
11
12 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_GRAPH;
13 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_ZONE;
14 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_VARIABLE_LIST;
15 extern SCIQLOP_CORE_EXPORT const QString MIME_TYPE_TIME_RANGE;
16
17
18 #endif // SCIQLOP_MIMETYPESDEF_H
@@ -0,0 +1,6
1 #include "Common/MimeTypesDef.h"
2
3 const QString MIME_TYPE_GRAPH = QStringLiteral("scqlop/graph");
4 const QString MIME_TYPE_ZONE = QStringLiteral("scqlop/zone");
5 const QString MIME_TYPE_VARIABLE_LIST = QStringLiteral("scqlop/var-list");
6 const QString MIME_TYPE_TIME_RANGE = QStringLiteral("scqlop/time-range");
@@ -0,0 +1,7
1 #ifndef SCIQLOP_VISUALIZATIONDEF_H
2 #define SCIQLOP_VISUALIZATIONDEF_H
3
4 /// Minimum height for graph added in zones (in pixels)
5 extern const int GRAPH_MINIMUM_HEIGHT;
6
7 #endif // SCIQLOP_VISUALIZATIONDEF_H
@@ -0,0 +1,3
1 #include "Common/VisualizationDef.h"
2
3 const int GRAPH_MINIMUM_HEIGHT = 300;
@@ -68,6 +68,8 public:
68 */
68 */
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
69 void deleteVariables(const QVector<std::shared_ptr<Variable> > &variables) noexcept;
70
70
71 QByteArray mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const;
72 QList<std::shared_ptr<Variable> > variablesForMimeData(const QByteArray &mimeData) const;
71
73
72 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
74 static AcquisitionZoomType getZoomType(const SqpRange &range, const SqpRange &oldRange);
73 signals:
75 signals:
@@ -18,6 +18,7 enum VariableRoles { ProgressRole = Qt::UserRole };
18
18
19 class IDataSeries;
19 class IDataSeries;
20 class Variable;
20 class Variable;
21 class VariableController;
21
22
22 /**
23 /**
23 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
24 * @brief The VariableModel class aims to hold the variables that have been created in SciQlop
@@ -25,7 +26,7 class Variable;
25 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 class SCIQLOP_CORE_EXPORT VariableModel : public QAbstractTableModel {
26 Q_OBJECT
27 Q_OBJECT
27 public:
28 public:
28 explicit VariableModel(QObject *parent = nullptr);
29 explicit VariableModel(VariableController *parent = nullptr);
29
30
30 /**
31 /**
31 * Adds an existing variable in the model.
32 * Adds an existing variable in the model.
@@ -73,7 +74,20 public:
73 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
74 virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
74 virtual QVariant headerData(int section, Qt::Orientation orientation,
75 virtual QVariant headerData(int section, Qt::Orientation orientation,
75 int role = Qt::DisplayRole) const override;
76 int role = Qt::DisplayRole) const override;
76
77 virtual Qt::ItemFlags flags(const QModelIndex &index) const override;
78
79 // ///////////////// //
80 // Drag&Drop methods //
81 // ///////////////// //
82
83 virtual Qt::DropActions supportedDropActions() const override;
84 virtual Qt::DropActions supportedDragActions() const override;
85 virtual QStringList mimeTypes() const override;
86 virtual QMimeData *mimeData(const QModelIndexList &indexes) const override;
87 virtual bool canDropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
88 const QModelIndex &parent) const override;
89 virtual bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
90 const QModelIndex &parent) override;
77
91
78 void abortProgress(const QModelIndex &index);
92 void abortProgress(const QModelIndex &index);
79
93
@@ -12,6 +12,7
12 #include <Data/VariableRequest.h>
12 #include <Data/VariableRequest.h>
13 #include <Time/TimeController.h>
13 #include <Time/TimeController.h>
14
14
15 #include <QDataStream>
15 #include <QMutex>
16 #include <QMutex>
16 #include <QThread>
17 #include <QThread>
17 #include <QUuid>
18 #include <QUuid>
@@ -277,6 +278,46 void VariableController::deleteVariables(
277 }
278 }
278 }
279 }
279
280
281 QByteArray
282 VariableController::mimeDataForVariables(const QList<std::shared_ptr<Variable> > &variables) const
283 {
284 auto encodedData = QByteArray{};
285
286 QVariantList ids;
287 for (auto &var : variables) {
288 auto itVar = impl->m_VariableToIdentifierMap.find(var);
289 if (itVar == impl->m_VariableToIdentifierMap.cend()) {
290 qCCritical(LOG_VariableController())
291 << tr("Impossible to find the data for an unknown variable.");
292 }
293
294 ids << itVar->second.toByteArray();
295 }
296
297 QDataStream stream{&encodedData, QIODevice::WriteOnly};
298 stream << ids;
299
300 return encodedData;
301 }
302
303 QList<std::shared_ptr<Variable> >
304 VariableController::variablesForMimeData(const QByteArray &mimeData) const
305 {
306 auto variables = QList<std::shared_ptr<Variable> >{};
307 QDataStream stream{mimeData};
308
309 QVariantList ids;
310 stream >> ids;
311
312 for (auto id : ids) {
313 auto uuid = QUuid(id.toByteArray());
314 auto var = impl->findVariable(uuid);
315 variables << var;
316 }
317
318 return variables;
319 }
320
280 std::shared_ptr<Variable>
321 std::shared_ptr<Variable>
281 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
322 VariableController::createVariable(const QString &name, const QVariantHash &metadata,
282 std::shared_ptr<IDataProvider> provider) noexcept
323 std::shared_ptr<IDataProvider> provider) noexcept
@@ -1,11 +1,14
1 #include <Variable/Variable.h>
1 #include <Variable/Variable.h>
2 #include <Variable/VariableController.h>
2 #include <Variable/VariableModel.h>
3 #include <Variable/VariableModel.h>
3
4
4 #include <Common/DateUtils.h>
5 #include <Common/DateUtils.h>
6 #include <Common/MimeTypesDef.h>
5 #include <Common/StringUtils.h>
7 #include <Common/StringUtils.h>
6
8
7 #include <Data/IDataSeries.h>
9 #include <Data/IDataSeries.h>
8
10
11 #include <QMimeData>
9 #include <QSize>
12 #include <QSize>
10 #include <unordered_map>
13 #include <unordered_map>
11
14
@@ -66,14 +69,16 struct VariableModel::VariableModelPrivate {
66 /// Variables created in SciQlop
69 /// Variables created in SciQlop
67 std::vector<std::shared_ptr<Variable> > m_Variables;
70 std::vector<std::shared_ptr<Variable> > m_Variables;
68 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
71 std::unordered_map<std::shared_ptr<Variable>, double> m_VariableToProgress;
72 VariableController *m_VariableController;
69
73
70 /// Return the row index of the variable. -1 if it's not found
74 /// Return the row index of the variable. -1 if it's not found
71 int indexOfVariable(Variable *variable) const noexcept;
75 int indexOfVariable(Variable *variable) const noexcept;
72 };
76 };
73
77
74 VariableModel::VariableModel(QObject *parent)
78 VariableModel::VariableModel(VariableController *parent)
75 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
79 : QAbstractTableModel{parent}, impl{spimpl::make_unique_impl<VariableModelPrivate>()}
76 {
80 {
81 impl->m_VariableController = parent;
77 }
82 }
78
83
79 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
84 void VariableModel::addVariable(std::shared_ptr<Variable> variable) noexcept
@@ -255,6 +260,59 QVariant VariableModel::headerData(int section, Qt::Orientation orientation, int
255 return QVariant{};
260 return QVariant{};
256 }
261 }
257
262
263 Qt::ItemFlags VariableModel::flags(const QModelIndex &index) const
264 {
265 return QAbstractTableModel::flags(index) | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
266 }
267
268 Qt::DropActions VariableModel::supportedDropActions() const
269 {
270 return Qt::MoveAction;
271 }
272
273 Qt::DropActions VariableModel::supportedDragActions() const
274 {
275 return Qt::CopyAction | Qt::MoveAction;
276 }
277
278 QStringList VariableModel::mimeTypes() const
279 {
280 return {MIME_TYPE_VARIABLE_LIST};
281 }
282
283 QMimeData *VariableModel::mimeData(const QModelIndexList &indexes) const
284 {
285 auto mimeData = new QMimeData;
286
287 QList<std::shared_ptr<Variable> > variableList;
288
289 for (const auto &index : indexes) {
290 if (index.column() == 0) { // only the first column
291 auto variable = impl->m_Variables.at(index.row());
292 if (variable.get() && index.isValid()) {
293 variableList << variable;
294 }
295 }
296 }
297
298 auto encodedData = impl->m_VariableController->mimeDataForVariables(variableList);
299 mimeData->setData(MIME_TYPE_VARIABLE_LIST, encodedData);
300
301 return mimeData;
302 }
303
304 bool VariableModel::canDropMimeData(const QMimeData *data, Qt::DropAction action, int row,
305 int column, const QModelIndex &parent) const
306 {
307 return false;
308 }
309
310 bool VariableModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column,
311 const QModelIndex &parent)
312 {
313 return false;
314 }
315
258 void VariableModel::abortProgress(const QModelIndex &index)
316 void VariableModel::abortProgress(const QModelIndex &index)
259 {
317 {
260 if (auto variable = impl->m_Variables.at(index.row())) {
318 if (auto variable = impl->m_Variables.at(index.row())) {
@@ -2,39 +2,23
2 #define SCIQLOP_DRAGDROPHELPER_H
2 #define SCIQLOP_DRAGDROPHELPER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QWidget>
6 #include <QWidget>
6
7
7 class QVBoxLayout;
8 class QVBoxLayout;
8 class QScrollArea;
9 class QScrollArea;
9 class VisualizationDragWidget;
10 class VisualizationDragWidget;
11 class VisualizationDragDropContainer;
10 class QMimeData;
12 class QMimeData;
11
13
12 /**
14 Q_DECLARE_LOGGING_CATEGORY(LOG_DragDropHelper)
13 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
14 * @note A QScrollArea inside an other QScrollArea is not fully supported.
15 */
16 class DragDropScroller : public QObject {
17 Q_OBJECT
18
19 public:
20 DragDropScroller(QObject *parent = nullptr);
21
22 void addScrollArea(QScrollArea *scrollArea);
23 void removeScrollArea(QScrollArea *scrollArea);
24
25 protected:
26 bool eventFilter(QObject *obj, QEvent *event);
27
28 private:
29 class DragDropScrollerPrivate;
30 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
31
32 private slots:
33 void onTimer();
34 };
35
15
36 /**
16 /**
37 * @brief Helper class for drag&drop operations.
17 * @brief Helper class for drag&drop operations.
18 * @note The helper is accessible from the sqpApp singleton and has the same life as the whole
19 * application (like a controller). But contrary to a controller, it doesn't live in a thread and
20 * can interect with the gui.
21 * @see SqpApplication
38 */
22 */
39 class DragDropHelper {
23 class DragDropHelper {
40 public:
24 public:
@@ -44,7 +28,15 public:
44 DragDropHelper();
28 DragDropHelper();
45 virtual ~DragDropHelper();
29 virtual ~DragDropHelper();
46
30
31 /// Resets some internal variables. Must be called before any new drag&drop operation.
32 void resetDragAndDrop();
33
34 /// Sets the visualization widget currently being drag on the visualization.
47 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
35 void setCurrentDragWidget(VisualizationDragWidget *dragWidget);
36
37 /// Returns the visualization widget currently being drag on the visualization.
38 /// Can be null if a new visualization widget is intended to be created by the drag&drop
39 /// operation.
48 VisualizationDragWidget *getCurrentDragWidget() const;
40 VisualizationDragWidget *getCurrentDragWidget() const;
49
41
50 QWidget &placeHolder() const;
42 QWidget &placeHolder() const;
@@ -52,6 +44,10 public:
52 void removePlaceHolder();
44 void removePlaceHolder();
53 bool isPlaceHolderSet() const;
45 bool isPlaceHolderSet() const;
54
46
47 /// Checks if the specified mime data is valid for a drop in the visualization
48 bool checkMimeDataForVisualization(const QMimeData *mimeData,
49 VisualizationDragDropContainer *dropContainer);
50
55 void addDragDropScrollArea(QScrollArea *scrollArea);
51 void addDragDropScrollArea(QScrollArea *scrollArea);
56 void removeDragDropScrollArea(QScrollArea *scrollArea);
52 void removeDragDropScrollArea(QScrollArea *scrollArea);
57
53
@@ -62,4 +58,28 private:
62 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
58 spimpl::unique_impl_ptr<DragDropHelperPrivate> impl;
63 };
59 };
64
60
61 /**
62 * @brief Event filter class which manage the scroll of QScrollArea during a drag&drop operation.
63 * @note A QScrollArea inside an other QScrollArea is not fully supported.
64 */
65 class DragDropScroller : public QObject {
66 Q_OBJECT
67
68 public:
69 DragDropScroller(QObject *parent = nullptr);
70
71 void addScrollArea(QScrollArea *scrollArea);
72 void removeScrollArea(QScrollArea *scrollArea);
73
74 protected:
75 bool eventFilter(QObject *obj, QEvent *event);
76
77 private:
78 class DragDropScrollerPrivate;
79 spimpl::unique_impl_ptr<DragDropScrollerPrivate> impl;
80
81 private slots:
82 void onTimer();
83 };
84
65 #endif // SCIQLOP_DRAGDROPHELPER_H
85 #endif // SCIQLOP_DRAGDROPHELPER_H
@@ -45,7 +45,8 public:
45 VariableController &variableController() noexcept;
45 VariableController &variableController() noexcept;
46 VisualizationController &visualizationController() noexcept;
46 VisualizationController &visualizationController() noexcept;
47
47
48 /// Accessors for the differents sciqlop helpers
48 /// Accessors for the differents sciqlop helpers, these helpers classes are like controllers but
49 /// doesn't live in a thread and access gui
49 DragDropHelper &dragDropHelper() noexcept;
50 DragDropHelper &dragDropHelper() noexcept;
50
51
51 private:
52 private:
@@ -2,10 +2,15
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
2 #define SCIQLOP_VISUALIZATIONDRAGDROPCONTAINER_H
3
3
4 #include <Common/spimpl.h>
4 #include <Common/spimpl.h>
5 #include <QLoggingCategory>
5 #include <QMimeData>
6 #include <QMimeData>
6 #include <QVBoxLayout>
7 #include <QVBoxLayout>
7 #include <QWidget>
8 #include <QWidget>
8
9
10 #include <functional>
11
12 Q_DECLARE_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer)
13
9 class VisualizationDragWidget;
14 class VisualizationDragWidget;
10
15
11 class VisualizationDragDropContainer : public QWidget {
16 class VisualizationDragDropContainer : public QWidget {
@@ -15,6 +20,8 signals:
15 void dropOccured(int dropIndex, const QMimeData *mimeData);
20 void dropOccured(int dropIndex, const QMimeData *mimeData);
16
21
17 public:
22 public:
23 using AcceptMimeDataFunction = std::function<bool(const QMimeData *mimeData)>;
24
18 VisualizationDragDropContainer(QWidget *parent = nullptr);
25 VisualizationDragDropContainer(QWidget *parent = nullptr);
19
26
20 void addDragWidget(VisualizationDragWidget *dragWidget);
27 void addDragWidget(VisualizationDragWidget *dragWidget);
@@ -25,6 +32,8 public:
25
32
26 int countDragWidget() const;
33 int countDragWidget() const;
27
34
35 void setAcceptMimeDataFunction(AcceptMimeDataFunction fun);
36
28 protected:
37 protected:
29 void dragEnterEvent(QDragEnterEvent *event);
38 void dragEnterEvent(QDragEnterEvent *event);
30 void dragLeaveEvent(QDragLeaveEvent *event);
39 void dragLeaveEvent(QDragLeaveEvent *event);
@@ -1,6 +1,14
1 #include "DragDropHelper.h"
1 #include "DragDropHelper.h"
2 #include "SqpApplication.h"
2 #include "SqpApplication.h"
3 #include "Visualization/VisualizationDragDropContainer.h"
3 #include "Visualization/VisualizationDragWidget.h"
4 #include "Visualization/VisualizationDragWidget.h"
5 #include "Visualization/VisualizationWidget.h"
6 #include "Visualization/operations/FindVariableOperation.h"
7
8 #include "Variable/VariableController.h"
9
10 #include "Common/MimeTypesDef.h"
11 #include "Common/VisualizationDef.h"
4
12
5 #include <QDir>
13 #include <QDir>
6 #include <QDragEnterEvent>
14 #include <QDragEnterEvent>
@@ -10,12 +18,11
10 #include <QTimer>
18 #include <QTimer>
11 #include <QVBoxLayout>
19 #include <QVBoxLayout>
12
20
13 const QString DragDropHelper::MIME_TYPE_GRAPH = "scqlop/graph";
14 const QString DragDropHelper::MIME_TYPE_ZONE = "scqlop/zone";
15
16 const int SCROLL_SPEED = 5;
21 const int SCROLL_SPEED = 5;
17 const int SCROLL_ZONE_SIZE = 50;
22 const int SCROLL_ZONE_SIZE = 50;
18
23
24 Q_LOGGING_CATEGORY(LOG_DragDropHelper, "DragDrophelper")
25
19 struct DragDropScroller::DragDropScrollerPrivate {
26 struct DragDropScroller::DragDropScrollerPrivate {
20
27
21 QList<QScrollArea *> m_ScrollAreas;
28 QList<QScrollArea *> m_ScrollAreas;
@@ -159,7 +166,11 struct DragDropHelper::DragDropHelperPrivate {
159 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
166 m_PlaceHolder->setSizePolicy(m_CurrentDragWidget->sizePolicy());
160 }
167 }
161 else {
168 else {
162 m_PlaceHolder->setMinimumSize(200, 200);
169 // Configuration of the placeHolder when there is no dragWidget
170 // (for instance with a drag from a variable)
171
172 m_PlaceHolder->setMinimumSize(0, GRAPH_MINIMUM_HEIGHT);
173 m_PlaceHolder->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
163 }
174 }
164 }
175 }
165 };
176 };
@@ -174,6 +185,11 DragDropHelper::~DragDropHelper()
174 QFile::remove(impl->m_ImageTempUrl);
185 QFile::remove(impl->m_ImageTempUrl);
175 }
186 }
176
187
188 void DragDropHelper::resetDragAndDrop()
189 {
190 setCurrentDragWidget(nullptr);
191 }
192
177 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
193 void DragDropHelper::setCurrentDragWidget(VisualizationDragWidget *dragWidget)
178 {
194 {
179 impl->m_CurrentDragWidget = dragWidget;
195 impl->m_CurrentDragWidget = dragWidget;
@@ -228,3 +244,46 QUrl DragDropHelper::imageTemporaryUrl(const QImage &image) const
228 image.save(impl->m_ImageTempUrl);
244 image.save(impl->m_ImageTempUrl);
229 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
245 return QUrl::fromLocalFile(impl->m_ImageTempUrl);
230 }
246 }
247
248 bool DragDropHelper::checkMimeDataForVisualization(const QMimeData *mimeData,
249 VisualizationDragDropContainer *dropContainer)
250 {
251 auto result = true;
252
253 if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
254 auto variables = sqpApp->variableController().variablesForMimeData(
255 mimeData->data(MIME_TYPE_VARIABLE_LIST));
256
257 if (variables.count() == 1) {
258 // Check that the viariable is not already in a graph
259
260 // Search for the top level VisualizationWidget
261 auto parent = dropContainer->parentWidget();
262 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
263 parent = parent->parentWidget();
264 }
265
266 if (parent) {
267 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
268
269 FindVariableOperation findVariableOperation{variables.first()};
270 visualizationWidget->accept(&findVariableOperation);
271 auto variableContainers = findVariableOperation.result();
272 if (!variableContainers.empty()) {
273 result = false;
274 }
275 }
276 else {
277 qCWarning(LOG_DragDropHelper()) << QObject::tr(
278 "DragDropHelper::checkMimeDataForVisualization, the parent "
279 "VisualizationWidget cannot be found.");
280 result = false;
281 }
282 }
283 else {
284 result = false;
285 }
286 }
287
288 return result;
289 }
@@ -12,6 +12,7
12 #include <QStyledItemDelegate>
12 #include <QStyledItemDelegate>
13 #include <QWidgetAction>
13 #include <QWidgetAction>
14
14
15 #include <DragDropHelper.h>
15 #include <SqpApplication.h>
16 #include <SqpApplication.h>
16
17
17 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
18 Q_LOGGING_CATEGORY(LOG_VariableInspectorWidget, "VariableInspectorWidget")
@@ -151,6 +152,11 VariableInspectorWidget::VariableInspectorWidget(QWidget *parent)
151 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
152 ui->tableView->setContextMenuPolicy(Qt::CustomContextMenu);
152 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
153 connect(ui->tableView, &QTableView::customContextMenuRequested, this,
153 &VariableInspectorWidget::onTableMenuRequested);
154 &VariableInspectorWidget::onTableMenuRequested);
155
156 // Resets the drag&drop operation on a left-click (the drag&drop is also started by a left
157 // click).
158 connect(ui->tableView, &QTableView::clicked,
159 [](const auto &modelIndex) { sqpApp->dragDropHelper().resetDragAndDrop(); });
154 }
160 }
155
161
156 VariableInspectorWidget::~VariableInspectorWidget()
162 VariableInspectorWidget::~VariableInspectorWidget()
@@ -3,6 +3,8
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"
7
6 #include <QDrag>
8 #include <QDrag>
7 #include <QDragEnterEvent>
9 #include <QDragEnterEvent>
8 #include <QVBoxLayout>
10 #include <QVBoxLayout>
@@ -10,11 +12,15
10 #include <cmath>
12 #include <cmath>
11 #include <memory>
13 #include <memory>
12
14
15 Q_LOGGING_CATEGORY(LOG_VisualizationDragDropContainer, "VisualizationDragDropContainer")
16
13 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
17 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
14
18
15 QVBoxLayout *m_Layout;
19 QVBoxLayout *m_Layout;
16 QStringList m_AcceptedMimeTypes;
20 QStringList m_AcceptedMimeTypes;
17 QStringList m_MergeAllowedMimeTypes;
21 QStringList m_MergeAllowedMimeTypes;
22 VisualizationDragDropContainer::AcceptMimeDataFunction m_AcceptMimeDataFun
23 = [](auto mimeData) { return true; };
18
24
19 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
25 explicit VisualizationDragDropContainerPrivate(QWidget *widget)
20 {
26 {
@@ -25,7 +31,7 struct VisualizationDragDropContainer::VisualizationDragDropContainerPrivate {
25 bool acceptMimeData(const QMimeData *data) const
31 bool acceptMimeData(const QMimeData *data) const
26 {
32 {
27 for (const auto &type : m_AcceptedMimeTypes) {
33 for (const auto &type : m_AcceptedMimeTypes) {
28 if (data->hasFormat(type)) {
34 if (data->hasFormat(type) && m_AcceptMimeDataFun(data)) {
29 return true;
35 return true;
30 }
36 }
31 }
37 }
@@ -121,10 +127,17 int VisualizationDragDropContainer::countDragWidget() const
121 return nbGraph;
127 return nbGraph;
122 }
128 }
123
129
130 void VisualizationDragDropContainer::setAcceptMimeDataFunction(
131 VisualizationDragDropContainer::AcceptMimeDataFunction fun)
132 {
133 impl->m_AcceptMimeDataFun = fun;
134 }
135
124 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
136 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidget,
125 const QPoint &dragPosition)
137 const QPoint &dragPosition)
126 {
138 {
127 auto &helper = sqpApp->dragDropHelper();
139 auto &helper = sqpApp->dragDropHelper();
140 helper.resetDragAndDrop();
128
141
129 // Note: The management of the drag object is done by Qt
142 // Note: The management of the drag object is done by Qt
130 auto drag = new QDrag{dragWidget};
143 auto drag = new QDrag{dragWidget};
@@ -149,10 +162,15 void VisualizationDragDropContainer::startDrag(VisualizationDragWidget *dragWidg
149 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
162 helper.insertPlaceHolder(impl->m_Layout, dragWidgetIndex);
150 dragWidget->setVisible(false);
163 dragWidget->setVisible(false);
151 }
164 }
152 }
153
165
154 // Note: The exec() is blocking on windows but not on linux and macOS
166 // Note: The exec() is blocking on windows but not on linux and macOS
155 drag->exec(Qt::MoveAction | Qt::CopyAction);
167 drag->exec(Qt::MoveAction | Qt::CopyAction);
168 }
169 else {
170 qCWarning(LOG_VisualizationDragDropContainer())
171 << tr("VisualizationDragDropContainer::startDrag, drag aborted, the specified "
172 "VisualizationDragWidget is not found in this container.");
173 }
156 }
174 }
157
175
158 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
176 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
@@ -164,20 +182,30 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
164
182
165 if (!impl->hasPlaceHolder()) {
183 if (!impl->hasPlaceHolder()) {
166 auto dragWidget = helper.getCurrentDragWidget();
184 auto dragWidget = helper.getCurrentDragWidget();
167 auto parentWidget
185
168 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
186 if (dragWidget) {
169 if (parentWidget) {
187 // If the drag&drop is internal to the visualization, entering the container hide
170 dragWidget->setVisible(false);
188 // the dragWidget which was hidden by the dragLeaveEvent
189 auto parentWidget
190 = qobject_cast<VisualizationDragDropContainer *>(dragWidget->parentWidget());
191 if (parentWidget) {
192 dragWidget->setVisible(false);
193 }
171 }
194 }
172
195
173 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
196 auto dragWidgetHovered = impl->getChildDragWidgetAt(this, event->pos());
174
197
175 if (dragWidgetHovered) {
198 if (dragWidgetHovered) {
176 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
199 auto hoveredWidgetIndex = impl->m_Layout->indexOf(dragWidgetHovered);
177 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
200
178 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
201 if (dragWidget) {
179 hoveredWidgetIndex
202 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
180 += 1; // Correction of the index if the drop occurs in the same container
203 if (dragWidgetIndex >= 0 && dragWidgetIndex <= hoveredWidgetIndex) {
204 // Correction of the index if the drop occurs in the same container
205 // and if the drag is started from the visualization (in that case, the
206 // dragWidget is hidden)
207 hoveredWidgetIndex += 1;
208 }
181 }
209 }
182
210
183 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
211 helper.insertPlaceHolder(impl->m_Layout, hoveredWidgetIndex);
@@ -186,6 +214,9 void VisualizationDragDropContainer::dragEnterEvent(QDragEnterEvent *event)
186 helper.insertPlaceHolder(impl->m_Layout, 0);
214 helper.insertPlaceHolder(impl->m_Layout, 0);
187 }
215 }
188 }
216 }
217 else {
218 // do nothing
219 }
189 }
220 }
190 else {
221 else {
191 event->ignore();
222 event->ignore();
@@ -203,19 +234,23 void VisualizationDragDropContainer::dragLeaveEvent(QDragLeaveEvent *event)
203 if (!impl->cursorIsInContainer(this)) {
234 if (!impl->cursorIsInContainer(this)) {
204 helper.removePlaceHolder();
235 helper.removePlaceHolder();
205
236
206 bool isInternal = true;
237 auto dragWidget = helper.getCurrentDragWidget();
207 if (isInternal) {
238 if (dragWidget) {
208 // Only if the drag is started from the visualization
239 // dragWidget has a value only if the drag is started from the visualization
209 // Show the drag widget at its original place
240 // In that case, shows the drag widget at its original place
210 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
241 // So the drag widget doesn't stay hidden if the drop occurs outside the visualization
211 // drop zone (It is not possible to catch a drop event outside of the application)
242 // drop zone (It is not possible to catch a drop event outside of the application)
212
243
213 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
214 if (dragWidget) {
244 if (dragWidget) {
215 dragWidget->setVisible(true);
245 dragWidget->setVisible(true);
216 }
246 }
217 }
247 }
218 }
248 }
249 else {
250 // Leave event probably received for a child widget.
251 // Do nothing.
252 // Note: The DragLeave event, doesn't have any mean to determine who sent it.
253 }
219
254
220 QWidget::dragLeaveEvent(event);
255 QWidget::dragLeaveEvent(event);
221 }
256 }
@@ -229,7 +264,8 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
229
264
230 auto nbDragWidget = countDragWidget();
265 auto nbDragWidget = countDragWidget();
231 if (nbDragWidget > 0) {
266 if (nbDragWidget > 0) {
232 auto graphHeight = size().height() / nbDragWidget;
267 auto graphHeight = qMax(size().height() / nbDragWidget, GRAPH_MINIMUM_HEIGHT);
268
233 auto dropIndex = floor(event->pos().y() / graphHeight);
269 auto dropIndex = floor(event->pos().y() / graphHeight);
234 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
270 auto zoneSize = qMin(graphHeight / 3.0, 150.0);
235
271
@@ -244,10 +280,15 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
244 dropIndex += 1;
280 dropIndex += 1;
245 }
281 }
246
282
247 auto dragWidgetIndex = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
283 if (helper.getCurrentDragWidget()) {
248 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
284 auto dragWidgetIndex
249 dropIndex += 1; // Correction of the index if the drop occurs in the same
285 = impl->m_Layout->indexOf(helper.getCurrentDragWidget());
250 // container
286 if (dragWidgetIndex >= 0 && dragWidgetIndex <= dropIndex) {
287 // Correction of the index if the drop occurs in the same container
288 // and if the drag is started from the visualization (in that case, the
289 // dragWidget is hidden)
290 dropIndex += 1;
291 }
251 }
292 }
252
293
253 if (dropIndex != placeHolderIndex) {
294 if (dropIndex != placeHolderIndex) {
@@ -261,6 +302,15 void VisualizationDragDropContainer::dragMoveEvent(QDragMoveEvent *event)
261 }
302 }
262 }
303 }
263 }
304 }
305 else {
306 qCWarning(LOG_VisualizationDragDropContainer())
307 << tr("VisualizationDragDropContainer::dragMoveEvent, no widget found in the "
308 "container");
309 }
310 }
311 else {
312 // No hovered drag widget, the mouse is probably hover the placeHolder
313 // Do nothing
264 }
314 }
265 }
315 }
266 else {
316 else {
@@ -274,18 +324,22 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
274 {
324 {
275 if (impl->acceptMimeData(event->mimeData())) {
325 if (impl->acceptMimeData(event->mimeData())) {
276 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
326 auto dragWidget = sqpApp->dragDropHelper().getCurrentDragWidget();
277 if (impl->hasPlaceHolder() && dragWidget) {
327 if (impl->hasPlaceHolder()) {
278 auto &helper = sqpApp->dragDropHelper();
328 auto &helper = sqpApp->dragDropHelper();
279
329
280 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
330 auto droppedIndex = impl->m_Layout->indexOf(&helper.placeHolder());
281
331
282 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
332 if (dragWidget) {
283 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
333 auto dragWidgetIndex = impl->m_Layout->indexOf(dragWidget);
284 droppedIndex
334 if (dragWidgetIndex >= 0 && dragWidgetIndex < droppedIndex) {
285 -= 1; // Correction of the index if the drop occurs in the same container
335 // Correction of the index if the drop occurs in the same container
286 }
336 // and if the drag is started from the visualization (in that case, the
337 // dragWidget is hidden)
338 droppedIndex -= 1;
339 }
287
340
288 dragWidget->setVisible(true);
341 dragWidget->setVisible(true);
342 }
289
343
290 event->acceptProposedAction();
344 event->acceptProposedAction();
291
345
@@ -293,6 +347,12 void VisualizationDragDropContainer::dropEvent(QDropEvent *event)
293
347
294 emit dropOccured(droppedIndex, event->mimeData());
348 emit dropOccured(droppedIndex, event->mimeData());
295 }
349 }
350 else {
351 qCWarning(LOG_VisualizationDragDropContainer())
352 << tr("VisualizationDragDropContainer::dropEvent, couldn't drop because the "
353 "placeHolder is not found.");
354 Q_ASSERT(false);
355 }
296 }
356 }
297 else {
357 else {
298 event->ignore();
358 event->ignore();
@@ -6,6 +6,7
6 #include "Visualization/VisualizationZoneWidget.h"
6 #include "Visualization/VisualizationZoneWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
7 #include "ui_VisualizationGraphWidget.h"
8
8
9 #include <Common/MimeTypesDef.h>
9 #include <Data/ArrayData.h>
10 #include <Data/ArrayData.h>
10 #include <Data/IDataSeries.h>
11 #include <Data/IDataSeries.h>
11 #include <DragDropHelper.h>
12 #include <DragDropHelper.h>
@@ -232,7 +233,7 QString VisualizationGraphWidget::name() const
232 QMimeData *VisualizationGraphWidget::mimeData() const
233 QMimeData *VisualizationGraphWidget::mimeData() const
233 {
234 {
234 auto mimeData = new QMimeData;
235 auto mimeData = new QMimeData;
235 mimeData->setData(DragDropHelper::MIME_TYPE_GRAPH, QByteArray());
236 mimeData->setData(MIME_TYPE_GRAPH, QByteArray());
236
237
237 return mimeData;
238 return mimeData;
238 }
239 }
@@ -7,6 +7,8
7
7
8 #include "Variable/VariableController.h"
8 #include "Variable/VariableController.h"
9
9
10 #include "Common/MimeTypesDef.h"
11
10 #include "DragDropHelper.h"
12 #include "DragDropHelper.h"
11 #include "SqpApplication.h"
13 #include "SqpApplication.h"
12
14
@@ -52,6 +54,11 struct VisualizationTabWidget::VisualizationTabWidgetPrivate {
52 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
54 explicit VisualizationTabWidgetPrivate(const QString &name) : m_Name{name} {}
53
55
54 QString m_Name;
56 QString m_Name;
57
58 void dropGraph(int index, VisualizationTabWidget *tabWidget);
59 void dropZone(int index, VisualizationTabWidget *tabWidget);
60 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
61 VisualizationTabWidget *tabWidget);
55 };
62 };
56
63
57 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
64 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *parent)
@@ -62,9 +69,13 VisualizationTabWidget::VisualizationTabWidget(const QString &name, QWidget *par
62 ui->setupUi(this);
69 ui->setupUi(this);
63
70
64 ui->dragDropContainer->setAcceptedMimeTypes(
71 ui->dragDropContainer->setAcceptedMimeTypes(
65 {DragDropHelper::MIME_TYPE_GRAPH, DragDropHelper::MIME_TYPE_ZONE});
72 {MIME_TYPE_GRAPH, MIME_TYPE_ZONE, MIME_TYPE_VARIABLE_LIST});
66 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
73 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
67 &VisualizationTabWidget::dropMimeData);
74 &VisualizationTabWidget::dropMimeData);
75 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
76 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
77 ui->dragDropContainer);
78 });
68 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
79 sqpApp->dragDropHelper().addDragDropScrollArea(ui->scrollArea);
69
80
70 // Widget is deleted when closed
81 // Widget is deleted when closed
@@ -162,58 +173,122 QLayout &VisualizationTabWidget::tabLayout() const noexcept
162
173
163 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
174 void VisualizationTabWidget::dropMimeData(int index, const QMimeData *mimeData)
164 {
175 {
176 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
177 impl->dropGraph(index, this);
178 }
179 else if (mimeData->hasFormat(MIME_TYPE_ZONE)) {
180 impl->dropZone(index, this);
181 }
182 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
183 auto variables = sqpApp->variableController().variablesForMimeData(
184 mimeData->data(MIME_TYPE_VARIABLE_LIST));
185 impl->dropVariables(variables, index, this);
186 }
187 else {
188 qCWarning(LOG_VisualizationZoneWidget())
189 << tr("VisualizationTabWidget::dropMimeData, unknown MIME data received.");
190 }
191 }
192
193 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropGraph(
194 int index, VisualizationTabWidget *tabWidget)
195 {
165 auto &helper = sqpApp->dragDropHelper();
196 auto &helper = sqpApp->dragDropHelper();
166 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
167 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
168 auto parentDragDropContainer
169 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
170 Q_ASSERT(parentDragDropContainer);
171
172 auto nbGraph = parentDragDropContainer->countDragWidget();
173
174 const auto &variables = graphWidget->variables();
175
176 if (!variables.isEmpty()) {
177 // Abort the requests for the variables (if any)
178 // Commented, because it's not sure if it's needed or not
179 // for (const auto& var : variables)
180 //{
181 // sqpApp->variableController().onAbortProgressRequested(var);
182 //}
183
184 if (nbGraph == 1) {
185 // This is the only graph in the previous zone, close the zone
186 graphWidget->parentZoneWidget()->close();
187 }
188 else {
189 // Close the graph
190 graphWidget->close();
191 }
192
197
193 createZone(variables, index);
198 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
199 if (!graphWidget) {
200 qCWarning(LOG_VisualizationZoneWidget())
201 << tr("VisualizationTabWidget::dropGraph, drop aborted, the dropped graph is not "
202 "found or invalid.");
203 Q_ASSERT(false);
204 return;
205 }
206
207 auto parentDragDropContainer
208 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
209 if (!parentDragDropContainer) {
210 qCWarning(LOG_VisualizationZoneWidget())
211 << tr("VisualizationTabWidget::dropGraph, drop aborted, the parent container of "
212 "the dropped graph is not found.");
213 Q_ASSERT(false);
214 return;
215 }
216
217 auto nbGraph = parentDragDropContainer->countDragWidget();
218
219 const auto &variables = graphWidget->variables();
220
221 if (!variables.isEmpty()) {
222 // Abort the requests for the variables (if any)
223 // Commented, because it's not sure if it's needed or not
224 // for (const auto& var : variables)
225 //{
226 // sqpApp->variableController().onAbortProgressRequested(var);
227 //}
228
229 if (nbGraph == 1) {
230 // This is the only graph in the previous zone, close the zone
231 graphWidget->parentZoneWidget()->close();
194 }
232 }
195 else {
233 else {
196 // The graph is empty, create an empty zone and move the graph inside
234 // Close the graph
235 graphWidget->close();
236 }
197
237
198 auto parentZoneWidget = graphWidget->parentZoneWidget();
238 tabWidget->createZone(variables, index);
239 }
240 else {
241 // The graph is empty, create an empty zone and move the graph inside
199
242
200 parentDragDropContainer->layout()->removeWidget(graphWidget);
243 auto parentZoneWidget = graphWidget->parentZoneWidget();
201
244
202 auto zoneWidget = createEmptyZone(index);
245 parentDragDropContainer->layout()->removeWidget(graphWidget);
203 zoneWidget->addGraph(graphWidget);
204
246
205 // Close the old zone if it was the only graph inside
247 auto zoneWidget = tabWidget->createEmptyZone(index);
206 if (nbGraph == 1) {
248 zoneWidget->addGraph(graphWidget);
207 parentZoneWidget->close();
249
208 }
250 // Close the old zone if it was the only graph inside
251 if (nbGraph == 1) {
252 parentZoneWidget->close();
209 }
253 }
210 }
254 }
211 else if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_ZONE)) {
255 }
212 // Simple move of the zone, no variable operation associated
213 auto zoneWidget = static_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
214 auto parentDragDropContainer = zoneWidget->parentWidget();
215 parentDragDropContainer->layout()->removeWidget(zoneWidget);
216
256
217 ui->dragDropContainer->insertDragWidget(index, zoneWidget);
257 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropZone(
258 int index, VisualizationTabWidget *tabWidget)
259 {
260 auto &helper = sqpApp->dragDropHelper();
261
262 auto zoneWidget = qobject_cast<VisualizationZoneWidget *>(helper.getCurrentDragWidget());
263 if (!zoneWidget) {
264 qCWarning(LOG_VisualizationZoneWidget())
265 << tr("VisualizationTabWidget::dropZone, drop aborted, the dropped zone is not "
266 "found or invalid.");
267 Q_ASSERT(false);
268 return;
269 }
270
271 auto parentDragDropContainer
272 = qobject_cast<VisualizationDragDropContainer *>(zoneWidget->parentWidget());
273 if (!parentDragDropContainer) {
274 qCWarning(LOG_VisualizationZoneWidget())
275 << tr("VisualizationTabWidget::dropZone, drop aborted, the parent container of "
276 "the dropped zone is not found.");
277 Q_ASSERT(false);
278 return;
218 }
279 }
280
281 // Simple move of the zone, no variable operation associated
282 parentDragDropContainer->layout()->removeWidget(zoneWidget);
283 tabWidget->ui->dragDropContainer->insertDragWidget(index, zoneWidget);
284 }
285
286 void VisualizationTabWidget::VisualizationTabWidgetPrivate::dropVariables(
287 const QList<std::shared_ptr<Variable> > &variables, int index,
288 VisualizationTabWidget *tabWidget)
289 {
290 // Note: we are sure that there is a single and compatible variable here
291 // because the AcceptMimeDataFunction, set on the drop container, makes the check before the
292 // drop can occur.
293 tabWidget->createZone(variables, index);
219 }
294 }
@@ -3,12 +3,18
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 "ui_VisualizationZoneWidget.h"
7 #include "ui_VisualizationZoneWidget.h"
7
8
9 #include "Common/MimeTypesDef.h"
10 #include "Common/VisualizationDef.h"
11
8 #include <Data/SqpRange.h>
12 #include <Data/SqpRange.h>
9 #include <Variable/Variable.h>
13 #include <Variable/Variable.h>
10 #include <Variable/VariableController.h>
14 #include <Variable/VariableController.h>
11
15
16 #include <Visualization/operations/FindVariableOperation.h>
17
12 #include <DragDropHelper.h>
18 #include <DragDropHelper.h>
13 #include <QUuid>
19 #include <QUuid>
14 #include <SqpApplication.h>
20 #include <SqpApplication.h>
@@ -20,8 +26,6 Q_LOGGING_CATEGORY(LOG_VisualizationZoneWidget, "VisualizationZoneWidget")
20
26
21 namespace {
27 namespace {
22
28
23 /// Minimum height for graph added in zones (in pixels)
24 const auto GRAPH_MINIMUM_HEIGHT = 300;
25
29
26 /// Generates a default name for a new graph, according to the number of graphs already displayed in
30 /// Generates a default name for a new graph, according to the number of graphs already displayed in
27 /// the zone
31 /// the zone
@@ -66,6 +70,10 struct VisualizationZoneWidget::VisualizationZoneWidgetPrivate {
66 }
70 }
67 QUuid m_SynchronisationGroupId;
71 QUuid m_SynchronisationGroupId;
68 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
72 std::unique_ptr<IGraphSynchronizer> m_Synchronizer;
73
74 void dropGraph(int index, VisualizationZoneWidget *zoneWidget);
75 void dropVariables(const QList<std::shared_ptr<Variable> > &variables, int index,
76 VisualizationZoneWidget *zoneWidget);
69 };
77 };
70
78
71 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
79 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *parent)
@@ -77,7 +85,11 VisualizationZoneWidget::VisualizationZoneWidget(const QString &name, QWidget *p
77
85
78 ui->zoneNameLabel->setText(name);
86 ui->zoneNameLabel->setText(name);
79
87
80 ui->dragDropContainer->setAcceptedMimeTypes({DragDropHelper::MIME_TYPE_GRAPH});
88 ui->dragDropContainer->setAcceptedMimeTypes({MIME_TYPE_GRAPH, MIME_TYPE_VARIABLE_LIST});
89 ui->dragDropContainer->setAcceptMimeDataFunction([this](auto mimeData) {
90 return sqpApp->dragDropHelper().checkMimeDataForVisualization(mimeData,
91 ui->dragDropContainer);
92 });
81 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
93 connect(ui->dragDropContainer, &VisualizationDragDropContainer::dropOccured, this,
82 &VisualizationZoneWidget::dropMimeData);
94 &VisualizationZoneWidget::dropMimeData);
83
95
@@ -315,7 +327,7 QString VisualizationZoneWidget::name() const
315 QMimeData *VisualizationZoneWidget::mimeData() const
327 QMimeData *VisualizationZoneWidget::mimeData() const
316 {
328 {
317 auto mimeData = new QMimeData;
329 auto mimeData = new QMimeData;
318 mimeData->setData(DragDropHelper::MIME_TYPE_ZONE, QByteArray());
330 mimeData->setData(MIME_TYPE_ZONE, QByteArray());
319
331
320 return mimeData;
332 return mimeData;
321 }
333 }
@@ -354,57 +366,119 void VisualizationZoneWidget::onVariableAboutToBeRemoved(std::shared_ptr<Variabl
354
366
355 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
367 void VisualizationZoneWidget::dropMimeData(int index, const QMimeData *mimeData)
356 {
368 {
369 if (mimeData->hasFormat(MIME_TYPE_GRAPH)) {
370 impl->dropGraph(index, this);
371 }
372 else if (mimeData->hasFormat(MIME_TYPE_VARIABLE_LIST)) {
373 auto variables = sqpApp->variableController().variablesForMimeData(
374 mimeData->data(MIME_TYPE_VARIABLE_LIST));
375 impl->dropVariables(variables, index, this);
376 }
377 else {
378 qCWarning(LOG_VisualizationZoneWidget())
379 << tr("VisualizationZoneWidget::dropMimeData, unknown MIME data received.");
380 }
381 }
382
383 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropGraph(
384 int index, VisualizationZoneWidget *zoneWidget)
385 {
357 auto &helper = sqpApp->dragDropHelper();
386 auto &helper = sqpApp->dragDropHelper();
358 if (mimeData->hasFormat(DragDropHelper::MIME_TYPE_GRAPH)) {
359 auto graphWidget = static_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
360 auto parentDragDropContainer
361 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
362 Q_ASSERT(parentDragDropContainer);
363
364 const auto &variables = graphWidget->variables();
365
366 if (parentDragDropContainer != ui->dragDropContainer && !variables.isEmpty()) {
367 // The drop didn't occur in the same zone
368
369 // Abort the requests for the variables (if any)
370 // Commented, because it's not sure if it's needed or not
371 // for (const auto& var : variables)
372 //{
373 // sqpApp->variableController().onAbortProgressRequested(var);
374 //}
375
376 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
377 auto nbGraph = parentDragDropContainer->countDragWidget();
378 if (nbGraph == 1) {
379 // This is the only graph in the previous zone, close the zone
380 previousParentZoneWidget->close();
381 }
382 else {
383 // Close the graph
384 graphWidget->close();
385 }
386
387
387 // Creates the new graph in the zone
388 auto graphWidget = qobject_cast<VisualizationGraphWidget *>(helper.getCurrentDragWidget());
388 createGraph(variables, index);
389 if (!graphWidget) {
390 qCWarning(LOG_VisualizationZoneWidget())
391 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the dropped graph is not "
392 "found or invalid.");
393 Q_ASSERT(false);
394 return;
395 }
396
397 auto parentDragDropContainer
398 = qobject_cast<VisualizationDragDropContainer *>(graphWidget->parentWidget());
399 if (!parentDragDropContainer) {
400 qCWarning(LOG_VisualizationZoneWidget())
401 << tr("VisualizationZoneWidget::dropGraph, drop aborted, the parent container of "
402 "the dropped graph is not found.");
403 Q_ASSERT(false);
404 return;
405 }
406
407 const auto &variables = graphWidget->variables();
408
409 if (parentDragDropContainer != zoneWidget->ui->dragDropContainer && !variables.isEmpty()) {
410 // The drop didn't occur in the same zone
411
412 // Abort the requests for the variables (if any)
413 // Commented, because it's not sure if it's needed or not
414 // for (const auto& var : variables)
415 //{
416 // sqpApp->variableController().onAbortProgressRequested(var);
417 //}
418
419 auto previousParentZoneWidget = graphWidget->parentZoneWidget();
420 auto nbGraph = parentDragDropContainer->countDragWidget();
421 if (nbGraph == 1) {
422 // This is the only graph in the previous zone, close the zone
423 previousParentZoneWidget->close();
389 }
424 }
390 else {
425 else {
391 // The drop occurred in the same zone or the graph is empty
426 // Close the graph
392 // Simple move of the graph, no variable operation associated
427 graphWidget->close();
393 parentDragDropContainer->layout()->removeWidget(graphWidget);
428 }
394
429
395 if (variables.isEmpty() && parentDragDropContainer != ui->dragDropContainer) {
430 // Creates the new graph in the zone
396 // The graph is empty and dropped in a different zone.
431 zoneWidget->createGraph(variables, index);
397 // Take the range of the first graph in the zone (if existing).
432 }
398 auto layout = ui->dragDropContainer->layout();
433 else {
399 if (layout->count() > 0) {
434 // The drop occurred in the same zone or the graph is empty
400 if (auto visualizationGraphWidget
435 // Simple move of the graph, no variable operation associated
401 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
436 parentDragDropContainer->layout()->removeWidget(graphWidget);
402 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
437
403 }
438 if (variables.isEmpty() && parentDragDropContainer != zoneWidget->ui->dragDropContainer) {
439 // The graph is empty and dropped in a different zone.
440 // Take the range of the first graph in the zone (if existing).
441 auto layout = zoneWidget->ui->dragDropContainer->layout();
442 if (layout->count() > 0) {
443 if (auto visualizationGraphWidget
444 = qobject_cast<VisualizationGraphWidget *>(layout->itemAt(0)->widget())) {
445 graphWidget->setGraphRange(visualizationGraphWidget->graphRange());
404 }
446 }
405 }
447 }
448 }
449
450 zoneWidget->ui->dragDropContainer->insertDragWidget(index, graphWidget);
451 }
452 }
453
454 void VisualizationZoneWidget::VisualizationZoneWidgetPrivate::dropVariables(
455 const QList<std::shared_ptr<Variable> > &variables, int index,
456 VisualizationZoneWidget *zoneWidget)
457 {
458 // Search for the top level VisualizationWidget
459 auto parent = zoneWidget->parentWidget();
460 while (parent && qobject_cast<VisualizationWidget *>(parent) == nullptr) {
461 parent = parent->parentWidget();
462 }
463
464 if (!parent) {
465 qCWarning(LOG_VisualizationZoneWidget())
466 << tr("VisualizationZoneWidget::dropVariables, drop aborted, the parent "
467 "VisualizationWidget cannot be found.");
468 Q_ASSERT(false);
469 return;
470 }
471
472 auto visualizationWidget = static_cast<VisualizationWidget *>(parent);
406
473
407 ui->dragDropContainer->insertDragWidget(index, graphWidget);
474 // Search for the first variable which can be dropped
475 for (auto variable : variables) {
476 FindVariableOperation findVariableOperation{variable};
477 visualizationWidget->accept(&findVariableOperation);
478 auto variableContainers = findVariableOperation.result();
479 if (variableContainers.empty()) {
480 zoneWidget->createGraph(variable, index);
481 break;
408 }
482 }
409 }
483 }
410 }
484 }
General Comments 1
Under Review
author

Auto status change to "Under Review"

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