mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-11-15 13:15:43 +08:00
Implemented initial support for dragging auto hide tabs
This commit is contained in:
parent
4bdc04e9d8
commit
4307f48d99
@ -39,6 +39,8 @@
|
|||||||
#include "DockAreaWidget.h"
|
#include "DockAreaWidget.h"
|
||||||
#include "DockManager.h"
|
#include "DockManager.h"
|
||||||
#include "DockWidget.h"
|
#include "DockWidget.h"
|
||||||
|
#include "FloatingDragPreview.h"
|
||||||
|
#include "DockOverlay.h"
|
||||||
|
|
||||||
namespace ads
|
namespace ads
|
||||||
{
|
{
|
||||||
@ -54,6 +56,11 @@ struct AutoHideTabPrivate
|
|||||||
CAutoHideSideBar* SideBar = nullptr;
|
CAutoHideSideBar* SideBar = nullptr;
|
||||||
Qt::Orientation Orientation{Qt::Vertical};
|
Qt::Orientation Orientation{Qt::Vertical};
|
||||||
QElapsedTimer TimeSinceHoverMousePress;
|
QElapsedTimer TimeSinceHoverMousePress;
|
||||||
|
bool MousePressed = false;
|
||||||
|
eDragState DragState = DraggingInactive;
|
||||||
|
QPoint GlobalDragStartMousePosition;
|
||||||
|
QPoint DragStartMousePosition;
|
||||||
|
IFloatingWidget* FloatingWidget = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
@ -99,6 +106,41 @@ struct AutoHideTabPrivate
|
|||||||
Action->setEnabled(Location != _this->sideBarLocation());
|
Action->setEnabled(Location != _this->sideBarLocation());
|
||||||
return Action;
|
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 <typename T>
|
||||||
|
IFloatingWidget* createFloatingWidget(T* Widget)
|
||||||
|
{
|
||||||
|
auto w = new CFloatingDragPreview(Widget);
|
||||||
|
_this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
|
||||||
|
{
|
||||||
|
DragState = DraggingInactive;
|
||||||
|
});
|
||||||
|
return w;
|
||||||
|
}
|
||||||
}; // struct DockWidgetTabPrivate
|
}; // 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)
|
void CAutoHideTab::setSideBar(CAutoHideSideBar* SideTabBar)
|
||||||
{
|
{
|
||||||
@ -267,22 +355,6 @@ bool CAutoHideTab::event(QEvent* event)
|
|||||||
d->forwardEventToDockContainer(event);
|
d->forwardEventToDockContainer(event);
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,9 @@ protected:
|
|||||||
void removeFromSideBar();
|
void removeFromSideBar();
|
||||||
virtual bool event(QEvent* event) override;
|
virtual bool event(QEvent* event) override;
|
||||||
virtual void contextMenuEvent(QContextMenuEvent* ev) 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:
|
public:
|
||||||
using Super = CPushButton;
|
using Super = CPushButton;
|
||||||
|
@ -55,6 +55,8 @@ class CIconProvider;
|
|||||||
class CDockComponentsFactory;
|
class CDockComponentsFactory;
|
||||||
class CDockFocusController;
|
class CDockFocusController;
|
||||||
class CAutoHideSideBar;
|
class CAutoHideSideBar;
|
||||||
|
class CAutoHideTab;
|
||||||
|
struct AutoHideTabPrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The central dock manager that maintains the complete docking system.
|
* The central dock manager that maintains the complete docking system.
|
||||||
@ -87,6 +89,8 @@ private:
|
|||||||
friend class CDockAreaTitleBar;
|
friend class CDockAreaTitleBar;
|
||||||
friend class CAutoHideDockContainer;
|
friend class CAutoHideDockContainer;
|
||||||
friend CAutoHideSideBar;
|
friend CAutoHideSideBar;
|
||||||
|
friend CAutoHideTab;
|
||||||
|
friend AutoHideTabPrivate;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user