From b9479dbd3dca36f63b97cdf3aaa3212397473bed Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 27 Jun 2023 10:12:51 +0200 Subject: [PATCH 01/27] Started implementing autohide drag functionality --- src/DockContainerWidget.cpp | 35 +++++++--- src/DockOverlay.cpp | 126 ++++++++++++++++++++++++++++++++++-- src/FloatingDragPreview.cpp | 17 +++++ src/ads_globals.cpp | 41 ++++++++++++ src/ads_globals.h | 24 +++++++ 5 files changed, 229 insertions(+), 14 deletions(-) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 73420ee..fa21da1 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -1626,14 +1626,16 @@ int CDockContainerWidget::visibleDockAreaCount() const void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos) { + //dockContainer()->createAndSetupAutoHideContainer(area, this); ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget(); CDockWidget* SingleDockWidget = topLevelDockWidget(); - CDockAreaWidget* DockArea = dockAreaAt(TargetPos); auto dropArea = InvalidDockWidgetArea; auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor(); bool Dropped = false; + CDockAreaWidget* DockArea = dockAreaAt(TargetPos); + std::cout << "DockArea: " << DockArea << " dropArea: " << dropArea << std::endl; if (DockArea) { auto dropOverlay = d->DockManager->dockAreaOverlay(); @@ -1654,15 +1656,30 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } // mouse is over container - if (InvalidDockWidgetArea == dropArea) + std::cout << "Mouse is over container" << std::endl; + if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea) { - dropArea = ContainerDropArea; - ADS_PRINT("Container Drop Content: " << dropArea); - if (dropArea != InvalidDockWidgetArea) - { - d->dropIntoContainer(FloatingWidget, dropArea); - Dropped = true; - } + if (internal::isSideBarArea(ContainerDropArea)) + { + auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); + std::cout << "Drop into sidebar " << std::endl; + auto NewDockAreas = FloatingWidget->findChildren( + QString(), Qt::FindChildrenRecursively); + for (auto DockArea : NewDockAreas) + { + auto DockWidgets = DockArea->dockWidgets(); + for (auto DockWidget : DockWidgets) + { + createAndSetupAutoHideContainer(SideBarLocation, DockWidget); + } + } + } + else + { + ADS_PRINT("Container Drop Content: " << ContainerDropArea); + d->dropIntoContainer(FloatingWidget, ContainerDropArea); + } + Dropped = true; } // Remove the auto hide widgets from the FloatingWidget and insert diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index afefa26..6243295 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -38,11 +38,15 @@ #include "DockAreaWidget.h" #include "DockAreaTitleBar.h" +#include "DockContainerWidget.h" +#include "AutoHideSideBar.h" +#include "DockManager.h" #include namespace ads { +static const int AutoHideAreaWidth = 32; /** * Private data class of CDockOverlay @@ -62,6 +66,12 @@ struct DockOverlayPrivate * Private data constructor */ DockOverlayPrivate(CDockOverlay* _public) : _this(_public) {} + + /** + * Returns the overlay width / height depending on the visibility + * of the sidebar + */ + int sideBarOverlaySize(SideBarLocation sideBarLocation); }; /** @@ -155,8 +165,20 @@ struct DockOverlayCrossPrivate QLabel* l = new QLabel(); l->setObjectName("DockWidgetAreaLabel"); - const qreal metric = dropIndicatiorWidth(l); - const QSizeF size(metric, metric); + qreal metric = dropIndicatiorWidth(l); + QSizeF size(metric, metric); + if (internal::isSideBarArea(DockWidgetArea)) + { + auto SideBarLocation = internal::toSideBarLocation(DockWidgetArea); + if (internal::isHorizontalSideBarLocation(SideBarLocation)) + { + size.setHeight(size.height() / 2); + } + else + { + size.setWidth(size.width() / 2); + } + } l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode)); l->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint); @@ -283,7 +305,7 @@ struct DockOverlayCrossPrivate p.restore(); // Draw arrow for outer container drop indicators - if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) + /*if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) { QRectF ArrowRect; ArrowRect.setSize(baseSize); @@ -317,7 +339,7 @@ struct DockOverlayCrossPrivate } p.drawPolygon(Arrow); - } + }*/ pm.setDevicePixelRatio(DevicePixelRatio); return pm; @@ -326,6 +348,22 @@ struct DockOverlayCrossPrivate }; +//============================================================================ +int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation) +{ + auto Container = qobject_cast(TargetWidget.data()); + auto SideBar = Container->sideTabBar(sideBarLocation); + if (!SideBar || !SideBar->isVisibleTo(Container)) + { + return AutoHideAreaWidth; + } + else + { + return (SideBar->orientation() == Qt::Horizontal) ? SideBar->height() : SideBar->width(); + } +} + + //============================================================================ CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) : QFrame(parent), @@ -375,15 +413,42 @@ DockWidgetAreas CDockOverlay::allowedAreas() const //============================================================================ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const { + if (!d->TargetWidget) + { + return InvalidDockWidgetArea; + } + DockWidgetArea Result = d->Cross->cursorLocation(); if (Result != InvalidDockWidgetArea) { return Result; } - CDockAreaWidget* DockArea = qobject_cast(d->TargetWidget.data()); + auto DockArea = qobject_cast(d->TargetWidget.data()); if (!DockArea) { + /*auto Rect = rect(); + const QPoint pos = mapFromGlobal(QCursor::pos()); + if (pos.x() < d->sideBarOverlaySize(SideBarLeft)) + { + return LeftAutoHideArea; + } + else if (pos.x() > (Rect.width() - d->sideBarOverlaySize(SideBarRight))) + { + return RightAutoHideArea; + } + else if (pos.y() < d->sideBarOverlaySize(SideBarTop)) + { + return TopAutoHideArea; + } + else if (pos.y() > (Rect.height() - d->sideBarOverlaySize(SideBarBottom))) + { + return BottomAutoHideArea; + } + else + { + return Result; + }*/ return Result; } @@ -490,6 +555,10 @@ void CDockOverlay::paintEvent(QPaintEvent* event) case BottomDockWidgetArea: r.setY(r.height() * (1 - 1 / Factor)); break; case LeftDockWidgetArea: r.setWidth(r.width() / Factor); break; case CenterDockWidgetArea: r = rect();break; + case LeftAutoHideArea: r.setWidth(d->sideBarOverlaySize(SideBarLeft)); break; + case RightAutoHideArea: r.setX(r.width() - d->sideBarOverlaySize(SideBarRight)); break; + case TopAutoHideArea: r.setHeight(d->sideBarOverlaySize(SideBarTop)); break; + case BottomAutoHideArea: r.setY(r.height() - d->sideBarOverlaySize(SideBarBottom)); break; default: return; } QPainter painter(this); @@ -574,6 +643,23 @@ QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area) default: return QPoint(); } } + else if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) + { + switch (area) + { + case TopDockWidgetArea: return QPoint(1, 3); + case RightDockWidgetArea: return QPoint(3, 5); + case BottomDockWidgetArea: return QPoint(5, 3); + case LeftDockWidgetArea: return QPoint(3, 1); + case CenterDockWidgetArea: return QPoint(3, 3); + + case TopAutoHideArea: return QPoint(0, 3); + case RightAutoHideArea: return QPoint(3, 6); + case BottomAutoHideArea: return QPoint(6, 3); + case LeftAutoHideArea: return QPoint(3, 0); + default: return QPoint(); + } + } else { switch (area) @@ -627,6 +713,16 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode) areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode)); areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode)); areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode)); + + if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled) + && CDockOverlay::ModeContainerOverlay == Mode) + { + areaWidgets.insert(TopAutoHideArea, d->createDropIndicatorWidget(TopAutoHideArea, Mode)); + areaWidgets.insert(RightAutoHideArea, d->createDropIndicatorWidget(RightAutoHideArea, Mode)); + areaWidgets.insert(BottomAutoHideArea, d->createDropIndicatorWidget(BottomAutoHideArea, Mode)); + areaWidgets.insert(LeftAutoHideArea, d->createDropIndicatorWidget(LeftAutoHideArea, Mode)); + } + #if QT_VERSION >= 0x050600 d->LastDevicePixelRatio = devicePixelRatioF(); #else @@ -713,6 +809,26 @@ void CDockOverlayCross::setAreaWidgets(const QHash& wi d->GridLayout->setColumnStretch(3, 0); d->GridLayout->setColumnStretch(4, 1); } + else if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) + { + d->GridLayout->setContentsMargins(4, 4, 4, 4); + d->GridLayout->setSpacing(4); + d->GridLayout->setRowStretch(0, 0); + d->GridLayout->setRowStretch(1, 0); + d->GridLayout->setRowStretch(2, 1); + d->GridLayout->setRowStretch(3, 1); + d->GridLayout->setRowStretch(4, 1); + d->GridLayout->setRowStretch(5, 0); + d->GridLayout->setRowStretch(6, 0); + + d->GridLayout->setColumnStretch(0, 0); + d->GridLayout->setColumnStretch(1, 0); + d->GridLayout->setColumnStretch(2, 1); + d->GridLayout->setColumnStretch(3, 1); + d->GridLayout->setColumnStretch(4, 1); + d->GridLayout->setColumnStretch(5, 0); + d->GridLayout->setColumnStretch(6, 0); + } else { d->GridLayout->setContentsMargins(4, 4, 4, 4); diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 8ee3b8e..4758853 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -347,6 +347,7 @@ void CFloatingDragPreview::startFloating(const QPoint &DragStartMousePos, void CFloatingDragPreview::finishDragging() { ADS_PRINT("CFloatingDragPreview::finishDragging"); + std::cout << "CFloatingDragPreview::finishDragging" << std::endl; auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(); auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor(); @@ -369,12 +370,28 @@ void CFloatingDragPreview::finishDragging() } else if (ContainerDropArea != InvalidDockWidgetArea) { + std::cout << "ContainerDropArea != InvalidDockWidgetArea " << ContainerDropArea << std::endl; // If there is only one single dock area, and we drop into the center // then we tabify the dropped widget into the only visible dock area if (d->DropContainer->visibleDockAreaCount() <= 1 && CenterDockWidgetArea == ContainerDropArea) { d->DropContainer->dropWidget(d->Content, ContainerDropArea, d->DropContainer->dockAreaAt(QCursor::pos())); } + else if (internal::isSideBarArea(ContainerDropArea)) + { + // Drop into AutoHideArea + auto DockWidget = qobject_cast(d->Content); + auto DockArea = qobject_cast(d->Content); + auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); + if (DockWidget) + { + DockWidget->toggleAutoHide(SideBarLocation); + } + else if (DockArea) + { + DockArea->toggleAutoHide(SideBarLocation); + } + } else { d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr); diff --git a/src/ads_globals.cpp b/src/ads_globals.cpp index 2afb675..3cb5579 100644 --- a/src/ads_globals.cpp +++ b/src/ads_globals.cpp @@ -333,6 +333,47 @@ CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area) } +//============================================================================ +SideBarLocation toSideBarLocation(DockWidgetArea Area) +{ + switch (Area) + { + case LeftAutoHideArea: return SideBarLeft; + case RightAutoHideArea: return SideBarRight; + case TopAutoHideArea: return SideBarTop; + case BottomAutoHideArea: return SideBarBottom; + default: + return SideBarNone; + } + + return SideBarNone; +} + + +//============================================================================ +bool isHorizontalSideBarLocation(SideBarLocation Location) +{ + switch (Location) + { + case SideBarTop: + case SideBarBottom: return true; + case SideBarLeft: + case SideBarRight: return false; + default: + return false; + } + + return false; +} + + +//============================================================================ +bool isSideBarArea(DockWidgetArea Area) +{ + return toSideBarLocation(Area) != SideBarNone; +} + + //============================================================================ QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity) { diff --git a/src/ads_globals.h b/src/ads_globals.h index aff8667..20c341e 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -82,6 +82,10 @@ enum DockWidgetArea TopDockWidgetArea = 0x04, BottomDockWidgetArea = 0x08, CenterDockWidgetArea = 0x10, + LeftAutoHideArea = 0x20, + RightAutoHideArea = 0x40, + TopAutoHideArea = 0x80, + BottomAutoHideArea = 0x100, InvalidDockWidgetArea = NoDockWidgetArea, OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea, @@ -194,6 +198,7 @@ void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To); */ void hideEmptyParentSplitters(CDockSplitter* FirstParentSplitter); + /** * Convenience class for QPair to provide better naming than first and * second @@ -212,6 +217,25 @@ public: */ CDockInsertParam dockAreaInsertParameters(DockWidgetArea Area); + +/** + * Returns the SieBarLocation for the AutoHide dock widget areas + */ +SideBarLocation toSideBarLocation(DockWidgetArea Area); + + +/** + * Returns true for the top or bottom side bar ansd false for the + * left and right side bar + */ +bool isHorizontalSideBarLocation(SideBarLocation Location); + + +/** + * Returns true, if the given dock area is a SideBar area + */ +bool isSideBarArea(DockWidgetArea Area); + /** * Searches for the parent widget of the given type. * Returns the parent widget of the given widget or 0 if the widget is not From f71c8ffe5d74d4d0bc220952533ccaeea61a83fc Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 27 Jun 2023 12:43:12 +0200 Subject: [PATCH 02/27] Tested various pin buttons --- src/DockOverlay.cpp | 88 ++++++++++++++++++++++++--------- src/ads.qrc | 2 + src/images/pin-button-big.svg | 2 + src/images/vs-pin-button_45.svg | 2 + src/src.pro | 2 +- 5 files changed, 72 insertions(+), 24 deletions(-) create mode 100644 src/images/pin-button-big.svg create mode 100644 src/images/vs-pin-button_45.svg diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 6243295..f2657df 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -35,6 +35,7 @@ #include #include #include +#include #include "DockAreaWidget.h" #include "DockAreaTitleBar.h" @@ -204,6 +205,11 @@ struct DockOverlayCrossPrivate { QColor borderColor = iconColor(CDockOverlayCross::FrameColor); QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor); + QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor); + if (overlayColor.alpha() == 255) + { + overlayColor.setAlpha(64); + } #if QT_VERSION >= 0x050600 double DevicePixelRatio = _this->window()->devicePixelRatioF(); @@ -261,22 +267,25 @@ struct DockOverlayCrossPrivate } QSizeF baseSize = baseRect.size(); - if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) + bool IsOuterContainerArea = (CDockOverlay::ModeContainerOverlay == Mode) + && (DockWidgetArea != CenterDockWidgetArea) + && !internal::isSideBarArea(DockWidgetArea); + + if (IsOuterContainerArea) { baseRect = areaRect; } - p.fillRect(baseRect, backgroundColor); + //if (!internal::isSideBarArea(DockWidgetArea)) + //{ + p.fillRect(baseRect, backgroundColor); + //} + if (areaRect.isValid()) { pen = p.pen(); pen.setColor(borderColor); - QColor Color = iconColor(CDockOverlayCross::OverlayColor); - if (Color.alpha() == 255) - { - Color.setAlpha(64); - } - p.setBrush(Color); + p.setBrush(overlayColor); p.setPen(Qt::NoPen); p.drawRect(areaRect); @@ -289,23 +298,26 @@ struct DockOverlayCrossPrivate } p.restore(); - p.save(); - // Draw outer border - pen = p.pen(); - pen.setColor(borderColor); - pen.setWidth(1); - p.setBrush(Qt::NoBrush); - p.setPen(pen); - p.drawRect(baseRect); + //if (!internal::isSideBarArea(DockWidgetArea)) + //{ + p.save(); + // Draw outer border + pen = p.pen(); + pen.setColor(borderColor); + pen.setWidth(1); + p.setBrush(Qt::NoBrush); + p.setPen(pen); + p.drawRect(baseRect); - // draw window title bar - p.setBrush(borderColor); - QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10)); - p.drawRect(FrameRect); - p.restore(); + // draw window title bar + p.setBrush(borderColor); + QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10)); + p.drawRect(FrameRect); + p.restore(); + //} // Draw arrow for outer container drop indicators - /*if (CDockOverlay::ModeContainerOverlay == Mode && DockWidgetArea != CenterDockWidgetArea) + if (IsOuterContainerArea) { QRectF ArrowRect; ArrowRect.setSize(baseSize); @@ -339,7 +351,37 @@ struct DockOverlayCrossPrivate } p.drawPolygon(Arrow); - }*/ + } + + // Draw the pin icons + if (internal::isSideBarArea(DockWidgetArea)) + { + static QIcon PinIcon; + if (PinIcon.isNull()) + { + std::cout << "Initializing pin icon" << std::endl; + QFile file(":/ads/images/vs-pin-button.svg"); + file.open(QIODevice::ReadOnly); + QByteArray baData = file.readAll(); + baData.replace("#000000", borderColor.name(QColor::HexRgb).toLatin1()); + //baData.replace("#ffffff", overlayColor.name(QColor::HexArgb).toLatin1()); + //std::cout << borderColor.name(QColor::HexRgb) << std::endl; + QSvgRenderer svgRenderer(baData); + QPixmap pix(svgRenderer.defaultSize()); + pix.fill(Qt::transparent); + // create painter to act over pixmap + QPainter pixPainter(&pix); + svgRenderer.render(&pixPainter); + PinIcon = QIcon(pix); + } + //p.drawPixmap(0, PinIcon.paint(painter, rect, alignment, mode, state)); + auto Rect = QRect(0, 0, 16, 16); + //Rect.setSize(baseRect.size() * 0.8); + Rect.moveCenter(baseRect.center().toPoint()); + PinIcon.paint(&p, Rect, Qt::AlignCenter); + //auto Pixmap = PinIcon.pixmap(_this->windowHandle(), QSize(16, 16)); + //p.drawPixmap(QPoint(0, 0), Pixmap); + } pm.setDevicePixelRatio(DevicePixelRatio); return pm; diff --git a/src/ads.qrc b/src/ads.qrc index 019f871..fb68e40 100644 --- a/src/ads.qrc +++ b/src/ads.qrc @@ -18,5 +18,7 @@ images/vs-pin-button.svg images/vs-pin-button-pinned.svg images/vs-pin-button-pinned-focused.svg + images/vs-pin-button_45.svg + images/pin-button-big.svg diff --git a/src/images/pin-button-big.svg b/src/images/pin-button-big.svg new file mode 100644 index 0000000..305d880 --- /dev/null +++ b/src/images/pin-button-big.svg @@ -0,0 +1,2 @@ + + diff --git a/src/images/vs-pin-button_45.svg b/src/images/vs-pin-button_45.svg new file mode 100644 index 0000000..d8dc061 --- /dev/null +++ b/src/images/vs-pin-button_45.svg @@ -0,0 +1,2 @@ + + diff --git a/src/src.pro b/src/src.pro index 79344b1..c134dc4 100644 --- a/src/src.pro +++ b/src/src.pro @@ -5,7 +5,7 @@ TARGET = $$qtLibraryTarget(qtadvanceddocking) DEFINES += QT_DEPRECATED_WARNINGS TEMPLATE = lib DESTDIR = $${ADS_OUT_ROOT}/lib -QT += core gui widgets +QT += core gui widgets svg !adsBuildStatic { CONFIG += shared From 047ea3c4940f6209976039ee8426f41d1c9fcea3 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 27 Jun 2023 20:43:44 +0200 Subject: [PATCH 03/27] Implemented new dock overlay icons for sidebar areas --- src/DockOverlay.cpp | 34 ++++++++++++++++++++++++++++------ 1 file changed, 28 insertions(+), 6 deletions(-) diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index f2657df..123df0a 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -48,6 +48,7 @@ namespace ads { static const int AutoHideAreaWidth = 32; +static const int AutoHideAreaMouseZone = 8; /** * Private data class of CDockOverlay @@ -73,6 +74,11 @@ struct DockOverlayPrivate * of the sidebar */ int sideBarOverlaySize(SideBarLocation sideBarLocation); + + /** + * The area where the mouse is considered in the sidebar + */ + int sideBarMouseZone(SideBarLocation sideBarLocation); }; /** @@ -406,6 +412,22 @@ int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation) } +//============================================================================ +int DockOverlayPrivate::sideBarMouseZone(SideBarLocation sideBarLocation) +{ + auto Container = qobject_cast(TargetWidget.data()); + auto SideBar = Container->sideTabBar(sideBarLocation); + if (!SideBar || !SideBar->isVisibleTo(Container)) + { + return AutoHideAreaMouseZone; + } + else + { + return (SideBar->orientation() == Qt::Horizontal) ? SideBar->height() : SideBar->width(); + } +} + + //============================================================================ CDockOverlay::CDockOverlay(QWidget* parent, eMode Mode) : QFrame(parent), @@ -469,28 +491,28 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const auto DockArea = qobject_cast(d->TargetWidget.data()); if (!DockArea) { - /*auto Rect = rect(); + auto Rect = rect(); const QPoint pos = mapFromGlobal(QCursor::pos()); - if (pos.x() < d->sideBarOverlaySize(SideBarLeft)) + if (pos.x() < d->sideBarMouseZone(SideBarLeft)) { return LeftAutoHideArea; } - else if (pos.x() > (Rect.width() - d->sideBarOverlaySize(SideBarRight))) + else if (pos.x() > (Rect.width() - d->sideBarMouseZone(SideBarRight))) { return RightAutoHideArea; } - else if (pos.y() < d->sideBarOverlaySize(SideBarTop)) + else if (pos.y() < d->sideBarMouseZone(SideBarTop)) { return TopAutoHideArea; } - else if (pos.y() > (Rect.height() - d->sideBarOverlaySize(SideBarBottom))) + else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom))) { return BottomAutoHideArea; } else { return Result; - }*/ + } return Result; } From 21189759dda6e3fa1be265d18cdef3860da6154e Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 28 Jun 2023 07:32:49 +0200 Subject: [PATCH 04/27] Removed drop icons for sidebar drops --- src/DockOverlay.cpp | 121 +++++++----------------------------- src/FloatingDragPreview.cpp | 2 + src/ads_globals.h | 1 + src/src.pro | 2 +- 4 files changed, 28 insertions(+), 98 deletions(-) diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 123df0a..4f30705 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -282,10 +282,7 @@ struct DockOverlayCrossPrivate baseRect = areaRect; } - //if (!internal::isSideBarArea(DockWidgetArea)) - //{ - p.fillRect(baseRect, backgroundColor); - //} + p.fillRect(baseRect, backgroundColor); if (areaRect.isValid()) { @@ -304,23 +301,22 @@ struct DockOverlayCrossPrivate } p.restore(); - //if (!internal::isSideBarArea(DockWidgetArea)) - //{ - p.save(); - // Draw outer border - pen = p.pen(); - pen.setColor(borderColor); - pen.setWidth(1); - p.setBrush(Qt::NoBrush); - p.setPen(pen); - p.drawRect(baseRect); - // draw window title bar - p.setBrush(borderColor); - QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10)); - p.drawRect(FrameRect); - p.restore(); - //} + p.save(); + // Draw outer border + pen = p.pen(); + pen.setColor(borderColor); + pen.setWidth(1); + p.setBrush(Qt::NoBrush); + p.setPen(pen); + p.drawRect(baseRect); + + // draw window title bar + p.setBrush(borderColor); + QRectF FrameRect(baseRect.topLeft(), QSizeF(baseRect.width(), baseSize.height() / 10)); + p.drawRect(FrameRect); + p.restore(); + // Draw arrow for outer container drop indicators if (IsOuterContainerArea) @@ -359,36 +355,6 @@ struct DockOverlayCrossPrivate p.drawPolygon(Arrow); } - // Draw the pin icons - if (internal::isSideBarArea(DockWidgetArea)) - { - static QIcon PinIcon; - if (PinIcon.isNull()) - { - std::cout << "Initializing pin icon" << std::endl; - QFile file(":/ads/images/vs-pin-button.svg"); - file.open(QIODevice::ReadOnly); - QByteArray baData = file.readAll(); - baData.replace("#000000", borderColor.name(QColor::HexRgb).toLatin1()); - //baData.replace("#ffffff", overlayColor.name(QColor::HexArgb).toLatin1()); - //std::cout << borderColor.name(QColor::HexRgb) << std::endl; - QSvgRenderer svgRenderer(baData); - QPixmap pix(svgRenderer.defaultSize()); - pix.fill(Qt::transparent); - // create painter to act over pixmap - QPainter pixPainter(&pix); - svgRenderer.render(&pixPainter); - PinIcon = QIcon(pix); - } - //p.drawPixmap(0, PinIcon.paint(painter, rect, alignment, mode, state)); - auto Rect = QRect(0, 0, 16, 16); - //Rect.setSize(baseRect.size() * 0.8); - Rect.moveCenter(baseRect.center().toPoint()); - PinIcon.paint(&p, Rect, Qt::AlignCenter); - //auto Pixmap = PinIcon.pixmap(_this->windowHandle(), QSize(16, 16)); - //p.drawPixmap(QPoint(0, 0), Pixmap); - } - pm.setDevicePixelRatio(DevicePixelRatio); return pm; } @@ -489,10 +455,12 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const } auto DockArea = qobject_cast(d->TargetWidget.data()); - if (!DockArea) + if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) { auto Rect = rect(); const QPoint pos = mapFromGlobal(QCursor::pos()); + + std::cout << "pos.y: " << pos.y() << " d->sideBarMouseZone(SideBarTop) " << d->sideBarMouseZone(SideBarTop) << std::endl; if (pos.x() < d->sideBarMouseZone(SideBarLeft)) { return LeftAutoHideArea; @@ -515,6 +483,10 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const } return Result; } + else if (!DockArea) + { + return Result; + } if (DockArea->allowedAreas().testFlag(CenterDockWidgetArea) && !DockArea->titleBar()->isHidden() @@ -612,6 +584,7 @@ void CDockOverlay::paintEvent(QPaintEvent* event) double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? 3 : 2; + std::cout << "paint: da: " << da << std::endl; switch (da) { case TopDockWidgetArea: r.setHeight(r.height() / Factor); break; @@ -707,23 +680,6 @@ QPoint DockOverlayCrossPrivate::areaGridPosition(const DockWidgetArea area) default: return QPoint(); } } - else if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) - { - switch (area) - { - case TopDockWidgetArea: return QPoint(1, 3); - case RightDockWidgetArea: return QPoint(3, 5); - case BottomDockWidgetArea: return QPoint(5, 3); - case LeftDockWidgetArea: return QPoint(3, 1); - case CenterDockWidgetArea: return QPoint(3, 3); - - case TopAutoHideArea: return QPoint(0, 3); - case RightAutoHideArea: return QPoint(3, 6); - case BottomAutoHideArea: return QPoint(6, 3); - case LeftAutoHideArea: return QPoint(3, 0); - default: return QPoint(); - } - } else { switch (area) @@ -778,15 +734,6 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode) areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode)); areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode)); - if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled) - && CDockOverlay::ModeContainerOverlay == Mode) - { - areaWidgets.insert(TopAutoHideArea, d->createDropIndicatorWidget(TopAutoHideArea, Mode)); - areaWidgets.insert(RightAutoHideArea, d->createDropIndicatorWidget(RightAutoHideArea, Mode)); - areaWidgets.insert(BottomAutoHideArea, d->createDropIndicatorWidget(BottomAutoHideArea, Mode)); - areaWidgets.insert(LeftAutoHideArea, d->createDropIndicatorWidget(LeftAutoHideArea, Mode)); - } - #if QT_VERSION >= 0x050600 d->LastDevicePixelRatio = devicePixelRatioF(); #else @@ -873,26 +820,6 @@ void CDockOverlayCross::setAreaWidgets(const QHash& wi d->GridLayout->setColumnStretch(3, 0); d->GridLayout->setColumnStretch(4, 1); } - else if (CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) - { - d->GridLayout->setContentsMargins(4, 4, 4, 4); - d->GridLayout->setSpacing(4); - d->GridLayout->setRowStretch(0, 0); - d->GridLayout->setRowStretch(1, 0); - d->GridLayout->setRowStretch(2, 1); - d->GridLayout->setRowStretch(3, 1); - d->GridLayout->setRowStretch(4, 1); - d->GridLayout->setRowStretch(5, 0); - d->GridLayout->setRowStretch(6, 0); - - d->GridLayout->setColumnStretch(0, 0); - d->GridLayout->setColumnStretch(1, 0); - d->GridLayout->setColumnStretch(2, 1); - d->GridLayout->setColumnStretch(3, 1); - d->GridLayout->setColumnStretch(4, 1); - d->GridLayout->setColumnStretch(5, 0); - d->GridLayout->setColumnStretch(6, 0); - } else { d->GridLayout->setContentsMargins(4, 4, 4, 4); diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 4758853..987577e 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -128,6 +128,8 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) auto DockAreaOverlay = DockManager->dockAreaOverlay(); auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); + std::cout << "ContainerDropArea " << ContainerDropArea << std::endl; + std::cout << "DockDropArea " << DockDropArea << std::endl; if (!TopContainer) { diff --git a/src/ads_globals.h b/src/ads_globals.h index 20c341e..e331576 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -89,6 +89,7 @@ enum DockWidgetArea InvalidDockWidgetArea = NoDockWidgetArea, OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea | BottomDockWidgetArea, + AutoHideDockAreas = LeftAutoHideArea | RightAutoHideArea | TopAutoHideArea | BottomAutoHideArea, AllDockAreas = OuterDockAreas | CenterDockWidgetArea }; Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea) diff --git a/src/src.pro b/src/src.pro index c134dc4..79344b1 100644 --- a/src/src.pro +++ b/src/src.pro @@ -5,7 +5,7 @@ TARGET = $$qtLibraryTarget(qtadvanceddocking) DEFINES += QT_DEPRECATED_WARNINGS TEMPLATE = lib DESTDIR = $${ADS_OUT_ROOT}/lib -QT += core gui widgets svg +QT += core gui widgets !adsBuildStatic { CONFIG += shared From f6ccaba6aa44d2407e28e918dcdd3cfe26bf8027 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 28 Jun 2023 10:19:59 +0200 Subject: [PATCH 05/27] Added dropIntoAutoHideSideBar() function --- src/DockContainerWidget.cpp | 55 +++++++++++++++++++++++++++++-------- src/DockOverlay.cpp | 4 --- src/FloatingDragPreview.cpp | 28 +++---------------- 3 files changed, 47 insertions(+), 40 deletions(-) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index fa21da1..8817c34 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -181,6 +181,11 @@ public: */ void dropIntoContainer(CFloatingDockContainer* FloatingWidget, DockWidgetArea area); + /** + * Drop floating widget into auto hide side bar + */ + void dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area); + /** * Drop floating widget into dock area */ @@ -505,6 +510,23 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float } +//============================================================================ +void DockContainerWidgetPrivate::dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area) +{ + auto SideBarLocation = internal::toSideBarLocation(area); + auto NewDockAreas = FloatingWidget->findChildren( + QString(), Qt::FindChildrenRecursively); + for (auto DockArea : NewDockAreas) + { + auto DockWidgets = DockArea->dockWidgets(); + for (auto DockWidget : DockWidgets) + { + _this->createAndSetupAutoHideContainer(SideBarLocation, DockWidget); + } + } +} + + //============================================================================ void DockContainerWidgetPrivate::dropIntoCenterOfSection( CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea) @@ -1661,18 +1683,8 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi { if (internal::isSideBarArea(ContainerDropArea)) { - auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); - std::cout << "Drop into sidebar " << std::endl; - auto NewDockAreas = FloatingWidget->findChildren( - QString(), Qt::FindChildrenRecursively); - for (auto DockArea : NewDockAreas) - { - auto DockWidgets = DockArea->dockWidgets(); - for (auto DockWidget : DockWidgets) - { - createAndSetupAutoHideContainer(SideBarLocation, DockWidget); - } - } + ADS_PRINT("Container Drop Content: " << ContainerDropArea); + d->dropIntoAutoHideSideBar(FloatingWidget, ContainerDropArea); } else { @@ -1712,10 +1724,29 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi d->DockManager->notifyFloatingWidgetDrop(FloatingWidget); } +/* + * else if (internal::isSideBarArea(ContainerDropArea)) + { + // Drop into AutoHideArea + auto DockWidget = qobject_cast(d->Content); + auto DockArea = qobject_cast(d->Content); + auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); + if (DockWidget) + { + DockWidget->toggleAutoHide(SideBarLocation); + } + else if (DockArea) + { + DockArea->toggleAutoHide(SideBarLocation); + } + } + */ + //============================================================================ void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget) { + std::cout << "CDockContainerWidget::dropWidget" << std::endl; CDockWidget* SingleDockWidget = topLevelDockWidget(); if (TargetAreaWidget) { diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 4f30705..492b036 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -35,7 +35,6 @@ #include #include #include -#include #include "DockAreaWidget.h" #include "DockAreaTitleBar.h" @@ -459,8 +458,6 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const { auto Rect = rect(); const QPoint pos = mapFromGlobal(QCursor::pos()); - - std::cout << "pos.y: " << pos.y() << " d->sideBarMouseZone(SideBarTop) " << d->sideBarMouseZone(SideBarTop) << std::endl; if (pos.x() < d->sideBarMouseZone(SideBarLeft)) { return LeftAutoHideArea; @@ -584,7 +581,6 @@ void CDockOverlay::paintEvent(QPaintEvent* event) double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? 3 : 2; - std::cout << "paint: da: " << da << std::endl; switch (da) { case TopDockWidgetArea: r.setHeight(r.height() / Factor); break; diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 987577e..8ca6926 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -128,8 +128,6 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) auto DockAreaOverlay = DockManager->dockAreaOverlay(); auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); - std::cout << "ContainerDropArea " << ContainerDropArea << std::endl; - std::cout << "DockDropArea " << DockDropArea << std::endl; if (!TopContainer) { @@ -349,7 +347,6 @@ void CFloatingDragPreview::startFloating(const QPoint &DragStartMousePos, void CFloatingDragPreview::finishDragging() { ADS_PRINT("CFloatingDragPreview::finishDragging"); - std::cout << "CFloatingDragPreview::finishDragging" << std::endl; auto DockDropArea = d->DockManager->dockAreaOverlay()->visibleDropAreaUnderCursor(); auto ContainerDropArea = d->DockManager->containerOverlay()->visibleDropAreaUnderCursor(); @@ -372,32 +369,15 @@ void CFloatingDragPreview::finishDragging() } else if (ContainerDropArea != InvalidDockWidgetArea) { - std::cout << "ContainerDropArea != InvalidDockWidgetArea " << ContainerDropArea << std::endl; + CDockAreaWidget* DockArea = nullptr; // If there is only one single dock area, and we drop into the center // then we tabify the dropped widget into the only visible dock area if (d->DropContainer->visibleDockAreaCount() <= 1 && CenterDockWidgetArea == ContainerDropArea) { - d->DropContainer->dropWidget(d->Content, ContainerDropArea, d->DropContainer->dockAreaAt(QCursor::pos())); - } - else if (internal::isSideBarArea(ContainerDropArea)) - { - // Drop into AutoHideArea - auto DockWidget = qobject_cast(d->Content); - auto DockArea = qobject_cast(d->Content); - auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); - if (DockWidget) - { - DockWidget->toggleAutoHide(SideBarLocation); - } - else if (DockArea) - { - DockArea->toggleAutoHide(SideBarLocation); - } - } - else - { - d->DropContainer->dropWidget(d->Content, ContainerDropArea, nullptr); + DockArea = d->DropContainer->dockAreaAt(QCursor::pos()); } + + d->DropContainer->dropWidget(d->Content, ContainerDropArea, DockArea); } else { From b801f0655dfc64dc81960fcd7af7dfe80b880b4b Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 28 Jun 2023 14:01:08 +0200 Subject: [PATCH 06/27] Improved dragging of widgets into AutoHideArea --- demo/MainWindow.cpp | 8 +++-- src/DockContainerWidget.cpp | 63 +++++++++++++++++++++++------------ src/DockContainerWidget.h | 7 ++++ src/DockOverlay.cpp | 31 +++++++++++++++++ src/DockOverlay.h | 5 +++ src/FloatingDockContainer.cpp | 14 ++++++-- src/FloatingDragPreview.cpp | 37 ++++++++++++++------ 7 files changed, 127 insertions(+), 38 deletions(-) diff --git a/demo/MainWindow.cpp b/demo/MainWindow.cpp index fb0a51b..9e8cf7c 100644 --- a/demo/MainWindow.cpp +++ b/demo/MainWindow.cpp @@ -437,8 +437,8 @@ void MainWindowPrivate::createContent() // For this Special Dock Area we want to avoid dropping on the center of it (i.e. we don't want this widget to be ever tabbified): { - SpecialDockArea->setAllowedAreas(ads::OuterDockAreas); - //SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea}); // just for testing + //SpecialDockArea->setAllowedAreas(ads::OuterDockAreas); + SpecialDockArea->setAllowedAreas({ads::LeftDockWidgetArea, ads::RightDockWidgetArea, ads::TopDockWidgetArea}); // just for testing } DockWidget = createLongTextLabelDockWidget(); @@ -506,7 +506,9 @@ void MainWindowPrivate::createContent() // Test dock area docking auto RighDockArea = DockManager->addDockWidget(ads::RightDockWidgetArea, createLongTextLabelDockWidget(), TopDockArea); - DockManager->addDockWidget(ads::TopDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); + DockWidget = createLongTextLabelDockWidget(); + DockWidget->setFeature(ads::CDockWidget::DockWidgetPinnable, false); + DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget, RighDockArea); auto BottomDockArea = DockManager->addDockWidget(ads::BottomDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea); auto LabelDockWidget = createLongTextLabelDockWidget(); diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 8817c34..95aeeb6 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -186,6 +186,12 @@ public: */ void dropIntoAutoHideSideBar(CFloatingDockContainer* FloatingWidget, DockWidgetArea area); + /** + * Creates a new tab for a widget dropped into the center of a section + */ + void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, + CDockAreaWidget* TargetArea); + /** * Drop floating widget into dock area */ @@ -207,13 +213,13 @@ public: /** * Creates a new tab for a widget dropped into the center of a section */ - void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, - CDockAreaWidget* TargetArea); + void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea); /** - * Creates a new tab for a widget dropped into the center of a section + * Moves the dock widget or dock area given in Widget parameter to + * a auto hide sidebar area */ - void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea); + void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area); /** @@ -760,6 +766,33 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg } +//============================================================================ +void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area) +{ + std::cout << "DockContainerWidgetPrivate::moveToAutoHideSideBar " << area << std::endl; + CDockWidget* DroppedDockWidget = qobject_cast(Widget); + CDockAreaWidget* DroppedDockArea = qobject_cast(Widget); + auto SideBarLocation = internal::toSideBarLocation(area); + + if (DroppedDockWidget) + { + _this->createAndSetupAutoHideContainer(SideBarLocation, DroppedDockWidget); + } + else + { + for (const auto DockWidget : DroppedDockArea->openedDockWidgets()) + { + if (!DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable)) + { + continue; + } + + _this->createAndSetupAutoHideContainer(SideBarLocation, DockWidget); + } + } +} + + //============================================================================ void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter ) { @@ -1724,24 +1757,6 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi d->DockManager->notifyFloatingWidgetDrop(FloatingWidget); } -/* - * else if (internal::isSideBarArea(ContainerDropArea)) - { - // Drop into AutoHideArea - auto DockWidget = qobject_cast(d->Content); - auto DockArea = qobject_cast(d->Content); - auto SideBarLocation = internal::toSideBarLocation(ContainerDropArea); - if (DockWidget) - { - DockWidget->toggleAutoHide(SideBarLocation); - } - else if (DockArea) - { - DockArea->toggleAutoHide(SideBarLocation); - } - } - */ - //============================================================================ void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget) @@ -1752,6 +1767,10 @@ void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, { d->moveToNewSection(Widget, TargetAreaWidget, DropArea); } + else if (internal::isSideBarArea(DropArea)) + { + d->moveToAutoHideSideBar(Widget, DropArea); + } else { d->moveToContainer(Widget, DropArea); diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 4a32e5a..2b080b4 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -103,6 +103,13 @@ protected: */ CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget); + /** + * The funtion does the same like createAndSetupAutoHideContainer() but checks + * if the given DockWidget is pinnable. If it is not pinnable, the + * function returns a nullptr. + */ + CAutoHideDockContainer* createAutoHideContainerIfPinnable(SideBarLocation area, CDockWidget* DockWidget); + /** * Helper function for creation of the root splitter */ diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 492b036..d04e839 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -209,6 +209,11 @@ struct DockOverlayCrossPrivate CDockOverlay::eMode Mode) { QColor borderColor = iconColor(CDockOverlayCross::FrameColor); + // TODO: remove, this is just for debugging + if (Mode == CDockOverlay::ModeContainerOverlay) + { + borderColor = Qt::red; + } QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor); QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor); if (overlayColor.alpha() == 255) @@ -426,12 +431,26 @@ CDockOverlay::~CDockOverlay() void CDockOverlay::setAllowedAreas(DockWidgetAreas areas) { if (areas == d->AllowedAreas) + { return; + } d->AllowedAreas = areas; d->Cross->reset(); } +//============================================================================ +void CDockOverlay::setAllowedArea(DockWidgetArea area, bool Enable) +{ + auto AreasOld = d->AllowedAreas; + d->AllowedAreas.setFlag(area, Enable); + if (AreasOld != d->AllowedAreas) + { + d->Cross->reset(); + } +} + + //============================================================================ DockWidgetAreas CDockOverlay::allowedAreas() const { @@ -456,6 +475,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const auto DockArea = qobject_cast(d->TargetWidget.data()); if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) { + std::cout << d->Mode << " Find out side bar area " << std::endl; auto Rect = rect(); const QPoint pos = mapFromGlobal(QCursor::pos()); if (pos.x() < d->sideBarMouseZone(SideBarLeft)) @@ -468,6 +488,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const } else if (pos.y() < d->sideBarMouseZone(SideBarTop)) { + std::cout << d->Mode << " TopAutoHideArea " << std::endl; return TopAutoHideArea; } else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom))) @@ -513,12 +534,14 @@ DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const //============================================================================ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) { + std::cout << d->Mode << " CDockOverlay::showOverlay()" << target << " " << target->objectName().toStdString() << std::endl; if (d->TargetWidget == target) { // Hint: We could update geometry of overlay here. DockWidgetArea da = dropAreaUnderCursor(); if (da != d->LastLocation) { + std::cout << d->Mode << " repaint()" << std::endl; repaint(); d->LastLocation = da; } @@ -543,6 +566,7 @@ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) //============================================================================ void CDockOverlay::hideOverlay() { + std::cout << d->Mode << " CDockOverlay::hideOverlay()" << std::endl; hide(); d->TargetWidget.clear(); d->LastLocation = InvalidDockWidgetArea; @@ -554,6 +578,7 @@ void CDockOverlay::hideOverlay() void CDockOverlay::enableDropPreview(bool Enable) { d->DropPreviewEnabled = Enable; + std::cout << d->Mode << " update() " << Enable << std::endl; update(); } @@ -581,6 +606,7 @@ void CDockOverlay::paintEvent(QPaintEvent* event) double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? 3 : 2; + std::cout << "CDockOverlay::paintEvent da: " << da << std::endl; switch (da) { case TopDockWidgetArea: r.setHeight(r.height() / Factor); break; @@ -596,6 +622,11 @@ void CDockOverlay::paintEvent(QPaintEvent* event) } QPainter painter(this); QColor Color = palette().color(QPalette::Active, QPalette::Highlight); + // TODO: This is just for debugging - remove later + if (d->Mode == CDockOverlay::ModeContainerOverlay) + { + Color = Qt::red; + } QPen Pen = painter.pen(); Pen.setColor(Color.darker(120)); Pen.setStyle(Qt::SolidLine); diff --git a/src/DockOverlay.h b/src/DockOverlay.h index 88905e0..3fe0ba9 100644 --- a/src/DockOverlay.h +++ b/src/DockOverlay.h @@ -72,6 +72,11 @@ public: */ void setAllowedAreas(DockWidgetAreas areas); + /** + * Enable / disable a certain area + */ + void setAllowedArea(DockWidgetArea area, bool Enable); + /** * Returns flags with all allowed drop areas */ diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index d6d9c02..bb2ffbd 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -585,11 +585,19 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos) } int VisibleDockAreas = TopContainer->visibleDockAreaCount(); - ContainerOverlay->setAllowedAreas( - VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); + DockWidgetAreas AllowedAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas; + auto DockArea = TopContainer->dockAreaAt(GlobalPos); + // If the dock container contains only one single DockArea, then we need + // to respect the allowed areas - only the center area is relevant here because + // all other allowed areas are from the container + if (VisibleDockAreas == 1 && DockArea) + { + AllowedAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea)); + } + ContainerOverlay->setAllowedAreas(AllowedAreas); + DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); - auto DockArea = TopContainer->dockAreaAt(GlobalPos); if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0) { DockAreaOverlay->enableDropPreview(true); diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 8ca6926..7291b2c 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -101,6 +101,7 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) { if (!_this->isVisible() || !DockManager) { + std::cout << "return 1" << std::endl; return; } @@ -126,20 +127,24 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) DropContainer = TopContainer; auto ContainerOverlay = DockManager->containerOverlay(); auto DockAreaOverlay = DockManager->dockAreaOverlay(); - auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); - auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); if (!TopContainer) { + std::cout << "ContainerOverlay->hideOverlay() 1" << std::endl; ContainerOverlay->hideOverlay(); + std::cout << "DockAreaOverlay->hideOverlay() 1" << std::endl; DockAreaOverlay->hideOverlay(); if (CDockManager::testConfigFlag(CDockManager::DragPreviewIsDynamic)) { + std::cout << "return 2" << std::endl; setHidden(false); } return; } + auto DockDropArea = DockAreaOverlay->dropAreaUnderCursor(); + auto ContainerDropArea = ContainerOverlay->dropAreaUnderCursor(); + int VisibleDockAreas = TopContainer->visibleDockAreaCount(); // Include the overlay widget we're dragging as a visible widget @@ -148,15 +153,25 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) { VisibleDockAreas++; } + std::cout << "VisibleDockAreas " << VisibleDockAreas << std::endl; - ContainerOverlay->setAllowedAreas( VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas); + DockWidgetAreas AllowedAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas; + //ContainerOverlay->enableDropPreview(ContainerDropArea != InvalidDockWidgetArea); auto DockArea = TopContainer->dockAreaAt(GlobalPos); + // If the dock container contains only one single DockArea, then we need + // to respect the allowed areas - only the center area is relevant here because + // all other allowed areas are from the container + if (VisibleDockAreas == 1 && DockArea) + { + AllowedAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea)); + } + ContainerOverlay->setAllowedAreas(AllowedAreas); if (DockArea && DockArea->isVisible() && VisibleDockAreas >= 0 && DockArea != ContentSourceArea) { DockAreaOverlay->enableDropPreview(true); DockAreaOverlay->setAllowedAreas( (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas()); - DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); + std::cout << "DockWidgetArea " << Area << std::endl; // A CenterDockWidgetArea for the dockAreaOverlay() indicates that // the mouse is in the title bar. If the ContainerArea is valid @@ -165,28 +180,30 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) if ((Area == CenterDockWidgetArea) && (ContainerDropArea != InvalidDockWidgetArea)) { DockAreaOverlay->enableDropPreview(false); + + std::cout << "ContainerOverlay->enableDropPreview(true) 1" << std::endl; ContainerOverlay->enableDropPreview(true); } else { + std::cout << "ContainerOverlay->enableDropPreview 2" << std::endl; ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); } ContainerOverlay->showOverlay(TopContainer); } else { + std::cout << "DockAreaOverlay->hideOverlay() 2" << std::endl; DockAreaOverlay->hideOverlay(); // If there is only one single visible dock area in a container, then // it does not make sense to show a dock overlay because the dock area - // would be removed and inserted at the same position + // would be removed and inserted at the same position. Only auto hide + // area is allowed if (VisibleDockAreas == 1) { - ContainerOverlay->hideOverlay(); - } - else - { - ContainerOverlay->showOverlay(TopContainer); + ContainerOverlay->setAllowedAreas(AutoHideDockAreas); } + ContainerOverlay->showOverlay(TopContainer); if (DockArea == ContentSourceArea && InvalidDockWidgetArea == ContainerDropArea) From e2929ade142785c629022eebcfd40766574cc392 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 28 Jun 2023 15:59:26 +0200 Subject: [PATCH 07/27] Fixed DockContainerWidget.cpp contentRect() function to work properly even if no dock widget is visible in container --- src/AutoHideDockContainer.cpp | 2 ++ src/DockContainerWidget.cpp | 30 ++++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 3762eec..56c1541 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -230,6 +230,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL //============================================================================ void CAutoHideDockContainer::updateSize() { + std::cout << "CAutoHideDockContainer::updateSize()" << std::endl; auto dockContainerParent = dockContainer(); if (!dockContainerParent) { @@ -237,6 +238,7 @@ void CAutoHideDockContainer::updateSize() } auto rect = dockContainerParent->contentRect(); + qDebug() << "dockContainerParent->contentRect() " << rect; switch (sideBarLocation()) { diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 95aeeb6..daa1231 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -145,7 +145,7 @@ public: QList AutoHideWidgets; QMap SideTabBarWidgets; QGridLayout* Layout = nullptr; - QSplitter* RootSplitter = nullptr; + CDockSplitter* RootSplitter = nullptr; bool isFloating = false; CDockAreaWidget* LastAddedAreaCache[5]; int VisibleDockAreaCount = -1; @@ -465,7 +465,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float CDockContainerWidget* FloatingDockContainer = FloatingWidget->dockContainer(); auto NewDockAreas = FloatingDockContainer->findChildren( QString(), Qt::FindChildrenRecursively); - QSplitter* Splitter = RootSplitter; + auto Splitter = RootSplitter; if (DockAreas.count() <= 1) { @@ -473,7 +473,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float } else if (Splitter->orientation() != InsertParam.orientation()) { - QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); + auto NewSplitter = newSplitter(InsertParam.orientation()); QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); NewSplitter->addWidget(Splitter); updateSplitterHandles(NewSplitter); @@ -1248,7 +1248,7 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW } else { - QSplitter* NewSplitter = newSplitter(InsertParam.orientation()); + auto NewSplitter = newSplitter(InsertParam.orientation()); if (InsertParam.append()) { QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter); @@ -1583,7 +1583,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area) } QWidget* widget = Splitter->widget(0); - QSplitter* ChildSplitter = qobject_cast(widget); + auto ChildSplitter = qobject_cast(widget); // If the one and only content widget of the splitter is not a splitter // then we are finished if (!ChildSplitter) @@ -1913,8 +1913,8 @@ bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing) } d->Layout->replaceWidget(d->RootSplitter, NewRootSplitter); - QSplitter* OldRoot = d->RootSplitter; - d->RootSplitter = qobject_cast(NewRootSplitter); + auto OldRoot = d->RootSplitter; + d->RootSplitter = qobject_cast(NewRootSplitter); OldRoot->deleteLater(); return true; @@ -2132,7 +2132,21 @@ QRect CDockContainerWidget::contentRect() const return QRect(); } - return d->RootSplitter->geometry(); + if (d->RootSplitter->hasVisibleContent()) + { + return d->RootSplitter->geometry(); + } + else + { + auto ContentRect = this->rect(); + ContentRect.adjust( + sideTabBar(SideBarLeft)->sizeHint().width(), + sideTabBar(SideBarTop)->sizeHint().height(), + -sideTabBar(SideBarRight)->sizeHint().width(), + -sideTabBar(SideBarBottom)->sizeHint().height()); + + return ContentRect; + } } From 1c6d86e70f2783318eb6ddc1175c0d7fc7d35f96 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 7 Jul 2023 11:21:54 +0200 Subject: [PATCH 08/27] Added support for make auto hide widget floating via double click or context menu --- src/AutoHideDockContainer.cpp | 14 ++++++++- src/AutoHideTab.cpp | 56 +++++++++++++++++++++++++++++++++++ src/AutoHideTab.h | 9 +++++- src/DockAreaTitleBar.cpp | 22 ++++++++++++++ src/DockAreaTitleBar.h | 6 ++++ src/DockAreaWidget.cpp | 7 +++++ src/DockAreaWidget.h | 6 ++++ src/DockOverlay.cpp | 7 ----- src/DockWidget.cpp | 10 ++++++- src/FloatingDockContainer.cpp | 40 ++++++++++++++----------- 10 files changed, 149 insertions(+), 28 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 56c1541..c25d60b 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -230,7 +230,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL //============================================================================ void CAutoHideDockContainer::updateSize() { - std::cout << "CAutoHideDockContainer::updateSize()" << std::endl; + qDebug() << "CAutoHideDockContainer::updateSize()"; auto dockContainerParent = dockContainer(); if (!dockContainerParent) { @@ -239,6 +239,10 @@ void CAutoHideDockContainer::updateSize() auto rect = dockContainerParent->contentRect(); qDebug() << "dockContainerParent->contentRect() " << rect; + qDebug() << "dockWidget()->rect()" << dockWidget()->rect(); + qDebug() << "dockAreaWidget()->rect(): " << dockAreaWidget()->rect(); + qDebug() << "CAutoHideDockContainer::isVisible " << this->isVisible(); + qDebug() << "CAutoHideDockContainer::rect " << this->rect(); switch (sideBarLocation()) { @@ -273,6 +277,9 @@ void CAutoHideDockContainer::updateSize() default: break; } + + qDebug() << "CAutoHideDockContainer::rect (after): " << this->rect(); + qDebug() << "dockAreaWidget()->rect(): " << dockAreaWidget()->rect(); } //============================================================================ @@ -326,6 +333,7 @@ CDockWidget* CAutoHideDockContainer::dockWidget() const //============================================================================ void CAutoHideDockContainer::addDockWidget(CDockWidget* DockWidget) { + std::cout << "CAutoHideDockContainer::addDockWidget " << std::endl; if (d->DockWidget) { // Remove the old dock widget at this area @@ -346,6 +354,10 @@ void CAutoHideDockContainer::addDockWidget(CDockWidget* DockWidget) } d->DockArea->addDockWidget(DockWidget); updateSize(); + // The dock area is not visible and will not update the size when updateSize() + // is called for this auto hide container. Therefore we explicitely resize + // it here. As soon as it will become visible, it will get the right size + d->DockArea->resize(size()); } diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index a6f7cc4..bee969b 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include "AutoHideDockContainer.h" #include "AutoHideSideBar.h" @@ -272,10 +273,65 @@ bool CAutoHideTab::event(QEvent* event) return Super::event(event); } + //============================================================================ bool CAutoHideTab::iconOnly() const { return CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideSideBarsIconOnly) && !icon().isNull(); } + +//============================================================================ +void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) +{ + ev->accept(); + //d->saveDragStartMousePosition(ev->globalPos()); + + const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable); + QAction* Action; + QMenu Menu(this); + + + Action = Menu.addAction(tr("Detach"), this, SLOT(setDockWidgetFloating())); + Action->setEnabled(isFloatable); + auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable); + Action->setEnabled(IsPinnable); + + auto menu = Menu.addMenu(tr("Pin To...")); + menu->setEnabled(IsPinnable); + //d->createAutoHideToAction(tr("Top"), SideBarTop, menu); + //d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); + //d->createAutoHideToAction(tr("Right"), SideBarRight, menu); + //d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); + + /*Menu.addSeparator(); + Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); + Action->setEnabled(isClosable()); + if (d->DockArea->openDockWidgetsCount() > 1) + { + Action = Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested())); + }*/ + Menu.exec(ev->globalPos()); +} + + +//============================================================================ +void CAutoHideTab::mouseDoubleClickEvent(QMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) + { + setDockWidgetFloating(); + } + + Super::mouseDoubleClickEvent(event); +} + + +//============================================================================ +void CAutoHideTab::setDockWidgetFloating() +{ + dockWidget()->setFloating(); +} + + } diff --git a/src/AutoHideTab.h b/src/AutoHideTab.h index ca8bb56..1e4a374 100644 --- a/src/AutoHideTab.h +++ b/src/AutoHideTab.h @@ -65,11 +65,12 @@ private: friend class CDockContainerWidget; friend DockContainerWidgetPrivate; - protected: void setSideBar(CAutoHideSideBar *SideTabBar); void removeFromSideBar(); virtual bool event(QEvent* event) override; + virtual void contextMenuEvent(QContextMenuEvent* ev) override; + virtual void mouseDoubleClickEvent(QMouseEvent *event) override; public: using Super = CPushButton; @@ -133,6 +134,12 @@ public: * not in a side bar */ CAutoHideSideBar* sideBar() const; + +public Q_SLOTS: + /** + * Set the dock widget floating, if it is floatable + */ + void setDockWidgetFloating(); }; // class AutoHideTab } // namespace ads diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index d5af9bf..defb664 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -260,6 +260,7 @@ void DockAreaTitleBarPrivate::createTabBar() //============================================================================ IFloatingWidget* DockAreaTitleBarPrivate::makeAreaFloating(const QPoint& Offset, eDragState DragState) { + qDebug() << "DockAreaTitleBarPrivate::makeAreaFloating " << DockArea->size(); QSize Size = DockArea->size(); this->DragState = DragState; bool CreateFloatingDockContainer = (DraggingFloatingWidget != DragState); @@ -660,6 +661,7 @@ void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev) //============================================================================ void CDockAreaTitleBar::mouseDoubleClickEvent(QMouseEvent *event) { + std::cout << "CDockAreaTitleBar::mouseDoubleClickEvent" << std::endl; // If this is the last dock area in a dock container it does not make // sense to move it to a new floating widget and leave this one // empty @@ -677,6 +679,26 @@ void CDockAreaTitleBar::mouseDoubleClickEvent(QMouseEvent *event) } +//============================================================================ +void CDockAreaTitleBar::setAreaFloating() +{ + // If this is the last dock area in a dock container it does not make + // sense to move it to a new floating widget and leave this one + // empty + if (d->DockArea->dockContainer()->isFloating() && d->DockArea->dockContainer()->dockAreaCount() == 1) + { + return; + } + + if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) + { + return; + } + + d->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive); +} + + //============================================================================ void CDockAreaTitleBar::contextMenuEvent(QContextMenuEvent* ev) { diff --git a/src/DockAreaTitleBar.h b/src/DockAreaTitleBar.h index a314640..76987a4 100644 --- a/src/DockAreaTitleBar.h +++ b/src/DockAreaTitleBar.h @@ -163,6 +163,12 @@ public: */ QString titleBarButtonToolTip(TitleBarButton Button) const; + /** + * Moves the dock area into its own floating widget if the area + * DockWidgetFloatable flag is true + */ + void setAreaFloating(); + Q_SIGNALS: /** * This signal is emitted if a tab in the tab bar is clicked by the user diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index c1d8d55..4cd8b86 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -1442,6 +1442,13 @@ bool CDockAreaWidget::isTopLevelArea() const } +//============================================================================ +void CDockAreaWidget::setFloating() +{ + d->TitleBar->setAreaFloating(); +} + + #ifdef Q_OS_WIN //============================================================================ bool CDockAreaWidget::event(QEvent *e) diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index a3ef76c..d95f519 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -414,6 +414,12 @@ public Q_SLOTS: */ void closeOtherAreas(); + /** + * Moves the dock area into its own floating widget if the area + * DockWidgetFloatable flag is true + */ + void setFloating(); + Q_SIGNALS: /** * This signal is emitted when user clicks on a tab at an index. diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index d04e839..096bc17 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -475,7 +475,6 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const auto DockArea = qobject_cast(d->TargetWidget.data()); if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) { - std::cout << d->Mode << " Find out side bar area " << std::endl; auto Rect = rect(); const QPoint pos = mapFromGlobal(QCursor::pos()); if (pos.x() < d->sideBarMouseZone(SideBarLeft)) @@ -488,7 +487,6 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const } else if (pos.y() < d->sideBarMouseZone(SideBarTop)) { - std::cout << d->Mode << " TopAutoHideArea " << std::endl; return TopAutoHideArea; } else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom))) @@ -534,14 +532,12 @@ DockWidgetArea CDockOverlay::visibleDropAreaUnderCursor() const //============================================================================ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) { - std::cout << d->Mode << " CDockOverlay::showOverlay()" << target << " " << target->objectName().toStdString() << std::endl; if (d->TargetWidget == target) { // Hint: We could update geometry of overlay here. DockWidgetArea da = dropAreaUnderCursor(); if (da != d->LastLocation) { - std::cout << d->Mode << " repaint()" << std::endl; repaint(); d->LastLocation = da; } @@ -566,7 +562,6 @@ DockWidgetArea CDockOverlay::showOverlay(QWidget* target) //============================================================================ void CDockOverlay::hideOverlay() { - std::cout << d->Mode << " CDockOverlay::hideOverlay()" << std::endl; hide(); d->TargetWidget.clear(); d->LastLocation = InvalidDockWidgetArea; @@ -578,7 +573,6 @@ void CDockOverlay::hideOverlay() void CDockOverlay::enableDropPreview(bool Enable) { d->DropPreviewEnabled = Enable; - std::cout << d->Mode << " update() " << Enable << std::endl; update(); } @@ -606,7 +600,6 @@ void CDockOverlay::paintEvent(QPaintEvent* event) double Factor = (CDockOverlay::ModeContainerOverlay == d->Mode) ? 3 : 2; - std::cout << "CDockOverlay::paintEvent da: " << da << std::endl; switch (da) { case TopDockWidgetArea: r.setHeight(r.height() / Factor); break; diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 9dde469..f16a187 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -1021,7 +1021,15 @@ void CDockWidget::setFloating() { return; } - d->TabWidget->detachDockWidget(); + + if (this->isAutoHide()) + { + dockAreaWidget()->setFloating(); + } + else + { + d->TabWidget->detachDockWidget(); + } } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 41db1d2..405ae46 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -499,10 +499,8 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent() return; } - if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() - != InvalidDockWidgetArea - || DockManager->containerOverlay()->dropAreaUnderCursor() - != InvalidDockWidgetArea) + if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea + || DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea) { CDockOverlay *Overlay = DockManager->containerOverlay(); if (!Overlay->dropOverlayRect().isValid()) @@ -510,21 +508,26 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent() Overlay = DockManager->dockAreaOverlay(); } - // Resize the floating widget to the size of the highlighted drop area - // rectangle - QRect Rect = Overlay->dropOverlayRect(); - int FrameWidth = (_this->frameSize().width() - _this->rect().width()) - / 2; - int TitleBarHeight = _this->frameSize().height() - - _this->rect().height() - FrameWidth; - if (Rect.isValid()) + // Do not resize if we drop into an autohide sidebar area to preserve + // the dock area size for the initial size of the auto hide area + if (!ads::internal::isSideBarArea(Overlay->dropAreaUnderCursor())) { - QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft()); - TopLeft.ry() += TitleBarHeight; - _this->setGeometry( - QRect(TopLeft, - QSize(Rect.width(), Rect.height() - TitleBarHeight))); - QApplication::processEvents(); + // Resize the floating widget to the size of the highlighted drop area + // rectangle + QRect Rect = Overlay->dropOverlayRect(); + int FrameWidth = (_this->frameSize().width() - _this->rect().width()) + / 2; + int TitleBarHeight = _this->frameSize().height() + - _this->rect().height() - FrameWidth; + if (Rect.isValid()) + { + QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft()); + TopLeft.ry() += TitleBarHeight; + _this->setGeometry( + QRect(TopLeft, + QSize(Rect.width(), Rect.height() - TitleBarHeight))); + QApplication::processEvents(); + } } DropContainer->dropFloatingWidget(_this, QCursor::pos()); } @@ -533,6 +536,7 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent() DockManager->dockAreaOverlay()->hideOverlay(); } + //============================================================================ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos) { From 4bdc04e9d873d96a1aa8fce0778143b2546a92ab Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 7 Jul 2023 13:35:55 +0200 Subject: [PATCH 09/27] Implemented Pin To functionality for Auto Hide Tabs --- src/AutoHideDockContainer.cpp | 21 +++++++++++-- src/AutoHideDockContainer.h | 17 +++++++++- src/AutoHideTab.cpp | 58 +++++++++++++++++++++++++---------- src/AutoHideTab.h | 4 ++- src/DockContainerWidget.cpp | 18 +++++------ src/DockContainerWidget.h | 2 +- src/DockOverlay.cpp | 4 +-- src/DockWidget.cpp | 28 ++++++++++++++++- src/DockWidget.h | 6 ++++ 9 files changed, 125 insertions(+), 33 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index c25d60b..cd87a5c 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -117,6 +117,7 @@ struct AutoHideDockContainerPrivate CResizeHandle* ResizeHandle = nullptr; QSize Size; // creates invalid size QPointer SideTab; + QSize OriginalDockWidgetSize; /** * Private data constructor @@ -214,7 +215,9 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL d->ResizeHandle->setMinResizeSize(64); bool OpaqueResize = CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize); d->ResizeHandle->setOpaqueResize(OpaqueResize); + std::cout << "d->DockArea->size(); " << d->DockArea->size().width() << std::endl; d->Size = d->DockArea->size(); + d->OriginalDockWidgetSize = DockWidget->size(); addDockWidget(DockWidget); parent->registerAutoHideWidget(this); @@ -303,7 +306,7 @@ CAutoHideDockContainer::~CAutoHideDockContainer() } //============================================================================ -CAutoHideSideBar* CAutoHideDockContainer::sideBar() const +CAutoHideSideBar* CAutoHideDockContainer::autoHideSideBar() const { if (d->SideTab) { @@ -312,7 +315,7 @@ CAutoHideSideBar* CAutoHideDockContainer::sideBar() const else { auto DockContainer = dockContainer(); - return DockContainer ? DockContainer->sideTabBar(d->SideTabBarArea) : nullptr; + return DockContainer ? DockContainer->autoHideSideBar(d->SideTabBarArea) : nullptr; } } @@ -657,5 +660,19 @@ bool CAutoHideDockContainer::event(QEvent* event) return Super::event(event); } + +//============================================================================ +QSize CAutoHideDockContainer::originalDockWidgetSize() const +{ + return d->OriginalDockWidgetSize; +} + + +//============================================================================ +Qt::Orientation CAutoHideDockContainer::orientation() const +{ + return autoHideSideBar()->orientation(); +} + } diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index d042b40..58b1c3e 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -93,7 +93,7 @@ public: /** * Get's the side tab bar */ - CAutoHideSideBar* sideBar() const; + CAutoHideSideBar* autoHideSideBar() const; /** * Returns the side tab @@ -166,6 +166,21 @@ public: * of this auto hide container. */ void setSize(int Size); + + /** + * Returns the original size of the dock widget at the time it has been + * added to this auto hide widget + */ + QSize originalDockWidgetSize() const; + + /** + * Returns orientation of this container. + * Left and right containers have a Qt::Vertical orientation and top / bottom + * containers have a Qt::Horizontal orientation. + * The function returns the orientation of the corresponding auto hide + * side bar. + */ + Qt::Orientation orientation() const; }; } // namespace ads diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index bee969b..ce807f3 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -42,6 +42,8 @@ namespace ads { +static const char* const LocationProperty = "Location"; + /** * Private data class of CDockWidgetTab class (pimpl) */ @@ -83,6 +85,20 @@ struct AutoHideTabPrivate DockContainer->handleAutoHideWidgetEvent(event, _this); } } + + /** + * Helper function to create and initialize the menu entries for + * the "Auto Hide Group To..." menu + */ + QAction* createAutoHideToAction(const QString& Title, SideBarLocation Location, + QMenu* Menu) + { + auto Action = Menu->addAction(Title); + Action->setProperty("Location", Location); + QObject::connect(Action, &QAction::triggered, _this, &CAutoHideTab::onAutoHideToActionClicked); + Action->setEnabled(Location != _this->sideBarLocation()); + return Action; + } }; // struct DockWidgetTabPrivate @@ -299,10 +315,10 @@ void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) auto menu = Menu.addMenu(tr("Pin To...")); menu->setEnabled(IsPinnable); - //d->createAutoHideToAction(tr("Top"), SideBarTop, menu); - //d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); - //d->createAutoHideToAction(tr("Right"), SideBarRight, menu); - //d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); + d->createAutoHideToAction(tr("Top"), SideBarTop, menu); + d->createAutoHideToAction(tr("Left"), SideBarLeft, menu); + d->createAutoHideToAction(tr("Right"), SideBarRight, menu); + d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); /*Menu.addSeparator(); Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); @@ -315,23 +331,33 @@ void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) } -//============================================================================ -void CAutoHideTab::mouseDoubleClickEvent(QMouseEvent *event) -{ - if (event->button() == Qt::LeftButton) - { - setDockWidgetFloating(); - } - - Super::mouseDoubleClickEvent(event); -} - - //============================================================================ void CAutoHideTab::setDockWidgetFloating() { + /*auto DockArea = dockWidget()->dockAreaWidget(); + auto AutoHideContainer = dockWidget()->autoHideDockContainer(); + auto OriginalSize = AutoHideContainer->originalDockWidgetSize(); + auto DockAreaSize = DockArea->size(); + if (ads::internal::isHorizontalSideBarLocation(sideBarLocation())) + { + DockAreaSize.setHeight(OriginalSize.height()); + } + else + { + DockAreaSize.setWidth(OriginalSize.width()); + } + DockArea->resize(DockAreaSize);*/ dockWidget()->setFloating(); } +//=========================================================================== +void CAutoHideTab::onAutoHideToActionClicked() +{ + int Location = sender()->property(LocationProperty).toInt(); + std::cout << "CAutoHideTab::onAutoHideToActionClicked " << Location << std::endl; + d->DockWidget->setAutoHide(true, (SideBarLocation)Location); +} + + } diff --git a/src/AutoHideTab.h b/src/AutoHideTab.h index 1e4a374..c9c6e0e 100644 --- a/src/AutoHideTab.h +++ b/src/AutoHideTab.h @@ -65,12 +65,14 @@ private: friend class CDockContainerWidget; friend DockContainerWidgetPrivate; +private Q_SLOTS: + void onAutoHideToActionClicked(); + protected: void setSideBar(CAutoHideSideBar *SideTabBar); void removeFromSideBar(); virtual bool event(QEvent* event) override; virtual void contextMenuEvent(QContextMenuEvent* ev) override; - virtual void mouseDoubleClickEvent(QMouseEvent *event) override; public: using Super = CPushButton; diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index daa1231..f968515 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -1156,12 +1156,12 @@ bool DockContainerWidgetPrivate::restoreSideBar(CDockingStateReader& s, continue; } - auto SideBar = _this->sideTabBar(Area); + auto SideBar = _this->autoHideSideBar(Area); CAutoHideDockContainer* AutoHideContainer; if (DockWidget->isAutoHide()) { AutoHideContainer = DockWidget->autoHideDockContainer(); - if (AutoHideContainer->sideBar() != SideBar) + if (AutoHideContainer->autoHideSideBar() != SideBar) { SideBar->addAutoHideWidget(AutoHideContainer); } @@ -1472,7 +1472,7 @@ CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer( DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager } - return sideTabBar(area)->insertDockWidget(-1, DockWidget); + return autoHideSideBar(area)->insertDockWidget(-1, DockWidget); } @@ -1731,7 +1731,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi // them into this widget for (auto AutohideWidget : FloatingWidget->dockContainer()->autoHideWidgets()) { - auto SideBar = sideTabBar(AutohideWidget->sideBarLocation()); + auto SideBar = autoHideSideBar(AutohideWidget->sideBarLocation()); SideBar->addAutoHideWidget(AutohideWidget); } @@ -2118,7 +2118,7 @@ void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea) } //============================================================================ -CAutoHideSideBar* CDockContainerWidget::sideTabBar(SideBarLocation area) const +CAutoHideSideBar* CDockContainerWidget::autoHideSideBar(SideBarLocation area) const { return d->SideTabBarWidgets[area]; } @@ -2140,10 +2140,10 @@ QRect CDockContainerWidget::contentRect() const { auto ContentRect = this->rect(); ContentRect.adjust( - sideTabBar(SideBarLeft)->sizeHint().width(), - sideTabBar(SideBarTop)->sizeHint().height(), - -sideTabBar(SideBarRight)->sizeHint().width(), - -sideTabBar(SideBarBottom)->sizeHint().height()); + autoHideSideBar(SideBarLeft)->sizeHint().width(), + autoHideSideBar(SideBarTop)->sizeHint().height(), + -autoHideSideBar(SideBarRight)->sizeHint().width(), + -autoHideSideBar(SideBarBottom)->sizeHint().height()); return ContentRect; } diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 2b080b4..6cc522b 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -329,7 +329,7 @@ public: /** * Returns the side tab widget for the given area */ - CAutoHideSideBar* sideTabBar(SideBarLocation area) const; + CAutoHideSideBar* autoHideSideBar(SideBarLocation area) const; /** diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 096bc17..127fd6e 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -370,7 +370,7 @@ struct DockOverlayCrossPrivate int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation) { auto Container = qobject_cast(TargetWidget.data()); - auto SideBar = Container->sideTabBar(sideBarLocation); + auto SideBar = Container->autoHideSideBar(sideBarLocation); if (!SideBar || !SideBar->isVisibleTo(Container)) { return AutoHideAreaWidth; @@ -386,7 +386,7 @@ int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation) int DockOverlayPrivate::sideBarMouseZone(SideBarLocation sideBarLocation) { auto Container = qobject_cast(TargetWidget.data()); - auto SideBar = Container->sideTabBar(sideBarLocation); + auto SideBar = Container->autoHideSideBar(sideBarLocation); if (!SideBar || !SideBar->isVisibleTo(Container)) { return AutoHideAreaMouseZone; diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index f16a187..a22bec2 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -555,6 +555,13 @@ bool CDockWidget::isAutoHide() const } +//============================================================================ +SideBarLocation CDockWidget::autoHideLocation() const +{ + return isAutoHide() ? autoHideDockContainer()->sideBarLocation() : SideBarNone; +} + + //============================================================================ bool CDockWidget::isFloating() const { @@ -1206,7 +1213,7 @@ void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) } // Do nothing if nothing changes - if (Enable == isAutoHide()) + if (Enable == isAutoHide() && Location == autoHideLocation()) { return; } @@ -1216,6 +1223,25 @@ void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) { DockArea->setAutoHide(false); } + else if (isAutoHide()) + { + auto AutoHideContainer = autoHideDockContainer(); + auto OldOrientation = AutoHideContainer->orientation(); + auto SideBar = dockContainer()->autoHideSideBar(Location); + SideBar->addAutoHideWidget(AutoHideContainer); + if (SideBar->orientation() != OldOrientation) + { + auto OriginalSize = AutoHideContainer->originalDockWidgetSize(); + if (SideBar->orientation() == Qt::Horizontal) + { + AutoHideContainer->setSize(OriginalSize.height()); + } + else + { + AutoHideContainer->setSize(OriginalSize.width()); + } + } + } else { auto area = (SideBarNone == Location) ? DockArea->calculateSideTabBarArea() : Location; diff --git a/src/DockWidget.h b/src/DockWidget.h index 43f8048..4e6b0c7 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -377,6 +377,12 @@ public: */ CAutoHideDockContainer* autoHideDockContainer() const; + /** + * Returns the auto hide side bar location or SideBarNone if, this is not + * an autohide dock widget + */ + SideBarLocation autoHideLocation() const; + /** * This property holds whether the dock widget is floating. * A dock widget is only floating, if it is the one and only widget inside From 4307f48d994ead83ff0bf1a96235caaac36d2f9b Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 7 Jul 2023 14:42:13 +0200 Subject: [PATCH 10/27] Implemented initial support for dragging auto hide tabs --- src/AutoHideTab.cpp | 239 +++++++++++++++++++++++++++++++++++++++++--- src/AutoHideTab.h | 3 + src/DockManager.h | 4 + 3 files changed, 230 insertions(+), 16 deletions(-) diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index ce807f3..5679186 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -39,6 +39,8 @@ #include "DockAreaWidget.h" #include "DockManager.h" #include "DockWidget.h" +#include "FloatingDragPreview.h" +#include "DockOverlay.h" namespace ads { @@ -54,6 +56,11 @@ struct AutoHideTabPrivate CAutoHideSideBar* SideBar = nullptr; Qt::Orientation Orientation{Qt::Vertical}; QElapsedTimer TimeSinceHoverMousePress; + bool MousePressed = false; + eDragState DragState = DraggingInactive; + QPoint GlobalDragStartMousePosition; + QPoint DragStartMousePosition; + IFloatingWidget* FloatingWidget = nullptr; /** * Private data constructor @@ -99,6 +106,41 @@ struct AutoHideTabPrivate Action->setEnabled(Location != _this->sideBarLocation()); return Action; } + + /** + * Test function for current drag state + */ + bool isDraggingState(eDragState dragState) const + { + return this->DragState == dragState; + } + + /** + * Saves the drag start position in global and local coordinates + */ + void saveDragStartMousePosition(const QPoint& GlobalPos) + { + GlobalDragStartMousePosition = GlobalPos; + DragStartMousePosition = _this->mapFromGlobal(GlobalPos); + } + + /** + * Starts floating of the dock widget that belongs to this title bar + * Returns true, if floating has been started and false if floating + * is not possible for any reason + */ + bool startFloating(eDragState DraggingState = DraggingFloatingWidget); + + template + IFloatingWidget* createFloatingWidget(T* Widget) + { + auto w = new CFloatingDragPreview(Widget); + _this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]() + { + DragState = DraggingInactive; + }); + return w; + } }; // struct DockWidgetTabPrivate @@ -127,6 +169,52 @@ void AutoHideTabPrivate::updateOrientation() } +//============================================================================ +bool AutoHideTabPrivate::startFloating(eDragState DraggingState) +{ + auto DockArea = DockWidget->dockAreaWidget(); + ADS_PRINT("isFloating " << dockContainer->isFloating()); + + ADS_PRINT("startFloating"); + DragState = DraggingState; + IFloatingWidget* FloatingWidget = nullptr; + FloatingWidget = createFloatingWidget(DockArea); + auto Size = DockArea->size(); + auto StartPos = DragStartMousePosition; + auto AutoHideContainer = DockWidget->autoHideDockContainer(); + switch (SideBar->sideBarLocation()) + { + case SideBarLeft: + StartPos.rx() = AutoHideContainer->rect().left() + 10; + break; + + case SideBarRight: + StartPos.rx() = AutoHideContainer->rect().right() - 10; + break; + + case SideBarTop: + StartPos.ry() = AutoHideContainer->rect().top() + 10; + break; + + case SideBarBottom: + StartPos.ry() = AutoHideContainer->rect().bottom() - 10; + break; + + case SideBarNone: + return false; + } + FloatingWidget->startFloating(StartPos, Size, DraggingFloatingWidget, _this); + auto DockManager = DockWidget->dockManager(); + auto Overlay = DockManager->containerOverlay(); + Overlay->setAllowedAreas(OuterDockAreas); + this->FloatingWidget = FloatingWidget; + qApp->postEvent(DockWidget, new QEvent((QEvent::Type)internal::DockedWidgetDragStartEvent)); + + return true; +} + + + //============================================================================ void CAutoHideTab::setSideBar(CAutoHideSideBar* SideTabBar) { @@ -267,22 +355,6 @@ bool CAutoHideTab::event(QEvent* event) d->forwardEventToDockContainer(event); break; - case QEvent::MouseButtonPress: - // If AutoHideShowOnMouseOver is active, then the showing is triggered - // by a MousePressEvent sent to this tab. To prevent accidental hiding - // of the tab by a mouse click, we wait at least 500 ms before we accept - // the mouse click - if (!event->spontaneous()) - { - d->TimeSinceHoverMousePress.restart(); - d->forwardEventToDockContainer(event); - } - else if (d->TimeSinceHoverMousePress.hasExpired(500)) - { - d->forwardEventToDockContainer(event); - } - break; - default: break; } @@ -360,4 +432,139 @@ void CAutoHideTab::onAutoHideToActionClicked() } +//============================================================================ +void CAutoHideTab::mousePressEvent(QMouseEvent* ev) +{ + // If AutoHideShowOnMouseOver is active, then the showing is triggered + // by a MousePressEvent sent to this tab. To prevent accidental hiding + // of the tab by a mouse click, we wait at least 500 ms before we accept + // the mouse click + if (!ev->spontaneous()) + { + d->TimeSinceHoverMousePress.restart(); + d->forwardEventToDockContainer(ev); + } + else if (d->TimeSinceHoverMousePress.hasExpired(500)) + { + d->forwardEventToDockContainer(ev); + } + + if (ev->button() == Qt::LeftButton) + { + ev->accept(); + d->MousePressed = true; + d->saveDragStartMousePosition(internal::globalPositionOf(ev)); + d->DragState = DraggingMousePressed; + } + Super::mousePressEvent(ev); +} + + + +//============================================================================ +void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev) +{ + if (ev->button() == Qt::LeftButton) + { + d->MousePressed = false; + auto CurrentDragState = d->DragState; + d->GlobalDragStartMousePosition = QPoint(); + d->DragStartMousePosition = QPoint(); + d->DragState = DraggingInactive; + + switch (CurrentDragState) + { + case DraggingTab: + // End of tab moving, emit signal + /*if (d->DockArea) + { + ev->accept(); + Q_EMIT moved(internal::globalPositionOf(ev)); + }*/ + break; + + case DraggingFloatingWidget: + ev->accept(); + d->FloatingWidget->finishDragging(); + break; + + default: + /*if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting)) + { + d->focusController()->setDockWidgetTabPressed(false); + }*/ + break; // do nothing + } + } + + Super::mouseReleaseEvent(ev); +} + + +//============================================================================ +void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev) +{ + std::cout << "CAutoHideTab::mouseMoveEvent" << std::endl; + if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) + { + d->DragState = DraggingInactive; + Super::mouseMoveEvent(ev); + return; + } + + // move floating window + if (d->isDraggingState(DraggingFloatingWidget)) + { + d->FloatingWidget->moveFloating(); + Super::mouseMoveEvent(ev); + return; + } + + // move tab + if (d->isDraggingState(DraggingTab)) + { + // Moving the tab is always allowed because it does not mean moving the + // dock widget around + //d->moveTab(ev); + } + + auto MappedPos = mapToParent(ev->pos()); + bool MouseOutsideBar = (MappedPos.x() < 0) || (MappedPos.x() > parentWidget()->rect().right()); + // Maybe a fixed drag distance is better here ? + int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - internal::globalPositionOf(ev).y()); + std::cout << "DragDistanceY " << DragDistanceY << " MouseOutsideBar " << MouseOutsideBar << std::endl; + if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar) + { + // Floating is only allowed for widgets that are floatable + // We can create the drag preview if the widget is movable. + auto Features = d->DockWidget->features(); + if (Features.testFlag(CDockWidget::DockWidgetFloatable) || (Features.testFlag(CDockWidget::DockWidgetMovable))) + { + // If we undock, we need to restore the initial position of this + // tab because it looks strange if it remains on its dragged position + /*if (d->isDraggingState(DraggingTab)) + { + parentWidget()->layout()->update(); + }*/ + d->startFloating(); + } + return; + } + /*else if (d->DockArea->openDockWidgetsCount() > 1 + && (internal::globalPositionOf(ev) - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving + { + // If we start dragging the tab, we save its inital position to + // restore it later + if (DraggingTab != d->DragState) + { + d->TabDragStartPosition = this->pos(); + } + d->DragState = DraggingTab; + return; + }*/ + + Super::mouseMoveEvent(ev); +} + + } diff --git a/src/AutoHideTab.h b/src/AutoHideTab.h index c9c6e0e..f883b5b 100644 --- a/src/AutoHideTab.h +++ b/src/AutoHideTab.h @@ -73,6 +73,9 @@ protected: void removeFromSideBar(); virtual bool event(QEvent* event) override; virtual void contextMenuEvent(QContextMenuEvent* ev) override; + virtual void mousePressEvent(QMouseEvent* ev) override; + virtual void mouseReleaseEvent(QMouseEvent* ev) override; + virtual void mouseMoveEvent(QMouseEvent* ev) override; public: using Super = CPushButton; diff --git a/src/DockManager.h b/src/DockManager.h index 8085f1c..55894fc 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -55,6 +55,8 @@ class CIconProvider; class CDockComponentsFactory; class CDockFocusController; class CAutoHideSideBar; +class CAutoHideTab; +struct AutoHideTabPrivate; /** * The central dock manager that maintains the complete docking system. @@ -87,6 +89,8 @@ private: friend class CDockAreaTitleBar; friend class CAutoHideDockContainer; friend CAutoHideSideBar; + friend CAutoHideTab; + friend AutoHideTabPrivate; public Q_SLOTS: /** From bf22e54fc36d58563d47aa7c35ed698d021a81dd Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Fri, 7 Jul 2023 15:20:43 +0200 Subject: [PATCH 11/27] Improved support for AutoHideTab drag and drop --- src/AutoHideDockContainer.cpp | 24 ++++++++++++--- src/AutoHideDockContainer.h | 11 ++++++- src/AutoHideTab.cpp | 57 ++++++----------------------------- src/DockOverlay.cpp | 10 ------ src/DockWidget.cpp | 13 +++----- 5 files changed, 43 insertions(+), 72 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index cd87a5c..535ff2b 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -117,7 +117,7 @@ struct AutoHideDockContainerPrivate CResizeHandle* ResizeHandle = nullptr; QSize Size; // creates invalid size QPointer SideTab; - QSize OriginalDockWidgetSize; + QSize InitialDockWidgetSize; /** * Private data constructor @@ -197,6 +197,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL Super(parent), d(new AutoHideDockContainerPrivate(this)) { + std::cout << "CAutoHideDockContainer::constructor" << std::endl; hide(); // auto hide dock container is initially always hidden d->SideTabBarArea = area; d->SideTab = componentsFactory()->createDockWidgetSideTab(nullptr); @@ -217,7 +218,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL d->ResizeHandle->setOpaqueResize(OpaqueResize); std::cout << "d->DockArea->size(); " << d->DockArea->size().width() << std::endl; d->Size = d->DockArea->size(); - d->OriginalDockWidgetSize = DockWidget->size(); + d->InitialDockWidgetSize = DockWidget->size(); addDockWidget(DockWidget); parent->registerAutoHideWidget(this); @@ -662,9 +663,9 @@ bool CAutoHideDockContainer::event(QEvent* event) //============================================================================ -QSize CAutoHideDockContainer::originalDockWidgetSize() const +QSize CAutoHideDockContainer::initialDockWidgetSize() const { - return d->OriginalDockWidgetSize; + return d->InitialDockWidgetSize; } @@ -674,5 +675,20 @@ Qt::Orientation CAutoHideDockContainer::orientation() const return autoHideSideBar()->orientation(); } + +//============================================================================ +void CAutoHideDockContainer::resetToInitialDockWidgetSize() +{ + auto OriginalSize = initialDockWidgetSize(); + if (orientation() == Qt::Horizontal) + { + setSize(OriginalSize.height()); + } + else + { + setSize(OriginalSize.width()); + } +} + } diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index 58b1c3e..7ff6ac9 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -171,7 +171,16 @@ public: * Returns the original size of the dock widget at the time it has been * added to this auto hide widget */ - QSize originalDockWidgetSize() const; + QSize initialDockWidgetSize() const; + + /** + * Resets the with or hight to the initial dock widget size dependinng on + * the orientation. + * If the orientation is Qt::Horizontal, then the height is reset to + * the initial size and if orientation is Qt::Vertical, then the width is + * reset to the initial size + */ + void resetToInitialDockWidgetSize(); /** * Returns orientation of this container. diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index 5679186..e311ff7 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -61,6 +61,7 @@ struct AutoHideTabPrivate QPoint GlobalDragStartMousePosition; QPoint DragStartMousePosition; IFloatingWidget* FloatingWidget = nullptr; + Qt::Orientation DragStartOrientation; /** * Private data constructor @@ -182,6 +183,7 @@ bool AutoHideTabPrivate::startFloating(eDragState DraggingState) auto Size = DockArea->size(); auto StartPos = DragStartMousePosition; auto AutoHideContainer = DockWidget->autoHideDockContainer(); + DragStartOrientation = AutoHideContainer->orientation(); switch (SideBar->sideBarLocation()) { case SideBarLeft: @@ -373,13 +375,12 @@ bool CAutoHideTab::iconOnly() const void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) { ev->accept(); - //d->saveDragStartMousePosition(ev->globalPos()); + d->saveDragStartMousePosition(ev->globalPos()); const bool isFloatable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable); QAction* Action; QMenu Menu(this); - Action = Menu.addAction(tr("Detach"), this, SLOT(setDockWidgetFloating())); Action->setEnabled(isFloatable); auto IsPinnable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable); @@ -392,13 +393,6 @@ void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) d->createAutoHideToAction(tr("Right"), SideBarRight, menu); d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); - /*Menu.addSeparator(); - Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested())); - Action->setEnabled(isClosable()); - if (d->DockArea->openDockWidgetsCount() > 1) - { - Action = Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested())); - }*/ Menu.exec(ev->globalPos()); } @@ -406,19 +400,6 @@ void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) //============================================================================ void CAutoHideTab::setDockWidgetFloating() { - /*auto DockArea = dockWidget()->dockAreaWidget(); - auto AutoHideContainer = dockWidget()->autoHideDockContainer(); - auto OriginalSize = AutoHideContainer->originalDockWidgetSize(); - auto DockAreaSize = DockArea->size(); - if (ads::internal::isHorizontalSideBarLocation(sideBarLocation())) - { - DockAreaSize.setHeight(OriginalSize.height()); - } - else - { - DockAreaSize.setWidth(OriginalSize.width()); - } - DockArea->resize(DockAreaSize);*/ dockWidget()->setFloating(); } @@ -427,7 +408,6 @@ void CAutoHideTab::setDockWidgetFloating() void CAutoHideTab::onAutoHideToActionClicked() { int Location = sender()->property(LocationProperty).toInt(); - std::cout << "CAutoHideTab::onAutoHideToActionClicked " << Location << std::endl; d->DockWidget->setAutoHide(true, (SideBarLocation)Location); } @@ -484,15 +464,16 @@ void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev) break; case DraggingFloatingWidget: + std::cout << "CAutoHideTab::mouseReleaseEvent" << std::endl; ev->accept(); d->FloatingWidget->finishDragging(); + if (d->DockWidget->isAutoHide() && d->DragStartOrientation != orientation()) + { + d->DockWidget->autoHideDockContainer()->resetToInitialDockWidgetSize(); + } break; default: - /*if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting)) - { - d->focusController()->setDockWidgetTabPressed(false); - }*/ break; // do nothing } } @@ -504,7 +485,6 @@ void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev) //============================================================================ void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev) { - std::cout << "CAutoHideTab::mouseMoveEvent" << std::endl; if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) { d->DragState = DraggingInactive; @@ -532,7 +512,6 @@ void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev) bool MouseOutsideBar = (MappedPos.x() < 0) || (MappedPos.x() > parentWidget()->rect().right()); // Maybe a fixed drag distance is better here ? int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - internal::globalPositionOf(ev).y()); - std::cout << "DragDistanceY " << DragDistanceY << " MouseOutsideBar " << MouseOutsideBar << std::endl; if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar) { // Floating is only allowed for widgets that are floatable @@ -540,30 +519,12 @@ void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev) auto Features = d->DockWidget->features(); if (Features.testFlag(CDockWidget::DockWidgetFloatable) || (Features.testFlag(CDockWidget::DockWidgetMovable))) { - // If we undock, we need to restore the initial position of this - // tab because it looks strange if it remains on its dragged position - /*if (d->isDraggingState(DraggingTab)) - { - parentWidget()->layout()->update(); - }*/ d->startFloating(); } return; } - /*else if (d->DockArea->openDockWidgetsCount() > 1 - && (internal::globalPositionOf(ev) - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving - { - // If we start dragging the tab, we save its inital position to - // restore it later - if (DraggingTab != d->DragState) - { - d->TabDragStartPosition = this->pos(); - } - d->DragState = DraggingTab; - return; - }*/ - Super::mouseMoveEvent(ev); + Super::mouseMoveEvent(ev); } diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 127fd6e..acf0690 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -209,11 +209,6 @@ struct DockOverlayCrossPrivate CDockOverlay::eMode Mode) { QColor borderColor = iconColor(CDockOverlayCross::FrameColor); - // TODO: remove, this is just for debugging - if (Mode == CDockOverlay::ModeContainerOverlay) - { - borderColor = Qt::red; - } QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor); QColor overlayColor = iconColor(CDockOverlayCross::OverlayColor); if (overlayColor.alpha() == 255) @@ -615,11 +610,6 @@ void CDockOverlay::paintEvent(QPaintEvent* event) } QPainter painter(this); QColor Color = palette().color(QPalette::Active, QPalette::Highlight); - // TODO: This is just for debugging - remove later - if (d->Mode == CDockOverlay::ModeContainerOverlay) - { - Color = Qt::red; - } QPen Pen = painter.pen(); Pen.setColor(Color.darker(120)); Pen.setStyle(Qt::SolidLine); diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index a22bec2..9327e2c 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -1229,17 +1229,12 @@ void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) auto OldOrientation = AutoHideContainer->orientation(); auto SideBar = dockContainer()->autoHideSideBar(Location); SideBar->addAutoHideWidget(AutoHideContainer); + // If we move a horizontal auto hide container to a vertical position + // then we resize it to the orginal dock widget size, to avoid + // an extremely streched dock widget after insertion if (SideBar->orientation() != OldOrientation) { - auto OriginalSize = AutoHideContainer->originalDockWidgetSize(); - if (SideBar->orientation() == Qt::Horizontal) - { - AutoHideContainer->setSize(OriginalSize.height()); - } - else - { - AutoHideContainer->setSize(OriginalSize.width()); - } + AutoHideContainer->resetToInitialDockWidgetSize(); } } else From 0a6c58fd6615cb59640e779adf11df1ea00f98f2 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 10 Jul 2023 09:34:11 +0200 Subject: [PATCH 12/27] Properly implemented drag and drop of auto hide tabs --- src/AutoHideDockContainer.cpp | 22 ++++++++++++++++++++++ src/AutoHideDockContainer.h | 6 ++++++ src/DockAreaWidget.cpp | 9 ++++++++- src/DockAreaWidget.h | 1 - src/DockContainerWidget.cpp | 28 ++++++++++++++++++++++------ src/DockWidget.cpp | 13 ++----------- src/FloatingDragPreview.cpp | 25 +++++++++++++++++++------ src/FloatingDragPreview.h | 2 +- 8 files changed, 80 insertions(+), 26 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 535ff2b..43df868 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -411,6 +411,7 @@ void CAutoHideDockContainer::moveContentsToParent() //============================================================================ void CAutoHideDockContainer::cleanupAndDelete() { + std::cout << "CAutoHideDockContainer::cleanupAndDelete()" << std::endl; const auto dockWidget = d->DockWidget; if (dockWidget) { @@ -690,5 +691,26 @@ void CAutoHideDockContainer::resetToInitialDockWidgetSize() } } + +//============================================================================ +void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBarLocation) +{ + if (NewSideBarLocation == sideBarLocation()) + { + return; + } + + auto OldOrientation = orientation(); + auto SideBar = dockContainer()->autoHideSideBar(NewSideBarLocation); + SideBar->addAutoHideWidget(this); + // If we move a horizontal auto hide container to a vertical position + // then we resize it to the orginal dock widget size, to avoid + // an extremely streched dock widget after insertion + if (SideBar->orientation() != OldOrientation) + { + resetToInitialDockWidgetSize(); + } +} + } diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index 7ff6ac9..3183682 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -190,6 +190,12 @@ public: * side bar. */ Qt::Orientation orientation() const; + + /** + * Removes the AutoHide container from the current side bar and adds + * it to the new side bar given in SideBarLocation + */ + void moveToNewSideBarLocation(SideBarLocation SideBarLocation); }; } // namespace ads diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 4cd8b86..8b1bdc8 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -1323,11 +1323,18 @@ void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location) { if (isAutoHide()) { - autoHideDockContainer()->moveContentsToParent(); + d->AutoHideDockContainer->moveContentsToParent(); } return; } + // If this is already an auto hide container, then move it to new location + if (isAutoHide()) + { + d->AutoHideDockContainer->moveToNewSideBarLocation(Location); + return; + } + auto area = (SideBarNone == Location) ? calculateSideTabBarArea() : Location; for (const auto DockWidget : openedDockWidgets()) { diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index d95f519..f1412e8 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -221,7 +221,6 @@ public: */ bool isAutoHide() const; - /** * Sets the current auto hide dock container */ diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index f968515..0655ce2 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -776,18 +776,34 @@ void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidg if (DroppedDockWidget) { - _this->createAndSetupAutoHideContainer(SideBarLocation, DroppedDockWidget); + if (_this == DroppedDockWidget->dockContainer()) + { + DroppedDockWidget->setAutoHide(true, SideBarLocation); + } + else + { + _this->createAndSetupAutoHideContainer(SideBarLocation, DroppedDockWidget); + } } else { - for (const auto DockWidget : DroppedDockArea->openedDockWidgets()) + if (_this == DroppedDockArea->dockContainer()) { - if (!DockWidget->features().testFlag(CDockWidget::DockWidgetPinnable)) + DroppedDockArea->setAutoHide(true, SideBarLocation); + } + else + { + for (const auto DockWidget : DroppedDockArea->openedDockWidgets()) { - continue; - } + if (!DockWidget->features().testFlag( + CDockWidget::DockWidgetPinnable)) + { + continue; + } - _this->createAndSetupAutoHideContainer(SideBarLocation, DockWidget); + _this->createAndSetupAutoHideContainer(SideBarLocation, + DockWidget); + } } } } diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index 9327e2c..af00a50 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -1219,23 +1219,14 @@ void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) } auto DockArea = dockAreaWidget(); + if (!Enable) { DockArea->setAutoHide(false); } else if (isAutoHide()) { - auto AutoHideContainer = autoHideDockContainer(); - auto OldOrientation = AutoHideContainer->orientation(); - auto SideBar = dockContainer()->autoHideSideBar(Location); - SideBar->addAutoHideWidget(AutoHideContainer); - // If we move a horizontal auto hide container to a vertical position - // then we resize it to the orginal dock widget size, to avoid - // an extremely streched dock widget after insertion - if (SideBar->orientation() != OldOrientation) - { - AutoHideContainer->resetToInitialDockWidgetSize(); - } + autoHideDockContainer()->moveToNewSideBarLocation(Location); } else { diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 7291b2c..5e52a09 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -22,6 +22,8 @@ #include "DockManager.h" #include "DockContainerWidget.h" #include "DockOverlay.h" +#include "AutoHideDockContainer.h" +#include "ads_globals.h" namespace ads { @@ -373,7 +375,7 @@ void CFloatingDragPreview::finishDragging() // state if they are dragged into a floating window if (ValidDropArea || d->isContentFloatable()) { - cleanupAutoHideContainerWidget(); + cleanupAutoHideContainerWidget(ContainerDropArea); } if (!d->DropContainer) @@ -408,18 +410,29 @@ void CFloatingDragPreview::finishDragging() //============================================================================ -void CFloatingDragPreview::cleanupAutoHideContainerWidget() +void CFloatingDragPreview::cleanupAutoHideContainerWidget(DockWidgetArea ContainerDropArea) { auto DroppedDockWidget = qobject_cast(d->Content); auto DroppedArea = qobject_cast(d->Content); - if (DroppedDockWidget && DroppedDockWidget->autoHideDockContainer()) + auto AutoHideContainer = DroppedDockWidget + ? DroppedDockWidget->autoHideDockContainer() + : DroppedArea->autoHideDockContainer(); + + if (!AutoHideContainer) { - DroppedDockWidget->autoHideDockContainer()->cleanupAndDelete(); + return; } - if (DroppedArea && DroppedArea->autoHideDockContainer()) + + // If the dropped widget is already an auto hide widget and if it is moved + // to a new side bar location in the same container, then we do not need + // to cleanup + if (ads::internal::isSideBarArea(ContainerDropArea) + && (d->DropContainer == AutoHideContainer->dockContainer())) { - DroppedArea->autoHideDockContainer()->cleanupAndDelete(); + return; } + + AutoHideContainer->cleanupAndDelete(); } diff --git a/src/FloatingDragPreview.h b/src/FloatingDragPreview.h index 236f80e..68e3e5c 100644 --- a/src/FloatingDragPreview.h +++ b/src/FloatingDragPreview.h @@ -95,7 +95,7 @@ public: // implements IFloatingWidget ----------------------------------------- /** * Cleanup auto hide container if the dragged widget has one */ - void cleanupAutoHideContainerWidget(); + void cleanupAutoHideContainerWidget(DockWidgetArea ContainerDropArea); Q_SIGNALS: /** From 6924e69b6badd737690c1ecc559a1b320b251684 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 10 Jul 2023 10:10:37 +0200 Subject: [PATCH 13/27] Fixed detaching of auto hide widgets in a floating widget --- src/DockAreaTitleBar.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index defb664..3950739 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -684,8 +684,10 @@ void CDockAreaTitleBar::setAreaFloating() { // If this is the last dock area in a dock container it does not make // sense to move it to a new floating widget and leave this one - // empty - if (d->DockArea->dockContainer()->isFloating() && d->DockArea->dockContainer()->dockAreaCount() == 1) + // empty. + auto DockContainer = d->DockArea->dockContainer(); + if (DockContainer->isFloating() && DockContainer->dockAreaCount() == 1 + && !d->DockArea->isAutoHide()) { return; } From df1bc94d9ee2c950c5ae67d88bbb58405a2ab49c Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 10 Jul 2023 10:18:09 +0200 Subject: [PATCH 14/27] Added Auto-Hide tab unpin context menu entry --- src/AutoHideTab.cpp | 11 ++++++++++- src/AutoHideTab.h | 5 +++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index e311ff7..d926902 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -393,6 +393,8 @@ void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) d->createAutoHideToAction(tr("Right"), SideBarRight, menu); d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); + Action = Menu.addAction(tr("Unpin (Dock)"), this, SLOT(unpinDockWidget())); + Menu.exec(ev->globalPos()); } @@ -400,7 +402,14 @@ void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) //============================================================================ void CAutoHideTab::setDockWidgetFloating() { - dockWidget()->setFloating(); + d->DockWidget->setFloating(); +} + + +//============================================================================ +void CAutoHideTab::unpinDockWidget() +{ + d->DockWidget->setAutoHide(false); } diff --git a/src/AutoHideTab.h b/src/AutoHideTab.h index f883b5b..8e94c45 100644 --- a/src/AutoHideTab.h +++ b/src/AutoHideTab.h @@ -145,6 +145,11 @@ public Q_SLOTS: * Set the dock widget floating, if it is floatable */ void setDockWidgetFloating(); + + /** + * Unpin and dock the auto hide widget + */ + void unpinDockWidget(); }; // class AutoHideTab } // namespace ads From 0627b3183f0531aa85f3369a999d6708a2c57b99 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 10 Jul 2023 10:38:21 +0200 Subject: [PATCH 15/27] Added "Close" action to AutoHideTab context menu --- src/AutoHideTab.cpp | 10 ++++++++++ src/AutoHideTab.h | 5 +++++ src/DockAreaWidget.cpp | 10 +--------- src/DockWidget.cpp | 16 ++++++++++++++++ src/DockWidget.h | 11 ++++++++++- 5 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index d926902..0acb737 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -394,6 +394,9 @@ void CAutoHideTab::contextMenuEvent(QContextMenuEvent* ev) d->createAutoHideToAction(tr("Bottom"), SideBarBottom, menu); Action = Menu.addAction(tr("Unpin (Dock)"), this, SLOT(unpinDockWidget())); + Menu.addSeparator(); + Action = Menu.addAction(tr("Close"), this, SLOT(requestCloseDockWidget())); + Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable)); Menu.exec(ev->globalPos()); } @@ -537,4 +540,11 @@ void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev) } +//============================================================================ +void CAutoHideTab::requestCloseDockWidget() +{ + d->DockWidget->requestCloseDockWidget(); +} + + } diff --git a/src/AutoHideTab.h b/src/AutoHideTab.h index 8e94c45..cf0d143 100644 --- a/src/AutoHideTab.h +++ b/src/AutoHideTab.h @@ -150,6 +150,11 @@ public Q_SLOTS: * Unpin and dock the auto hide widget */ void unpinDockWidget(); + + /** + * Calls the requestCloseDockWidget() function for the assigned dock widget + */ + void requestCloseDockWidget(); }; // class AutoHideTab } // namespace ads diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 8b1bdc8..95309c6 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -626,15 +626,7 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent() void CDockAreaWidget::onTabCloseRequested(int Index) { ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index); - auto* DockWidget = dockWidget(Index); - if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) || DockWidget->features().testFlag(CDockWidget::CustomCloseHandling)) - { - DockWidget->closeDockWidgetInternal(); - } - else - { - DockWidget->toggleView(false); - } + dockWidget(Index)->requestCloseDockWidget(); } diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index af00a50..a180cf6 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -1059,6 +1059,22 @@ void CDockWidget::closeDockWidget() } + +//============================================================================ +void CDockWidget::requestCloseDockWidget() +{ + if (features().testFlag(CDockWidget::DockWidgetDeleteOnClose) + || features().testFlag(CDockWidget::CustomCloseHandling)) + { + closeDockWidgetInternal(false); + } + else + { + toggleView(false); + } +} + + //============================================================================ bool CDockWidget::closeDockWidgetInternal(bool ForceClose) { diff --git a/src/DockWidget.h b/src/DockWidget.h index 4e6b0c7..188c14b 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -584,10 +584,19 @@ public Q_SLOTS: void deleteDockWidget(); /** - * Closes the dock widget + * Closes the dock widget. + * The function forces closing of the dock widget even for CustomCloseHandling. */ void closeDockWidget(); + /** + * Request closing of the dock widget. + * For DockWidget with default close handling, the function does the same + * like clodeDockWidget() but if the flas CustomCloseHandling is set, + * the function only emits the closeRequested() signal. + */ + void requestCloseDockWidget(); + /** * Shows the widget in full-screen mode. * Normally this function only affects windows. To make the interface From 8a82e4cf577501622c24d1bdcc1b08f9728b4de0 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Mon, 10 Jul 2023 12:07:44 +0200 Subject: [PATCH 16/27] Removed debug output and fixed painting of SideBar drag overlays --- src/DockOverlay.cpp | 2 ++ src/FloatingDragPreview.cpp | 11 +---------- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index acf0690..800756b 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -583,6 +583,7 @@ bool CDockOverlay::dropPreviewEnabled() const void CDockOverlay::paintEvent(QPaintEvent* event) { Q_UNUSED(event); + // Draw rect based on location if (!d->DropPreviewEnabled) { @@ -608,6 +609,7 @@ void CDockOverlay::paintEvent(QPaintEvent* event) case BottomAutoHideArea: r.setY(r.height() - d->sideBarOverlaySize(SideBarBottom)); break; default: return; } + QPainter painter(this); QColor Color = palette().color(QPalette::Active, QPalette::Highlight); QPen Pen = painter.pen(); diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 5e52a09..ff69e6f 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -103,7 +103,6 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) { if (!_this->isVisible() || !DockManager) { - std::cout << "return 1" << std::endl; return; } @@ -132,13 +131,10 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) if (!TopContainer) { - std::cout << "ContainerOverlay->hideOverlay() 1" << std::endl; ContainerOverlay->hideOverlay(); - std::cout << "DockAreaOverlay->hideOverlay() 1" << std::endl; DockAreaOverlay->hideOverlay(); if (CDockManager::testConfigFlag(CDockManager::DragPreviewIsDynamic)) { - std::cout << "return 2" << std::endl; setHidden(false); } return; @@ -155,7 +151,6 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) { VisibleDockAreas++; } - std::cout << "VisibleDockAreas " << VisibleDockAreas << std::endl; DockWidgetAreas AllowedAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas; //ContainerOverlay->enableDropPreview(ContainerDropArea != InvalidDockWidgetArea); @@ -168,12 +163,12 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) AllowedAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea)); } ContainerOverlay->setAllowedAreas(AllowedAreas); + ContainerOverlay->enableDropPreview(ContainerDropArea != InvalidDockWidgetArea); if (DockArea && DockArea->isVisible() && VisibleDockAreas >= 0 && DockArea != ContentSourceArea) { DockAreaOverlay->enableDropPreview(true); DockAreaOverlay->setAllowedAreas( (VisibleDockAreas == 1) ? NoDockWidgetArea : DockArea->allowedAreas()); DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea); - std::cout << "DockWidgetArea " << Area << std::endl; // A CenterDockWidgetArea for the dockAreaOverlay() indicates that // the mouse is in the title bar. If the ContainerArea is valid @@ -182,20 +177,16 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) if ((Area == CenterDockWidgetArea) && (ContainerDropArea != InvalidDockWidgetArea)) { DockAreaOverlay->enableDropPreview(false); - - std::cout << "ContainerOverlay->enableDropPreview(true) 1" << std::endl; ContainerOverlay->enableDropPreview(true); } else { - std::cout << "ContainerOverlay->enableDropPreview 2" << std::endl; ContainerOverlay->enableDropPreview(InvalidDockWidgetArea == Area); } ContainerOverlay->showOverlay(TopContainer); } else { - std::cout << "DockAreaOverlay->hideOverlay() 2" << std::endl; DockAreaOverlay->hideOverlay(); // If there is only one single visible dock area in a container, then // it does not make sense to show a dock overlay because the dock area From 2760fb1fe980219722d39a020f5af9b2fbd34660 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 11 Jul 2023 08:25:34 +0200 Subject: [PATCH 17/27] AutoHide dock area now always shows pin button independently from DockAreaHasAutoHideButton flag --- src/DockAreaTitleBar.cpp | 28 +++++++++++++++++++-------- src/DockAreaTitleBar.h | 41 +++++++++++++++++++++++++++++++++++++++- src/DockAreaTitleBar_p.h | 31 ------------------------------ src/DockAreaWidget.cpp | 1 + 4 files changed, 61 insertions(+), 40 deletions(-) diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 3950739..20554f8 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -68,10 +68,10 @@ static const char* const LocationProperty = "Location"; struct DockAreaTitleBarPrivate { CDockAreaTitleBar* _this; - QPointer TabsMenuButton; - QPointer AutoHideButton; - QPointer UndockButton; - QPointer CloseButton; + QPointer TabsMenuButton; + QPointer AutoHideButton; + QPointer UndockButton; + QPointer CloseButton; QBoxLayout* Layout; CDockAreaWidget* DockArea; CDockAreaTabBar* TabBar; @@ -540,7 +540,7 @@ void CDockAreaTitleBar::onAutoHideToActionClicked() //============================================================================ -QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const +CTitleBarButton* CDockAreaTitleBar::button(TitleBarButton which) const { switch (which) { @@ -805,9 +805,9 @@ QString CDockAreaTitleBar::titleBarButtonToolTip(TitleBarButton Button) const } //============================================================================ -CTitleBarButton::CTitleBarButton(bool visible, QWidget* parent) +CTitleBarButton::CTitleBarButton(bool showInTitleBar, QWidget* parent) : tTitleBarButton(parent), - Visible(visible), + ShowInTitleBar(showInTitleBar), HideWhenDisabled(CDockManager::testConfigFlag(CDockManager::DockAreaHideDisabledButtons)) { setFocusPolicy(Qt::NoFocus); @@ -817,7 +817,7 @@ CTitleBarButton::CTitleBarButton(bool visible, QWidget* parent) void CTitleBarButton::setVisible(bool visible) { // 'visible' can stay 'true' if and only if this button is configured to generaly visible: - visible = visible && this->Visible; + visible = visible && this->ShowInTitleBar; // 'visible' can stay 'true' unless: this button is configured to be invisible when it is disabled and it is currently disabled: if (visible && HideWhenDisabled) @@ -828,6 +828,18 @@ void CTitleBarButton::setVisible(bool visible) Super::setVisible(visible); } + +//============================================================================ +void CTitleBarButton::setShowInTitleBar(bool Show) +{ + this->ShowInTitleBar = Show; + if (!Show) + { + setVisible(false); + } +} + + //============================================================================ bool CTitleBarButton::event(QEvent *ev) { diff --git a/src/DockAreaTitleBar.h b/src/DockAreaTitleBar.h index 76987a4..46ac231 100644 --- a/src/DockAreaTitleBar.h +++ b/src/DockAreaTitleBar.h @@ -30,6 +30,7 @@ //============================================================================ // INCLUDES //============================================================================ +#include #include #include "ads_globals.h" @@ -43,6 +44,44 @@ class CDockAreaWidget; struct DockAreaTitleBarPrivate; class CElidingLabel; +using tTitleBarButton = QToolButton; + +/** +* Title bar button of a dock area that customizes tTitleBarButton appearance/behaviour +* according to various config flags such as: +* CDockManager::DockAreaHas_xxx_Button - if set to 'false' keeps the button always invisible +* CDockManager::DockAreaHideDisabledButtons - if set to 'true' hides button when it is disabled +*/ +class CTitleBarButton : public tTitleBarButton +{ + Q_OBJECT + +private: + bool ShowInTitleBar = true; + bool HideWhenDisabled = false; + +public: + using Super = tTitleBarButton; + CTitleBarButton(bool ShowInTitleBar = true, QWidget* parent = nullptr); + + /** + * Adjust this visibility change request with our internal settings: + */ + virtual void setVisible(bool visible) override; + + /** + * Configures, if the title bar button should be shown in title bar + */ + void setShowInTitleBar(bool Show); + +protected: + /** + * Handle EnabledChanged signal to set button invisible if the configured + */ + bool event(QEvent *ev) override; +}; + + /** * Title bar of a dock area. * The title bar contains a tabbar with all tabs for a dock widget group and @@ -121,7 +160,7 @@ public: /** * Returns the button corresponding to the given title bar button identifier */ - QAbstractButton* button(TitleBarButton which) const; + CTitleBarButton* button(TitleBarButton which) const; /** * Returns the auto hide title label, used when the dock area is expanded and auto hidden diff --git a/src/DockAreaTitleBar_p.h b/src/DockAreaTitleBar_p.h index b94a510..599c45f 100644 --- a/src/DockAreaTitleBar_p.h +++ b/src/DockAreaTitleBar_p.h @@ -31,43 +31,12 @@ // INCLUDES //============================================================================ #include -#include #include "ads_globals.h" namespace ads { -using tTitleBarButton = QToolButton; -/** -* Title bar button of a dock area that customizes tTitleBarButton appearance/behaviour -* according to various config flags such as: -* CDockManager::DockAreaHas_xxx_Button - if set to 'false' keeps the button always invisible -* CDockManager::DockAreaHideDisabledButtons - if set to 'true' hides button when it is disabled -*/ -class CTitleBarButton : public tTitleBarButton -{ - Q_OBJECT - -private: - bool Visible = true; - bool HideWhenDisabled = false; - -public: - using Super = tTitleBarButton; - CTitleBarButton(bool visible = true, QWidget* parent = nullptr); - - /** - * Adjust this visibility change request with our internal settings: - */ - virtual void setVisible(bool visible) override; - -protected: - /** - * Handle EnabledChanged signal to set button invisible if the configured - */ - bool event(QEvent *ev) override; -}; /** diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 95309c6..29186a2 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -467,6 +467,7 @@ void CDockAreaWidget::setAutoHideDockContainer(CAutoHideDockContainer* AutoHideD d->AutoHideDockContainer = AutoHideDockContainer; updateAutoHideButtonCheckState(); updateTitleBarButtonsToolTips(); + d->TitleBar->button(TitleBarButtonAutoHide)->setShowInTitleBar(true); } From cb5e9f60a1e7ef72627d674932d787c759ba0abf Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 11 Jul 2023 08:26:03 +0200 Subject: [PATCH 18/27] Changed default auto hide config - added flag AutoHideCloseButtonCollapsesDock --- src/DockManager.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/DockManager.h b/src/DockManager.h index 55894fc..8f24bec 100644 --- a/src/DockManager.h +++ b/src/DockManager.h @@ -252,7 +252,9 @@ public: AutoHideCloseButtonCollapsesDock = 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely DefaultAutoHideConfig = AutoHideFeatureEnabled - | DockAreaHasAutoHideButton ///< the default configuration for left and right side bars + | DockAreaHasAutoHideButton + | AutoHideCloseButtonCollapsesDock + }; Q_DECLARE_FLAGS(AutoHideFlags, eAutoHideFlag) From 364ee33f9cc3d9be86a856a008b40fb7449af90b Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 11 Jul 2023 10:27:08 +0200 Subject: [PATCH 19/27] Removed some std::cout debug output --- src/AutoHideDockContainer.cpp | 4 ---- src/AutoHideTab.cpp | 1 - src/DockAreaTitleBar.cpp | 1 - src/DockContainerWidget.cpp | 3 --- 4 files changed, 9 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 43df868..0ab151a 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -197,7 +197,6 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL Super(parent), d(new AutoHideDockContainerPrivate(this)) { - std::cout << "CAutoHideDockContainer::constructor" << std::endl; hide(); // auto hide dock container is initially always hidden d->SideTabBarArea = area; d->SideTab = componentsFactory()->createDockWidgetSideTab(nullptr); @@ -216,7 +215,6 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL d->ResizeHandle->setMinResizeSize(64); bool OpaqueResize = CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize); d->ResizeHandle->setOpaqueResize(OpaqueResize); - std::cout << "d->DockArea->size(); " << d->DockArea->size().width() << std::endl; d->Size = d->DockArea->size(); d->InitialDockWidgetSize = DockWidget->size(); @@ -337,7 +335,6 @@ CDockWidget* CAutoHideDockContainer::dockWidget() const //============================================================================ void CAutoHideDockContainer::addDockWidget(CDockWidget* DockWidget) { - std::cout << "CAutoHideDockContainer::addDockWidget " << std::endl; if (d->DockWidget) { // Remove the old dock widget at this area @@ -411,7 +408,6 @@ void CAutoHideDockContainer::moveContentsToParent() //============================================================================ void CAutoHideDockContainer::cleanupAndDelete() { - std::cout << "CAutoHideDockContainer::cleanupAndDelete()" << std::endl; const auto dockWidget = d->DockWidget; if (dockWidget) { diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index 0acb737..067b8f7 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -476,7 +476,6 @@ void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev) break; case DraggingFloatingWidget: - std::cout << "CAutoHideTab::mouseReleaseEvent" << std::endl; ev->accept(); d->FloatingWidget->finishDragging(); if (d->DockWidget->isAutoHide() && d->DragStartOrientation != orientation()) diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 20554f8..611015a 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -661,7 +661,6 @@ void CDockAreaTitleBar::mouseMoveEvent(QMouseEvent* ev) //============================================================================ void CDockAreaTitleBar::mouseDoubleClickEvent(QMouseEvent *event) { - std::cout << "CDockAreaTitleBar::mouseDoubleClickEvent" << std::endl; // If this is the last dock area in a dock container it does not make // sense to move it to a new floating widget and leave this one // empty diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 0655ce2..860c666 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -769,7 +769,6 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg //============================================================================ void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area) { - std::cout << "DockContainerWidgetPrivate::moveToAutoHideSideBar " << area << std::endl; CDockWidget* DroppedDockWidget = qobject_cast(Widget); CDockAreaWidget* DroppedDockArea = qobject_cast(Widget); auto SideBarLocation = internal::toSideBarLocation(area); @@ -1727,7 +1726,6 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } // mouse is over container - std::cout << "Mouse is over container" << std::endl; if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea) { if (internal::isSideBarArea(ContainerDropArea)) @@ -1777,7 +1775,6 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi //============================================================================ void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget) { - std::cout << "CDockContainerWidget::dropWidget" << std::endl; CDockWidget* SingleDockWidget = topLevelDockWidget(); if (TargetAreaWidget) { From 39bc7f1780fc42239ea69a04deb510d041cac62e Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Tue, 11 Jul 2023 10:28:17 +0200 Subject: [PATCH 20/27] Properly consider pinnable flag of dock widget when painting the drop overlays - no auto hide overlay for non pinnable dock widgets --- src/DockOverlay.cpp | 12 ++++++---- src/FloatingDockContainer.cpp | 12 +++++++--- src/FloatingDragPreview.cpp | 42 ++++++++++++++++++++++++++--------- 3 files changed, 49 insertions(+), 17 deletions(-) diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 800756b..e750264 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -472,19 +472,23 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const { auto Rect = rect(); const QPoint pos = mapFromGlobal(QCursor::pos()); - if (pos.x() < d->sideBarMouseZone(SideBarLeft)) + if ((pos.x() < d->sideBarMouseZone(SideBarLeft)) + && d->AllowedAreas.testFlag(LeftAutoHideArea)) { return LeftAutoHideArea; } - else if (pos.x() > (Rect.width() - d->sideBarMouseZone(SideBarRight))) + else if (pos.x() > (Rect.width() - d->sideBarMouseZone(SideBarRight)) + && d->AllowedAreas.testFlag(RightAutoHideArea)) { return RightAutoHideArea; } - else if (pos.y() < d->sideBarMouseZone(SideBarTop)) + else if (pos.y() < d->sideBarMouseZone(SideBarTop) + && d->AllowedAreas.testFlag(TopAutoHideArea)) { return TopAutoHideArea; } - else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom))) + else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom)) + && d->AllowedAreas.testFlag(BottomAutoHideArea)) { return BottomAutoHideArea; } diff --git a/src/FloatingDockContainer.cpp b/src/FloatingDockContainer.cpp index 405ae46..16c7489 100644 --- a/src/FloatingDockContainer.cpp +++ b/src/FloatingDockContainer.cpp @@ -590,16 +590,22 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos) } int VisibleDockAreas = TopContainer->visibleDockAreaCount(); - DockWidgetAreas AllowedAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas; + DockWidgetAreas AllowedContainerAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas; auto DockArea = TopContainer->dockAreaAt(GlobalPos); // If the dock container contains only one single DockArea, then we need // to respect the allowed areas - only the center area is relevant here because // all other allowed areas are from the container if (VisibleDockAreas == 1 && DockArea) { - AllowedAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea)); + AllowedContainerAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea)); } - ContainerOverlay->setAllowedAreas(AllowedAreas); + + if (DockContainer->features().testFlag(CDockWidget::DockWidgetPinnable)) + { + AllowedContainerAreas |= AutoHideDockAreas; + } + + ContainerOverlay->setAllowedAreas(AllowedContainerAreas); DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer); ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea); diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index ff69e6f..52303ad 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -35,6 +35,7 @@ struct FloatingDragPreviewPrivate { CFloatingDragPreview *_this; QWidget* Content; + CDockWidget::DockWidgetFeatures ContentFeatures; CDockAreaWidget* ContentSourceArea = nullptr; QPoint DragStartMousePosition; CDockManager* DockManager; @@ -79,20 +80,36 @@ struct FloatingDragPreviewPrivate * Returns true, if the content is floatable */ bool isContentFloatable() const + { + return this->ContentFeatures.testFlag(CDockWidget::DockWidgetFloatable); + } + + /** + * Returns true, if the content is pinnable + */ + bool isContentPinnable() const + { + return this->ContentFeatures.testFlag(CDockWidget::DockWidgetPinnable); + } + + /** + * Returns the content features + */ + CDockWidget::DockWidgetFeatures contentFeatures() const { CDockWidget* DockWidget = qobject_cast(Content); - if (DockWidget && DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable)) + if (DockWidget) { - return true; + return DockWidget->features(); } CDockAreaWidget* DockArea = qobject_cast(Content); - if (DockArea && DockArea->features().testFlag(CDockWidget::DockWidgetFloatable)) + if (DockArea) { - return true; + return DockArea->features(); } - return false; + return CDockWidget::DockWidgetFeatures(); } }; // struct LedArrayPanelPrivate @@ -152,7 +169,7 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) VisibleDockAreas++; } - DockWidgetAreas AllowedAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas; + DockWidgetAreas AllowedContainerAreas = (VisibleDockAreas > 1) ? OuterDockAreas : AllDockAreas; //ContainerOverlay->enableDropPreview(ContainerDropArea != InvalidDockWidgetArea); auto DockArea = TopContainer->dockAreaAt(GlobalPos); // If the dock container contains only one single DockArea, then we need @@ -160,9 +177,14 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &GlobalPos) // all other allowed areas are from the container if (VisibleDockAreas == 1 && DockArea) { - AllowedAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea)); + AllowedContainerAreas.setFlag(CenterDockWidgetArea, DockArea->allowedAreas().testFlag(CenterDockWidgetArea)); } - ContainerOverlay->setAllowedAreas(AllowedAreas); + + if (isContentPinnable()) + { + AllowedContainerAreas |= AutoHideDockAreas; + } + ContainerOverlay->setAllowedAreas(AllowedContainerAreas); ContainerOverlay->enableDropPreview(ContainerDropArea != InvalidDockWidgetArea); if (DockArea && DockArea->isVisible() && VisibleDockAreas >= 0 && DockArea != ContentSourceArea) { @@ -259,6 +281,7 @@ CFloatingDragPreview::CFloatingDragPreview(QWidget* Content, QWidget* parent) : d(new FloatingDragPreviewPrivate(this)) { d->Content = Content; + d->ContentFeatures = d->contentFeatures(); setAttribute(Qt::WA_DeleteOnClose); if (CDockManager::testConfigFlag(CDockManager::DragPreviewHasWindowFrame)) { @@ -278,8 +301,6 @@ CFloatingDragPreview::CFloatingDragPreview(QWidget* Content, QWidget* parent) : setWindowFlags(Flags); #endif - setWindowOpacity(0.6); - // Create a static image of the widget that should get undocked // This is like some kind preview image like it is uses in drag and drop // operations @@ -437,6 +458,7 @@ void CFloatingDragPreview::paintEvent(QPaintEvent* event) } QPainter painter(this); + painter.setOpacity(0.6); if (CDockManager::testConfigFlag(CDockManager::DragPreviewShowsContentPixmap)) { painter.drawPixmap(QPoint(0, 0), d->ContentPreviewPixmap); From f4fc0dab292f47cfdea6dda94a34139c7f1c74a5 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 12 Jul 2023 09:39:20 +0200 Subject: [PATCH 21/27] Added support for dropping dock widget to a certain tab postion of a dock area --- src/DockAreaTabBar.cpp | 25 +++++++++++++++++++ src/DockAreaTabBar.h | 8 ++++++ src/DockContainerWidget.cpp | 50 +++++++++++++++++++++++-------------- src/DockContainerWidget.h | 3 ++- src/DockOverlay.cpp | 16 +++++++++++- src/DockOverlay.h | 11 ++++++++ src/FloatingDragPreview.cpp | 3 ++- 7 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index 48e3c22..85215a1 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -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 diff --git a/src/DockAreaTabBar.h b/src/DockAreaTabBar.h index 781f5e9..aeab66f 100644 --- a/src/DockAreaTabBar.h +++ b/src/DockAreaTabBar.h @@ -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 */ diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 860c666..8156d3b 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -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(Widget); auto DroppedArea = qobject_cast(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)) { diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 6cc522b..700a8cb 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -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 diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index e750264..e54a14c 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -41,6 +41,7 @@ #include "DockContainerWidget.h" #include "AutoHideSideBar.h" #include "DockManager.h" +#include "DockAreaTabBar.h" #include @@ -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 { diff --git a/src/DockOverlay.h b/src/DockOverlay.h index 3fe0ba9..36376f5 100644 --- a/src/DockOverlay.h +++ b/src/DockOverlay.h @@ -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 diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index 52303ad..b1c18e1 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -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) { From be727c58905b81eb4792a4688927a0b1d6563065 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 12 Jul 2023 10:42:24 +0200 Subject: [PATCH 22/27] Added initial support for inserting dropped dock widgets at a certain sidebar position --- src/AutoHideDockContainer.cpp | 5 +-- src/AutoHideDockContainer.h | 2 +- src/AutoHideSideBar.cpp | 64 +++++++++++++++++++++++++++-------- src/AutoHideSideBar.h | 19 +++++++++-- src/DockAreaWidget.cpp | 6 ++-- src/DockAreaWidget.h | 2 +- src/DockContainerWidget.cpp | 21 ++++++------ src/DockContainerWidget.h | 4 +-- src/DockOverlay.cpp | 23 +++++++++---- src/DockWidget.cpp | 4 +-- src/DockWidget.h | 2 +- src/FloatingDragPreview.cpp | 3 +- 12 files changed, 107 insertions(+), 48 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 0ab151a..c17b195 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -689,7 +689,8 @@ void CAutoHideDockContainer::resetToInitialDockWidgetSize() //============================================================================ -void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBarLocation) +void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBarLocation, + int TabIndex) { if (NewSideBarLocation == sideBarLocation()) { @@ -698,7 +699,7 @@ void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBar auto OldOrientation = orientation(); auto SideBar = dockContainer()->autoHideSideBar(NewSideBarLocation); - SideBar->addAutoHideWidget(this); + SideBar->addAutoHideWidget(this, TabIndex); // If we move a horizontal auto hide container to a vertical position // then we resize it to the orginal dock widget size, to avoid // an extremely streched dock widget after insertion diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index 3183682..0eafc42 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -195,7 +195,7 @@ public: * Removes the AutoHide container from the current side bar and adds * it to the new side bar given in SideBarLocation */ - void moveToNewSideBarLocation(SideBarLocation SideBarLocation); + void moveToNewSideBarLocation(SideBarLocation SideBarLocation, int TabIndex = -1); }; } // namespace ads diff --git a/src/AutoHideSideBar.cpp b/src/AutoHideSideBar.cpp index f0aa03d..ae79f54 100644 --- a/src/AutoHideSideBar.cpp +++ b/src/AutoHideSideBar.cpp @@ -233,7 +233,8 @@ void CAutoHideSideBar::removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidg } //============================================================================ -void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget) +void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, + int Index) { auto SideBar = AutoHideWidget->autoHideTab()->sideBar(); if (SideBar == this) @@ -248,7 +249,7 @@ void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget) AutoHideWidget->setParent(d->ContainerWidget); AutoHideWidget->setSideBarLocation(d->SideTabArea); d->ContainerWidget->registerAutoHideWidget(AutoHideWidget); - insertTab(-1, AutoHideWidget->autoHideTab()); + insertTab(Index, AutoHideWidget->autoHideTab()); } @@ -302,14 +303,14 @@ Qt::Orientation CAutoHideSideBar::orientation() const //============================================================================ -CAutoHideTab* CAutoHideSideBar::tabAt(int index) const +CAutoHideTab* CAutoHideSideBar::tab(int index) const { return qobject_cast(d->TabsLayout->itemAt(index)->widget()); } //============================================================================ -int CAutoHideSideBar::tabCount() const +int CAutoHideSideBar::count() const { return d->TabsLayout->count() - 1; } @@ -318,17 +319,17 @@ int CAutoHideSideBar::tabCount() const //============================================================================ int CAutoHideSideBar::visibleTabCount() const { - int count = 0; + int VisibleTabCount = 0; auto ParentWidget = parentWidget(); - for (auto i = 0; i < tabCount(); i++) + for (auto i = 0; i < count(); i++) { - if (tabAt(i)->isVisibleTo(ParentWidget)) + if (tab(i)->isVisibleTo(ParentWidget)) { - count++; + VisibleTabCount++; } } - return count; + return VisibleTabCount; } @@ -336,9 +337,9 @@ int CAutoHideSideBar::visibleTabCount() const bool CAutoHideSideBar::hasVisibleTabs() const { auto ParentWidget = parentWidget(); - for (auto i = 0; i < tabCount(); i++) + for (auto i = 0; i < count(); i++) { - if (tabAt(i)->isVisibleTo(ParentWidget)) + if (tab(i)->isVisibleTo(ParentWidget)) { return true; } @@ -358,18 +359,18 @@ SideBarLocation CAutoHideSideBar::sideBarLocation() const //============================================================================ void CAutoHideSideBar::saveState(QXmlStreamWriter& s) const { - if (!tabCount()) + if (!count()) { return; } s.writeStartElement("SideBar"); s.writeAttribute("Area", QString::number(sideBarLocation())); - s.writeAttribute("Tabs", QString::number(tabCount())); + s.writeAttribute("Tabs", QString::number(count())); - for (auto i = 0; i < tabCount(); ++i) + for (auto i = 0; i < count(); ++i) { - auto Tab = tabAt(i); + auto Tab = tab(i); if (!Tab) { continue; @@ -417,5 +418,38 @@ CDockContainerWidget* CAutoHideSideBar::dockContainer() const return d->ContainerWidget; } + +//=========================================================================== +int CAutoHideSideBar::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(); +} + + +//=========================================================================== +int CAutoHideSideBar::tabInsertIndexAt(const QPoint& Pos) const +{ + int Index = tabAt(Pos); + return (Index < 0) ? -1 : Index; +} + } // namespace ads diff --git a/src/AutoHideSideBar.h b/src/AutoHideSideBar.h index 1b0cab5..c0cdddc 100644 --- a/src/AutoHideSideBar.h +++ b/src/AutoHideSideBar.h @@ -117,7 +117,7 @@ public: * If the AutoHideWidget is in another sidebar, then it will be removed * from this sidebar. */ - void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget); + void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, int Index = -1); /** * Returns orientation of side tab. @@ -127,12 +127,25 @@ public: /* * get the side tab widget at position, returns nullptr if it's out of bounds */ - CAutoHideTab* tabAt(int index) const; + CAutoHideTab* 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; + + /** + * Returns the tab insertion index for the given mouse cursor position + */ + int tabInsertIndexAt(const QPoint& Pos) const; /* * Gets the count of the tab widgets */ - int tabCount() const; + int count() const; /** * Returns the number of visible tabs to its parent widget. diff --git a/src/DockAreaWidget.cpp b/src/DockAreaWidget.cpp index 29186a2..6146c66 100644 --- a/src/DockAreaWidget.cpp +++ b/src/DockAreaWidget.cpp @@ -1305,7 +1305,7 @@ SideBarLocation CDockAreaWidget::calculateSideTabBarArea() const //============================================================================ -void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location) +void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex) { if (!isAutoHideFeatureEnabled()) { @@ -1324,7 +1324,7 @@ void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location) // If this is already an auto hide container, then move it to new location if (isAutoHide()) { - d->AutoHideDockContainer->moveToNewSideBarLocation(Location); + d->AutoHideDockContainer->moveToNewSideBarLocation(Location, TabIndex); return; } @@ -1341,7 +1341,7 @@ void CDockAreaWidget::setAutoHide(bool Enable, SideBarLocation Location) continue; } - dockContainer()->createAndSetupAutoHideContainer(area, DockWidget); + dockContainer()->createAndSetupAutoHideContainer(area, DockWidget, TabIndex++); } } diff --git a/src/DockAreaWidget.h b/src/DockAreaWidget.h index f1412e8..e88153e 100644 --- a/src/DockAreaWidget.h +++ b/src/DockAreaWidget.h @@ -400,7 +400,7 @@ public Q_SLOTS: * If the dock area is switched to auto hide mode, then all dock widgets * that are pinable will be added to the sidebar */ - void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone); + void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone, int TabIndex = -1); /** * Switches the dock area to auto hide mode or vice versa depending on its diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 8156d3b..e0e5144 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -220,7 +220,7 @@ public: * Moves the dock widget or dock area given in Widget parameter to * a auto hide sidebar area */ - void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area); + void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex = -2); /** @@ -777,7 +777,7 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg //============================================================================ -void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area) +void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex) { CDockWidget* DroppedDockWidget = qobject_cast(Widget); CDockAreaWidget* DroppedDockArea = qobject_cast(Widget); @@ -787,18 +787,18 @@ void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidg { if (_this == DroppedDockWidget->dockContainer()) { - DroppedDockWidget->setAutoHide(true, SideBarLocation); + DroppedDockWidget->setAutoHide(true, SideBarLocation, TabIndex); } else { - _this->createAndSetupAutoHideContainer(SideBarLocation, DroppedDockWidget); + _this->createAndSetupAutoHideContainer(SideBarLocation, DroppedDockWidget, TabIndex); } } else { if (_this == DroppedDockArea->dockContainer()) { - DroppedDockArea->setAutoHide(true, SideBarLocation); + DroppedDockArea->setAutoHide(true, SideBarLocation, TabIndex); } else { @@ -811,7 +811,7 @@ void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget* Widget, DockWidg } _this->createAndSetupAutoHideContainer(SideBarLocation, - DockWidget); + DockWidget, TabIndex++); } } } @@ -988,7 +988,7 @@ void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter& s) { for (const auto sideTabBar : SideTabBarWidgets.values()) { - if (!sideTabBar->tabCount()) + if (!sideTabBar->count()) { continue; } @@ -1484,7 +1484,7 @@ CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockW //============================================================================ CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer( - SideBarLocation area, CDockWidget* DockWidget) + SideBarLocation area, CDockWidget* DockWidget, int TabIndex) { if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) { @@ -1497,7 +1497,8 @@ CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer( DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager } - return autoHideSideBar(area)->insertDockWidget(-1, DockWidget); + qDebug() << "CDockContainerWidget::createAndSetupAutoHideContainer TabIndex: " << TabIndex; + return autoHideSideBar(area)->insertDockWidget(TabIndex, DockWidget); } @@ -1794,7 +1795,7 @@ void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, } else if (internal::isSideBarArea(DropArea)) { - d->moveToAutoHideSideBar(Widget, DropArea); + d->moveToAutoHideSideBar(Widget, DropArea, TabIndex); } else { diff --git a/src/DockContainerWidget.h b/src/DockContainerWidget.h index 700a8cb..11fc339 100644 --- a/src/DockContainerWidget.h +++ b/src/DockContainerWidget.h @@ -101,7 +101,7 @@ protected: * Initializing inserts the tabs into the side tab widget and hides it * Returns nullptr if you try and insert into an area where the configuration is not enabled */ - CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget); + CAutoHideDockContainer* createAndSetupAutoHideContainer(SideBarLocation area, CDockWidget* DockWidget, int TabIndex = -1); /** * The funtion does the same like createAndSetupAutoHideContainer() but checks @@ -133,7 +133,7 @@ protected: * TargetAreaWidget */ void dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget, - int TabIndex = -2); + int TabIndex = -1); /** * Adds the given dock area to this container widget diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index e54a14c..40d84c1 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -471,6 +471,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const return Result; } + auto CursorPos = QCursor::pos(); auto DockArea = qobject_cast(d->TargetWidget.data()); if (!DockArea && CDockManager::autoHideConfigFlags().testFlag(CDockManager::AutoHideFeatureEnabled)) { @@ -479,26 +480,34 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const if ((pos.x() < d->sideBarMouseZone(SideBarLeft)) && d->AllowedAreas.testFlag(LeftAutoHideArea)) { - return LeftAutoHideArea; + Result = LeftAutoHideArea; } else if (pos.x() > (Rect.width() - d->sideBarMouseZone(SideBarRight)) && d->AllowedAreas.testFlag(RightAutoHideArea)) { - return RightAutoHideArea; + Result = RightAutoHideArea; } else if (pos.y() < d->sideBarMouseZone(SideBarTop) && d->AllowedAreas.testFlag(TopAutoHideArea)) { - return TopAutoHideArea; + Result = TopAutoHideArea; } else if (pos.y() > (Rect.height() - d->sideBarMouseZone(SideBarBottom)) && d->AllowedAreas.testFlag(BottomAutoHideArea)) { - return BottomAutoHideArea; + Result = BottomAutoHideArea; } - else + + auto SideBarLocation = ads::internal::toSideBarLocation(Result); + if (SideBarLocation != SideBarNone) { - return Result; + auto Container = qobject_cast(d->TargetWidget.data()); + auto SideBar = Container->autoHideSideBar(SideBarLocation); + if (SideBar->isVisible()) + { + d->TabIndex = SideBar->tabInsertIndexAt(SideBar->mapFromGlobal(CursorPos)); + qDebug() << "TabIndex " << d->TabIndex; + } } return Result; } @@ -507,13 +516,13 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const return Result; } - auto CursorPos = QCursor::pos(); if (DockArea->allowedAreas().testFlag(CenterDockWidgetArea) && !DockArea->titleBar()->isHidden() && DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(CursorPos))) { auto TabBar = DockArea->titleBar()->tabBar(); d->TabIndex = TabBar->tabAt(TabBar->mapFromGlobal(CursorPos)); + qDebug() << "TabIndex " << d->TabIndex; return CenterDockWidgetArea; } diff --git a/src/DockWidget.cpp b/src/DockWidget.cpp index a180cf6..60cbff0 100644 --- a/src/DockWidget.cpp +++ b/src/DockWidget.cpp @@ -1221,7 +1221,7 @@ void CDockWidget::raise() //============================================================================ -void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) +void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location, int TabIndex) { if (!CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideFeatureEnabled)) { @@ -1247,7 +1247,7 @@ void CDockWidget::setAutoHide(bool Enable, SideBarLocation Location) else { auto area = (SideBarNone == Location) ? DockArea->calculateSideTabBarArea() : Location; - dockContainer()->createAndSetupAutoHideContainer(area, this); + dockContainer()->createAndSetupAutoHideContainer(area, this, TabIndex); } } diff --git a/src/DockWidget.h b/src/DockWidget.h index 188c14b..c181932 100644 --- a/src/DockWidget.h +++ b/src/DockWidget.h @@ -621,7 +621,7 @@ public Q_SLOTS: * Sets the dock widget into auto hide mode if this feature is enabled * via CDockManager::setAutoHideFlags(CDockManager::AutoHideFeatureEnabled) */ - void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone); + void setAutoHide(bool Enable, SideBarLocation Location = SideBarNone, int TabIndex = -1); /** * Switches the dock widget to auto hide mode or vice versa depending on its diff --git a/src/FloatingDragPreview.cpp b/src/FloatingDragPreview.cpp index b1c18e1..f7a45a2 100644 --- a/src/FloatingDragPreview.cpp +++ b/src/FloatingDragPreview.cpp @@ -409,7 +409,8 @@ void CFloatingDragPreview::finishDragging() DockArea = d->DropContainer->dockAreaAt(QCursor::pos()); } - d->DropContainer->dropWidget(d->Content, ContainerDropArea, DockArea); + d->DropContainer->dropWidget(d->Content, ContainerDropArea, DockArea, + d->DockManager->containerOverlay()->tabIndexUnderCursor()); } else { From f5cfe9e05a026142bf6206d53ee3aca0ec8b579a Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 12 Jul 2023 14:01:39 +0200 Subject: [PATCH 23/27] Fixed tab insertion when dragging side tab --- src/AutoHideDockContainer.cpp | 12 +++++-- src/AutoHideDockContainer.h | 5 +++ src/AutoHideSideBar.cpp | 59 ++++++++++++++++++++++++++++++----- src/AutoHideSideBar.h | 15 ++++++--- src/AutoHideTab.cpp | 12 +++++++ src/AutoHideTab.h | 5 +++ src/DockAreaTitleBar.cpp | 1 - src/DockContainerWidget.cpp | 12 +++---- src/DockOverlay.cpp | 2 -- 9 files changed, 99 insertions(+), 24 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index c17b195..171a517 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -232,7 +232,6 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL //============================================================================ void CAutoHideDockContainer::updateSize() { - qDebug() << "CAutoHideDockContainer::updateSize()"; auto dockContainerParent = dockContainer(); if (!dockContainerParent) { @@ -692,7 +691,9 @@ void CAutoHideDockContainer::resetToInitialDockWidgetSize() void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBarLocation, int TabIndex) { - if (NewSideBarLocation == sideBarLocation()) + qDebug() << "CAutoHideDockContainer::moveToNewSideBarLocation TabIndex " << + TabIndex << " this->tabIndex: " << this->tabIndex(); + if (NewSideBarLocation == sideBarLocation() && TabIndex == this->tabIndex()) { return; } @@ -709,5 +710,12 @@ void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBar } } + +//============================================================================ +int CAutoHideDockContainer::tabIndex() const +{ + return d->SideTab->tabIndex(); +} + } diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index 0eafc42..469e1e3 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -105,6 +105,11 @@ public: */ CDockWidget* dockWidget() const; + /** + * Returns the index of this container in the sidebar + */ + int tabIndex() const; + /** * Adds a dock widget and removes the previous dock widget */ diff --git a/src/AutoHideSideBar.cpp b/src/AutoHideSideBar.cpp index ae79f54..d0628d1 100644 --- a/src/AutoHideSideBar.cpp +++ b/src/AutoHideSideBar.cpp @@ -234,12 +234,24 @@ void CAutoHideSideBar::removeAutoHideWidget(CAutoHideDockContainer* AutoHideWidg //============================================================================ void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, - int Index) + int TabIndex) { auto SideBar = AutoHideWidget->autoHideTab()->sideBar(); if (SideBar == this) { - return; + // If we move to the same tab index or if we insert before the next + // tab index, then we will end at the same tab position and can leave + if (AutoHideWidget->tabIndex() == TabIndex || (AutoHideWidget->tabIndex() + 1) == TabIndex) + { + return; + } + + // We remove this auto hide widget from the sidebar in the code below + // and therefore need to correct the TabIndex here + if (AutoHideWidget->tabIndex() < TabIndex) + { + --TabIndex; + } } if (SideBar) @@ -249,7 +261,7 @@ void CAutoHideSideBar::addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, AutoHideWidget->setParent(d->ContainerWidget); AutoHideWidget->setSideBarLocation(d->SideTabArea); d->ContainerWidget->registerAutoHideWidget(AutoHideWidget); - insertTab(Index, AutoHideWidget->autoHideTab()); + insertTab(TabIndex, AutoHideWidget->autoHideTab()); } @@ -349,6 +361,21 @@ bool CAutoHideSideBar::hasVisibleTabs() const } +//============================================================================ +int CAutoHideSideBar::indexOfTab(const CAutoHideTab& Tab) const +{ + for (auto i = 0; i < count(); i++) + { + if (tab(i) == &Tab) + { + return i; + } + } + + return -1; +} + + //============================================================================ SideBarLocation CAutoHideSideBar::sideBarLocation() const { @@ -424,13 +451,24 @@ int CAutoHideSideBar::tabAt(const QPoint& Pos) const { if (!isVisible()) { - return -2; + return InvalidTabIndex; } - if (Pos.x() < tab(0)->geometry().x()) + if (orientation() == Qt::Horizontal) { - return -1; + if (Pos.x() < tab(0)->geometry().x()) + { + return -1; + } } + else + { + if (Pos.y() < tab(0)->geometry().y()) + { + return -1; + } + } + for (int i = 0; i < count(); ++i) { @@ -448,7 +486,14 @@ int CAutoHideSideBar::tabAt(const QPoint& Pos) const int CAutoHideSideBar::tabInsertIndexAt(const QPoint& Pos) const { int Index = tabAt(Pos); - return (Index < 0) ? -1 : Index; + if (Index == InvalidTabIndex) + { + return Append; + } + else + { + return (Index < 0) ? 0 : Index; + } } } // namespace ads diff --git a/src/AutoHideSideBar.h b/src/AutoHideSideBar.h index c0cdddc..a82034a 100644 --- a/src/AutoHideSideBar.h +++ b/src/AutoHideSideBar.h @@ -84,6 +84,8 @@ protected: public: using Super = QScrollArea; + static constexpr int Append = -1; + static constexpr int InvalidTabIndex = -2; /** * Default Constructor @@ -117,7 +119,7 @@ public: * If the AutoHideWidget is in another sidebar, then it will be removed * from this sidebar. */ - void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, int Index = -1); + void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, int Index = Append); /** * Returns orientation of side tab. @@ -125,15 +127,15 @@ public: Qt::Orientation orientation() const; /* - * get the side tab widget at position, returns nullptr if it's out of bounds + * Get the side tab widget at position, returns nullptr if it's out of bounds */ CAutoHideTab* 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. + * position is right of the last tab. Returns InvalidTabIndex (-2) to + * indicate an invalid value. */ int tabAt(const QPoint& Pos) const; @@ -142,6 +144,11 @@ public: */ int tabInsertIndexAt(const QPoint& Pos) const; + /** + * Returns the index of the given tab + */ + int indexOfTab(const CAutoHideTab& Tab) const; + /* * Gets the count of the tab widgets */ diff --git a/src/AutoHideTab.cpp b/src/AutoHideTab.cpp index 067b8f7..089fddf 100644 --- a/src/AutoHideTab.cpp +++ b/src/AutoHideTab.cpp @@ -546,4 +546,16 @@ void CAutoHideTab::requestCloseDockWidget() } +//============================================================================ +int CAutoHideTab::tabIndex() const +{ + if (!d->SideBar) + { + return -1; + } + + return d->SideBar->indexOfTab(*this); +} + + } diff --git a/src/AutoHideTab.h b/src/AutoHideTab.h index cf0d143..3a42df8 100644 --- a/src/AutoHideTab.h +++ b/src/AutoHideTab.h @@ -140,6 +140,11 @@ public: */ CAutoHideSideBar* sideBar() const; + /** + * Returns the index of this tab in the sideBar + */ + int tabIndex() const; + public Q_SLOTS: /** * Set the dock widget floating, if it is floatable diff --git a/src/DockAreaTitleBar.cpp b/src/DockAreaTitleBar.cpp index 611015a..646d653 100644 --- a/src/DockAreaTitleBar.cpp +++ b/src/DockAreaTitleBar.cpp @@ -260,7 +260,6 @@ void DockAreaTitleBarPrivate::createTabBar() //============================================================================ IFloatingWidget* DockAreaTitleBarPrivate::makeAreaFloating(const QPoint& Offset, eDragState DragState) { - qDebug() << "DockAreaTitleBarPrivate::makeAreaFloating " << DockArea->size(); QSize Size = DockArea->size(); this->DragState = DragState; bool CreateFloatingDockContainer = (DraggingFloatingWidget != DragState); diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index e0e5144..b64b133 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -523,12 +523,13 @@ void DockContainerWidgetPrivate::dropIntoAutoHideSideBar(CFloatingDockContainer* auto SideBarLocation = internal::toSideBarLocation(area); auto NewDockAreas = FloatingWidget->findChildren( QString(), Qt::FindChildrenRecursively); + int TabIndex = DockManager->containerOverlay()->tabIndexUnderCursor(); for (auto DockArea : NewDockAreas) { auto DockWidgets = DockArea->dockWidgets(); for (auto DockWidget : DockWidgets) { - _this->createAndSetupAutoHideContainer(SideBarLocation, DockWidget); + _this->createAndSetupAutoHideContainer(SideBarLocation, DockWidget, TabIndex++); } } } @@ -574,7 +575,6 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection( void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget, 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) @@ -672,8 +672,6 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex) { - qDebug() << "DockContainerWidgetPrivate::moveIntoCenterOfSection TabIndex: " - << TabIndex; auto DroppedDockWidget = qobject_cast(Widget); auto DroppedArea = qobject_cast(Widget); @@ -715,8 +713,6 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA 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) @@ -1707,7 +1703,6 @@ int CDockContainerWidget::visibleDockAreaCount() const void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget, const QPoint& TargetPos) { - //dockContainer()->createAndSetupAutoHideContainer(area, this); ADS_PRINT("CDockContainerWidget::dropFloatingWidget"); CDockWidget* SingleDroppedDockWidget = FloatingWidget->topLevelDockWidget(); CDockWidget* SingleDockWidget = topLevelDockWidget(); @@ -1716,6 +1711,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi bool Dropped = false; CDockAreaWidget* DockArea = dockAreaAt(TargetPos); + // mouse is over dock area if (DockArea) { auto dropOverlay = d->DockManager->dockAreaOverlay(); @@ -1736,7 +1732,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi } } - // mouse is over container + // mouse is over container or auto hide side bar if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != ContainerDropArea) { if (internal::isSideBarArea(ContainerDropArea)) diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index 40d84c1..eca58f1 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -506,7 +506,6 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const if (SideBar->isVisible()) { d->TabIndex = SideBar->tabInsertIndexAt(SideBar->mapFromGlobal(CursorPos)); - qDebug() << "TabIndex " << d->TabIndex; } } return Result; @@ -522,7 +521,6 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const { auto TabBar = DockArea->titleBar()->tabBar(); d->TabIndex = TabBar->tabAt(TabBar->mapFromGlobal(CursorPos)); - qDebug() << "TabIndex " << d->TabIndex; return CenterDockWidgetArea; } From 7140e5e32aebc20b824b5a17bd2467214a43cddd Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 12 Jul 2023 14:22:05 +0200 Subject: [PATCH 24/27] Properly handle dragging of dock widget into DockWidgetTabBar and AutoHideSideBar --- src/AutoHideSideBar.cpp | 7 ++++--- src/AutoHideSideBar.h | 4 +--- src/DockAreaTabBar.cpp | 17 ++++++++++++++++- src/DockAreaTabBar.h | 5 +++++ src/DockContainerWidget.cpp | 15 +++++++-------- src/DockOverlay.cpp | 2 +- src/ads_globals.h | 7 +++++++ 7 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/AutoHideSideBar.cpp b/src/AutoHideSideBar.cpp index d0628d1..f08172e 100644 --- a/src/AutoHideSideBar.cpp +++ b/src/AutoHideSideBar.cpp @@ -196,6 +196,7 @@ void CAutoHideSideBar::insertTab(int Index, CAutoHideTab* SideTab) { SideTab->setSideBar(this); SideTab->installEventFilter(this); + // Default insertion is append if (Index < 0) { d->TabsLayout->insertWidget(d->TabsLayout->count() - 1, SideTab); @@ -451,7 +452,7 @@ int CAutoHideSideBar::tabAt(const QPoint& Pos) const { if (!isVisible()) { - return InvalidTabIndex; + return TabInvalidIndex; } if (orientation() == Qt::Horizontal) @@ -486,9 +487,9 @@ int CAutoHideSideBar::tabAt(const QPoint& Pos) const int CAutoHideSideBar::tabInsertIndexAt(const QPoint& Pos) const { int Index = tabAt(Pos); - if (Index == InvalidTabIndex) + if (Index == TabInvalidIndex) { - return Append; + return TabDefaultInsertIndex; } else { diff --git a/src/AutoHideSideBar.h b/src/AutoHideSideBar.h index a82034a..cf38bbf 100644 --- a/src/AutoHideSideBar.h +++ b/src/AutoHideSideBar.h @@ -84,8 +84,6 @@ protected: public: using Super = QScrollArea; - static constexpr int Append = -1; - static constexpr int InvalidTabIndex = -2; /** * Default Constructor @@ -119,7 +117,7 @@ public: * If the AutoHideWidget is in another sidebar, then it will be removed * from this sidebar. */ - void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, int Index = Append); + void addAutoHideWidget(CAutoHideDockContainer* AutoHideWidget, int Index = TabDefaultInsertIndex); /** * Returns orientation of side tab. diff --git a/src/DockAreaTabBar.cpp b/src/DockAreaTabBar.cpp index 85215a1..6b1739d 100644 --- a/src/DockAreaTabBar.cpp +++ b/src/DockAreaTabBar.cpp @@ -510,7 +510,7 @@ int CDockAreaTabBar::tabAt(const QPoint& Pos) const { if (!isVisible()) { - return -2; + return TabInvalidIndex; } if (Pos.x() < tab(0)->geometry().x()) @@ -529,6 +529,21 @@ int CDockAreaTabBar::tabAt(const QPoint& Pos) const return count(); } + +//=========================================================================== +int CDockAreaTabBar::tabInsertIndexAt(const QPoint& Pos) const +{ + int Index = tabAt(Pos); + if (Index == TabInvalidIndex) + { + return TabDefaultInsertIndex; + } + else + { + return (Index < 0) ? 0 : Index; + } +} + } // namespace ads diff --git a/src/DockAreaTabBar.h b/src/DockAreaTabBar.h index aeab66f..f93094f 100644 --- a/src/DockAreaTabBar.h +++ b/src/DockAreaTabBar.h @@ -121,6 +121,11 @@ public: */ int tabAt(const QPoint& Pos) const; + /** + * Returns the tab insertion index for the given mouse cursor position + */ + int tabInsertIndexAt(const QPoint& Pos) const; + /** * Filters the tab widget events */ diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index b64b133..081481d 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -190,20 +190,20 @@ public: * Creates a new tab for a widget dropped into the center of a section */ void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget, - CDockAreaWidget* TargetArea, int TabIndex = -2); + CDockAreaWidget* TargetArea, int TabIndex = 0); /** * Drop floating widget into dock area */ void dropIntoSection(CFloatingDockContainer* FloatingWidget, - CDockAreaWidget* TargetArea, DockWidgetArea area, int TabIndex = -2); + CDockAreaWidget* TargetArea, DockWidgetArea area, int TabIndex = 0); /** * 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, - int TabIndex = -2); + int TabIndex = 0); /** * Moves the dock widget or dock area given in Widget parameter to a @@ -214,13 +214,13 @@ public: /** * Creates a new tab for a widget dropped into the center of a section */ - void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex = -2); + void moveIntoCenterOfSection(QWidget* Widget, CDockAreaWidget* TargetArea, int TabIndex = 0); /** * Moves the dock widget or dock area given in Widget parameter to * a auto hide sidebar area */ - void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex = -2); + void moveToAutoHideSideBar(QWidget* Widget, DockWidgetArea area, int TabIndex = TabDefaultInsertIndex); /** @@ -543,7 +543,7 @@ void DockContainerWidgetPrivate::dropIntoCenterOfSection( auto NewDockWidgets = FloatingContainer->dockWidgets(); auto TopLevelDockArea = FloatingContainer->topLevelDockArea(); int NewCurrentIndex = -1; - TabIndex = (TabIndex < 0) ? 0 : TabIndex; + TabIndex = qMax(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 @@ -675,7 +675,7 @@ void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget* Widget, CDockA auto DroppedDockWidget = qobject_cast(Widget); auto DroppedArea = qobject_cast(Widget); - TabIndex = (TabIndex < 0) ? 0 : TabIndex; + TabIndex = qMax(0, TabIndex); if (DroppedDockWidget) { CDockAreaWidget* OldDockArea = DroppedDockWidget->dockAreaWidget(); @@ -1493,7 +1493,6 @@ CAutoHideDockContainer* CDockContainerWidget::createAndSetupAutoHideContainer( DockWidget->setDockManager(d->DockManager); // Auto hide Dock Container needs a valid dock manager } - qDebug() << "CDockContainerWidget::createAndSetupAutoHideContainer TabIndex: " << TabIndex; return autoHideSideBar(area)->insertDockWidget(TabIndex, DockWidget); } diff --git a/src/DockOverlay.cpp b/src/DockOverlay.cpp index eca58f1..3ae43a2 100644 --- a/src/DockOverlay.cpp +++ b/src/DockOverlay.cpp @@ -520,7 +520,7 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const && DockArea->titleBarGeometry().contains(DockArea->mapFromGlobal(CursorPos))) { auto TabBar = DockArea->titleBar()->tabBar(); - d->TabIndex = TabBar->tabAt(TabBar->mapFromGlobal(CursorPos)); + d->TabIndex = TabBar->tabInsertIndexAt(TabBar->mapFromGlobal(CursorPos)); return CenterDockWidgetArea; } diff --git a/src/ads_globals.h b/src/ads_globals.h index e331576..53e612b 100644 --- a/src/ads_globals.h +++ b/src/ads_globals.h @@ -95,6 +95,13 @@ enum DockWidgetArea Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea) +enum eTabIndex +{ + TabDefaultInsertIndex = -1, + TabInvalidIndex = -2 +}; + + enum TitleBarButton { TitleBarButtonTabsMenu, From e239cdb3549354cfdf276b59614364d756d6ab35 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Wed, 12 Jul 2023 14:37:45 +0200 Subject: [PATCH 25/27] Improved sizing of AutoHideWidgets when dragging between side bars --- src/AutoHideDockContainer.cpp | 37 +++++++++++++---------------------- src/AutoHideDockContainer.h | 6 ------ 2 files changed, 14 insertions(+), 29 deletions(-) diff --git a/src/AutoHideDockContainer.cpp b/src/AutoHideDockContainer.cpp index 171a517..4d8cac2 100644 --- a/src/AutoHideDockContainer.cpp +++ b/src/AutoHideDockContainer.cpp @@ -117,7 +117,7 @@ struct AutoHideDockContainerPrivate CResizeHandle* ResizeHandle = nullptr; QSize Size; // creates invalid size QPointer SideTab; - QSize InitialDockWidgetSize; + QSize SizeCache; /** * Private data constructor @@ -216,7 +216,7 @@ CAutoHideDockContainer::CAutoHideDockContainer(CDockWidget* DockWidget, SideBarL bool OpaqueResize = CDockManager::testConfigFlag(CDockManager::OpaqueSplitterResize); d->ResizeHandle->setOpaqueResize(OpaqueResize); d->Size = d->DockArea->size(); - d->InitialDockWidgetSize = DockWidget->size(); + d->SizeCache = DockWidget->size(); addDockWidget(DockWidget); parent->registerAutoHideWidget(this); @@ -239,12 +239,6 @@ void CAutoHideDockContainer::updateSize() } auto rect = dockContainerParent->contentRect(); - qDebug() << "dockContainerParent->contentRect() " << rect; - qDebug() << "dockWidget()->rect()" << dockWidget()->rect(); - qDebug() << "dockAreaWidget()->rect(): " << dockAreaWidget()->rect(); - qDebug() << "CAutoHideDockContainer::isVisible " << this->isVisible(); - qDebug() << "CAutoHideDockContainer::rect " << this->rect(); - switch (sideBarLocation()) { case SideBarLocation::SideBarTop: @@ -279,8 +273,14 @@ void CAutoHideDockContainer::updateSize() break; } - qDebug() << "CAutoHideDockContainer::rect (after): " << this->rect(); - qDebug() << "dockAreaWidget()->rect(): " << dockAreaWidget()->rect(); + if (orientation() == Qt::Horizontal) + { + d->SizeCache.setHeight(this->height()); + } + else + { + d->SizeCache.setWidth(this->width()); + } } //============================================================================ @@ -658,31 +658,24 @@ bool CAutoHideDockContainer::event(QEvent* event) } -//============================================================================ -QSize CAutoHideDockContainer::initialDockWidgetSize() const -{ - return d->InitialDockWidgetSize; -} - - //============================================================================ Qt::Orientation CAutoHideDockContainer::orientation() const { - return autoHideSideBar()->orientation(); + return ads::internal::isHorizontalSideBarLocation(d->SideTabBarArea) + ? Qt::Horizontal : Qt::Vertical; } //============================================================================ void CAutoHideDockContainer::resetToInitialDockWidgetSize() { - auto OriginalSize = initialDockWidgetSize(); if (orientation() == Qt::Horizontal) { - setSize(OriginalSize.height()); + setSize(d->SizeCache.height()); } else { - setSize(OriginalSize.width()); + setSize(d->SizeCache.width()); } } @@ -691,8 +684,6 @@ void CAutoHideDockContainer::resetToInitialDockWidgetSize() void CAutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation NewSideBarLocation, int TabIndex) { - qDebug() << "CAutoHideDockContainer::moveToNewSideBarLocation TabIndex " << - TabIndex << " this->tabIndex: " << this->tabIndex(); if (NewSideBarLocation == sideBarLocation() && TabIndex == this->tabIndex()) { return; diff --git a/src/AutoHideDockContainer.h b/src/AutoHideDockContainer.h index 469e1e3..fc984a7 100644 --- a/src/AutoHideDockContainer.h +++ b/src/AutoHideDockContainer.h @@ -172,12 +172,6 @@ public: */ void setSize(int Size); - /** - * Returns the original size of the dock widget at the time it has been - * added to this auto hide widget - */ - QSize initialDockWidgetSize() const; - /** * Resets the with or hight to the initial dock widget size dependinng on * the orientation. From 65ae86a46dc495f6fc2c93f628f0bcea031f1269 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 13 Jul 2023 07:25:09 +0200 Subject: [PATCH 26/27] Removed debug output --- src/DockContainerWidget.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/DockContainerWidget.cpp b/src/DockContainerWidget.cpp index 081481d..974142f 100644 --- a/src/DockContainerWidget.cpp +++ b/src/DockContainerWidget.cpp @@ -1782,7 +1782,6 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi void CDockContainerWidget::dropWidget(QWidget* Widget, DockWidgetArea DropArea, CDockAreaWidget* TargetAreaWidget, int TabIndex) { - qDebug() << "CDockContainerWidget::dropWidget TabIndex: " << TabIndex; CDockWidget* SingleDockWidget = topLevelDockWidget(); if (TargetAreaWidget) { From 1a1352e4560eff17a53d913d2706add3ce49db96 Mon Sep 17 00:00:00 2001 From: Uwe Kindler Date: Thu, 13 Jul 2023 13:53:29 +0200 Subject: [PATCH 27/27] Updated README.md for 4.1 release --- README.md | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/README.md b/README.md index 7cbc70a..fe041a8 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,70 @@ integrated development environments (IDEs) such as Visual Studio. ## New and Noteworthy +Release [4.1](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest) significantly improves the Auto-Hide functionality and also brings improvements +for Drag and Drop of dock widgets into dock area tabs. These are the highlights of the new version: + +#### Drag & Drop to Auto-Hide + +Now you can easily drag any dock widget or any floating widget to the +borders of a window to pin it as a auto-hide tab in one of the 4 sidebars. +If you drag a dock widget close the one of the four window borders, special +drop overlays will be shown to indicate the drop area for auto-hide widgets: + +![Auo-Hide drag to Sidebar](doc/AutoHide_Drag_to_Sidebar.gif) + +Of course, this also works with dock areas: + +![Auo-Hide drag Dock Area](doc/AutoHide_Drag_DockArea.gif) + +If you drag a dock widget or dock area into a sidebar, then you even have +control over where tabs are inserted. Simply drag your mouse over a specific +auto-hide tab, and your dragged dock widget will be inserted before this tab. +Drag to the sidebar area behind the last tab, and the dragged widget will be +appended as last tab. In the following screen capture, the **Image Viewer 1** will +be inserted before the **Table 0** Auto-Hide tab and the **Image Viewer 2** +is appende behind the last tab: + +![Auo-Hide tab insert order](doc/AutoHide_Tab_Insert_Order.gif) + +#### Auto-Hide Tab Insertion Order + +It is also possible to drag Auto-Hide tabs to a new auto-hide position. +That means, you can drag them to a different border or sidebar: + +![Auto-Hide change sidebar](doc/AutoHide_Change_Sidebar.gif) + +#### Auto-Hide Tab Sorting + +You can drag Auto-Hide tabs to a new position in the current sidebar +to sort them: + +![Auo-Hide sort tabs](doc/AutoHide_Sort_Tabs.gif) + +#### Auto-Hide Drag to Float / Dock + +But that is not all. You can also simply move Auto-Hide tabs to another +floating widget or dock them via drag and drop: + +![Auo-Hide drag to float or dock](doc/AutoHide_Drag_to_Float_or_Dock.gif) + +#### Auto-Hide Context Menu + +All Auto-Hide tabs now have a context menu, that provides all the functionality +that you know from Dock widget tabs. With the **Pin To...** item from the +context menu it is very easy to move an Auto-Hide tab to a different Auto-Hide +sidebar: + +![Auo-Hide context menu](doc/AutoHide_Context_Menu.png) + +#### Dock Area Tab Insert Order + +And last but not least the new version also improves the docking of widgets +into the tabs of a Dock area. Just as with Auto-Hide tabs, you can now determine the position at which a tab is inserted by moving the mouse over an already existing tab (insertion before the tab) or behind the last tab +(appending): + +![Dock area tab insert order](doc/DockArea_Tab_Insertion_Order.gif) + The [release 4.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/latest) adds the following features: @@ -77,6 +141,12 @@ know it from Visual Studio. ### Overview - [New and Noteworthy](#new-and-noteworthy) + - [Drag \& Drop to Auto-Hide](#drag--drop-to-auto-hide) + - [Auto-Hide Tab Insertion Order](#auto-hide-tab-insertion-order) + - [Auto-Hide Tab Sorting](#auto-hide-tab-sorting) + - [Auto-Hide Drag to Float / Dock](#auto-hide-drag-to-float--dock) + - [Auto-Hide Context Menu](#auto-hide-context-menu) + - [Dock Area Tab Insert Order](#dock-area-tab-insert-order) - [Features](#features) - [Overview](#overview) - [Docking everywhere - no central widget](#docking-everywhere---no-central-widget)