Added support for dropping dock widget to a certain tab postion of a dock area

This commit is contained in:
Uwe Kindler 2023-07-12 09:39:20 +02:00
parent 39bc7f1780
commit f4fc0dab29
7 changed files with 94 additions and 22 deletions

View File

@ -504,6 +504,31 @@ QSize CDockAreaTabBar::sizeHint() const
return d->TabsContainerWidget->sizeHint();
}
//===========================================================================
int CDockAreaTabBar::tabAt(const QPoint& Pos) const
{
if (!isVisible())
{
return -2;
}
if (Pos.x() < tab(0)->geometry().x())
{
return -1;
}
for (int i = 0; i < count(); ++i)
{
if (tab(i)->geometry().contains(Pos))
{
return i;
}
}
return count();
}
} // namespace ads

View File

@ -113,6 +113,14 @@ public:
*/
CDockWidgetTab* tab(int Index) const;
/**
* Returns the tab at the given position.
* Returns -1 if the position is left of the first tab and count() if the
* position is right of the last tab. Returns -2 to indicate an invalid
* value.
*/
int tabAt(const QPoint& Pos) const;
/**
* Filters the tab widget events
*/

View File

@ -190,19 +190,20 @@ public:
* Creates a new tab for a widget dropped into the center of a section
*/
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea);
CDockAreaWidget* TargetArea, int TabIndex = -2);
/**
* Drop floating widget into dock area
*/
void dropIntoSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea, DockWidgetArea area);
CDockAreaWidget* TargetArea, DockWidgetArea area, int TabIndex = -2);
/**
* Moves the dock widget or dock area given in Widget parameter to a
* new dock widget area
*/
void moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area);
void moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area,
int TabIndex = -2);
/**
* Moves the dock widget or dock area given in Widget parameter to a
@ -213,7 +214,7 @@ public:
/**
* Creates a new tab for a widget dropped into the center of a section
*/
void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea);
void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex = -2);
/**
* Moves the dock widget or dock area given in Widget parameter to
@ -535,12 +536,13 @@ void DockContainerWidgetPrivate::dropIntoAutoHideSideBar(CFloatingDockContainer*
//============================================================================
void DockContainerWidgetPrivate::dropIntoCenterOfSection(
CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea)
CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea, int TabIndex)
{
CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
auto NewDockWidgets = FloatingContainer->dockWidgets();
auto TopLevelDockArea = FloatingContainer->topLevelDockArea();
int NewCurrentIndex = -1;
TabIndex = (TabIndex < 0) ? 0 : TabIndex;
// If the floating widget contains only one single dock are, then the
// current dock widget of the dock area will also be the future current
@ -553,7 +555,7 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
for (int i = 0; i < NewDockWidgets.count(); ++i)
{
CDockWidget* DockWidget = NewDockWidgets[i];
TargetArea->insertDockWidget(i, DockWidget, false);
TargetArea->insertDockWidget(TabIndex + i, DockWidget, false);
// If the floating widget contains multiple visible dock areas, then we
// simply pick the first visible open dock widget and make it
// the current one.
@ -562,7 +564,7 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
NewCurrentIndex = i;
}
}
TargetArea->setCurrentIndex(NewCurrentIndex);
TargetArea->setCurrentIndex(NewCurrentIndex + TabIndex);
TargetArea->updateTitleBarVisibility();
return;
}
@ -570,13 +572,14 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection(
//============================================================================
void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea, DockWidgetArea area)
CDockAreaWidget* TargetArea, DockWidgetArea area, int TabIndex)
{
qDebug() << "DockContainerWidgetPrivate::dropIntoSection TabIndex: " << TabIndex;
// Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area
if (CenterDockWidgetArea == area)
{
dropIntoCenterOfSection(FloatingWidget, TargetArea);
dropIntoCenterOfSection(FloatingWidget, TargetArea, TabIndex);
return;
}
@ -666,11 +669,15 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
//============================================================================
void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea)
void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea,
int TabIndex)
{
qDebug() << "DockContainerWidgetPrivate::moveIntoCenterOfSection TabIndex: "
<< TabIndex;
auto DroppedDockWidget = qobject_cast<CDockWidget*>(Widget);
auto DroppedArea = qobject_cast<CDockAreaWidget*>(Widget);
TabIndex = (TabIndex < 0) ? 0 : TabIndex;
if (DroppedDockWidget)
{
CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget();
@ -683,7 +690,7 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
{
OldDockArea->removeDockWidget(DroppedDockWidget);
}
TargetArea->insertDockWidget(0, DroppedDockWidget, true);
TargetArea->insertDockWidget(TabIndex, DroppedDockWidget, true);
}
else
{
@ -692,9 +699,9 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
for (int i = 0; i < NewDockWidgets.count(); ++i)
{
CDockWidget* DockWidget = NewDockWidgets[i];
TargetArea->insertDockWidget(i, DockWidget, false);
TargetArea->insertDockWidget(TabIndex + i, DockWidget, false);
}
TargetArea->setCurrentIndex(NewCurrentIndex);
TargetArea->setCurrentIndex(TabIndex + NewCurrentIndex);
DroppedArea->dockContainer()->removeDockArea(DroppedArea);
DroppedArea->deleteLater();
}
@ -705,13 +712,16 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA
//============================================================================
void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area)
void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidget* TargetArea, DockWidgetArea area,
int TabIndex)
{
qDebug() << "DockContainerWidgetPrivate::moveToNewSection TabIndex: "
<< TabIndex;
// Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area
if (CenterDockWidgetArea == area)
{
moveIntoCenterOfSection(Widget, TargetArea);
moveIntoCenterOfSection(Widget, TargetArea, TabIndex);
return;
}
@ -1705,7 +1715,6 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
bool Dropped = false;
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
std::cout << "DockArea: " << DockArea << " dropArea: " << dropArea << std::endl;
if (DockArea)
{
auto dropOverlay = d->DockManager->dockAreaOverlay();
@ -1720,7 +1729,8 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
if (dropArea != InvalidDockWidgetArea)
{
ADS_PRINT("Dock Area Drop Content: " << dropArea);
d->dropIntoSection(FloatingWidget, DockArea, dropArea);
int TabIndex = d->DockManager->dockAreaOverlay()->tabIndexUnderCursor();
d->dropIntoSection(FloatingWidget, DockArea, dropArea, TabIndex);
Dropped = true;
}
}
@ -1773,12 +1783,14 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
//============================================================================
void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget)
void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget,
int TabIndex)
{
qDebug() << "CDockContainerWidget::dropWidget TabIndex: " << TabIndex;
CDockWidget* SingleDockWidget = topLevelDockWidget();
if (TargetAreaWidget)
{
d->moveToNewSection(Widget, TargetAreaWidget, DropArea);
d->moveToNewSection(Widget, TargetAreaWidget, DropArea, TabIndex);
}
else if (internal::isSideBarArea(DropArea))
{

View File

@ -132,7 +132,8 @@ protected:
* a nullptr, then the DropArea indicates the drop area in the given
* TargetAreaWidget
*/
void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget);
void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget,
int TabIndex = -2);
/**
* Adds the given dock area to this container widget

View File

@ -41,6 +41,7 @@
#include "DockContainerWidget.h"
#include "AutoHideSideBar.h"
#include "DockManager.h"
#include "DockAreaTabBar.h"
#include <iostream>
@ -48,6 +49,7 @@ namespace ads
{
static const int AutoHideAreaWidth = 32;
static const int AutoHideAreaMouseZone = 8;
static const int InvalidTabIndex = -2;
/**
* Private data class of CDockOverlay
@ -62,6 +64,7 @@ struct DockOverlayPrivate
bool DropPreviewEnabled = true;
CDockOverlay::eMode Mode = CDockOverlay::ModeDockAreaOverlay;
QRect DropAreaRect;
int TabIndex = InvalidTabIndex;
/**
* Private data constructor
@ -456,6 +459,7 @@ DockWidgetAreas CDockOverlay::allowedAreas() const
//============================================================================
DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
{
d->TabIndex = InvalidTabIndex;
if (!d->TargetWidget)
{
return InvalidDockWidgetArea;
@ -503,10 +507,13 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
return Result;
}
auto CursorPos = QCursor::pos();
if (DockArea->allowedAreas().testFlag(CenterDockWidgetArea)
&& !DockArea->titleBar()->isHidden()
&& DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(QCursor::pos())))
&& DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(CursorPos)))
{
auto TabBar = DockArea->titleBar()->tabBar();
d->TabIndex = TabBar->tabAt(TabBar->mapFromGlobal(CursorPos));
return CenterDockWidgetArea;
}
@ -514,6 +521,13 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
}
//============================================================================
int CDockOverlay::tabIndexUnderCursor() const
{
return d->TabIndex;
}
//============================================================================
DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const
{

View File

@ -87,6 +87,17 @@ public:
*/
DockWidgetArea dropAreaUnderCursor() const;
/**
* If the drop area is the CenterDockWidgetArea or a sidebar area,
* then this function returns the index of the tab under cursor.
* Call this function after call to dropAreaUnderCursor() because this
* function updates the tab index.
* A value of -1 indicates a position before the first tab and a value of
* tabCount() indicates a position behind the last tab.
* A value of -2 indicates an valid value
*/
int tabIndexUnderCursor() const;
/**
* This function returns the same like dropAreaUnderCursor() if this
* overlay is not hidden and if drop preview is enabled and returns

View File

@ -396,7 +396,8 @@ void CFloatingDragPreview::finishDragging()
}
else if (DockDropArea != InvalidDockWidgetArea)
{
d->DropContainer->dropWidget(d->Content, DockDropArea, d->DropContainer->dockAreaAt(QCursor::pos()));
d->DropContainer->dropWidget(d->Content, DockDropArea, d->DropContainer->dockAreaAt(QCursor::pos()),
d->DockManager->dockAreaOverlay()->tabIndexUnderCursor());
}
else if (ContainerDropArea != InvalidDockWidgetArea)
{