Skip to content

Commit 4307f48

Browse files
Implemented initial support for dragging auto hide tabs
1 parent 4bdc04e commit 4307f48

File tree

3 files changed

+230
-16
lines changed

3 files changed

+230
-16
lines changed

src/AutoHideTab.cpp

Lines changed: 223 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
#include "DockAreaWidget.h"
4040
#include "DockManager.h"
4141
#include "DockWidget.h"
42+
#include "FloatingDragPreview.h"
43+
#include "DockOverlay.h"
4244

4345
namespace ads
4446
{
@@ -54,6 +56,11 @@ struct AutoHideTabPrivate
5456
CAutoHideSideBar* SideBar = nullptr;
5557
Qt::Orientation Orientation{Qt::Vertical};
5658
QElapsedTimer TimeSinceHoverMousePress;
59+
bool MousePressed = false;
60+
eDragState DragState = DraggingInactive;
61+
QPoint GlobalDragStartMousePosition;
62+
QPoint DragStartMousePosition;
63+
IFloatingWidget* FloatingWidget = nullptr;
5764

5865
/**
5966
* Private data constructor
@@ -99,6 +106,41 @@ struct AutoHideTabPrivate
99106
Action->setEnabled(Location != _this->sideBarLocation());
100107
return Action;
101108
}
109+
110+
/**
111+
* Test function for current drag state
112+
*/
113+
bool isDraggingState(eDragState dragState) const
114+
{
115+
return this->DragState == dragState;
116+
}
117+
118+
/**
119+
* Saves the drag start position in global and local coordinates
120+
*/
121+
void saveDragStartMousePosition(const QPoint& GlobalPos)
122+
{
123+
GlobalDragStartMousePosition = GlobalPos;
124+
DragStartMousePosition = _this->mapFromGlobal(GlobalPos);
125+
}
126+
127+
/**
128+
* Starts floating of the dock widget that belongs to this title bar
129+
* Returns true, if floating has been started and false if floating
130+
* is not possible for any reason
131+
*/
132+
bool startFloating(eDragState DraggingState = DraggingFloatingWidget);
133+
134+
template <typename T>
135+
IFloatingWidget* createFloatingWidget(T* Widget)
136+
{
137+
auto w = new CFloatingDragPreview(Widget);
138+
_this->connect(w, &CFloatingDragPreview::draggingCanceled, [=]()
139+
{
140+
DragState = DraggingInactive;
141+
});
142+
return w;
143+
}
102144
}; // struct DockWidgetTabPrivate
103145

104146

@@ -127,6 +169,52 @@ void AutoHideTabPrivate::updateOrientation()
127169
}
128170

129171

172+
//============================================================================
173+
bool AutoHideTabPrivate::startFloating(eDragState DraggingState)
174+
{
175+
auto DockArea = DockWidget->dockAreaWidget();
176+
ADS_PRINT("isFloating " << dockContainer->isFloating());
177+
178+
ADS_PRINT("startFloating");
179+
DragState = DraggingState;
180+
IFloatingWidget* FloatingWidget = nullptr;
181+
FloatingWidget = createFloatingWidget(DockArea);
182+
auto Size = DockArea->size();
183+
auto StartPos = DragStartMousePosition;
184+
auto AutoHideContainer = DockWidget->autoHideDockContainer();
185+
switch (SideBar->sideBarLocation())
186+
{
187+
case SideBarLeft:
188+
StartPos.rx() = AutoHideContainer->rect().left() + 10;
189+
break;
190+
191+
case SideBarRight:
192+
StartPos.rx() = AutoHideContainer->rect().right() - 10;
193+
break;
194+
195+
case SideBarTop:
196+
StartPos.ry() = AutoHideContainer->rect().top() + 10;
197+
break;
198+
199+
case SideBarBottom:
200+
StartPos.ry() = AutoHideContainer->rect().bottom() - 10;
201+
break;
202+
203+
case SideBarNone:
204+
return false;
205+
}
206+
FloatingWidget->startFloating(StartPos, Size, DraggingFloatingWidget, _this);
207+
auto DockManager = DockWidget->dockManager();
208+
auto Overlay = DockManager->containerOverlay();
209+
Overlay->setAllowedAreas(OuterDockAreas);
210+
this->FloatingWidget = FloatingWidget;
211+
qApp->postEvent(DockWidget, new QEvent((QEvent::Type)internal::DockedWidgetDragStartEvent));
212+
213+
return true;
214+
}
215+
216+
217+
130218
//============================================================================
131219
void CAutoHideTab::setSideBar(CAutoHideSideBar* SideTabBar)
132220
{
@@ -267,22 +355,6 @@ bool CAutoHideTab::event(QEvent* event)
267355
d->forwardEventToDockContainer(event);
268356
break;
269357

270-
case QEvent::MouseButtonPress:
271-
// If AutoHideShowOnMouseOver is active, then the showing is triggered
272-
// by a MousePressEvent sent to this tab. To prevent accidental hiding
273-
// of the tab by a mouse click, we wait at least 500 ms before we accept
274-
// the mouse click
275-
if (!event->spontaneous())
276-
{
277-
d->TimeSinceHoverMousePress.restart();
278-
d->forwardEventToDockContainer(event);
279-
}
280-
else if (d->TimeSinceHoverMousePress.hasExpired(500))
281-
{
282-
d->forwardEventToDockContainer(event);
283-
}
284-
break;
285-
286358
default:
287359
break;
288360
}
@@ -360,4 +432,139 @@ void CAutoHideTab::onAutoHideToActionClicked()
360432
}
361433

362434

