Improved tab dragging, added support for undocking if mouse leaves tabbar during tb dragging

This commit is contained in:
Uwe Kindler 2020-02-19 22:07:17 +01:00
parent 3f09d5c6ea
commit e8332575f8
3 changed files with 28 additions and 26 deletions

View File

@ -488,7 +488,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
// uncomment the following line if you want to use opaque undocking and // uncomment the following line if you want to use opaque undocking and
// opaque splitter resizing // opaque splitter resizing
// CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig); //CDockManager::setConfigFlags(CDockManager::DefaultOpaqueConfig);
// uncomment the following line if you want a fixed tab width that does // uncomment the following line if you want a fixed tab width that does
// not change if the visibility of the close button changes // not change if the visibility of the close button changes

View File

@ -35,6 +35,7 @@
#include <QDebug> #include <QDebug>
#include <QBoxLayout> #include <QBoxLayout>
#include <QApplication> #include <QApplication>
#include <QtGlobal>
#include "FloatingDockContainer.h" #include "FloatingDockContainer.h"
#include "DockAreaWidget.h" #include "DockAreaWidget.h"
@ -69,6 +70,16 @@ struct DockAreaTabBarPrivate
* The function reassigns the stylesheet to update the tabs * The function reassigns the stylesheet to update the tabs
*/ */
void updateTabs(); void updateTabs();
/**
* Convenience function to access first tab
*/
CDockWidgetTab* firstTab() const {return _this->tab(0);}
/**
* Convenience function to access last tab
*/
CDockWidgetTab* lastTab() const {return _this->tab(_this->count() - 1);}
}; };
// struct DockAreaTabBarPrivate // struct DockAreaTabBarPrivate
@ -366,6 +377,8 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
int fromIndex = d->TabsLayout->indexOf(MovingTab); int fromIndex = d->TabsLayout->indexOf(MovingTab);
auto MousePos = mapFromGlobal(GlobalPos); auto MousePos = mapFromGlobal(GlobalPos);
MousePos.rx() = qMax(d->firstTab()->geometry().left(), MousePos.x());
MousePos.rx() = qMin(d->lastTab()->geometry().right(), MousePos.x());
int toIndex = -1; int toIndex = -1;
// Find tab under mouse // Find tab under mouse
for (int i = 0; i < count(); ++i) for (int i = 0; i < count(); ++i)
@ -381,38 +394,23 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
if (toIndex == fromIndex) if (toIndex == fromIndex)
{ {
toIndex = -1; toIndex = -1;
continue;
}
if (toIndex < 0)
{
toIndex = 0;
} }
break; break;
} }
// Now check if the mouse is behind the last tab if (toIndex > -1)
if (toIndex < 0)
{
if (MousePos.x() > tab(count() - 1)->geometry().right())
{
ADS_PRINT("after all tabs");
toIndex = count() - 1;
}
else
{
toIndex = fromIndex;
}
}
d->TabsLayout->removeWidget(MovingTab);
d->TabsLayout->insertWidget(toIndex, MovingTab);
if (toIndex >= 0)
{ {
d->TabsLayout->removeWidget(MovingTab);
d->TabsLayout->insertWidget(toIndex, MovingTab);
ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex); ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex);
emit tabMoved(fromIndex, toIndex); emit tabMoved(fromIndex, toIndex);
setCurrentIndex(toIndex); setCurrentIndex(toIndex);
} }
else
{
// Ensure that the moved tab is reset to its start position
d->TabsLayout->update();
}
} }
//=========================================================================== //===========================================================================

View File

@ -215,6 +215,8 @@ void DockWidgetTabPrivate::moveTab(QMouseEvent* ev)
QPoint Distance = ev->globalPos() - GlobalDragStartMousePosition; QPoint Distance = ev->globalPos() - GlobalDragStartMousePosition;
Distance.setY(0); Distance.setY(0);
auto TargetPos = Distance + TabDragStartPosition; auto TargetPos = Distance + TabDragStartPosition;
TargetPos.rx() = qMax(TargetPos.x(), 0);
TargetPos.rx() = qMin(_this->parentWidget()->rect().right() - _this->width() + 1, TargetPos.rx());
_this->move(TargetPos); _this->move(TargetPos);
_this->raise(); _this->raise();
} }
@ -364,9 +366,11 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
d->moveTab(ev); 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 ? // Maybe a fixed drag distance is better here ?
int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - ev->globalPos().y()); int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - ev->globalPos().y());
if (DragDistanceY >= CDockManager::startDragDistance()) if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar)
{ {
// If this is the last dock area in a dock container with only // If this is the last dock area in a dock container with only
// one single dock widget it does not make sense to move it to a new // one single dock widget it does not make sense to move it to a new
@ -390,7 +394,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
// tab because it looks strange if it remains on its dragged position // tab because it looks strange if it remains on its dragged position
if (d->isDraggingState(DraggingTab) && !CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking)) if (d->isDraggingState(DraggingTab) && !CDockManager::configFlags().testFlag(CDockManager::OpaqueUndocking))
{ {
this->move(d->TabDragStartPosition); parentWidget()->layout()->update();
} }
d->startFloating(); d->startFloating();
} }