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