435+
//============================================================================
436+
void CAutoHideTab::mousePressEvent(QMouseEvent* ev)
437+
{
438+
// If AutoHideShowOnMouseOver is active, then the showing is triggered
439+
// by a MousePressEvent sent to this tab. To prevent accidental hiding
440+
// of the tab by a mouse click, we wait at least 500 ms before we accept
441+
// the mouse click
442+
if (!ev->spontaneous())
443+
{
444+
d->TimeSinceHoverMousePress.restart();
445+
d->forwardEventToDockContainer(ev);
446+
}
447+
else if (d->TimeSinceHoverMousePress.hasExpired(500))
448+
{
449+
d->forwardEventToDockContainer(ev);
450+
}
451+
452+
if (ev->button() == Qt::LeftButton)
453+
{
454+
ev->accept();
455+
d->MousePressed = true;
456+
d->saveDragStartMousePosition(internal::globalPositionOf(ev));
457+
d->DragState = DraggingMousePressed;
458+
}
459+
Super::mousePressEvent(ev);
460+
}
461+
462+
463+
464+
//============================================================================
465+
void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev)
466+
{
467+
if (ev->button() == Qt::LeftButton)
468+
{
469+
d->MousePressed = false;
470+
auto CurrentDragState = d->DragState;
471+
d->GlobalDragStartMousePosition = QPoint();
472+
d->DragStartMousePosition = QPoint();
473+
d->DragState = DraggingInactive;
474+
475+
switch (CurrentDragState)
476+
{
477+
case DraggingTab:
478+
// End of tab moving, emit signal
479+
/*if (d->DockArea)
480+
{
481+
ev->accept();
482+
Q_EMIT moved(internal::globalPositionOf(ev));
483+
}*/
484+
break;
485+
486+
case DraggingFloatingWidget:
487+
ev->accept();
488+
d->FloatingWidget->finishDragging();
489+
break;
490+
491+
default:
492+
/*if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
493+
{
494+
d->focusController()->setDockWidgetTabPressed(false);
495+
}*/
496+
break; // do nothing
497+
}
498+
}
499+
500+
Super::mouseReleaseEvent(ev);
501+
}
502+
503+
504+
//============================================================================
505+
void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev)
506+
{
507+
std::cout << "CAutoHideTab::mouseMoveEvent" << std::endl;
508+
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
509+
{
510+
d->DragState = DraggingInactive;
511+
Super::mouseMoveEvent(ev);
512+
return;
513+
}
514+
515+
// move floating window
516+
if (d->isDraggingState(DraggingFloatingWidget))
517+
{
518+
d->FloatingWidget->moveFloating();
519+
Super::mouseMoveEvent(ev);
520+
return;
521+
}
522+
523+
// move tab
524+
if (d->isDraggingState(DraggingTab))
525+
{
526+
// Moving the tab is always allowed because it does not mean moving the
527+
// dock widget around
528+
//d->moveTab(ev);
529+
}
530+
531+
auto MappedPos = mapToParent(ev->pos());
532+
bool MouseOutsideBar = (MappedPos.x() < 0) || (MappedPos.x() > parentWidget()->rect().right());
533+
// Maybe a fixed drag distance is better here ?
534+
int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - internal::globalPositionOf(ev).y());
535+
std::cout << "DragDistanceY " << DragDistanceY << " MouseOutsideBar " << MouseOutsideBar << std::endl;
536+
if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar)
537+
{
538+
// Floating is only allowed for widgets that are floatable
539+
// We can create the drag preview if the widget is movable.
540+
auto Features = d->DockWidget->features();
541+
if (Features.testFlag(CDockWidget::DockWidgetFloatable) || (Features.testFlag(CDockWidget::DockWidgetMovable)))
542+
{
543+
// If we undock, we need to restore the initial position of this
544+
// tab because it looks strange if it remains on its dragged position
545+
/*if (d->isDraggingState(DraggingTab))
546+
{
547+
parentWidget()->layout()->update();
548+
}*/
549+
d->startFloating();
550+
}
551+
return;
552+
}
553+
/*else if (d->DockArea->openDockWidgetsCount() > 1
554+
&& (internal::globalPositionOf(ev) - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
555+
{
556+
// If we start dragging the tab, we save its inital position to
557+
// restore it later
558+
if (DraggingTab != d->DragState)
559+
{
560+
d->TabDragStartPosition = this->pos();
561+
}
562+
d->DragState = DraggingTab;
563+
return;
564+
}*/
565+
566+
Super::mouseMoveEvent(ev);
567+
}
568+
569+
363570
}

src/AutoHideTab.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ private Q_SLOTS:
7373
void removeFromSideBar();
7474
virtual bool event(QEvent* event) override;
7575
virtual void contextMenuEvent(QContextMenuEvent* ev) override;
76+
virtual void mousePressEvent(QMouseEvent* ev) override;
77+
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
78+
virtual void mouseMoveEvent(QMouseEvent* ev) override;
7679

7780
public:
7881
using Super = CPushButton;

src/DockManager.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,8 @@ class CIconProvider;
5555
class CDockComponentsFactory;
5656
class CDockFocusController;
5757
class CAutoHideSideBar;
58+
class CAutoHideTab;
59+
struct AutoHideTabPrivate;
5860

5961
/**
6062
* The central dock manager that maintains the complete docking system.
@@ -87,6 +89,8 @@ class ADS_EXPORT CDockManager : public CDockContainerWidget
8789
friend class CDockAreaTitleBar;
8890
friend class CAutoHideDockContainer;
8991
friend CAutoHideSideBar;
92+
friend CAutoHideTab;
93+
friend AutoHideTabPrivate;
9094

9195
public Q_SLOTS:
9296
/**

0 commit comments

Comments
 (0)