Added support for make auto hide widget floating via double click or context menu

This commit is contained in:
Uwe Kindler 2023-07-07 11:21:54 +02:00
parent 0b3c3f0123
commit 1c6d86e70f
10 changed files with 149 additions and 28 deletions

View File

@ -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());
}

View File

@ -32,6 +32,7 @@
#include <QBoxLayout>
#include <QApplication>
#include <QElapsedTimer>
#include <QMenu>
#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();
}
}

View File

@ -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

View File

@ -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)
{

View File

@ -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

View File

@ -1442,6 +1442,13 @@ bool CDockAreaWidget::isTopLevelArea() const
}
//============================================================================
void CDockAreaWidget::setFloating()
{
d->TitleBar->setAreaFloating();
}
#ifdef Q_OS_WIN
//============================================================================
bool CDockAreaWidget::event(QEvent *e)

View File

@ -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.

View File

@ -475,7 +475,6 @@ DockWidgetArea CDockOverlay::dropAreaUnderCursor() const
auto DockArea = qobject_cast<CDockAreaWidget*>(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;

View File

@ -1021,7 +1021,15 @@ void CDockWidget::setFloating()
{
return;
}
d->TabWidget->detachDockWidget();
if (this->isAutoHide())
{
dockAreaWidget()->setFloating();
}
else
{
d->TabWidget->detachDockWidget();
}
}

View File

@ -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)
{