Skip to content

Commit 6c687d2

Browse files
Fixxed isse #131 - Crash on dropping in same area multiple times
1 parent 708add3 commit 6c687d2

File tree

7 files changed

+102
-37
lines changed

7 files changed

+102
-37
lines changed

src/DockContainerWidget.cpp

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -679,6 +679,23 @@ void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea
679679
}
680680
else
681681
{
682+
// We check, if we insert the dropped widget into the same place that
683+
// it already has and do nothing, if it is the same place. It would
684+
// also work without this check, but it looks nicer with the check
685+
// because there will be no layout updates
686+
auto Splitter = internal::findParent<CDockSplitter*>(DroppedDockArea);
687+
auto InsertParam = internal::dockAreaInsertParameters(area);
688+
if (Splitter == RootSplitter && InsertParam.orientation() == Splitter->orientation())
689+
{
690+
if (InsertParam.append() && Splitter->lastWidget() == DroppedDockArea)
691+
{
692+
return;
693+
}
694+
else if (!InsertParam.append() && Splitter->firstWidget() == DroppedDockArea)
695+
{
696+
return;
697+
}
698+
}
682699
DroppedDockArea->dockContainer()->removeDockArea(DroppedDockArea);
683700
NewDockArea = DroppedDockArea;
684701
}
@@ -1435,42 +1452,38 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
14351452
}
14361453

14371454

1438-
//============================================================================
1439-
void CDockContainerWidget::dropWidget(QWidget* Widget, const QPoint& TargetPos)
1455+
/**
1456+
* Returns the dock area for a dropped widget.
1457+
*/
1458+
CDockAreaWidget* droppedDockArea(QWidget* Widget)
14401459
{
1441-
ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
1442-
CDockWidget* SingleDockWidget = topLevelDockWidget();
1443-
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
1444-
auto dropArea = InvalidDockWidgetArea;
1445-
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
1446-
1447-
if (DockArea)
1460+
auto DroppedArea = qobject_cast<CDockAreaWidget*>(Widget);
1461+
if (!DroppedArea)
14481462
{
1449-
auto dropOverlay = d->DockManager->dockAreaOverlay();
1450-
dropOverlay->setAllowedAreas(DockArea->allowedAreas());
1451-
dropArea = dropOverlay->showOverlay(DockArea);
1452-
if (ContainerDropArea != InvalidDockWidgetArea &&
1453-
ContainerDropArea != dropArea)
1454-
{
1455-
dropArea = InvalidDockWidgetArea;
1456-
}
1463+
auto DroppedWidget = qobject_cast<CDockWidget*>(Widget);
1464+
DroppedArea = DroppedWidget->dockAreaWidget();
1465+
}
14571466

1458-
if (dropArea != InvalidDockWidgetArea)
1459-
{
1460-
ADS_PRINT("Dock Area Drop Content: " << dropArea);
1461-
d->moveToNewSection(Widget, DockArea, dropArea);
1462-
}
1467+
return DroppedArea;
1468+
}
1469+
1470+
1471+
//============================================================================
1472+
void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget)
1473+
{
1474+
if (TargetAreaWidget && TargetAreaWidget == droppedDockArea(Widget))
1475+
{
1476+
return;
14631477
}
14641478

1465-
// mouse is over container
1466-
if (InvalidDockWidgetArea == dropArea)
1479+
CDockWidget* SingleDockWidget = topLevelDockWidget();
1480+
if (TargetAreaWidget)
14671481
{
1468-
dropArea = ContainerDropArea;
1469-
ADS_PRINT("Container Drop Content: " << dropArea);
1470-
if (dropArea != InvalidDockWidgetArea)
1471-
{
1472-
d->moveToContainer(Widget, dropArea);
1473-
}
1482+
d->moveToNewSection(Widget, TargetAreaWidget, DropArea);
1483+
}
1484+
else
1485+
{
1486+
d->moveToContainer(Widget, DropArea);
14741487
}
14751488

14761489
// If there was a top level widget before the drop, then it is not top

src/DockContainerWidget.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,13 @@ class ADS_EXPORT CDockContainerWidget : public QFrame
9696
void dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos);
9797

