Refactored, fixed and improved drag hover functionality

This commit is contained in:
Uwe Kindler 2024-10-28 15:39:29 +01:00
parent eb9b439d11
commit f964ce2c68
3 changed files with 91 additions and 68 deletions

View File

@ -660,8 +660,7 @@ bool CAutoHideDockContainer::event(QEvent* event)
//============================================================================ //============================================================================
void CAutoHideDockContainer::dragLeaveEvent(QDragLeaveEvent*) void CAutoHideDockContainer::dragLeaveEvent(QDragLeaveEvent*)
{ {
if (CDockManager::testAutoHideConfigFlag( if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
CDockManager::AutoHideOpenOnDragHover))
{ {
collapseView(true); collapseView(true);
} }

View File

@ -34,6 +34,7 @@
#include <QElapsedTimer> #include <QElapsedTimer>
#include <QMenu> #include <QMenu>
#include <QEvent> #include <QEvent>
#include <QTimer>
#include "AutoHideDockContainer.h" #include "AutoHideDockContainer.h"
#include "AutoHideSideBar.h" #include "AutoHideSideBar.h"
@ -57,7 +58,7 @@ struct AutoHideTabPrivate
CAutoHideSideBar* SideBar = nullptr; CAutoHideSideBar* SideBar = nullptr;
Qt::Orientation Orientation{Qt::Vertical}; Qt::Orientation Orientation{Qt::Vertical};
QElapsedTimer TimeSinceHoverMousePress; QElapsedTimer TimeSinceHoverMousePress;
QElapsedTimer TimeSinceDragOver; QTimer DragOverTimer;
bool MousePressed = false; bool MousePressed = false;
eDragState DragState = DraggingInactive; eDragState DragState = DraggingInactive;
QPoint GlobalDragStartMousePosition; QPoint GlobalDragStartMousePosition;
@ -258,6 +259,11 @@ CAutoHideTab::CAutoHideTab(QWidget* parent) :
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) { if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) {
setAcceptDrops(true); setAcceptDrops(true);
} }
d->DragOverTimer.setInterval(CDockManager::configParam(
CDockManager::AutoHideOpenOnDragHoverDelay_ms, 500).toInt());
d->DragOverTimer.setSingleShot(true);
connect(&d->DragOverTimer, &QTimer::timeout, this, &CAutoHideTab::onDragHoverDelayExpired);
} }
@ -498,81 +504,76 @@ void CAutoHideTab::mouseReleaseEvent(QMouseEvent* ev)
//============================================================================ //============================================================================
void CAutoHideTab::mouseMoveEvent(QMouseEvent* ev) void CAutoHideTab::mouseMoveEvent(QMouseEvent *ev)
{ {
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) 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());
if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar)
{ {
// Floating is only allowed for widgets that are floatable d->DragState = DraggingInactive;
// We can create the drag preview if the widget is movable. Super::mouseMoveEvent(ev);
auto Features = d->DockWidget->features(); return;
if (Features.testFlag(CDockWidget::DockWidgetFloatable) || (Features.testFlag(CDockWidget::DockWidgetMovable)))
{
d->startFloating();
}
return;
} }
Super::mouseMoveEvent(ev); // 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());
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)))
{
d->startFloating();
}
return;
}
Super::mouseMoveEvent(ev);
} }
//============================================================================ //============================================================================
void CAutoHideTab::dragEnterEvent(QDragEnterEvent* ev) { void CAutoHideTab::dragEnterEvent(QDragEnterEvent *ev)
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) { {
if (!d->TimeSinceDragOver.isValid()) { Q_UNUSED(ev);
d->TimeSinceDragOver.restart(); if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
ev->accept(); {
} d->DragOverTimer.start();
else if (d->TimeSinceDragOver.hasExpired(500)) { ev->accept();
ev->accept(); }
}
}
} }
//============================================================================ //============================================================================
void CAutoHideTab::dragLeaveEvent(QDragLeaveEvent* ev) { void CAutoHideTab::dragLeaveEvent(QDragLeaveEvent *ev)
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)) { {
d->TimeSinceDragOver.invalidate(); Q_UNUSED(ev);
d->forwardEventToDockContainer(ev); if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover))
} {
d->DragOverTimer.stop();
}
} }
//============================================================================
void CAutoHideTab::dragMoveEvent(QDragMoveEvent* ev) {
if (CDockManager::testAutoHideConfigFlag(CDockManager::AutoHideOpenOnDragHover)
&& d->TimeSinceDragOver.isValid()
&& d->TimeSinceDragOver.hasExpired(500)) {
d->TimeSinceDragOver.invalidate();
d->DockWidget->autoHideDockContainer()->collapseView(false);
ev->accept();
}
}
//============================================================================ //============================================================================
void CAutoHideTab::requestCloseDockWidget() void CAutoHideTab::requestCloseDockWidget()
@ -580,7 +581,6 @@ void CAutoHideTab::requestCloseDockWidget()
d->DockWidget->requestCloseDockWidget(); d->DockWidget->requestCloseDockWidget();
} }
//============================================================================ //============================================================================
int CAutoHideTab::tabIndex() const int CAutoHideTab::tabIndex() const
{ {
@ -593,4 +593,28 @@ int CAutoHideTab::tabIndex() const
} }
//============================================================================
void CAutoHideTab::onDragHoverDelayExpired()
{
static const char* const PropertyId = "ActiveDragOverAutoHideContainer";
// First we check if there is an active auto hide container that is visible
// In this case, we collapse it before we open the new one
auto v = d->DockWidget->dockManager()->property(PropertyId);
if (v.isValid())
{
auto ActiveAutoHideContainer = v.value<QPointer<CAutoHideDockContainer>>();
if (ActiveAutoHideContainer)
{
ActiveAutoHideContainer->collapseView(true);
}
}
auto AutoHideContainer = d->DockWidget->autoHideDockContainer();
AutoHideContainer->collapseView(false);
d->DockWidget->dockManager()->setProperty(PropertyId,
QVariant::fromValue(QPointer(AutoHideContainer)));
}
} }

View File

@ -67,6 +67,7 @@ private:
private Q_SLOTS: private Q_SLOTS:
void onAutoHideToActionClicked(); void onAutoHideToActionClicked();
void onDragHoverDelayExpired();
protected: protected:
void setSideBar(CAutoHideSideBar *SideTabBar); void setSideBar(CAutoHideSideBar *SideTabBar);
@ -78,7 +79,6 @@ protected:
virtual void mouseMoveEvent(QMouseEvent* ev) override; virtual void mouseMoveEvent(QMouseEvent* ev) override;
virtual void dragEnterEvent(QDragEnterEvent* ev) override; virtual void dragEnterEvent(QDragEnterEvent* ev) override;
virtual void dragLeaveEvent(QDragLeaveEvent* ev) override; virtual void dragLeaveEvent(QDragLeaveEvent* ev) override;
virtual void dragMoveEvent(QDragMoveEvent* ev) override;
public: public:
using Super = CPushButton; using Super = CPushButton;