9898
/**
99-
* Drop a dock area or a dock widget given in widget parameter
99+
* Drop a dock area or a dock widget given in widget parameter.
100+
* If the TargetAreaWidget is a nullptr, then the DropArea indicates
101+
* the drop area for the container. If the given TargetAreaWidget is not
102+
* a nullptr, then the DropArea indicates the drop area in the given
103+
* TargetAreaWidget
100104
*/
101-
void dropWidget(QWidget* Widget, const QPoint& TargetPos);
105+
void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget);
102106

103107
/**
104108
* Adds the given dock area to this container widget

src/DockOverlay.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,20 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
396396
}
397397

398398

399+
//============================================================================
400+
DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
401+
{
402+
if (isHidden() || !d->DropPreviewEnabled)
403+
{
404+
return InvalidDockWidgetArea;
405+
}
406+
else
407+
{
408+
return dropAreaUnderCursor();
409+
}
410+
}
411+
412+
399413
//============================================================================
400414
DockWidgetArea CDockOverlay::showOverlay(QWidget* target)
401415
{

src/DockOverlay.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,13 @@ class ADS_EXPORT CDockOverlay : public QFrame
8181
*/
8282
DockWidgetArea dropAreaUnderCursor() const;
8383

84+
/**
85+
* This function returns the same like dropAreaUnderCursor() if this
86+
* overlay is not hidden and if drop preview is enabled and returns
87+
* InvalidDockWidgetArea if it is hidden or drop preview is disabled.
88+
*/
89+
DockWidgetArea visibleDropAreaUnderCursor() const;
90+
8491
/**
8592
* Show the drop overly for the given target widget
8693
*/

src/DockSplitter.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,20 @@ bool CDockSplitter::hasVisibleContent() const
8888
return false;
8989
}
9090

91+
92+
//============================================================================
93+
QWidget* CDockSplitter::firstWidget() const
94+
{
95+
return (count() > 0) ? widget(0) : nullptr;
96+
}
97+
98+
99+
//============================================================================
100+
QWidget* CDockSplitter::lastWidget() const
101+
{
102+
return (count() > 0) ? widget(count() - 1) : nullptr;
103+
}
104+
91105
} // namespace ads
92106

93107
//---------------------------------------------------------------------------

src/DockSplitter.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@ class ADS_EXPORT CDockSplitter : public QSplitter
6161
* Returns true, if any of the internal widgets is visible
6262
*/
6363
bool hasVisibleContent() const;
64+
65+
/**
66+
* Returns first widget or nullptr if splitter is empty
67+
*/
68+
QWidget* firstWidget() const;
69+
70+
/**
71+
* Returns last widget of nullptr is splitter is empty
72+
*/
73+
QWidget* lastWidget() const;
6474
}; // class CDockSplitter
6575

6676
} // namespace ads

src/FloatingDragPreview.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,12 +286,15 @@ void CFloatingDragPreview::moveEvent(QMoveEvent *event)
286286
void CFloatingDragPreview::finishDragging()
287287
{
288288
ADS_PRINT("CFloatingDragPreview::finishDragging");
289-
auto DockDropArea = d->DockManager->dockAreaOverlay()->dropAreaUnderCursor();
290-
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
291-
bool DropPossible = (DockDropArea != InvalidDockWidgetArea) || (ContainerDropArea != InvalidDockWidgetArea);
292-
if (d->DropContainer && DropPossible)
289+
auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor();
290+
auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor();
291+
if (d->DropContainer && (DockDropArea != InvalidDockWidgetArea))
293292
{
294-
d->DropContainer->dropWidget(d->Content, QCursor::pos());
293+
d->DropContainer->dropWidget(d->Content, DockDropArea, d->DropContainer->dockAreaAt(QCursor::pos()));
294+
}
295+
else if (d->DropContainer && (ContainerDropArea != InvalidDockWidgetArea))
296+
{
297+
d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr);
295298
}
296299
else
297300
{

0 commit comments

Comments
 (0)