forked from qt-creator/qt-creator
ADS: Integrate newest base repository commits
* Add drag and drop to auto hide Base repository was merged until commit 65600a4dcd072fd2773b661823816db6392c34eb Change-Id: I09dd6613869368d3cf0c701055a6972db915561d Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
This commit is contained in:
committed by
Henning Gründl
parent
16ef838f23
commit
bb635325e7
@@ -63,6 +63,45 @@ DockInsertParam dockAreaInsertParameters(DockWidgetArea area)
|
|||||||
return DockInsertParam(Qt::Vertical, false);
|
return DockInsertParam(Qt::Vertical, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SideBarLocation toSideBarLocation(DockWidgetArea area)
|
||||||
|
{
|
||||||
|
switch (area) {
|
||||||
|
case LeftAutoHideArea:
|
||||||
|
return SideBarLeft;
|
||||||
|
case RightAutoHideArea:
|
||||||
|
return SideBarRight;
|
||||||
|
case TopAutoHideArea:
|
||||||
|
return SideBarTop;
|
||||||
|
case BottomAutoHideArea:
|
||||||
|
return SideBarBottom;
|
||||||
|
default:
|
||||||
|
return SideBarNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SideBarNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isHorizontalSideBarLocation(SideBarLocation location)
|
||||||
|
{
|
||||||
|
switch (location) {
|
||||||
|
case SideBarTop:
|
||||||
|
case SideBarBottom:
|
||||||
|
return true;
|
||||||
|
case SideBarLeft:
|
||||||
|
case SideBarRight:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isSideBarArea(DockWidgetArea area)
|
||||||
|
{
|
||||||
|
return toSideBarLocation(area) != SideBarNone;
|
||||||
|
}
|
||||||
|
|
||||||
QPixmap createTransparentPixmap(const QPixmap &source, qreal opacity)
|
QPixmap createTransparentPixmap(const QPixmap &source, qreal opacity)
|
||||||
{
|
{
|
||||||
QPixmap transparentPixmap(source.size());
|
QPixmap transparentPixmap(source.size());
|
||||||
|
@@ -16,11 +16,11 @@ class QSplitter;
|
|||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#if defined(ADVANCEDDOCKINGSYSTEM_LIBRARY)
|
#if defined(ADVANCEDDOCKINGSYSTEM_LIBRARY)
|
||||||
# define ADS_EXPORT Q_DECL_EXPORT
|
#define ADS_EXPORT Q_DECL_EXPORT
|
||||||
#elif defined(ADVANCEDDOCKINGSYSTEM_STATIC_LIBRARY)
|
#elif defined(ADVANCEDDOCKINGSYSTEM_STATIC_LIBRARY)
|
||||||
# define ADS_EXPORT
|
#define ADS_EXPORT
|
||||||
#else
|
#else
|
||||||
# define ADS_EXPORT Q_DECL_IMPORT
|
#define ADS_EXPORT Q_DECL_IMPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//#define ADS_DEBUG_PRINT
|
//#define ADS_DEBUG_PRINT
|
||||||
@@ -47,14 +47,21 @@ enum DockWidgetArea {
|
|||||||
TopDockWidgetArea = 0x04,
|
TopDockWidgetArea = 0x04,
|
||||||
BottomDockWidgetArea = 0x08,
|
BottomDockWidgetArea = 0x08,
|
||||||
CenterDockWidgetArea = 0x10,
|
CenterDockWidgetArea = 0x10,
|
||||||
|
LeftAutoHideArea = 0x20,
|
||||||
|
RightAutoHideArea = 0x40,
|
||||||
|
TopAutoHideArea = 0x80,
|
||||||
|
BottomAutoHideArea = 0x100,
|
||||||
|
|
||||||
InvalidDockWidgetArea = NoDockWidgetArea,
|
InvalidDockWidgetArea = NoDockWidgetArea,
|
||||||
OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea
|
OuterDockAreas = TopDockWidgetArea | LeftDockWidgetArea | RightDockWidgetArea
|
||||||
| BottomDockWidgetArea,
|
| BottomDockWidgetArea,
|
||||||
|
AutoHideDockAreas = LeftAutoHideArea | RightAutoHideArea | TopAutoHideArea | BottomAutoHideArea,
|
||||||
AllDockAreas = OuterDockAreas | CenterDockWidgetArea
|
AllDockAreas = OuterDockAreas | CenterDockWidgetArea
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)
|
Q_DECLARE_FLAGS(DockWidgetAreas, DockWidgetArea)
|
||||||
|
|
||||||
|
enum eTabIndex { TabDefaultInsertIndex = -1, TabInvalidIndex = -2 };
|
||||||
|
|
||||||
enum eTitleBarButton {
|
enum eTitleBarButton {
|
||||||
TitleBarButtonTabsMenu,
|
TitleBarButtonTabsMenu,
|
||||||
TitleBarButtonUndock,
|
TitleBarButtonUndock,
|
||||||
@@ -137,6 +144,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
DockInsertParam dockAreaInsertParameters(DockWidgetArea area);
|
DockInsertParam dockAreaInsertParameters(DockWidgetArea area);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the SieBarLocation for the AutoHide dock widget areas.
|
||||||
|
*/
|
||||||
|
SideBarLocation toSideBarLocation(DockWidgetArea area);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true for the top or bottom side bar ansd false for the left and right side bar.
|
||||||
|
*/
|
||||||
|
bool isHorizontalSideBarLocation(SideBarLocation location);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true, if the given dock area is a SideBar area.
|
||||||
|
*/
|
||||||
|
bool isSideBarArea(DockWidgetArea area);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Searches for the parent widget of the given type. Returns the parent widget of the given
|
* Searches for the parent widget of the given type. Returns the parent widget of the given
|
||||||
* widget or 0 if the widget is not child of any widget of type T.
|
* widget or 0 if the widget is not child of any widget of type T.
|
||||||
|
@@ -90,6 +90,7 @@ struct AutoHideDockContainerPrivate
|
|||||||
ResizeHandle *m_resizeHandle = nullptr;
|
ResizeHandle *m_resizeHandle = nullptr;
|
||||||
QSize m_size; // creates invalid size
|
QSize m_size; // creates invalid size
|
||||||
QPointer<AutoHideTab> m_sideTab;
|
QPointer<AutoHideTab> m_sideTab;
|
||||||
|
QSize m_sizeCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
@@ -181,6 +182,7 @@ AutoHideDockContainer::AutoHideDockContainer(DockWidget *dockWidget,
|
|||||||
bool opaqueResize = DockManager::testConfigFlag(DockManager::OpaqueSplitterResize);
|
bool opaqueResize = DockManager::testConfigFlag(DockManager::OpaqueSplitterResize);
|
||||||
d->m_resizeHandle->setOpaqueResize(opaqueResize);
|
d->m_resizeHandle->setOpaqueResize(opaqueResize);
|
||||||
d->m_size = d->m_dockArea->size();
|
d->m_size = d->m_dockArea->size();
|
||||||
|
d->m_sizeCache = dockWidget->size();
|
||||||
|
|
||||||
addDockWidget(dockWidget);
|
addDockWidget(dockWidget);
|
||||||
parent->registerAutoHideWidget(this);
|
parent->registerAutoHideWidget(this);
|
||||||
@@ -228,6 +230,11 @@ void AutoHideDockContainer::updateSize()
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (orientation() == Qt::Horizontal)
|
||||||
|
d->m_sizeCache.setHeight(this->height());
|
||||||
|
else
|
||||||
|
d->m_sizeCache.setWidth(this->width());
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoHideDockContainer::~AutoHideDockContainer()
|
AutoHideDockContainer::~AutoHideDockContainer()
|
||||||
@@ -245,13 +252,13 @@ AutoHideDockContainer::~AutoHideDockContainer()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoHideSideBar *AutoHideDockContainer::sideBar() const
|
AutoHideSideBar *AutoHideDockContainer::autoHideSideBar() const
|
||||||
{
|
{
|
||||||
if (d->m_sideTab) {
|
if (d->m_sideTab) {
|
||||||
return d->m_sideTab->sideBar();
|
return d->m_sideTab->sideBar();
|
||||||
} else {
|
} else {
|
||||||
auto container = dockContainer();
|
auto container = dockContainer();
|
||||||
return container ? container->sideTabBar(d->m_sideTabBarArea) : nullptr;
|
return container ? container->autoHideSideBar(d->m_sideTabBarArea) : nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -277,14 +284,18 @@ void AutoHideDockContainer::addDockWidget(DockWidget *dockWidget)
|
|||||||
DockAreaWidget *oldDockArea = dockWidget->dockAreaWidget();
|
DockAreaWidget *oldDockArea = dockWidget->dockAreaWidget();
|
||||||
auto isRestoringState = dockWidget->dockManager()->isRestoringState();
|
auto isRestoringState = dockWidget->dockManager()->isRestoringState();
|
||||||
if (oldDockArea && !isRestoringState) {
|
if (oldDockArea && !isRestoringState) {
|
||||||
// The initial size should be a little bit bigger than the original dock
|
// The initial size should be a little bit bigger than the original dock area size to
|
||||||
// area size to prevent that the resize handle of this auto hid dock area
|
// prevent that the resize handle of this auto hid dock area is near of the splitter of
|
||||||
// is near of the splitter of the old dock area.
|
// the old dock area.
|
||||||
d->m_size = oldDockArea->size() + QSize(16, 16);
|
d->m_size = oldDockArea->size() + QSize(16, 16);
|
||||||
oldDockArea->removeDockWidget(dockWidget);
|
oldDockArea->removeDockWidget(dockWidget);
|
||||||
}
|
}
|
||||||
d->m_dockArea->addDockWidget(dockWidget);
|
d->m_dockArea->addDockWidget(dockWidget);
|
||||||
updateSize();
|
updateSize();
|
||||||
|
// The dock area is not visible and will not update the size when updateSize() is called for
|
||||||
|
// this auto hide container. Therefore we explicitly resize it here. As soon as it will
|
||||||
|
// become visible, it will get the right size
|
||||||
|
d->m_dockArea->resize(size());
|
||||||
}
|
}
|
||||||
|
|
||||||
SideBarLocation AutoHideDockContainer::sideBarLocation() const
|
SideBarLocation AutoHideDockContainer::sideBarLocation() const
|
||||||
@@ -393,6 +404,39 @@ void AutoHideDockContainer::setSize(int size)
|
|||||||
updateSize();
|
updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Qt::Orientation AutoHideDockContainer::orientation() const
|
||||||
|
{
|
||||||
|
return internal::isHorizontalSideBarLocation(d->m_sideTabBarArea) ? Qt::Horizontal
|
||||||
|
: Qt::Vertical;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideDockContainer::resetToInitialDockWidgetSize()
|
||||||
|
{
|
||||||
|
if (orientation() == Qt::Horizontal)
|
||||||
|
setSize(d->m_sizeCache.height());
|
||||||
|
else
|
||||||
|
setSize(d->m_sizeCache.width());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideDockContainer::moveToNewSideBarLocation(SideBarLocation newSideBarLocation, int index)
|
||||||
|
{
|
||||||
|
if (newSideBarLocation == sideBarLocation() && index == tabIndex())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto oldOrientation = orientation();
|
||||||
|
auto sideBar = dockContainer()->autoHideSideBar(newSideBarLocation);
|
||||||
|
sideBar->addAutoHideWidget(this, index);
|
||||||
|
// If we move a horizontal auto hide container to a vertical position then we resize it to the
|
||||||
|
// orginal dock widget size, to avoid an extremely stretched dock widget after insertion.
|
||||||
|
if (sideBar->orientation() != oldOrientation)
|
||||||
|
resetToInitialDockWidgetSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AutoHideDockContainer::tabIndex() const
|
||||||
|
{
|
||||||
|
return d->m_sideTab->tabIndex();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if the object given in ancestor is an ancestor of the object given in descendant
|
* Returns true if the object given in ancestor is an ancestor of the object given in descendant
|
||||||
*/
|
*/
|
||||||
|
@@ -66,7 +66,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get's the side tab bar
|
* Get's the side tab bar
|
||||||
*/
|
*/
|
||||||
AutoHideSideBar *sideBar() const;
|
AutoHideSideBar *autoHideSideBar() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the side tab
|
* Returns the side tab
|
||||||
@@ -137,6 +137,32 @@ public:
|
|||||||
* Depending on the sidebar location this will set the width or height of this auto hide container.
|
* Depending on the sidebar location this will set the width or height of this auto hide container.
|
||||||
*/
|
*/
|
||||||
void setSize(int size);
|
void setSize(int size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns orientation of this container.
|
||||||
|
* Left and right containers have a Qt::Vertical orientation and top / bottom containers have
|
||||||
|
* a Qt::Horizontal orientation. The function returns the orientation of the corresponding
|
||||||
|
* auto hide side bar.
|
||||||
|
*/
|
||||||
|
Qt::Orientation orientation() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the with or hight to the initial dock widget size dependinng on the orientation.
|
||||||
|
* If the orientation is Qt::Horizontal, then the height is reset to the initial size and if
|
||||||
|
* orientation is Qt::Vertical, then the width is reset to the initial size.
|
||||||
|
*/
|
||||||
|
void resetToInitialDockWidgetSize();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the AutoHide container from the current side bar and adds it to the new side bar
|
||||||
|
* given in SideBarLocation.
|
||||||
|
*/
|
||||||
|
void moveToNewSideBarLocation(SideBarLocation sideBarLocation, int index = -1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of this container in the sidebar.
|
||||||
|
*/
|
||||||
|
int tabIndex() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace ADS
|
} // namespace ADS
|
||||||
|
@@ -147,6 +147,7 @@ void AutoHideSideBar::insertTab(int index, AutoHideTab *sideTab)
|
|||||||
{
|
{
|
||||||
sideTab->setSideBar(this);
|
sideTab->setSideBar(this);
|
||||||
sideTab->installEventFilter(this);
|
sideTab->installEventFilter(this);
|
||||||
|
// Default insertion is append
|
||||||
if (index < 0)
|
if (index < 0)
|
||||||
d->m_tabsLayout->insertWidget(d->m_tabsLayout->count() - 1, sideTab);
|
d->m_tabsLayout->insertWidget(d->m_tabsLayout->count() - 1, sideTab);
|
||||||
else
|
else
|
||||||
@@ -177,19 +178,28 @@ void AutoHideSideBar::removeAutoHideWidget(AutoHideDockContainer *autoHideWidget
|
|||||||
autoHideWidget->setParent(nullptr);
|
autoHideWidget->setParent(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoHideSideBar::addAutoHideWidget(AutoHideDockContainer *autoHideWidget)
|
void AutoHideSideBar::addAutoHideWidget(AutoHideDockContainer *autoHideWidget, int index)
|
||||||
{
|
{
|
||||||
auto sideBar = autoHideWidget->autoHideTab()->sideBar();
|
auto sideBar = autoHideWidget->autoHideTab()->sideBar();
|
||||||
if (sideBar == this)
|
if (sideBar == this) {
|
||||||
|
// If we move to the same tab index or if we insert before the next tab index, then we will
|
||||||
|
// end at the same tab position and can leave.
|
||||||
|
if (autoHideWidget->tabIndex() == index || (autoHideWidget->tabIndex() + 1) == index)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
// We remove this auto hide widget from the sidebar in the code below and therefore need
|
||||||
|
// to correct the TabIndex here.
|
||||||
|
if (autoHideWidget->tabIndex() < index)
|
||||||
|
--index;
|
||||||
|
}
|
||||||
|
|
||||||
if (sideBar)
|
if (sideBar)
|
||||||
sideBar->removeAutoHideWidget(autoHideWidget);
|
sideBar->removeAutoHideWidget(autoHideWidget);
|
||||||
|
|
||||||
autoHideWidget->setParent(d->m_containerWidget);
|
autoHideWidget->setParent(d->m_containerWidget);
|
||||||
autoHideWidget->setSideBarLocation(d->m_sideTabArea);
|
autoHideWidget->setSideBarLocation(d->m_sideTabArea);
|
||||||
d->m_containerWidget->registerAutoHideWidget(autoHideWidget);
|
d->m_containerWidget->registerAutoHideWidget(autoHideWidget);
|
||||||
insertTab(-1, autoHideWidget->autoHideTab());
|
insertTab(index, autoHideWidget->autoHideTab());
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoHideSideBar::removeTab(AutoHideTab *sideTab)
|
void AutoHideSideBar::removeTab(AutoHideTab *sideTab)
|
||||||
@@ -228,33 +238,73 @@ Qt::Orientation AutoHideSideBar::orientation() const
|
|||||||
return d->m_orientation;
|
return d->m_orientation;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoHideTab *AutoHideSideBar::tabAt(int index) const
|
AutoHideTab *AutoHideSideBar::tab(int index) const
|
||||||
{
|
{
|
||||||
return qobject_cast<AutoHideTab *>(d->m_tabsLayout->itemAt(index)->widget());
|
return qobject_cast<AutoHideTab *>(d->m_tabsLayout->itemAt(index)->widget());
|
||||||
}
|
}
|
||||||
|
|
||||||
int AutoHideSideBar::tabCount() const
|
int AutoHideSideBar::tabAt(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
if (!isVisible())
|
||||||
|
return TabInvalidIndex;
|
||||||
|
|
||||||
|
if (orientation() == Qt::Horizontal) {
|
||||||
|
if (pos.x() < tab(0)->geometry().x())
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
if (pos.y() < tab(0)->geometry().y())
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < count(); ++i) {
|
||||||
|
if (tab(i)->geometry().contains(pos))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int AutoHideSideBar::tabInsertIndexAt(const QPoint &pos) const
|
||||||
|
{
|
||||||
|
int index = tabAt(pos);
|
||||||
|
if (index == TabInvalidIndex)
|
||||||
|
return TabDefaultInsertIndex;
|
||||||
|
else
|
||||||
|
return (index < 0) ? 0 : index;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AutoHideSideBar::indexOfTab(const AutoHideTab &autoHideTab) const
|
||||||
|
{
|
||||||
|
for (auto i = 0; i < count(); i++) {
|
||||||
|
if (tab(i) == &autoHideTab)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AutoHideSideBar::count() const
|
||||||
{
|
{
|
||||||
return d->m_tabsLayout->count() - 1;
|
return d->m_tabsLayout->count() - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int AutoHideSideBar::visibleTabCount() const
|
int AutoHideSideBar::visibleTabCount() const
|
||||||
{
|
{
|
||||||
int count = 0;
|
int c = 0;
|
||||||
auto parent = parentWidget();
|
auto parent = parentWidget();
|
||||||
for (auto i = 0; i < tabCount(); i++) {
|
for (auto i = 0; i < count(); i++) {
|
||||||
if (tabAt(i)->isVisibleTo(parent))
|
if (tab(i)->isVisibleTo(parent))
|
||||||
count++;
|
c++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return count;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AutoHideSideBar::hasVisibleTabs() const
|
bool AutoHideSideBar::hasVisibleTabs() const
|
||||||
{
|
{
|
||||||
auto parent = parentWidget();
|
auto parent = parentWidget();
|
||||||
for (auto i = 0; i < tabCount(); i++) {
|
for (auto i = 0; i < count(); i++) {
|
||||||
if (tabAt(i)->isVisibleTo(parent))
|
if (tab(i)->isVisibleTo(parent))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -268,19 +318,19 @@ SideBarLocation AutoHideSideBar::sideBarLocation() const
|
|||||||
|
|
||||||
void AutoHideSideBar::saveState(QXmlStreamWriter &s) const
|
void AutoHideSideBar::saveState(QXmlStreamWriter &s) const
|
||||||
{
|
{
|
||||||
if (!tabCount())
|
if (!count())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s.writeStartElement("sideBar");
|
s.writeStartElement("sideBar");
|
||||||
s.writeAttribute("area", QString::number(sideBarLocation()));
|
s.writeAttribute("area", QString::number(sideBarLocation()));
|
||||||
s.writeAttribute("tabs", QString::number(tabCount()));
|
s.writeAttribute("tabs", QString::number(count()));
|
||||||
|
|
||||||
for (auto i = 0; i < tabCount(); ++i) {
|
for (auto i = 0; i < count(); ++i) {
|
||||||
auto tab = tabAt(i);
|
auto currentTab = tab(i);
|
||||||
if (!tab)
|
if (!currentTab)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
tab->dockWidget()->autoHideDockContainer()->saveState(s);
|
currentTab->dockWidget()->autoHideDockContainer()->saveState(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
s.writeEndElement();
|
s.writeEndElement();
|
||||||
|
@@ -91,7 +91,7 @@ public:
|
|||||||
* Adds the given AutoHideWidget to this sidebar. If the AutoHideWidget is in another sidebar,
|
* Adds the given AutoHideWidget to this sidebar. If the AutoHideWidget is in another sidebar,
|
||||||
* then it will be removed from this sidebar.
|
* then it will be removed from this sidebar.
|
||||||
*/
|
*/
|
||||||
void addAutoHideWidget(AutoHideDockContainer *autoHideWidget);
|
void addAutoHideWidget(AutoHideDockContainer *autoHideWidget, int index = TabDefaultInsertIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns orientation of side tab.
|
* Returns orientation of side tab.
|
||||||
@@ -101,12 +101,29 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Get the side tab widget at position, returns nullptr if it's out of bounds.
|
* Get the side tab widget at position, returns nullptr if it's out of bounds.
|
||||||
*/
|
*/
|
||||||
AutoHideTab *tabAt(int index) const;
|
AutoHideTab *tab(int index) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tab at the given position.
|
||||||
|
* Returns -1 if the position is left of the first tab and count() if the position is right
|
||||||
|
* of the last tab. Returns InvalidTabIndex (-2) to indicate an invalid value.
|
||||||
|
*/
|
||||||
|
int tabAt(const QPoint &pos) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tab insertion index for the given mouse cursor position.
|
||||||
|
*/
|
||||||
|
int tabInsertIndexAt(const QPoint &pos) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of the given tab.
|
||||||
|
*/
|
||||||
|
int indexOfTab(const AutoHideTab &tab) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the count of the tab widgets.
|
* Gets the count of the tab widgets.
|
||||||
*/
|
*/
|
||||||
int tabCount() const;
|
int count() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of visible tabs to its parent widget.
|
* Returns the number of visible tabs to its parent widget.
|
||||||
|
@@ -6,14 +6,22 @@
|
|||||||
#include "ads_globals_p.h"
|
#include "ads_globals_p.h"
|
||||||
#include "autohidedockcontainer.h"
|
#include "autohidedockcontainer.h"
|
||||||
#include "autohidesidebar.h"
|
#include "autohidesidebar.h"
|
||||||
|
#include "dockareawidget.h"
|
||||||
#include "dockmanager.h"
|
#include "dockmanager.h"
|
||||||
|
#include "dockoverlay.h"
|
||||||
#include "dockwidget.h"
|
#include "dockwidget.h"
|
||||||
|
#include "floatingdragpreview.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QBoxLayout>
|
#include <QBoxLayout>
|
||||||
|
#include <QContextMenuEvent>
|
||||||
#include <QElapsedTimer>
|
#include <QElapsedTimer>
|
||||||
|
#include <QMenu>
|
||||||
|
|
||||||
namespace ADS {
|
namespace ADS {
|
||||||
|
|
||||||
|
static const char *const g_locationProperty = "Location";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data class of CDockWidgetTab class (pimpl)
|
* Private data class of CDockWidgetTab class (pimpl)
|
||||||
*/
|
*/
|
||||||
@@ -24,6 +32,12 @@ struct AutoHideTabPrivate
|
|||||||
AutoHideSideBar *m_sideBar = nullptr;
|
AutoHideSideBar *m_sideBar = nullptr;
|
||||||
Qt::Orientation m_orientation{Qt::Vertical};
|
Qt::Orientation m_orientation{Qt::Vertical};
|
||||||
QElapsedTimer m_timeSinceHoverMousePress;
|
QElapsedTimer m_timeSinceHoverMousePress;
|
||||||
|
bool m_mousePressed = false;
|
||||||
|
eDragState m_dragState = DraggingInactive;
|
||||||
|
QPoint m_globalDragStartMousePosition;
|
||||||
|
QPoint m_dragStartMousePosition;
|
||||||
|
AbstractFloatingWidget *m_floatingWidget = nullptr;
|
||||||
|
Qt::Orientation m_dragStartOrientation;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
@@ -52,6 +66,48 @@ struct AutoHideTabPrivate
|
|||||||
if (container)
|
if (container)
|
||||||
container->handleAutoHideWidgetEvent(event, q);
|
container->handleAutoHideWidgetEvent(event, q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to create and initialize the menu entries for the "Auto Hide Group To..." menu.
|
||||||
|
*/
|
||||||
|
QAction *createAutoHideToAction(const QString &title, SideBarLocation location, QMenu *menu)
|
||||||
|
{
|
||||||
|
auto action = menu->addAction(title);
|
||||||
|
action->setProperty("Location", location);
|
||||||
|
QObject::connect(action, &QAction::triggered, q, &AutoHideTab::onAutoHideToActionClicked);
|
||||||
|
action->setEnabled(location != q->sideBarLocation());
|
||||||
|
return action;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test function for current drag state.
|
||||||
|
*/
|
||||||
|
bool isDraggingState(eDragState dragState) const { return m_dragState == dragState; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Saves the drag start position in global and local coordinates.
|
||||||
|
*/
|
||||||
|
void saveDragStartMousePosition(const QPoint &globalPos)
|
||||||
|
{
|
||||||
|
m_globalDragStartMousePosition = globalPos;
|
||||||
|
m_dragStartMousePosition = q->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>
|
||||||
|
AbstractFloatingWidget *createFloatingWidget(T *widget)
|
||||||
|
{
|
||||||
|
auto w = new FloatingDragPreview(widget);
|
||||||
|
q->connect(w, &FloatingDragPreview::draggingCanceled, [=]() {
|
||||||
|
m_dragState = DraggingInactive;
|
||||||
|
});
|
||||||
|
return w;
|
||||||
|
}
|
||||||
}; // struct DockWidgetTabPrivate
|
}; // struct DockWidgetTabPrivate
|
||||||
|
|
||||||
AutoHideTabPrivate::AutoHideTabPrivate(AutoHideTab *parent)
|
AutoHideTabPrivate::AutoHideTabPrivate(AutoHideTab *parent)
|
||||||
@@ -71,25 +127,47 @@ void AutoHideTabPrivate::updateOrientation()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AutoHideTab::setSideBar(AutoHideSideBar *sideTabBar)
|
bool AutoHideTabPrivate::startFloating(eDragState draggingState)
|
||||||
{
|
{
|
||||||
d->m_sideBar = sideTabBar;
|
auto dockArea = m_dockWidget->dockAreaWidget();
|
||||||
if (d->m_sideBar)
|
qCInfo(adsLog) << Q_FUNC_INFO << "isFloating " << dockContainer()->isFloating();
|
||||||
d->updateOrientation();
|
|
||||||
}
|
|
||||||
|
|
||||||
AutoHideSideBar *AutoHideTab::sideBar() const
|
m_dragState = draggingState;
|
||||||
{
|
AbstractFloatingWidget *floatingWidget = nullptr;
|
||||||
return d->m_sideBar;
|
floatingWidget = createFloatingWidget(dockArea);
|
||||||
}
|
auto size = dockArea->size();
|
||||||
|
auto startPos = m_dragStartMousePosition;
|
||||||
|
auto autoHideContainer = m_dockWidget->autoHideDockContainer();
|
||||||
|
m_dragStartOrientation = autoHideContainer->orientation();
|
||||||
|
|
||||||
void AutoHideTab::removeFromSideBar()
|
switch (m_sideBar->sideBarLocation()) {
|
||||||
{
|
case SideBarLeft:
|
||||||
if (d->m_sideBar == nullptr)
|
startPos.rx() = autoHideContainer->rect().left() + 10;
|
||||||
return;
|
break;
|
||||||
|
|
||||||
d->m_sideBar->removeTab(this);
|
case SideBarRight:
|
||||||
setSideBar(nullptr);
|
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, q);
|
||||||
|
auto dockManager = m_dockWidget->dockManager();
|
||||||
|
auto overlay = dockManager->containerOverlay();
|
||||||
|
overlay->setAllowedAreas(OuterDockAreas);
|
||||||
|
m_floatingWidget = floatingWidget;
|
||||||
|
qApp->postEvent(m_dockWidget, new QEvent((QEvent::Type) internal::g_dockedWidgetDragStartEvent));
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoHideTab::AutoHideTab(QWidget *parent)
|
AutoHideTab::AutoHideTab(QWidget *parent)
|
||||||
@@ -164,6 +242,61 @@ void AutoHideTab::setDockWidget(DockWidget *dockWidget)
|
|||||||
setIcon(d->m_dockWidget->icon());
|
setIcon(d->m_dockWidget->icon());
|
||||||
setToolTip(dockWidget->windowTitle());
|
setToolTip(dockWidget->windowTitle());
|
||||||
}
|
}
|
||||||
|
bool AutoHideTab::iconOnly() const
|
||||||
|
{
|
||||||
|
return DockManager::testAutoHideConfigFlag(DockManager::AutoHideSideBarsIconOnly)
|
||||||
|
&& !icon().isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
AutoHideSideBar *AutoHideTab::sideBar() const
|
||||||
|
{
|
||||||
|
return d->m_sideBar;
|
||||||
|
}
|
||||||
|
|
||||||
|
int AutoHideTab::tabIndex() const
|
||||||
|
{
|
||||||
|
if (!d->m_sideBar)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return d->m_sideBar->indexOfTab(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::setDockWidgetFloating()
|
||||||
|
{
|
||||||
|
d->m_dockWidget->setFloating();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::unpinDockWidget()
|
||||||
|
{
|
||||||
|
d->m_dockWidget->setAutoHide(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::requestCloseDockWidget()
|
||||||
|
{
|
||||||
|
d->m_dockWidget->requestCloseDockWidget();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::onAutoHideToActionClicked()
|
||||||
|
{
|
||||||
|
int location = sender()->property(g_locationProperty).toInt();
|
||||||
|
d->m_dockWidget->setAutoHide(true, (SideBarLocation) location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::setSideBar(AutoHideSideBar *sideTabBar)
|
||||||
|
{
|
||||||
|
d->m_sideBar = sideTabBar;
|
||||||
|
if (d->m_sideBar)
|
||||||
|
d->updateOrientation();
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::removeFromSideBar()
|
||||||
|
{
|
||||||
|
if (d->m_sideBar == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d->m_sideBar->removeTab(this);
|
||||||
|
setSideBar(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
bool AutoHideTab::event(QEvent *event)
|
bool AutoHideTab::event(QEvent *event)
|
||||||
{
|
{
|
||||||
@@ -194,10 +327,138 @@ bool AutoHideTab::event(QEvent *event)
|
|||||||
return Super::event(event);
|
return Super::event(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AutoHideTab::iconOnly() const
|
void AutoHideTab::contextMenuEvent(QContextMenuEvent *event)
|
||||||
{
|
{
|
||||||
return DockManager::testAutoHideConfigFlag(DockManager::AutoHideSideBarsIconOnly)
|
event->accept();
|
||||||
&& !icon().isNull();
|
d->saveDragStartMousePosition(event->globalPos());
|
||||||
|
|
||||||
|
const bool isFloatable = d->m_dockWidget->features().testFlag(DockWidget::DockWidgetFloatable);
|
||||||
|
QMenu menu(this);
|
||||||
|
|
||||||
|
QAction *detachAction = menu.addAction(tr("Detach"));
|
||||||
|
detachAction->connect(detachAction,
|
||||||
|
&QAction::triggered,
|
||||||
|
this,
|
||||||
|
&AutoHideTab::setDockWidgetFloating);
|
||||||
|
detachAction->setEnabled(isFloatable);
|
||||||
|
|
||||||
|
auto isPinnable = d->m_dockWidget->features().testFlag(DockWidget::DockWidgetPinnable);
|
||||||
|
detachAction->setEnabled(isPinnable);
|
||||||
|
|
||||||
|
auto pinToMenu = menu.addMenu(tr("Pin To..."));
|
||||||
|
pinToMenu->setEnabled(isPinnable);
|
||||||
|
d->createAutoHideToAction(tr("Top"), SideBarTop, pinToMenu);
|
||||||
|
d->createAutoHideToAction(tr("Left"), SideBarLeft, pinToMenu);
|
||||||
|
d->createAutoHideToAction(tr("Right"), SideBarRight, pinToMenu);
|
||||||
|
d->createAutoHideToAction(tr("Bottom"), SideBarBottom, pinToMenu);
|
||||||
|
|
||||||
|
QAction *unpinAction = menu.addAction(tr("Unpin (Dock)"));
|
||||||
|
unpinAction->connect(unpinAction, &QAction::triggered, this, &AutoHideTab::unpinDockWidget);
|
||||||
|
menu.addSeparator();
|
||||||
|
QAction *closeAction = menu.addAction(tr("Close"));
|
||||||
|
closeAction->connect(closeAction,
|
||||||
|
&QAction::triggered,
|
||||||
|
this,
|
||||||
|
&AutoHideTab::requestCloseDockWidget);
|
||||||
|
closeAction->setEnabled(d->m_dockWidget->features().testFlag(DockWidget::DockWidgetClosable));
|
||||||
|
|
||||||
|
menu.exec(event->globalPos());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::mousePressEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
// 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->m_timeSinceHoverMousePress.restart();
|
||||||
|
d->forwardEventToDockContainer(event);
|
||||||
|
} else if (d->m_timeSinceHoverMousePress.hasExpired(500)) {
|
||||||
|
d->forwardEventToDockContainer(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
event->accept();
|
||||||
|
d->m_mousePressed = true;
|
||||||
|
d->saveDragStartMousePosition(event->globalPosition().toPoint());
|
||||||
|
d->m_dragState = DraggingMousePressed;
|
||||||
|
}
|
||||||
|
|
||||||
|
Super::mousePressEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::mouseReleaseEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (event->button() == Qt::LeftButton) {
|
||||||
|
d->m_mousePressed = false;
|
||||||
|
auto currentDragState = d->m_dragState;
|
||||||
|
d->m_globalDragStartMousePosition = QPoint();
|
||||||
|
d->m_dragStartMousePosition = QPoint();
|
||||||
|
d->m_dragState = DraggingInactive;
|
||||||
|
|
||||||
|
switch (currentDragState) {
|
||||||
|
case DraggingTab:
|
||||||
|
// End of tab moving, emit signal
|
||||||
|
//if (d->DockArea) {
|
||||||
|
// event->accept();
|
||||||
|
// Q_EMIT moved(internal::globalPositionOf(event));
|
||||||
|
//}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case DraggingFloatingWidget:
|
||||||
|
event->accept();
|
||||||
|
d->m_floatingWidget->finishDragging();
|
||||||
|
if (d->m_dockWidget->isAutoHide() && d->m_dragStartOrientation != orientation())
|
||||||
|
d->m_dockWidget->autoHideDockContainer()->resetToInitialDockWidgetSize();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break; // do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Super::mouseReleaseEvent(event);
|
||||||
|
}
|
||||||
|
|
||||||
|
void AutoHideTab::mouseMoveEvent(QMouseEvent *event)
|
||||||
|
{
|
||||||
|
if (!(event->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive)) {
|
||||||
|
d->m_dragState = DraggingInactive;
|
||||||
|
Super::mouseMoveEvent(event);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move floating window
|
||||||
|
if (d->isDraggingState(DraggingFloatingWidget)) {
|
||||||
|
d->m_floatingWidget->moveFloating();
|
||||||
|
Super::mouseMoveEvent(event);
|
||||||
|
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(event->pos());
|
||||||
|
bool mouseOutsideBar = (mappedPos.x() < 0) || (mappedPos.x() > parentWidget()->rect().right());
|
||||||
|
// Maybe a fixed drag distance is better here ?
|
||||||
|
int dragDistanceY = qAbs(d->m_globalDragStartMousePosition.y()
|
||||||
|
- event->globalPosition().toPoint().y());
|
||||||
|
if (dragDistanceY >= DockManager::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->m_dockWidget->features();
|
||||||
|
if (Features.testFlag(DockWidget::DockWidgetFloatable)
|
||||||
|
|| (Features.testFlag(DockWidget::DockWidgetMovable))) {
|
||||||
|
d->startFloating();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Super::mouseMoveEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ADS
|
} // namespace ADS
|
||||||
|
@@ -38,10 +38,16 @@ private:
|
|||||||
friend class DockContainerWidget;
|
friend class DockContainerWidget;
|
||||||
friend DockContainerWidgetPrivate;
|
friend DockContainerWidgetPrivate;
|
||||||
|
|
||||||
|
void onAutoHideToActionClicked();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setSideBar(AutoHideSideBar *sideTabBar);
|
void setSideBar(AutoHideSideBar *sideTabBar);
|
||||||
void removeFromSideBar();
|
void removeFromSideBar();
|
||||||
virtual bool event(QEvent *event) override;
|
virtual bool event(QEvent *event) override;
|
||||||
|
virtual void contextMenuEvent(QContextMenuEvent *event) override;
|
||||||
|
virtual void mousePressEvent(QMouseEvent *event) override;
|
||||||
|
virtual void mouseReleaseEvent(QMouseEvent *event) override;
|
||||||
|
virtual void mouseMoveEvent(QMouseEvent *event) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Super = PushButton;
|
using Super = PushButton;
|
||||||
@@ -102,6 +108,26 @@ public:
|
|||||||
* Returns the side bar that contains this tab or a nullptr if the tab is not in a side bar.
|
* Returns the side bar that contains this tab or a nullptr if the tab is not in a side bar.
|
||||||
*/
|
*/
|
||||||
AutoHideSideBar *sideBar() const;
|
AutoHideSideBar *sideBar() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the index of this tab in the sideBar.
|
||||||
|
*/
|
||||||
|
int tabIndex() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the dock widget floating, if it is floatable
|
||||||
|
*/
|
||||||
|
void setDockWidgetFloating();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Unpin and dock the auto hide widget.
|
||||||
|
*/
|
||||||
|
void unpinDockWidget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls the requestCloseDockWidget() function for the assigned dock widget.
|
||||||
|
*/
|
||||||
|
void requestCloseDockWidget();
|
||||||
}; // class AutoHideTab
|
}; // class AutoHideTab
|
||||||
|
|
||||||
} // namespace ADS
|
} // namespace ADS
|
||||||
|
@@ -104,6 +104,75 @@ DockAreaTabBar::~DockAreaTabBar()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockAreaTabBar::onTabClicked(DockWidgetTab *sourceTab)
|
||||||
|
{
|
||||||
|
const int index = d->m_tabsLayout->indexOf(sourceTab);
|
||||||
|
if (index < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
setCurrentIndex(index);
|
||||||
|
emit tabBarClicked(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockAreaTabBar::onTabCloseRequested(DockWidgetTab *sourceTab)
|
||||||
|
{
|
||||||
|
const int index = d->m_tabsLayout->indexOf(sourceTab);
|
||||||
|
closeTab(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockAreaTabBar::onCloseOtherTabsRequested(DockWidgetTab *sourceTab)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < count(); ++i) {
|
||||||
|
auto currentTab = tab(i);
|
||||||
|
if (currentTab->isClosable() && !currentTab->isHidden() && currentTab != sourceTab) {
|
||||||
|
// If the dock widget is deleted with the closeTab() call, its tab it will no longer
|
||||||
|
// be in the layout, and thus the index needs to be updated to not skip any tabs.
|
||||||
|
int offset = currentTab->dockWidget()->features().testFlag(
|
||||||
|
DockWidget::DockWidgetDeleteOnClose)
|
||||||
|
? 1
|
||||||
|
: 0;
|
||||||
|
closeTab(i);
|
||||||
|
// If the the dock widget blocks closing, i.e. if the flag CustomCloseHandling is set,
|
||||||
|
// and the dock widget is still open, then we do not need to correct the index.
|
||||||
|
if (currentTab->dockWidget()->isClosed())
|
||||||
|
i -= offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockAreaTabBar::onTabWidgetMoved(DockWidgetTab *sourceTab, const QPoint &globalPosition)
|
||||||
|
{
|
||||||
|
const int fromIndex = d->m_tabsLayout->indexOf(sourceTab);
|
||||||
|
auto mousePos = mapFromGlobal(globalPosition);
|
||||||
|
mousePos.rx() = qMax(d->firstTab()->geometry().left(), mousePos.x());
|
||||||
|
mousePos.rx() = qMin(d->lastTab()->geometry().right(), mousePos.x());
|
||||||
|
int toIndex = -1;
|
||||||
|
// Find tab under mouse
|
||||||
|
for (int i = 0; i < count(); ++i) {
|
||||||
|
DockWidgetTab *dropTab = tab(i);
|
||||||
|
if (dropTab == sourceTab || !dropTab->isVisibleTo(this)
|
||||||
|
|| !dropTab->geometry().contains(mousePos))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
toIndex = d->m_tabsLayout->indexOf(dropTab);
|
||||||
|
if (toIndex == fromIndex)
|
||||||
|
toIndex = -1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (toIndex > -1) {
|
||||||
|
d->m_tabsLayout->removeWidget(sourceTab);
|
||||||
|
d->m_tabsLayout->insertWidget(toIndex, sourceTab);
|
||||||
|
qCInfo(adsLog) << "tabMoved from" << fromIndex << "to" << toIndex;
|
||||||
|
emit tabMoved(fromIndex, toIndex);
|
||||||
|
setCurrentIndex(toIndex);
|
||||||
|
} else {
|
||||||
|
// Ensure that the moved tab is reset to its start position
|
||||||
|
d->m_tabsLayout->update();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DockAreaTabBar::wheelEvent(QWheelEvent *event)
|
void DockAreaTabBar::wheelEvent(QWheelEvent *event)
|
||||||
{
|
{
|
||||||
event->accept();
|
event->accept();
|
||||||
@@ -114,23 +183,6 @@ void DockAreaTabBar::wheelEvent(QWheelEvent *event)
|
|||||||
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
horizontalScrollBar()->setValue(horizontalScrollBar()->value() - 20);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockAreaTabBar::setCurrentIndex(int index)
|
|
||||||
{
|
|
||||||
if (index == d->m_currentIndex)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (index < -1 || index > (count() - 1)) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
emit currentChanging(index);
|
|
||||||
d->m_currentIndex = index;
|
|
||||||
d->updateTabs();
|
|
||||||
updateGeometry();
|
|
||||||
emit currentChanged(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
int DockAreaTabBar::count() const
|
int DockAreaTabBar::count() const
|
||||||
{
|
{
|
||||||
// The tab bar contains a stretch item as last item
|
// The tab bar contains a stretch item as last item
|
||||||
@@ -226,42 +278,6 @@ DockWidgetTab *DockAreaTabBar::currentTab() const
|
|||||||
return qobject_cast<DockWidgetTab *>(d->m_tabsLayout->itemAt(d->m_currentIndex)->widget());
|
return qobject_cast<DockWidgetTab *>(d->m_tabsLayout->itemAt(d->m_currentIndex)->widget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockAreaTabBar::onTabClicked(DockWidgetTab *sourceTab)
|
|
||||||
{
|
|
||||||
const int index = d->m_tabsLayout->indexOf(sourceTab);
|
|
||||||
if (index < 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
setCurrentIndex(index);
|
|
||||||
emit tabBarClicked(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockAreaTabBar::onTabCloseRequested(DockWidgetTab *sourceTab)
|
|
||||||
{
|
|
||||||
const int index = d->m_tabsLayout->indexOf(sourceTab);
|
|
||||||
closeTab(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockAreaTabBar::onCloseOtherTabsRequested(DockWidgetTab *sourceTab)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < count(); ++i) {
|
|
||||||
auto currentTab = tab(i);
|
|
||||||
if (currentTab->isClosable() && !currentTab->isHidden() && currentTab != sourceTab) {
|
|
||||||
// If the dock widget is deleted with the closeTab() call, its tab it will no longer
|
|
||||||
// be in the layout, and thus the index needs to be updated to not skip any tabs.
|
|
||||||
int offset = currentTab->dockWidget()->features().testFlag(
|
|
||||||
DockWidget::DockWidgetDeleteOnClose)
|
|
||||||
? 1
|
|
||||||
: 0;
|
|
||||||
closeTab(i);
|
|
||||||
// If the the dock widget blocks closing, i.e. if the flag CustomCloseHandling is set,
|
|
||||||
// and the dock widget is still open, then we do not need to correct the index.
|
|
||||||
if (currentTab->dockWidget()->isClosed())
|
|
||||||
i -= offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
DockWidgetTab *DockAreaTabBar::tab(int index) const
|
DockWidgetTab *DockAreaTabBar::tab(int index) const
|
||||||
{
|
{
|
||||||
if (index >= count() || index < 0)
|
if (index >= count() || index < 0)
|
||||||
@@ -270,49 +286,29 @@ DockWidgetTab *DockAreaTabBar::tab(int index) const
|
|||||||
return qobject_cast<DockWidgetTab *>(d->m_tabsLayout->itemAt(index)->widget());
|
return qobject_cast<DockWidgetTab *>(d->m_tabsLayout->itemAt(index)->widget());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockAreaTabBar::onTabWidgetMoved(DockWidgetTab *sourceTab, const QPoint &globalPosition)
|
int DockAreaTabBar::tabAt(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
const int fromIndex = d->m_tabsLayout->indexOf(sourceTab);
|
if (!isVisible())
|
||||||
auto mousePos = mapFromGlobal(globalPosition);
|
return TabInvalidIndex;
|
||||||
mousePos.rx() = qMax(d->firstTab()->geometry().left(), mousePos.x());
|
|
||||||
mousePos.rx() = qMin(d->lastTab()->geometry().right(), mousePos.x());
|
if (pos.x() < tab(0)->geometry().x())
|
||||||
int toIndex = -1;
|
return -1;
|
||||||
// Find tab under mouse
|
|
||||||
for (int i = 0; i < count(); ++i) {
|
for (int i = 0; i < count(); ++i) {
|
||||||
DockWidgetTab *dropTab = tab(i);
|
if (tab(i)->geometry().contains(pos))
|
||||||
if (dropTab == sourceTab || !dropTab->isVisibleTo(this)
|
return i;
|
||||||
|| !dropTab->geometry().contains(mousePos))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
toIndex = d->m_tabsLayout->indexOf(dropTab);
|
|
||||||
if (toIndex == fromIndex)
|
|
||||||
toIndex = -1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (toIndex > -1) {
|
return count();
|
||||||
d->m_tabsLayout->removeWidget(sourceTab);
|
|
||||||
d->m_tabsLayout->insertWidget(toIndex, sourceTab);
|
|
||||||
qCInfo(adsLog) << "tabMoved from" << fromIndex << "to" << toIndex;
|
|
||||||
emit tabMoved(fromIndex, toIndex);
|
|
||||||
setCurrentIndex(toIndex);
|
|
||||||
} else {
|
|
||||||
// Ensure that the moved tab is reset to its start position
|
|
||||||
d->m_tabsLayout->update();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockAreaTabBar::closeTab(int index)
|
int DockAreaTabBar::tabInsertIndexAt(const QPoint &pos) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= count())
|
int index = tabAt(pos);
|
||||||
return;
|
if (index == TabInvalidIndex)
|
||||||
|
return TabDefaultInsertIndex;
|
||||||
auto dockWidgetTab = tab(index);
|
else
|
||||||
if (dockWidgetTab->isHidden())
|
return (index < 0) ? 0 : index;
|
||||||
return;
|
|
||||||
|
|
||||||
emit tabCloseRequested(index);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockAreaTabBar::eventFilter(QObject *watched, QEvent *event)
|
bool DockAreaTabBar::eventFilter(QObject *watched, QEvent *event)
|
||||||
@@ -362,4 +358,33 @@ QSize DockAreaTabBar::sizeHint() const
|
|||||||
return d->m_tabsContainerWidget->sizeHint();
|
return d->m_tabsContainerWidget->sizeHint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockAreaTabBar::setCurrentIndex(int index)
|
||||||
|
{
|
||||||
|
if (index == d->m_currentIndex)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (index < -1 || index > (count() - 1)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Invalid index" << index;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit currentChanging(index);
|
||||||
|
d->m_currentIndex = index;
|
||||||
|
d->updateTabs();
|
||||||
|
updateGeometry();
|
||||||
|
emit currentChanged(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockAreaTabBar::closeTab(int index)
|
||||||
|
{
|
||||||
|
if (index < 0 || index >= count())
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto dockWidgetTab = tab(index);
|
||||||
|
if (dockWidgetTab->isHidden())
|
||||||
|
return;
|
||||||
|
|
||||||
|
emit tabCloseRequested(index);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ADS
|
} // namespace ADS
|
||||||
|
@@ -86,6 +86,18 @@ public:
|
|||||||
*/
|
*/
|
||||||
DockWidgetTab *tab(int index) const;
|
DockWidgetTab *tab(int index) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tab at the given position.
|
||||||
|
* Returns -1 if the position is left of the first tab and count() if the position is right
|
||||||
|
* of the last tab. Returns -2 to indicate an invalid value.
|
||||||
|
*/
|
||||||
|
int tabAt(const QPoint &pos) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the tab insertion index for the given mouse cursor position.
|
||||||
|
*/
|
||||||
|
int tabInsertIndexAt(const QPoint &pos) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Filters the tab widget events
|
* Filters the tab widget events
|
||||||
*/
|
*/
|
||||||
|
@@ -44,10 +44,10 @@ class DockAreaTitleBarPrivate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
DockAreaTitleBar *q;
|
DockAreaTitleBar *q;
|
||||||
QPointer<TitleBarButtonType> m_tabsMenuButton;
|
QPointer<TitleBarButton> m_tabsMenuButton;
|
||||||
QPointer<TitleBarButtonType> m_autoHideButton;
|
QPointer<TitleBarButton> m_autoHideButton;
|
||||||
QPointer<TitleBarButtonType> m_undockButton;
|
QPointer<TitleBarButton> m_undockButton;
|
||||||
QPointer<TitleBarButtonType> m_closeButton;
|
QPointer<TitleBarButton> m_closeButton;
|
||||||
QBoxLayout *m_layout = nullptr;
|
QBoxLayout *m_layout = nullptr;
|
||||||
DockAreaWidget *m_dockArea = nullptr;
|
DockAreaWidget *m_dockArea = nullptr;
|
||||||
DockAreaTabBar *m_tabBar = nullptr;
|
DockAreaTabBar *m_tabBar = nullptr;
|
||||||
@@ -306,9 +306,9 @@ void DockAreaTitleBarPrivate::startFloating(const QPoint &offset)
|
|||||||
qApp->postEvent(m_dockArea, new QEvent((QEvent::Type) internal::g_dockedWidgetDragStartEvent));
|
qApp->postEvent(m_dockArea, new QEvent((QEvent::Type) internal::g_dockedWidgetDragStartEvent));
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBarButton::TitleBarButton(bool visible, QWidget *parent)
|
TitleBarButton::TitleBarButton(bool showInTitleBar, QWidget *parent)
|
||||||
: TitleBarButtonType(parent)
|
: TitleBarButtonType(parent)
|
||||||
, m_visible(visible)
|
, m_showInTitleBar(showInTitleBar)
|
||||||
, m_hideWhenDisabled(
|
, m_hideWhenDisabled(
|
||||||
DockAreaTitleBarPrivate::testConfigFlag(DockManager::DockAreaHideDisabledButtons))
|
DockAreaTitleBarPrivate::testConfigFlag(DockManager::DockAreaHideDisabledButtons))
|
||||||
{
|
{
|
||||||
@@ -317,8 +317,8 @@ TitleBarButton::TitleBarButton(bool visible, QWidget *parent)
|
|||||||
|
|
||||||
void TitleBarButton::setVisible(bool visible)
|
void TitleBarButton::setVisible(bool visible)
|
||||||
{
|
{
|
||||||
// 'visible' can stay 'true' if and only if this button is configured to generaly visible:
|
// 'visible' can stay 'true' if and only if this button is configured to generally visible:
|
||||||
visible = visible && m_visible;
|
visible = visible && m_showInTitleBar;
|
||||||
|
|
||||||
// 'visible' can stay 'true' unless: this button is configured to be invisible when it
|
// 'visible' can stay 'true' unless: this button is configured to be invisible when it
|
||||||
// is disabled and it is currently disabled:
|
// is disabled and it is currently disabled:
|
||||||
@@ -328,6 +328,14 @@ void TitleBarButton::setVisible(bool visible)
|
|||||||
Super::setVisible(visible);
|
Super::setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TitleBarButton::setShowInTitleBar(bool show)
|
||||||
|
{
|
||||||
|
m_showInTitleBar = show;
|
||||||
|
|
||||||
|
if (!show)
|
||||||
|
setVisible(false);
|
||||||
|
}
|
||||||
|
|
||||||
bool TitleBarButton::event(QEvent *event)
|
bool TitleBarButton::event(QEvent *event)
|
||||||
{
|
{
|
||||||
if (QEvent::EnabledChange == event->type() && m_hideWhenDisabled) {
|
if (QEvent::EnabledChange == event->type() && m_hideWhenDisabled) {
|
||||||
@@ -524,7 +532,7 @@ void DockAreaTitleBar::onAutoHideToActionClicked()
|
|||||||
d->m_dockArea->toggleAutoHide((SideBarLocation) location);
|
d->m_dockArea->toggleAutoHide((SideBarLocation) location);
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractButton *DockAreaTitleBar::button(eTitleBarButton which) const
|
TitleBarButton *DockAreaTitleBar::button(eTitleBarButton which) const
|
||||||
{
|
{
|
||||||
switch (which) {
|
switch (which) {
|
||||||
case TitleBarButtonTabsMenu:
|
case TitleBarButtonTabsMenu:
|
||||||
@@ -733,4 +741,19 @@ QString DockAreaTitleBar::titleBarButtonToolTip(eTitleBarButton button) const
|
|||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockAreaTitleBar::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.
|
||||||
|
auto dockContainer = d->m_dockArea->dockContainer();
|
||||||
|
if (dockContainer->isFloating() && dockContainer->dockAreaCount() == 1
|
||||||
|
&& !d->m_dockArea->isAutoHide())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!d->m_dockArea->features().testFlag(DockWidget::DockWidgetFloatable))
|
||||||
|
return;
|
||||||
|
|
||||||
|
d->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ADS
|
} // namespace ADS
|
||||||
|
@@ -30,17 +30,22 @@ using TitleBarButtonType = QToolButton;
|
|||||||
class TitleBarButton : public TitleBarButtonType
|
class TitleBarButton : public TitleBarButtonType
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
bool m_visible = true;
|
bool m_showInTitleBar = true;
|
||||||
bool m_hideWhenDisabled = false;
|
bool m_hideWhenDisabled = false;
|
||||||
public:
|
public:
|
||||||
using Super = TitleBarButtonType;
|
using Super = TitleBarButtonType;
|
||||||
TitleBarButton(bool visible = true, QWidget *parent = nullptr);
|
TitleBarButton(bool showInTitleBar = true, QWidget *parent = nullptr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adjust this visibility change request with our internal settings:
|
* Adjust this visibility change request with our internal settings:
|
||||||
*/
|
*/
|
||||||
void setVisible(bool visible) override;
|
void setVisible(bool visible) override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures, if the title bar button should be shown in title bar
|
||||||
|
*/
|
||||||
|
void setShowInTitleBar(bool show);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/**
|
/**
|
||||||
* Handle EnabledChanged signal to set button invisible if the configured
|
* Handle EnabledChanged signal to set button invisible if the configured
|
||||||
@@ -139,7 +144,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Returns the button corresponding to the given title bar button identifier
|
* Returns the button corresponding to the given title bar button identifier
|
||||||
*/
|
*/
|
||||||
QAbstractButton *button(eTitleBarButton which) const;
|
TitleBarButton *button(eTitleBarButton which) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the auto hide title label, used when the dock area is expanded and auto hidden
|
* Returns the auto hide title label, used when the dock area is expanded and auto hidden
|
||||||
@@ -181,6 +186,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
QString titleBarButtonToolTip(eTitleBarButton button) const;
|
QString titleBarButtonToolTip(eTitleBarButton button) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the dock area into its own floating widget if the area DockWidgetFloatable flag is true.
|
||||||
|
*/
|
||||||
|
void setAreaFloating();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* This signal is emitted if a tab in the tab bar is clicked by the user
|
* This signal is emitted if a tab in the tab bar is clicked by the user
|
||||||
|
@@ -374,6 +374,7 @@ void DockAreaWidget::setAutoHideDockContainer(AutoHideDockContainer *autoHideDoc
|
|||||||
d->m_autoHideDockContainer = autoHideDockContainer;
|
d->m_autoHideDockContainer = autoHideDockContainer;
|
||||||
updateAutoHideButtonCheckState();
|
updateAutoHideButtonCheckState();
|
||||||
updateTitleBarButtonsToolTips();
|
updateTitleBarButtonsToolTips();
|
||||||
|
d->m_titleBar->button(TitleBarButtonAutoHide)->setShowInTitleBar(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockAreaWidget::addDockWidget(DockWidget *dockWidget)
|
void DockAreaWidget::addDockWidget(DockWidget *dockWidget)
|
||||||
@@ -504,12 +505,7 @@ void DockAreaWidget::hideAreaWithNoVisibleContent()
|
|||||||
void DockAreaWidget::onTabCloseRequested(int index)
|
void DockAreaWidget::onTabCloseRequested(int index)
|
||||||
{
|
{
|
||||||
qCInfo(adsLog) << Q_FUNC_INFO << "index" << index;
|
qCInfo(adsLog) << Q_FUNC_INFO << "index" << index;
|
||||||
auto *currentDockWidget = dockWidget(index);
|
dockWidget(index)->requestCloseDockWidget();
|
||||||
if (currentDockWidget->features().testFlag(DockWidget::DockWidgetDeleteOnClose)
|
|
||||||
|| currentDockWidget->features().testFlag(DockWidget::CustomCloseHandling))
|
|
||||||
currentDockWidget->closeDockWidgetInternal();
|
|
||||||
else
|
|
||||||
currentDockWidget->toggleView(false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DockWidget *DockAreaWidget::currentDockWidget() const
|
DockWidget *DockAreaWidget::currentDockWidget() const
|
||||||
@@ -1075,27 +1071,33 @@ SideBarLocation DockAreaWidget::calculateSideTabBarArea() const
|
|||||||
return sideTab;
|
return sideTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockAreaWidget::setAutoHide(bool enable, SideBarLocation location)
|
void DockAreaWidget::setAutoHide(bool enable, SideBarLocation location, int tabIndex)
|
||||||
{
|
{
|
||||||
if (!isAutoHideFeatureEnabled())
|
if (!isAutoHideFeatureEnabled())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!enable) {
|
if (!enable) {
|
||||||
if (isAutoHide())
|
if (isAutoHide())
|
||||||
autoHideDockContainer()->moveContentsToParent();
|
d->m_autoHideDockContainer->moveContentsToParent();
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If this is already an auto hide container, then move it to new location.
|
||||||
|
if (isAutoHide()) {
|
||||||
|
d->m_autoHideDockContainer->moveToNewSideBarLocation(location, tabIndex);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto area = (SideBarNone == location) ? calculateSideTabBarArea() : location;
|
auto area = (SideBarNone == location) ? calculateSideTabBarArea() : location;
|
||||||
for (const auto DockWidget : openedDockWidgets()) {
|
for (const auto dockWidget : openedDockWidgets()) {
|
||||||
if (enable == isAutoHide())
|
if (enable == isAutoHide())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!DockWidget->features().testFlag(DockWidget::DockWidgetPinnable))
|
if (!dockWidget->features().testFlag(DockWidget::DockWidgetPinnable))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
dockContainer()->createAndSetupAutoHideContainer(area, DockWidget);
|
dockContainer()->createAndSetupAutoHideContainer(area, dockWidget, tabIndex++);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1112,6 +1114,11 @@ void DockAreaWidget::closeOtherAreas()
|
|||||||
dockContainer()->closeOtherAreas(this);
|
dockContainer()->closeOtherAreas(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockAreaWidget::setFloating()
|
||||||
|
{
|
||||||
|
d->m_titleBar->setAreaFloating();
|
||||||
|
}
|
||||||
|
|
||||||
DockAreaTitleBar *DockAreaWidget::titleBar() const
|
DockAreaTitleBar *DockAreaWidget::titleBar() const
|
||||||
{
|
{
|
||||||
return d->m_titleBar;
|
return d->m_titleBar;
|
||||||
|
@@ -369,7 +369,7 @@ public:
|
|||||||
* If the dock area is switched to auto hide mode, then all dock widgets
|
* If the dock area is switched to auto hide mode, then all dock widgets
|
||||||
* that are pinable will be added to the sidebar
|
* that are pinable will be added to the sidebar
|
||||||
*/
|
*/
|
||||||
void setAutoHide(bool enable, SideBarLocation location = SideBarNone);
|
void setAutoHide(bool enable, SideBarLocation location = SideBarNone, int tabIndex = -1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches the dock area to auto hide mode or vice versa depending on its
|
* Switches the dock area to auto hide mode or vice versa depending on its
|
||||||
@@ -382,6 +382,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void closeOtherAreas();
|
void closeOtherAreas();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Moves the dock area into its own floating widget if the area DockWidgetFloatable flag is true.
|
||||||
|
*/
|
||||||
|
void setFloating();
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
* This signal is emitted when user clicks on a tab at an index.
|
* This signal is emitted when user clicks on a tab at an index.
|
||||||
|
@@ -84,7 +84,7 @@ public:
|
|||||||
QList<AutoHideDockContainer *> m_autoHideWidgets;
|
QList<AutoHideDockContainer *> m_autoHideWidgets;
|
||||||
QMap<SideBarLocation, AutoHideSideBar *> m_sideTabBarWidgets;
|
QMap<SideBarLocation, AutoHideSideBar *> m_sideTabBarWidgets;
|
||||||
QGridLayout *m_layout = nullptr;
|
QGridLayout *m_layout = nullptr;
|
||||||
QSplitter *m_rootSplitter = nullptr;
|
DockSplitter *m_rootSplitter = nullptr;
|
||||||
bool m_isFloating = false;
|
bool m_isFloating = false;
|
||||||
DockAreaWidget *m_lastAddedAreaCache[5];
|
DockAreaWidget *m_lastAddedAreaCache[5];
|
||||||
int m_visibleDockAreaCount = -1;
|
int m_visibleDockAreaCount = -1;
|
||||||
@@ -122,34 +122,51 @@ public:
|
|||||||
*/
|
*/
|
||||||
void dropIntoContainer(FloatingDockContainer *floatingWidget, DockWidgetArea area);
|
void dropIntoContainer(FloatingDockContainer *floatingWidget, DockWidgetArea area);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Drop floating widget into auto hide side bar
|
||||||
|
*/
|
||||||
|
void dropIntoAutoHideSideBar(FloatingDockContainer *floatingWidget, DockWidgetArea area);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new tab for a widget dropped into the center of a section
|
||||||
|
*/
|
||||||
|
void dropIntoCenterOfSection(FloatingDockContainer *floatingWidget,
|
||||||
|
DockAreaWidget *targetArea,
|
||||||
|
int tabIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Drop floating widget into dock area
|
* Drop floating widget into dock area
|
||||||
*/
|
*/
|
||||||
void dropIntoSection(FloatingDockContainer *floatingWidget,
|
void dropIntoSection(FloatingDockContainer *floatingWidget,
|
||||||
DockAreaWidget *targetArea,
|
DockAreaWidget *targetArea,
|
||||||
DockWidgetArea area);
|
DockWidgetArea area,
|
||||||
|
int tabIndex = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the dock widget or dock area given in Widget parameter to a
|
* Moves the dock widget or dock area given in Widget parameter to a new dock widget area.
|
||||||
* new dock widget area
|
|
||||||
*/
|
*/
|
||||||
void moveToNewSection(QWidget *widget, DockAreaWidget *targetArea, DockWidgetArea area);
|
void moveToNewSection(QWidget *widget,
|
||||||
|
DockAreaWidget *targetArea,
|
||||||
|
DockWidgetArea area,
|
||||||
|
int tabIndex = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Moves the dock widget or dock area given in Widget parameter to a
|
* Moves the dock widget or dock area given in Widget parameter to a dock area in container.
|
||||||
* a dock area in container
|
|
||||||
*/
|
*/
|
||||||
void moveToContainer(QWidget *widget, DockWidgetArea area);
|
void moveToContainer(QWidget *widget, DockWidgetArea area);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new tab for a widget dropped into the center of a section
|
* Creates a new tab for a widget dropped into the center of a section
|
||||||
*/
|
*/
|
||||||
void dropIntoCenterOfSection(FloatingDockContainer *floatingWidget, DockAreaWidget *targetArea);
|
void moveIntoCenterOfSection(QWidget *widget, DockAreaWidget *targetArea, int tabIndex = 0);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new tab for a widget dropped into the center of a section
|
* Moves the dock widget or dock area given in Widget parameter to
|
||||||
|
* a auto hide sidebar area
|
||||||
*/
|
*/
|
||||||
void moveIntoCenterOfSection(QWidget *widget, DockAreaWidget *targetArea);
|
void moveToAutoHideSideBar(QWidget *widget,
|
||||||
|
DockWidgetArea area,
|
||||||
|
int tabIndex = TabDefaultInsertIndex);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds new dock areas to the internal dock area list
|
* Adds new dock areas to the internal dock area list
|
||||||
@@ -371,12 +388,12 @@ void DockContainerWidgetPrivate::dropIntoContainer(FloatingDockContainer *floati
|
|||||||
auto newDockAreas
|
auto newDockAreas
|
||||||
= floatingDockContainer->findChildren<DockAreaWidget *>(QString(),
|
= floatingDockContainer->findChildren<DockAreaWidget *>(QString(),
|
||||||
Qt::FindChildrenRecursively);
|
Qt::FindChildrenRecursively);
|
||||||
QSplitter *splitter = m_rootSplitter;
|
auto *splitter = m_rootSplitter;
|
||||||
|
|
||||||
if (m_dockAreas.count() <= 1) {
|
if (m_dockAreas.count() <= 1) {
|
||||||
splitter->setOrientation(insertParam.orientation());
|
splitter->setOrientation(insertParam.orientation());
|
||||||
} else if (splitter->orientation() != insertParam.orientation()) {
|
} else if (splitter->orientation() != insertParam.orientation()) {
|
||||||
QSplitter *newSplitter = createSplitter(insertParam.orientation());
|
auto *newSplitter = createSplitter(insertParam.orientation());
|
||||||
QLayoutItem *layoutItem = m_layout->replaceWidget(splitter, newSplitter);
|
QLayoutItem *layoutItem = m_layout->replaceWidget(splitter, newSplitter);
|
||||||
newSplitter->addWidget(splitter);
|
newSplitter->addWidget(splitter);
|
||||||
updateSplitterHandles(newSplitter);
|
updateSplitterHandles(newSplitter);
|
||||||
@@ -411,42 +428,58 @@ void DockContainerWidgetPrivate::dropIntoContainer(FloatingDockContainer *floati
|
|||||||
q->dumpLayout();
|
q->dumpLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockContainerWidgetPrivate::dropIntoAutoHideSideBar(FloatingDockContainer *floatingWidget,
|
||||||
|
DockWidgetArea area)
|
||||||
|
{
|
||||||
|
auto sideBarLocation = internal::toSideBarLocation(area);
|
||||||
|
auto newDockAreas = floatingWidget->findChildren<DockAreaWidget *>(QString(),
|
||||||
|
Qt::FindChildrenRecursively);
|
||||||
|
int tabIndex = m_dockManager->containerOverlay()->tabIndexUnderCursor();
|
||||||
|
for (auto dockArea : newDockAreas) {
|
||||||
|
auto dockWidgets = dockArea->dockWidgets();
|
||||||
|
for (auto dockWidget : dockWidgets)
|
||||||
|
q->createAndSetupAutoHideContainer(sideBarLocation, dockWidget, tabIndex++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DockContainerWidgetPrivate::dropIntoCenterOfSection(FloatingDockContainer *floatingWidget,
|
void DockContainerWidgetPrivate::dropIntoCenterOfSection(FloatingDockContainer *floatingWidget,
|
||||||
DockAreaWidget *targetArea)
|
DockAreaWidget *targetArea,
|
||||||
|
int tabIndex)
|
||||||
{
|
{
|
||||||
DockContainerWidget *floatingContainer = floatingWidget->dockContainer();
|
DockContainerWidget *floatingContainer = floatingWidget->dockContainer();
|
||||||
auto newDockWidgets = floatingContainer->dockWidgets();
|
auto newDockWidgets = floatingContainer->dockWidgets();
|
||||||
auto topLevelDockArea = floatingContainer->topLevelDockArea();
|
auto topLevelDockArea = floatingContainer->topLevelDockArea();
|
||||||
int newCurrentIndex = -1;
|
int newCurrentIndex = -1;
|
||||||
|
tabIndex = qMax(0, tabIndex);
|
||||||
|
|
||||||
// If the floating widget contains only one single dock are, then the
|
// If the floating widget contains only one single dock are, then the current dock widget of
|
||||||
// current dock widget of the dock area will also be the future current
|
// the dock area will also be the future current dock widget in the drop area.
|
||||||
// dock widget in the drop area.
|
|
||||||
if (topLevelDockArea)
|
if (topLevelDockArea)
|
||||||
newCurrentIndex = topLevelDockArea->currentIndex();
|
newCurrentIndex = topLevelDockArea->currentIndex();
|
||||||
|
|
||||||
for (int i = 0; i < newDockWidgets.count(); ++i) {
|
for (int i = 0; i < newDockWidgets.count(); ++i) {
|
||||||
DockWidget *dockWidget = newDockWidgets[i];
|
DockWidget *dockWidget = newDockWidgets[i];
|
||||||
|
targetArea->insertDockWidget(tabIndex + i, dockWidget, false);
|
||||||
targetArea->insertDockWidget(i, dockWidget, false);
|
targetArea->insertDockWidget(i, dockWidget, false);
|
||||||
// If the floating widget contains multiple visible dock areas, then we
|
// If the floating widget contains multiple visible dock areas, then we simply pick the
|
||||||
// simply pick the first visible open dock widget and make it
|
// first visible open dock widget and make it the current one.
|
||||||
// the current one.
|
|
||||||
if (newCurrentIndex < 0 && !dockWidget->isClosed())
|
if (newCurrentIndex < 0 && !dockWidget->isClosed())
|
||||||
newCurrentIndex = i;
|
newCurrentIndex = i;
|
||||||
}
|
}
|
||||||
targetArea->setCurrentIndex(newCurrentIndex);
|
targetArea->setCurrentIndex(newCurrentIndex + tabIndex);
|
||||||
targetArea->updateTitleBarVisibility();
|
targetArea->updateTitleBarVisibility();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockContainerWidgetPrivate::dropIntoSection(FloatingDockContainer *floatingWidget,
|
void DockContainerWidgetPrivate::dropIntoSection(FloatingDockContainer *floatingWidget,
|
||||||
DockAreaWidget *targetArea,
|
DockAreaWidget *targetArea,
|
||||||
DockWidgetArea area)
|
DockWidgetArea area,
|
||||||
|
int tabIndex)
|
||||||
{
|
{
|
||||||
// Dropping into center means all dock widgets in the dropped floating
|
// Dropping into center means all dock widgets in the dropped floating widget will become
|
||||||
// widget will become tabs of the drop area
|
// tabs of the drop area.
|
||||||
if (CenterDockWidgetArea == area) {
|
if (CenterDockWidgetArea == area) {
|
||||||
dropIntoCenterOfSection(floatingWidget, targetArea);
|
dropIntoCenterOfSection(floatingWidget, targetArea, tabIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,44 +558,15 @@ void DockContainerWidgetPrivate::dropIntoSection(FloatingDockContainer *floating
|
|||||||
q->dumpLayout();
|
q->dumpLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget *widget, DockAreaWidget *targetArea)
|
|
||||||
{
|
|
||||||
auto droppedDockWidget = qobject_cast<DockWidget *>(widget);
|
|
||||||
auto droppedArea = qobject_cast<DockAreaWidget *>(widget);
|
|
||||||
|
|
||||||
if (droppedDockWidget) {
|
|
||||||
DockAreaWidget *oldDockArea = droppedDockWidget->dockAreaWidget();
|
|
||||||
if (oldDockArea == targetArea)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (oldDockArea)
|
|
||||||
oldDockArea->removeDockWidget(droppedDockWidget);
|
|
||||||
|
|
||||||
targetArea->insertDockWidget(0, droppedDockWidget, true);
|
|
||||||
} else {
|
|
||||||
QList<DockWidget *> newDockWidgets = droppedArea->dockWidgets();
|
|
||||||
int newCurrentIndex = droppedArea->currentIndex();
|
|
||||||
for (int i = 0; i < newDockWidgets.count(); ++i) {
|
|
||||||
DockWidget *dockWidget = newDockWidgets[i];
|
|
||||||
targetArea->insertDockWidget(i, dockWidget, false);
|
|
||||||
}
|
|
||||||
targetArea->setCurrentIndex(newCurrentIndex);
|
|
||||||
droppedArea->dockContainer()->removeDockArea(droppedArea);
|
|
||||||
droppedArea->deleteLater();
|
|
||||||
}
|
|
||||||
|
|
||||||
targetArea->updateTitleBarVisibility();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockContainerWidgetPrivate::moveToNewSection(QWidget *widget,
|
void DockContainerWidgetPrivate::moveToNewSection(QWidget *widget,
|
||||||
DockAreaWidget *targetArea,
|
DockAreaWidget *targetArea,
|
||||||
DockWidgetArea area)
|
DockWidgetArea area,
|
||||||
|
int tabIndex)
|
||||||
{
|
{
|
||||||
// Dropping into center means all dock widgets in the dropped floating
|
// Dropping into center means all dock widgets in the dropped floating widget will become
|
||||||
// widget will become tabs of the drop area
|
// tabs of the drop area.
|
||||||
if (CenterDockWidgetArea == area) {
|
if (CenterDockWidgetArea == area) {
|
||||||
moveIntoCenterOfSection(widget, targetArea);
|
moveIntoCenterOfSection(widget, targetArea, tabIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -612,31 +616,6 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget *widget,
|
|||||||
addDockAreasToList({newDockArea});
|
addDockAreasToList({newDockArea});
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockContainerWidgetPrivate::updateSplitterHandles(QSplitter *splitter)
|
|
||||||
{
|
|
||||||
if (!m_dockManager->centralWidget() || !splitter)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (int i = 0; i < splitter->count(); ++i)
|
|
||||||
splitter->setStretchFactor(i, widgetResizesWithContainer(splitter->widget(i)) ? 1 : 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget *widget)
|
|
||||||
{
|
|
||||||
if (!m_dockManager->centralWidget())
|
|
||||||
return true;
|
|
||||||
|
|
||||||
auto area = qobject_cast<DockAreaWidget *>(widget);
|
|
||||||
if (area)
|
|
||||||
return area->isCentralWidgetArea();
|
|
||||||
|
|
||||||
auto innerSplitter = qobject_cast<DockSplitter *>(widget);
|
|
||||||
if (innerSplitter)
|
|
||||||
return innerSplitter->isResizingWithContainer();
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DockContainerWidgetPrivate::moveToContainer(QWidget *widget, DockWidgetArea area)
|
void DockContainerWidgetPrivate::moveToContainer(QWidget *widget, DockWidgetArea area)
|
||||||
{
|
{
|
||||||
DockWidget *droppedDockWidget = qobject_cast<DockWidget *>(widget);
|
DockWidget *droppedDockWidget = qobject_cast<DockWidget *>(widget);
|
||||||
@@ -671,6 +650,92 @@ void DockContainerWidgetPrivate::moveToContainer(QWidget *widget, DockWidgetArea
|
|||||||
m_lastAddedAreaCache[areaIdToIndex(area)] = newDockArea;
|
m_lastAddedAreaCache[areaIdToIndex(area)] = newDockArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockContainerWidgetPrivate::moveIntoCenterOfSection(QWidget *widget,
|
||||||
|
DockAreaWidget *targetArea,
|
||||||
|
int tabIndex)
|
||||||
|
{
|
||||||
|
auto droppedDockWidget = qobject_cast<DockWidget *>(widget);
|
||||||
|
auto droppedArea = qobject_cast<DockAreaWidget *>(widget);
|
||||||
|
tabIndex = qMax(0, tabIndex);
|
||||||
|
|
||||||
|
if (droppedDockWidget) {
|
||||||
|
DockAreaWidget *oldDockArea = droppedDockWidget->dockAreaWidget();
|
||||||
|
if (oldDockArea == targetArea)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (oldDockArea)
|
||||||
|
oldDockArea->removeDockWidget(droppedDockWidget);
|
||||||
|
|
||||||
|
targetArea->insertDockWidget(tabIndex, droppedDockWidget, true);
|
||||||
|
} else {
|
||||||
|
QList<DockWidget *> newDockWidgets = droppedArea->dockWidgets();
|
||||||
|
int newCurrentIndex = droppedArea->currentIndex();
|
||||||
|
for (int i = 0; i < newDockWidgets.count(); ++i) {
|
||||||
|
DockWidget *dockWidget = newDockWidgets[i];
|
||||||
|
targetArea->insertDockWidget(tabIndex + i, dockWidget, false);
|
||||||
|
}
|
||||||
|
targetArea->setCurrentIndex(tabIndex + newCurrentIndex);
|
||||||
|
droppedArea->dockContainer()->removeDockArea(droppedArea);
|
||||||
|
droppedArea->deleteLater();
|
||||||
|
}
|
||||||
|
|
||||||
|
targetArea->updateTitleBarVisibility();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockContainerWidgetPrivate::moveToAutoHideSideBar(QWidget *widget,
|
||||||
|
DockWidgetArea area,
|
||||||
|
int tabIndex)
|
||||||
|
{
|
||||||
|
DockWidget *droppedDockWidget = qobject_cast<DockWidget *>(widget);
|
||||||
|
DockAreaWidget *droppedDockArea = qobject_cast<DockAreaWidget *>(widget);
|
||||||
|
auto sideBarLocation = internal::toSideBarLocation(area);
|
||||||
|
|
||||||
|
if (droppedDockWidget) {
|
||||||
|
if (q == droppedDockWidget->dockContainer())
|
||||||
|
droppedDockWidget->setAutoHide(true, sideBarLocation, tabIndex);
|
||||||
|
else
|
||||||
|
q->createAndSetupAutoHideContainer(sideBarLocation, droppedDockWidget, tabIndex);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (q == droppedDockArea->dockContainer()) {
|
||||||
|
droppedDockArea->setAutoHide(true, sideBarLocation, tabIndex);
|
||||||
|
} else {
|
||||||
|
for (const auto dockWidget : droppedDockArea->openedDockWidgets()) {
|
||||||
|
if (!dockWidget->features().testFlag(DockWidget::DockWidgetPinnable))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
q->createAndSetupAutoHideContainer(sideBarLocation, dockWidget, tabIndex++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockContainerWidgetPrivate::updateSplitterHandles(QSplitter *splitter)
|
||||||
|
{
|
||||||
|
if (!m_dockManager->centralWidget() || !splitter)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (int i = 0; i < splitter->count(); ++i)
|
||||||
|
splitter->setStretchFactor(i, widgetResizesWithContainer(splitter->widget(i)) ? 1 : 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget *widget)
|
||||||
|
{
|
||||||
|
if (!m_dockManager->centralWidget())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto area = qobject_cast<DockAreaWidget *>(widget);
|
||||||
|
if (area)
|
||||||
|
return area->isCentralWidgetArea();
|
||||||
|
|
||||||
|
auto innerSplitter = qobject_cast<DockSplitter *>(widget);
|
||||||
|
if (innerSplitter)
|
||||||
|
return innerSplitter->isResizingWithContainer();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void DockContainerWidgetPrivate::addDockAreasToList(const QList<DockAreaWidget *> newDockAreas)
|
void DockContainerWidgetPrivate::addDockAreasToList(const QList<DockAreaWidget *> newDockAreas)
|
||||||
{
|
{
|
||||||
const int countBefore = m_dockAreas.count();
|
const int countBefore = m_dockAreas.count();
|
||||||
@@ -740,7 +805,7 @@ void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter &stream, Q
|
|||||||
void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter &s)
|
void DockContainerWidgetPrivate::saveAutoHideWidgetsState(QXmlStreamWriter &s)
|
||||||
{
|
{
|
||||||
for (const auto sideTabBar : m_sideTabBarWidgets.values()) {
|
for (const auto sideTabBar : m_sideTabBarWidgets.values()) {
|
||||||
if (!sideTabBar->tabCount())
|
if (!sideTabBar->count())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
sideTabBar->saveState(s);
|
sideTabBar->saveState(s);
|
||||||
@@ -896,11 +961,11 @@ bool DockContainerWidgetPrivate::restoreSideBar(DockingStateReader &stateReader,
|
|||||||
if (!dockWidget || testing)
|
if (!dockWidget || testing)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto sideBar = q->sideTabBar(area);
|
auto sideBar = q->autoHideSideBar(area);
|
||||||
AutoHideDockContainer *autoHideContainer;
|
AutoHideDockContainer *autoHideContainer;
|
||||||
if (dockWidget->isAutoHide()) {
|
if (dockWidget->isAutoHide()) {
|
||||||
autoHideContainer = dockWidget->autoHideDockContainer();
|
autoHideContainer = dockWidget->autoHideDockContainer();
|
||||||
if (autoHideContainer->sideBar() != sideBar)
|
if (autoHideContainer->autoHideSideBar() != sideBar)
|
||||||
sideBar->addAutoHideWidget(autoHideContainer);
|
sideBar->addAutoHideWidget(autoHideContainer);
|
||||||
} else {
|
} else {
|
||||||
autoHideContainer = sideBar->insertDockWidget(-1, dockWidget);
|
autoHideContainer = sideBar->insertDockWidget(-1, dockWidget);
|
||||||
@@ -931,7 +996,7 @@ void DockContainerWidgetPrivate::addDockArea(DockAreaWidget *newDockArea, DockWi
|
|||||||
if (m_dockAreas.count() <= 1)
|
if (m_dockAreas.count() <= 1)
|
||||||
m_rootSplitter->setOrientation(insertParam.orientation());
|
m_rootSplitter->setOrientation(insertParam.orientation());
|
||||||
|
|
||||||
QSplitter *splitter = m_rootSplitter;
|
auto *splitter = m_rootSplitter;
|
||||||
if (splitter->orientation() == insertParam.orientation()) {
|
if (splitter->orientation() == insertParam.orientation()) {
|
||||||
insertWidgetIntoSplitter(splitter, newDockArea, insertParam.append());
|
insertWidgetIntoSplitter(splitter, newDockArea, insertParam.append());
|
||||||
updateSplitterHandles(splitter);
|
updateSplitterHandles(splitter);
|
||||||
@@ -939,7 +1004,7 @@ void DockContainerWidgetPrivate::addDockArea(DockAreaWidget *newDockArea, DockWi
|
|||||||
splitter->show();
|
splitter->show();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
QSplitter *newSplitter = createSplitter(insertParam.orientation());
|
auto *newSplitter = createSplitter(insertParam.orientation());
|
||||||
if (insertParam.append()) {
|
if (insertParam.append()) {
|
||||||
QLayoutItem *layoutItem = m_layout->replaceWidget(splitter, newSplitter);
|
QLayoutItem *layoutItem = m_layout->replaceWidget(splitter, newSplitter);
|
||||||
newSplitter->addWidget(splitter);
|
newSplitter->addWidget(splitter);
|
||||||
@@ -1108,7 +1173,8 @@ DockAreaWidget *DockContainerWidget::addDockWidget(DockWidgetArea area,
|
|||||||
}
|
}
|
||||||
|
|
||||||
AutoHideDockContainer *DockContainerWidget::createAndSetupAutoHideContainer(SideBarLocation area,
|
AutoHideDockContainer *DockContainerWidget::createAndSetupAutoHideContainer(SideBarLocation area,
|
||||||
DockWidget *dockWidget)
|
DockWidget *dockWidget,
|
||||||
|
int tabIndex)
|
||||||
{
|
{
|
||||||
if (!DockManager::testAutoHideConfigFlag(DockManager::AutoHideFeatureEnabled)) {
|
if (!DockManager::testAutoHideConfigFlag(DockManager::AutoHideFeatureEnabled)) {
|
||||||
Q_ASSERT_X(false,
|
Q_ASSERT_X(false,
|
||||||
@@ -1121,7 +1187,7 @@ AutoHideDockContainer *DockContainerWidget::createAndSetupAutoHideContainer(Side
|
|||||||
d->m_dockManager); // Auto hide Dock Container needs a valid dock manager
|
d->m_dockManager); // Auto hide Dock Container needs a valid dock manager
|
||||||
}
|
}
|
||||||
|
|
||||||
return sideTabBar(area)->insertDockWidget(-1, dockWidget);
|
return autoHideSideBar(area)->insertDockWidget(tabIndex, dockWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockContainerWidget::removeDockWidget(DockWidget *dockWidget)
|
void DockContainerWidget::removeDockWidget(DockWidget *dockWidget)
|
||||||
@@ -1210,7 +1276,7 @@ void DockContainerWidget::removeDockArea(DockAreaWidget *area)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QWidget *widget = splitter->widget(0);
|
QWidget *widget = splitter->widget(0);
|
||||||
QSplitter *childSplitter = qobject_cast<QSplitter *>(widget);
|
auto *childSplitter = qobject_cast<DockSplitter *>(widget);
|
||||||
// If the one and only content widget of the splitter is not a splitter
|
// If the one and only content widget of the splitter is not a splitter
|
||||||
// then we are finished
|
// then we are finished
|
||||||
if (!childSplitter) {
|
if (!childSplitter) {
|
||||||
@@ -1227,7 +1293,7 @@ void DockContainerWidget::removeDockArea(DockAreaWidget *area)
|
|||||||
qCInfo(adsLog) << "RootSplitter replaced by child splitter";
|
qCInfo(adsLog) << "RootSplitter replaced by child splitter";
|
||||||
} else if (splitter->count() == 1) {
|
} else if (splitter->count() == 1) {
|
||||||
qCInfo(adsLog) << "Replacing splitter with content";
|
qCInfo(adsLog) << "Replacing splitter with content";
|
||||||
QSplitter *parentSplitter = internal::findParent<QSplitter *>(splitter);
|
auto *parentSplitter = internal::findParent<QSplitter *>(splitter);
|
||||||
auto sizes = parentSplitter->sizes();
|
auto sizes = parentSplitter->sizes();
|
||||||
QWidget *widget = splitter->widget(0);
|
QWidget *widget = splitter->widget(0);
|
||||||
widget->setParent(this);
|
widget->setParent(this);
|
||||||
@@ -1299,11 +1365,12 @@ void DockContainerWidget::dropFloatingWidget(FloatingDockContainer *floatingWidg
|
|||||||
qCInfo(adsLog) << Q_FUNC_INFO;
|
qCInfo(adsLog) << Q_FUNC_INFO;
|
||||||
DockWidget *singleDroppedDockWidget = floatingWidget->topLevelDockWidget();
|
DockWidget *singleDroppedDockWidget = floatingWidget->topLevelDockWidget();
|
||||||
DockWidget *singleDockWidget = topLevelDockWidget();
|
DockWidget *singleDockWidget = topLevelDockWidget();
|
||||||
DockAreaWidget *dockArea = dockAreaAt(targetPosition);
|
|
||||||
auto dropArea = InvalidDockWidgetArea;
|
auto dropArea = InvalidDockWidgetArea;
|
||||||
auto containerDropArea = d->m_dockManager->containerOverlay()->dropAreaUnderCursor();
|
auto containerDropArea = d->m_dockManager->containerOverlay()->dropAreaUnderCursor();
|
||||||
bool dropped = false;
|
bool dropped = false;
|
||||||
|
|
||||||
|
DockAreaWidget *dockArea = dockAreaAt(targetPosition);
|
||||||
|
// Mouse is over dock area
|
||||||
if (dockArea) {
|
if (dockArea) {
|
||||||
auto dropOverlay = d->m_dockManager->dockAreaOverlay();
|
auto dropOverlay = d->m_dockManager->dockAreaOverlay();
|
||||||
dropOverlay->setAllowedAreas(dockArea->allowedAreas());
|
dropOverlay->setAllowedAreas(dockArea->allowedAreas());
|
||||||
@@ -1313,24 +1380,27 @@ void DockContainerWidget::dropFloatingWidget(FloatingDockContainer *floatingWidg
|
|||||||
|
|
||||||
if (dropArea != InvalidDockWidgetArea) {
|
if (dropArea != InvalidDockWidgetArea) {
|
||||||
qCInfo(adsLog) << "Dock Area Drop Content: " << dropArea;
|
qCInfo(adsLog) << "Dock Area Drop Content: " << dropArea;
|
||||||
d->dropIntoSection(floatingWidget, dockArea, dropArea);
|
int tabIndex = d->m_dockManager->dockAreaOverlay()->tabIndexUnderCursor();
|
||||||
|
d->dropIntoSection(floatingWidget, dockArea, dropArea, tabIndex);
|
||||||
dropped = true;
|
dropped = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mouse is over container
|
// Mouse is over container or auto hide side bar
|
||||||
if (InvalidDockWidgetArea == dropArea) {
|
if (InvalidDockWidgetArea == dropArea && InvalidDockWidgetArea != containerDropArea) {
|
||||||
dropArea = containerDropArea;
|
qCInfo(adsLog) << "Container Drop Content: " << containerDropArea;
|
||||||
qCInfo(adsLog) << "Container Drop Content: " << dropArea;
|
|
||||||
if (dropArea != InvalidDockWidgetArea) {
|
if (internal::isSideBarArea(containerDropArea))
|
||||||
d->dropIntoContainer(floatingWidget, dropArea);
|
d->dropIntoAutoHideSideBar(floatingWidget, containerDropArea);
|
||||||
|
else
|
||||||
|
d->dropIntoContainer(floatingWidget, containerDropArea);
|
||||||
|
|
||||||
dropped = true;
|
dropped = true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Remove the auto hide widgets from the FloatingWidget and insert them into this widget
|
// Remove the auto hide widgets from the FloatingWidget and insert them into this widget
|
||||||
for (auto autohideWidget : floatingWidget->dockContainer()->autoHideWidgets()) {
|
for (auto autohideWidget : floatingWidget->dockContainer()->autoHideWidgets()) {
|
||||||
auto sideBar = sideTabBar(autohideWidget->sideBarLocation());
|
auto sideBar = autoHideSideBar(autohideWidget->sideBarLocation());
|
||||||
sideBar->addAutoHideWidget(autohideWidget);
|
sideBar->addAutoHideWidget(autohideWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1356,11 +1426,14 @@ void DockContainerWidget::dropFloatingWidget(FloatingDockContainer *floatingWidg
|
|||||||
|
|
||||||
void DockContainerWidget::dropWidget(QWidget *widget,
|
void DockContainerWidget::dropWidget(QWidget *widget,
|
||||||
DockWidgetArea dropArea,
|
DockWidgetArea dropArea,
|
||||||
DockAreaWidget *targetAreaWidget)
|
DockAreaWidget *targetAreaWidget,
|
||||||
|
int tabIndex)
|
||||||
{
|
{
|
||||||
DockWidget *singleDockWidget = topLevelDockWidget();
|
DockWidget *singleDockWidget = topLevelDockWidget();
|
||||||
if (targetAreaWidget)
|
if (targetAreaWidget)
|
||||||
d->moveToNewSection(widget, targetAreaWidget, dropArea);
|
d->moveToNewSection(widget, targetAreaWidget, dropArea, tabIndex);
|
||||||
|
else if (internal::isSideBarArea(dropArea))
|
||||||
|
d->moveToAutoHideSideBar(widget, dropArea, tabIndex);
|
||||||
else
|
else
|
||||||
d->moveToContainer(widget, dropArea);
|
d->moveToContainer(widget, dropArea);
|
||||||
|
|
||||||
@@ -1466,7 +1539,7 @@ bool DockContainerWidget::restoreState(DockingStateReader &stateReader, bool tes
|
|||||||
|
|
||||||
d->m_layout->replaceWidget(d->m_rootSplitter, newRootSplitter);
|
d->m_layout->replaceWidget(d->m_rootSplitter, newRootSplitter);
|
||||||
QSplitter *oldRoot = d->m_rootSplitter;
|
QSplitter *oldRoot = d->m_rootSplitter;
|
||||||
d->m_rootSplitter = qobject_cast<QSplitter *>(newRootSplitter);
|
d->m_rootSplitter = qobject_cast<DockSplitter *>(newRootSplitter);
|
||||||
oldRoot->deleteLater();
|
oldRoot->deleteLater();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -1621,7 +1694,7 @@ void DockContainerWidget::closeOtherAreas(DockAreaWidget *keepOpenArea)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AutoHideSideBar *DockContainerWidget::sideTabBar(SideBarLocation area) const
|
AutoHideSideBar *DockContainerWidget::autoHideSideBar(SideBarLocation area) const
|
||||||
{
|
{
|
||||||
return d->m_sideTabBarWidgets[area];
|
return d->m_sideTabBarWidgets[area];
|
||||||
}
|
}
|
||||||
@@ -1639,7 +1712,17 @@ QRect DockContainerWidget::contentRectGlobal() const
|
|||||||
if (!d->m_rootSplitter)
|
if (!d->m_rootSplitter)
|
||||||
return QRect();
|
return QRect();
|
||||||
|
|
||||||
return internal::globalGeometry(d->m_rootSplitter);
|
if (d->m_rootSplitter->hasVisibleContent()) {
|
||||||
|
return d->m_rootSplitter->geometry();
|
||||||
|
} else {
|
||||||
|
auto contentRect = rect();
|
||||||
|
contentRect.adjust(autoHideSideBar(SideBarLeft)->sizeHint().width(),
|
||||||
|
autoHideSideBar(SideBarTop)->sizeHint().height(),
|
||||||
|
-autoHideSideBar(SideBarRight)->sizeHint().width(),
|
||||||
|
-autoHideSideBar(SideBarBottom)->sizeHint().height());
|
||||||
|
|
||||||
|
return contentRect;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DockManager *DockContainerWidget::dockManager() const
|
DockManager *DockContainerWidget::dockManager() const
|
||||||
|
@@ -74,7 +74,8 @@ protected:
|
|||||||
* Returns nullptr if you try and insert into an area where the configuration is not enabled
|
* Returns nullptr if you try and insert into an area where the configuration is not enabled
|
||||||
*/
|
*/
|
||||||
AutoHideDockContainer *createAndSetupAutoHideContainer(SideBarLocation area,
|
AutoHideDockContainer *createAndSetupAutoHideContainer(SideBarLocation area,
|
||||||
DockWidget *dockWidget);
|
DockWidget *dockWidget,
|
||||||
|
int tabIndex = -1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper function for creation of the root splitter
|
* Helper function for creation of the root splitter
|
||||||
@@ -98,7 +99,10 @@ protected:
|
|||||||
* a nullptr, then the DropArea indicates the drop area in the given
|
* a nullptr, then the DropArea indicates the drop area in the given
|
||||||
* TargetAreaWidget
|
* TargetAreaWidget
|
||||||
*/
|
*/
|
||||||
void dropWidget(QWidget *widget, DockWidgetArea dropArea, DockAreaWidget *targetAreaWidget);
|
void dropWidget(QWidget *widget,
|
||||||
|
DockWidgetArea dropArea,
|
||||||
|
DockAreaWidget *targetAreaWidget,
|
||||||
|
int tabIndex = -1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds the given dock area to this container widget
|
* Adds the given dock area to this container widget
|
||||||
@@ -299,7 +303,7 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Returns the side tab widget for the given area
|
* Returns the side tab widget for the given area
|
||||||
*/
|
*/
|
||||||
AutoHideSideBar *sideTabBar(SideBarLocation area) const;
|
AutoHideSideBar *autoHideSideBar(SideBarLocation area) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Access function for auto hide widgets
|
* Access function for auto hide widgets
|
||||||
|
@@ -48,6 +48,8 @@ struct DockAreaWidgetPrivate;
|
|||||||
class IconProvider;
|
class IconProvider;
|
||||||
class DockFocusController;
|
class DockFocusController;
|
||||||
class AutoHideSideBar;
|
class AutoHideSideBar;
|
||||||
|
class AutoHideTab;
|
||||||
|
struct AutoHideTabPrivate;
|
||||||
|
|
||||||
inline constexpr QStringView workspaceFolderName{u"workspaces"};
|
inline constexpr QStringView workspaceFolderName{u"workspaces"};
|
||||||
inline constexpr QStringView workspaceFileExtension{u"wrk"};
|
inline constexpr QStringView workspaceFileExtension{u"wrk"};
|
||||||
@@ -84,6 +86,8 @@ private:
|
|||||||
friend class DockAreaTitleBar;
|
friend class DockAreaTitleBar;
|
||||||
friend class AutoHideDockContainer;
|
friend class AutoHideDockContainer;
|
||||||
friend AutoHideSideBar;
|
friend AutoHideSideBar;
|
||||||
|
friend AutoHideTab;
|
||||||
|
friend AutoHideTabPrivate;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
using Super = DockContainerWidget;
|
using Super = DockContainerWidget;
|
||||||
@@ -182,8 +186,8 @@ public:
|
|||||||
= 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely
|
= 0x40, ///< Close button of an auto hide container collapses the dock instead of hiding it completely
|
||||||
|
|
||||||
DefaultAutoHideConfig
|
DefaultAutoHideConfig
|
||||||
= AutoHideFeatureEnabled
|
= AutoHideFeatureEnabled | DockAreaHasAutoHideButton
|
||||||
| DockAreaHasAutoHideButton ///< the default configuration for left and right side bars
|
| AutoHideCloseButtonCollapsesDock ///< the default configuration for left and right side bars
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(AutoHideFlags, eAutoHideFlag)
|
Q_DECLARE_FLAGS(AutoHideFlags, eAutoHideFlag)
|
||||||
|
|
||||||
|
@@ -3,8 +3,12 @@
|
|||||||
|
|
||||||
#include "dockoverlay.h"
|
#include "dockoverlay.h"
|
||||||
|
|
||||||
|
#include "autohidesidebar.h"
|
||||||
|
#include "dockareatabbar.h"
|
||||||
#include "dockareatitlebar.h"
|
#include "dockareatitlebar.h"
|
||||||
#include "dockareawidget.h"
|
#include "dockareawidget.h"
|
||||||
|
#include "dockcontainerwidget.h"
|
||||||
|
#include "dockmanager.h"
|
||||||
|
|
||||||
#include <utils/hostosinfo.h>
|
#include <utils/hostosinfo.h>
|
||||||
|
|
||||||
@@ -25,6 +29,10 @@
|
|||||||
|
|
||||||
namespace ADS {
|
namespace ADS {
|
||||||
|
|
||||||
|
static const int g_autoHideAreaWidth = 32;
|
||||||
|
static const int g_autoHideAreaMouseZone = 8;
|
||||||
|
static const int g_invalidTabIndex = -2;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data class of DockOverlay
|
* Private data class of DockOverlay
|
||||||
*/
|
*/
|
||||||
@@ -39,6 +47,7 @@ public:
|
|||||||
bool m_dropPreviewEnabled = true;
|
bool m_dropPreviewEnabled = true;
|
||||||
DockOverlay::eMode m_mode = DockOverlay::ModeDockAreaOverlay;
|
DockOverlay::eMode m_mode = DockOverlay::ModeDockAreaOverlay;
|
||||||
QRect m_dropAreaRect;
|
QRect m_dropAreaRect;
|
||||||
|
int m_tabIndex = g_invalidTabIndex;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
@@ -46,6 +55,16 @@ public:
|
|||||||
DockOverlayPrivate(DockOverlay *parent)
|
DockOverlayPrivate(DockOverlay *parent)
|
||||||
: q(parent)
|
: q(parent)
|
||||||
{}
|
{}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the overlay width / height depending on the visibility of the sidebar.
|
||||||
|
*/
|
||||||
|
int sideBarOverlaySize(SideBarLocation sideBarLocation);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The area where the mouse is considered in the sidebar.
|
||||||
|
*/
|
||||||
|
int sideBarMouseZone(SideBarLocation sideBarLocation);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,7 +151,15 @@ public:
|
|||||||
label->setObjectName("DockWidgetAreaLabel");
|
label->setObjectName("DockWidgetAreaLabel");
|
||||||
|
|
||||||
const qreal metric = dropIndicatorWidth(label);
|
const qreal metric = dropIndicatorWidth(label);
|
||||||
const QSizeF size(metric, metric);
|
QSizeF size(metric, metric);
|
||||||
|
|
||||||
|
if (internal::isSideBarArea(dockWidgetArea)) {
|
||||||
|
auto sideBarLocation = internal::toSideBarLocation(dockWidgetArea);
|
||||||
|
if (internal::isHorizontalSideBarLocation(sideBarLocation))
|
||||||
|
size.setHeight(size.height() / 2);
|
||||||
|
else
|
||||||
|
size.setWidth(size.width() / 2);
|
||||||
|
}
|
||||||
|
|
||||||
label->setPixmap(createHighDpiDropIndicatorPixmap(size, dockWidgetArea, mode));
|
label->setPixmap(createHighDpiDropIndicatorPixmap(size, dockWidgetArea, mode));
|
||||||
label->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
label->setWindowFlags(Qt::Tool | Qt::FramelessWindowHint);
|
||||||
@@ -159,6 +186,11 @@ public:
|
|||||||
{
|
{
|
||||||
const QColor borderColor = iconColor(DockOverlayCross::FrameColor);
|
const QColor borderColor = iconColor(DockOverlayCross::FrameColor);
|
||||||
const QColor backgroundColor = iconColor(DockOverlayCross::WindowBackgroundColor);
|
const QColor backgroundColor = iconColor(DockOverlayCross::WindowBackgroundColor);
|
||||||
|
|
||||||
|
QColor overlayColor = iconColor(DockOverlayCross::OverlayColor);
|
||||||
|
if (overlayColor.alpha() == 255)
|
||||||
|
overlayColor.setAlpha(64);
|
||||||
|
|
||||||
const double devicePixelRatio = q->window()->devicePixelRatioF();
|
const double devicePixelRatio = q->window()->devicePixelRatioF();
|
||||||
const QSizeF pixmapSize = size * devicePixelRatio;
|
const QSizeF pixmapSize = size * devicePixelRatio;
|
||||||
QPixmap pixmap(pixmapSize.toSize());
|
QPixmap pixmap(pixmapSize.toSize());
|
||||||
@@ -223,19 +255,18 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
const QSizeF baseSize = baseRect.size();
|
const QSizeF baseSize = baseRect.size();
|
||||||
if (DockOverlay::ModeContainerOverlay == mode && dockWidgetArea != CenterDockWidgetArea) {
|
bool isOuterContainerArea = (DockOverlay::ModeContainerOverlay == mode)
|
||||||
|
&& (dockWidgetArea != CenterDockWidgetArea)
|
||||||
|
&& !internal::isSideBarArea(dockWidgetArea);
|
||||||
|
if (isOuterContainerArea)
|
||||||
baseRect = areaRect;
|
baseRect = areaRect;
|
||||||
}
|
|
||||||
|
|
||||||
painter.fillRect(baseRect, backgroundColor);
|
painter.fillRect(baseRect, backgroundColor);
|
||||||
|
|
||||||
if (areaRect.isValid()) {
|
if (areaRect.isValid()) {
|
||||||
pen = painter.pen();
|
pen = painter.pen();
|
||||||
pen.setColor(borderColor);
|
pen.setColor(borderColor);
|
||||||
QColor color = iconColor(DockOverlayCross::OverlayColor);
|
painter.setBrush(overlayColor);
|
||||||
if (color.alpha() == 255) {
|
|
||||||
color.setAlpha(64);
|
|
||||||
}
|
|
||||||
painter.setBrush(color);
|
|
||||||
painter.setPen(Qt::NoPen);
|
painter.setPen(Qt::NoPen);
|
||||||
painter.drawRect(areaRect);
|
painter.drawRect(areaRect);
|
||||||
|
|
||||||
@@ -264,7 +295,7 @@ public:
|
|||||||
painter.restore();
|
painter.restore();
|
||||||
|
|
||||||
// Draw arrow for outer container drop indicators
|
// Draw arrow for outer container drop indicators
|
||||||
if (DockOverlay::ModeContainerOverlay == mode && dockWidgetArea != CenterDockWidgetArea) {
|
if (isOuterContainerArea) {
|
||||||
QRectF arrowRect;
|
QRectF arrowRect;
|
||||||
arrowRect.setSize(baseSize);
|
arrowRect.setSize(baseSize);
|
||||||
arrowRect.setWidth(arrowRect.width() / 4.6);
|
arrowRect.setWidth(arrowRect.width() / 4.6);
|
||||||
@@ -302,6 +333,26 @@ public:
|
|||||||
}
|
}
|
||||||
}; // class DockOverlayCrossPrivate
|
}; // class DockOverlayCrossPrivate
|
||||||
|
|
||||||
|
int DockOverlayPrivate::sideBarOverlaySize(SideBarLocation sideBarLocation)
|
||||||
|
{
|
||||||
|
auto container = qobject_cast<DockContainerWidget *>(m_targetWidget.data());
|
||||||
|
auto sideBar = container->autoHideSideBar(sideBarLocation);
|
||||||
|
if (!sideBar || !sideBar->isVisibleTo(container))
|
||||||
|
return g_autoHideAreaWidth;
|
||||||
|
else
|
||||||
|
return (sideBar->orientation() == Qt::Horizontal) ? sideBar->height() : sideBar->width();
|
||||||
|
}
|
||||||
|
|
||||||
|
int DockOverlayPrivate::sideBarMouseZone(SideBarLocation sideBarLocation)
|
||||||
|
{
|
||||||
|
auto container = qobject_cast<DockContainerWidget *>(m_targetWidget.data());
|
||||||
|
auto sideBar = container->autoHideSideBar(sideBarLocation);
|
||||||
|
if (!sideBar || !sideBar->isVisibleTo(container))
|
||||||
|
return g_autoHideAreaMouseZone;
|
||||||
|
else
|
||||||
|
return (sideBar->orientation() == Qt::Horizontal) ? sideBar->height() : sideBar->width();
|
||||||
|
}
|
||||||
|
|
||||||
DockOverlay::DockOverlay(QWidget *parent, eMode mode)
|
DockOverlay::DockOverlay(QWidget *parent, eMode mode)
|
||||||
: QFrame(parent)
|
: QFrame(parent)
|
||||||
, d(new DockOverlayPrivate(this))
|
, d(new DockOverlayPrivate(this))
|
||||||
@@ -338,6 +389,14 @@ void DockOverlay::setAllowedAreas(DockWidgetAreas areas)
|
|||||||
d->m_cross->reset();
|
d->m_cross->reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockOverlay::setAllowedArea(DockWidgetArea area, bool enable)
|
||||||
|
{
|
||||||
|
auto areasOld = d->m_allowedAreas;
|
||||||
|
d->m_allowedAreas.setFlag(area, enable);
|
||||||
|
if (areasOld != d->m_allowedAreas)
|
||||||
|
d->m_cross->reset();
|
||||||
|
}
|
||||||
|
|
||||||
DockWidgetAreas DockOverlay::allowedAreas() const
|
DockWidgetAreas DockOverlay::allowedAreas() const
|
||||||
{
|
{
|
||||||
return d->m_allowedAreas;
|
return d->m_allowedAreas;
|
||||||
@@ -345,21 +404,62 @@ DockWidgetAreas DockOverlay::allowedAreas() const
|
|||||||
|
|
||||||
DockWidgetArea DockOverlay::dropAreaUnderCursor() const
|
DockWidgetArea DockOverlay::dropAreaUnderCursor() const
|
||||||
{
|
{
|
||||||
|
d->m_tabIndex = g_invalidTabIndex;
|
||||||
|
if (!d->m_targetWidget)
|
||||||
|
return InvalidDockWidgetArea;
|
||||||
|
|
||||||
DockWidgetArea result = d->m_cross->cursorLocation();
|
DockWidgetArea result = d->m_cross->cursorLocation();
|
||||||
if (result != InvalidDockWidgetArea)
|
if (result != InvalidDockWidgetArea)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(d->m_targetWidget.data());
|
auto cursorPos = QCursor::pos();
|
||||||
if (!dockArea)
|
auto dockArea = qobject_cast<DockAreaWidget *>(d->m_targetWidget.data());
|
||||||
|
if (!dockArea
|
||||||
|
&& DockManager::autoHideConfigFlags().testFlag(DockManager::AutoHideFeatureEnabled)) {
|
||||||
|
auto rectangle = rect();
|
||||||
|
const QPoint pos = mapFromGlobal(QCursor::pos());
|
||||||
|
if ((pos.x() < d->sideBarMouseZone(SideBarLeft))
|
||||||
|
&& d->m_allowedAreas.testFlag(LeftAutoHideArea)) {
|
||||||
|
result = LeftAutoHideArea;
|
||||||
|
} else if (pos.x() > (rectangle.width() - d->sideBarMouseZone(SideBarRight))
|
||||||
|
&& d->m_allowedAreas.testFlag(RightAutoHideArea)) {
|
||||||
|
result = RightAutoHideArea;
|
||||||
|
} else if (pos.y() < d->sideBarMouseZone(SideBarTop)
|
||||||
|
&& d->m_allowedAreas.testFlag(TopAutoHideArea)) {
|
||||||
|
result = TopAutoHideArea;
|
||||||
|
} else if (pos.y() > (rectangle.height() - d->sideBarMouseZone(SideBarBottom))
|
||||||
|
&& d->m_allowedAreas.testFlag(BottomAutoHideArea)) {
|
||||||
|
result = BottomAutoHideArea;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto sideBarLocation = internal::toSideBarLocation(result);
|
||||||
|
if (sideBarLocation != SideBarNone) {
|
||||||
|
auto Container = qobject_cast<DockContainerWidget *>(d->m_targetWidget.data());
|
||||||
|
auto SideBar = Container->autoHideSideBar(sideBarLocation);
|
||||||
|
if (SideBar->isVisible()) {
|
||||||
|
d->m_tabIndex = SideBar->tabInsertIndexAt(SideBar->mapFromGlobal(cursorPos));
|
||||||
|
}
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
|
} else if (!dockArea) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
if (dockArea->allowedAreas().testFlag(CenterDockWidgetArea) && !dockArea->titleBar()->isHidden()
|
if (dockArea->allowedAreas().testFlag(CenterDockWidgetArea) && !dockArea->titleBar()->isHidden()
|
||||||
&& dockArea->titleBarGeometry().contains(dockArea->mapFromGlobal(QCursor::pos())))
|
&& dockArea->titleBarGeometry().contains(dockArea->mapFromGlobal(cursorPos))) {
|
||||||
|
auto tabBar = dockArea->titleBar()->tabBar();
|
||||||
|
d->m_tabIndex = tabBar->tabInsertIndexAt(tabBar->mapFromGlobal(cursorPos));
|
||||||
return CenterDockWidgetArea;
|
return CenterDockWidgetArea;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int DockOverlay::tabIndexUnderCursor() const
|
||||||
|
{
|
||||||
|
return d->m_tabIndex;
|
||||||
|
}
|
||||||
|
|
||||||
DockWidgetArea DockOverlay::visibleDropAreaUnderCursor() const
|
DockWidgetArea DockOverlay::visibleDropAreaUnderCursor() const
|
||||||
{
|
{
|
||||||
if (isHidden() || !d->m_dropPreviewEnabled)
|
if (isHidden() || !d->m_dropPreviewEnabled)
|
||||||
@@ -416,6 +516,7 @@ bool DockOverlay::dropPreviewEnabled() const
|
|||||||
void DockOverlay::paintEvent(QPaintEvent *event)
|
void DockOverlay::paintEvent(QPaintEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(event)
|
Q_UNUSED(event)
|
||||||
|
|
||||||
// Draw rect based on location
|
// Draw rect based on location
|
||||||
if (!d->m_dropPreviewEnabled) {
|
if (!d->m_dropPreviewEnabled) {
|
||||||
d->m_dropAreaRect = QRect();
|
d->m_dropAreaRect = QRect();
|
||||||
@@ -442,9 +543,22 @@ void DockOverlay::paintEvent(QPaintEvent *event)
|
|||||||
case CenterDockWidgetArea:
|
case CenterDockWidgetArea:
|
||||||
rectangle = rect();
|
rectangle = rect();
|
||||||
break;
|
break;
|
||||||
|
case LeftAutoHideArea:
|
||||||
|
rectangle.setWidth(d->sideBarOverlaySize(SideBarLeft));
|
||||||
|
break;
|
||||||
|
case RightAutoHideArea:
|
||||||
|
rectangle.setX(rectangle.width() - d->sideBarOverlaySize(SideBarRight));
|
||||||
|
break;
|
||||||
|
case TopAutoHideArea:
|
||||||
|
rectangle.setHeight(d->sideBarOverlaySize(SideBarTop));
|
||||||
|
break;
|
||||||
|
case BottomAutoHideArea:
|
||||||
|
rectangle.setY(rectangle.height() - d->sideBarOverlaySize(SideBarBottom));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
QColor color = palette().color(QPalette::Active, QPalette::Highlight);
|
QColor color = palette().color(QPalette::Active, QPalette::Highlight);
|
||||||
QPen pen = painter.pen();
|
QPen pen = painter.pen();
|
||||||
|
@@ -52,11 +52,26 @@ public:
|
|||||||
*/
|
*/
|
||||||
DockWidgetAreas allowedAreas() const;
|
DockWidgetAreas allowedAreas() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable / disable a certain area
|
||||||
|
*/
|
||||||
|
void setAllowedArea(DockWidgetArea area, bool enable);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the drop area under the current cursor location
|
* Returns the drop area under the current cursor location
|
||||||
*/
|
*/
|
||||||
DockWidgetArea dropAreaUnderCursor() const;
|
DockWidgetArea dropAreaUnderCursor() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the drop area is the CenterDockWidgetArea or a sidebar area, then this function returns
|
||||||
|
* the index of the tab under cursor. Call this function after call to dropAreaUnderCursor()
|
||||||
|
* because this function updates the tab index.
|
||||||
|
* A value of -1 indicates a position before the first tab and a value of tabCount() indicates
|
||||||
|
* a position behind the last tab.
|
||||||
|
* A value of -2 indicates an valid value
|
||||||
|
*/
|
||||||
|
int tabIndexUnderCursor() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function returns the same like dropAreaUnderCursor() if this
|
* This function returns the same like dropAreaUnderCursor() if this
|
||||||
* overlay is not hidden and if drop preview is enabled and returns
|
* overlay is not hidden and if drop preview is enabled and returns
|
||||||
|
@@ -409,6 +409,11 @@ bool DockWidget::isAutoHide() const
|
|||||||
return !d->m_sideTabWidget.isNull();
|
return !d->m_sideTabWidget.isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SideBarLocation DockWidget::autoHideLocation() const
|
||||||
|
{
|
||||||
|
return isAutoHide() ? autoHideDockContainer()->sideBarLocation() : SideBarNone;
|
||||||
|
}
|
||||||
|
|
||||||
bool DockWidget::isFloating() const
|
bool DockWidget::isFloating() const
|
||||||
{
|
{
|
||||||
if (!isInFloatingContainer())
|
if (!isInFloatingContainer())
|
||||||
@@ -746,6 +751,9 @@ void DockWidget::setFloating()
|
|||||||
if (isClosed())
|
if (isClosed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (isAutoHide())
|
||||||
|
dockAreaWidget()->setFloating();
|
||||||
|
else
|
||||||
d->m_tabWidget->detachDockWidget();
|
d->m_tabWidget->detachDockWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -764,6 +772,15 @@ void DockWidget::closeDockWidget()
|
|||||||
closeDockWidgetInternal(true);
|
closeDockWidgetInternal(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockWidget::requestCloseDockWidget()
|
||||||
|
{
|
||||||
|
if (features().testFlag(DockWidget::DockWidgetDeleteOnClose)
|
||||||
|
|| features().testFlag(DockWidget::CustomCloseHandling))
|
||||||
|
closeDockWidgetInternal(false);
|
||||||
|
else
|
||||||
|
toggleView(false);
|
||||||
|
}
|
||||||
|
|
||||||
bool DockWidget::closeDockWidgetInternal(bool forceClose)
|
bool DockWidget::closeDockWidgetInternal(bool forceClose)
|
||||||
{
|
{
|
||||||
if (!forceClose)
|
if (!forceClose)
|
||||||
@@ -859,21 +876,24 @@ void DockWidget::raise()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidget::setAutoHide(bool enable, SideBarLocation location)
|
void DockWidget::setAutoHide(bool enable, SideBarLocation location, int tabIndex)
|
||||||
{
|
{
|
||||||
if (!DockManager::testAutoHideConfigFlag(DockManager::AutoHideFeatureEnabled))
|
if (!DockManager::testAutoHideConfigFlag(DockManager::AutoHideFeatureEnabled))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Do nothing if nothing changes
|
// Do nothing if nothing changes
|
||||||
if (enable == isAutoHide())
|
if (enable == isAutoHide() && location == autoHideLocation())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto dockArea = dockAreaWidget();
|
auto dockArea = dockAreaWidget();
|
||||||
|
|
||||||
if (!enable) {
|
if (!enable) {
|
||||||
dockArea->setAutoHide(false);
|
dockArea->setAutoHide(false);
|
||||||
|
} else if (isAutoHide()) {
|
||||||
|
autoHideDockContainer()->moveToNewSideBarLocation(location);
|
||||||
} else {
|
} else {
|
||||||
auto area = (SideBarNone == location) ? dockArea->calculateSideTabBarArea() : location;
|
auto area = (SideBarNone == location) ? dockArea->calculateSideTabBarArea() : location;
|
||||||
dockContainer()->createAndSetupAutoHideContainer(area, this);
|
dockContainer()->createAndSetupAutoHideContainer(area, this, tabIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -338,16 +338,20 @@ public:
|
|||||||
bool isAutoHide() const;
|
bool isAutoHide() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the auto hide dock container of this dock widget
|
* Returns the auto hide dock container of this dock widget or 0 if there is none.
|
||||||
* or 0 if there is none
|
|
||||||
*/
|
*/
|
||||||
AutoHideDockContainer *autoHideDockContainer() const;
|
AutoHideDockContainer *autoHideDockContainer() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the auto hide side bar location or SideBarNone if, this is not an autohide dock widget.
|
||||||
|
*/
|
||||||
|
SideBarLocation autoHideLocation() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This property holds whether the dock widget is floating.
|
* This property holds whether the dock widget is floating.
|
||||||
* A dock widget is only floating, if it is the one and only widget inside
|
* A dock widget is only floating, if it is the one and only widget inside of a floating
|
||||||
* of a floating container. If there are more than one dock widget in a
|
* container. If there are more than one dock widget in a floating container, the all dock
|
||||||
* floating container, the all dock widgets are docked and not floating.
|
* widgets are docked and not floating.
|
||||||
*/
|
*/
|
||||||
bool isFloating() const;
|
bool isFloating() const;
|
||||||
|
|
||||||
@@ -546,23 +550,28 @@ public: // reimplements QFrame
|
|||||||
*/
|
*/
|
||||||
void closeDockWidget();
|
void closeDockWidget();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Request closing of the dock widget.
|
||||||
|
* For DockWidget with default close handling, the function does the same like clodeDockWidget()
|
||||||
|
* but if the flag CustomCloseHandling is set, the function only emits the closeRequested() signal.
|
||||||
|
*/
|
||||||
|
void requestCloseDockWidget();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Shows the widget in full-screen mode.
|
* Shows the widget in full-screen mode.
|
||||||
* Normally this function only affects windows. To make the interface
|
* Normally this function only affects windows. To make the interface compatible to QDockWidget,
|
||||||
* compatible to QDockWidget, this function also maximizes a floating
|
* this function also maximizes a floating dock widget.
|
||||||
* dock widget.
|
|
||||||
*
|
*
|
||||||
* \note Full-screen mode works fine under Windows, but has certain
|
* \note Full-screen mode works fine under Windows, but has certain problems (doe not work)
|
||||||
* problems (doe not work) under X (Linux). These problems are due to
|
* under X (Linux). These problems are due to limitations of the ICCCM protocol that specifies
|
||||||
* limitations of the ICCCM protocol that specifies the communication
|
* the communication between X11 clients and the window manager. ICCCM simply does not
|
||||||
* between X11 clients and the window manager. ICCCM simply does not
|
|
||||||
* understand the concept of non-decorated full-screen windows.
|
* understand the concept of non-decorated full-screen windows.
|
||||||
*/
|
*/
|
||||||
void showFullScreen();
|
void showFullScreen();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function complements showFullScreen() to restore the widget
|
* This function complements showFullScreen() to restore the widget after it has been in full
|
||||||
* after it has been in full screen mode.
|
* screen mode.
|
||||||
*/
|
*/
|
||||||
void showNormal();
|
void showNormal();
|
||||||
|
|
||||||
@@ -570,11 +579,10 @@ public: // reimplements QFrame
|
|||||||
* Sets the dock widget into auto hide mode if this feature is enabled
|
* Sets the dock widget into auto hide mode if this feature is enabled
|
||||||
* via CDockManager::setAutoHideFlags(CDockManager::AutoHideFeatureEnabled)
|
* via CDockManager::setAutoHideFlags(CDockManager::AutoHideFeatureEnabled)
|
||||||
*/
|
*/
|
||||||
void setAutoHide(bool enable, SideBarLocation location = SideBarNone);
|
void setAutoHide(bool enable, SideBarLocation location = SideBarNone, int tabIndex = -1);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Switches the dock widget to auto hide mode or vice versa depending on its
|
* Switches the dock widget to auto hide mode or vice versa depending on its current state.
|
||||||
* current state.
|
|
||||||
*/
|
*/
|
||||||
void toggleAutoHide(SideBarLocation location = SideBarNone);
|
void toggleAutoHide(SideBarLocation location = SideBarNone);
|
||||||
|
|
||||||
|
@@ -58,7 +58,6 @@ public:
|
|||||||
TabButton *m_closeButton = nullptr;
|
TabButton *m_closeButton = nullptr;
|
||||||
QPoint m_tabDragStartPosition;
|
QPoint m_tabDragStartPosition;
|
||||||
QSize m_iconSize;
|
QSize m_iconSize;
|
||||||
bool m_mousePressed = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
@@ -340,7 +339,6 @@ void DockWidgetTab::mousePressEvent(QMouseEvent *event)
|
|||||||
{
|
{
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
event->accept();
|
event->accept();
|
||||||
d->m_mousePressed = true;
|
|
||||||
d->saveDragStartMousePosition(event->globalPosition().toPoint());
|
d->saveDragStartMousePosition(event->globalPosition().toPoint());
|
||||||
d->m_dragState = DraggingMousePressed;
|
d->m_dragState = DraggingMousePressed;
|
||||||
if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) {
|
if (DockManager::testConfigFlag(DockManager::FocusHighlighting)) {
|
||||||
@@ -356,7 +354,6 @@ void DockWidgetTab::mousePressEvent(QMouseEvent *event)
|
|||||||
void DockWidgetTab::mouseReleaseEvent(QMouseEvent *event)
|
void DockWidgetTab::mouseReleaseEvent(QMouseEvent *event)
|
||||||
{
|
{
|
||||||
if (event->button() == Qt::LeftButton) {
|
if (event->button() == Qt::LeftButton) {
|
||||||
d->m_mousePressed = false;
|
|
||||||
auto currentDragState = d->m_dragState;
|
auto currentDragState = d->m_dragState;
|
||||||
d->m_globalDragStartMousePosition = QPoint();
|
d->m_globalDragStartMousePosition = QPoint();
|
||||||
d->m_dragStartMousePosition = QPoint();
|
d->m_dragStartMousePosition = QPoint();
|
||||||
|
@@ -167,11 +167,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setIconSize(const QSize &size);
|
void setIconSize(const QSize &size);
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns true, if the tab has been clicked and the mouse is currently pressed.
|
|
||||||
*/
|
|
||||||
bool mousePressed() const;
|
|
||||||
|
|
||||||
void setVisible(bool visible) override;
|
void setVisible(bool visible) override;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@@ -455,6 +455,9 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
|||||||
if (!overlay->dropOverlayRect().isValid())
|
if (!overlay->dropOverlayRect().isValid())
|
||||||
overlay = m_dockManager->dockAreaOverlay();
|
overlay = m_dockManager->dockAreaOverlay();
|
||||||
|
|
||||||
|
// 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 (!internal::isSideBarArea(overlay->dropAreaUnderCursor())) {
|
||||||
// Resize the floating widget to the size of the highlighted drop area rectangle
|
// Resize the floating widget to the size of the highlighted drop area rectangle
|
||||||
QRect rect = overlay->dropOverlayRect();
|
QRect rect = overlay->dropOverlayRect();
|
||||||
int frameWidth = (q->frameSize().width() - q->rect().width()) / 2;
|
int frameWidth = (q->frameSize().width() - q->rect().width()) / 2;
|
||||||
@@ -465,6 +468,7 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
|||||||
q->setGeometry(QRect(topLeft, QSize(rect.width(), rect.height() - titleBarHeight)));
|
q->setGeometry(QRect(topLeft, QSize(rect.width(), rect.height() - titleBarHeight)));
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
m_dropContainer->dropFloatingWidget(q, QCursor::pos());
|
m_dropContainer->dropFloatingWidget(q, QCursor::pos());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -510,10 +514,23 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &globalPositi
|
|||||||
}
|
}
|
||||||
|
|
||||||
int visibleDockAreas = topContainer->visibleDockAreaCount();
|
int visibleDockAreas = topContainer->visibleDockAreaCount();
|
||||||
containerOverlay->setAllowedAreas(visibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
|
|
||||||
|
DockWidgetAreas allowedContainerAreas = (visibleDockAreas > 1) ? OuterDockAreas : AllDockAreas;
|
||||||
|
auto dockArea = topContainer->dockAreaAt(globalPosition);
|
||||||
|
// If the dock container contains only one single DockArea, then we need to respect the allowed
|
||||||
|
// areas - only the center area is relevant here because all other allowed areas are from the
|
||||||
|
// container.
|
||||||
|
if (visibleDockAreas == 1 && dockArea)
|
||||||
|
allowedContainerAreas.setFlag(CenterDockWidgetArea,
|
||||||
|
dockArea->allowedAreas().testFlag(CenterDockWidgetArea));
|
||||||
|
|
||||||
|
if (m_dockContainer->features().testFlag(DockWidget::DockWidgetPinnable))
|
||||||
|
allowedContainerAreas |= AutoHideDockAreas;
|
||||||
|
|
||||||
|
containerOverlay->setAllowedAreas(allowedContainerAreas);
|
||||||
|
|
||||||
DockWidgetArea containerArea = containerOverlay->showOverlay(topContainer);
|
DockWidgetArea containerArea = containerOverlay->showOverlay(topContainer);
|
||||||
containerOverlay->enableDropPreview(containerArea != InvalidDockWidgetArea);
|
containerOverlay->enableDropPreview(containerArea != InvalidDockWidgetArea);
|
||||||
auto dockArea = topContainer->dockAreaAt(globalPosition);
|
|
||||||
if (dockArea && dockArea->isVisible() && visibleDockAreas > 0) {
|
if (dockArea && dockArea->isVisible() && visibleDockAreas > 0) {
|
||||||
dockAreaOverlay->enableDropPreview(true);
|
dockAreaOverlay->enableDropPreview(true);
|
||||||
dockAreaOverlay->setAllowedAreas((visibleDockAreas == 1) ? NoDockWidgetArea
|
dockAreaOverlay->setAllowedAreas((visibleDockAreas == 1) ? NoDockWidgetArea
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
#include "floatingdragpreview.h"
|
#include "floatingdragpreview.h"
|
||||||
#include "ads_globals_p.h"
|
#include "ads_globals_p.h"
|
||||||
|
|
||||||
|
#include "ads_globals.h"
|
||||||
#include "autohidedockcontainer.h"
|
#include "autohidedockcontainer.h"
|
||||||
#include "dockareawidget.h"
|
#include "dockareawidget.h"
|
||||||
#include "dockcontainerwidget.h"
|
#include "dockcontainerwidget.h"
|
||||||
@@ -31,6 +32,7 @@ class FloatingDragPreviewPrivate
|
|||||||
public:
|
public:
|
||||||
FloatingDragPreview *q;
|
FloatingDragPreview *q;
|
||||||
QWidget *m_content = nullptr;
|
QWidget *m_content = nullptr;
|
||||||
|
DockWidget::DockWidgetFeatures m_contentFeatures;
|
||||||
DockAreaWidget *m_contentSourceArea = nullptr;
|
DockAreaWidget *m_contentSourceArea = nullptr;
|
||||||
QPoint m_dragStartMousePosition;
|
QPoint m_dragStartMousePosition;
|
||||||
DockManager *m_dockManager = nullptr;
|
DockManager *m_dockManager = nullptr;
|
||||||
@@ -70,19 +72,35 @@ public:
|
|||||||
void createFloatingWidget();
|
void createFloatingWidget();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true, if the content is floatable.
|
* Returns true, if the content is floatable
|
||||||
*/
|
*/
|
||||||
bool isContentFloatable() const
|
bool isContentFloatable() const
|
||||||
|
{
|
||||||
|
return m_contentFeatures.testFlag(DockWidget::DockWidgetFloatable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns true, if the content is pinnable
|
||||||
|
*/
|
||||||
|
bool isContentPinnable() const
|
||||||
|
{
|
||||||
|
return m_contentFeatures.testFlag(DockWidget::DockWidgetPinnable);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the content features
|
||||||
|
*/
|
||||||
|
DockWidget::DockWidgetFeatures contentFeatures() const
|
||||||
{
|
{
|
||||||
DockWidget *dockWidget = qobject_cast<DockWidget *>(m_content);
|
DockWidget *dockWidget = qobject_cast<DockWidget *>(m_content);
|
||||||
if (dockWidget && dockWidget->features().testFlag(DockWidget::DockWidgetFloatable))
|
if (dockWidget)
|
||||||
return true;
|
return dockWidget->features();
|
||||||
|
|
||||||
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(m_content);
|
DockAreaWidget *dockArea = qobject_cast<DockAreaWidget *>(m_content);
|
||||||
if (dockArea && dockArea->features().testFlag(DockWidget::DockWidgetFloatable))
|
if (dockArea)
|
||||||
return true;
|
return dockArea->features();
|
||||||
|
|
||||||
return false;
|
return DockWidget::DockWidgetFeatures();
|
||||||
}
|
}
|
||||||
}; // class FloatingDragPreviewPrivate
|
}; // class FloatingDragPreviewPrivate
|
||||||
|
|
||||||
@@ -107,8 +125,6 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &globalPosition
|
|||||||
m_dropContainer = topContainer;
|
m_dropContainer = topContainer;
|
||||||
auto containerOverlay = m_dockManager->containerOverlay();
|
auto containerOverlay = m_dockManager->containerOverlay();
|
||||||
auto dockAreaOverlay = m_dockManager->dockAreaOverlay();
|
auto dockAreaOverlay = m_dockManager->dockAreaOverlay();
|
||||||
auto dockDropArea = dockAreaOverlay->dropAreaUnderCursor();
|
|
||||||
auto containerDropArea = containerOverlay->dropAreaUnderCursor();
|
|
||||||
|
|
||||||
if (!topContainer) {
|
if (!topContainer) {
|
||||||
containerOverlay->hideOverlay();
|
containerOverlay->hideOverlay();
|
||||||
@@ -119,6 +135,9 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &globalPosition
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
auto dockDropArea = dockAreaOverlay->dropAreaUnderCursor();
|
||||||
|
auto containerDropArea = containerOverlay->dropAreaUnderCursor();
|
||||||
|
|
||||||
int visibleDockAreas = topContainer->visibleDockAreaCount();
|
int visibleDockAreas = topContainer->visibleDockAreaCount();
|
||||||
|
|
||||||
// Include the overlay widget we're dragging as a visible widget
|
// Include the overlay widget we're dragging as a visible widget
|
||||||
@@ -126,8 +145,22 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &globalPosition
|
|||||||
if (dockAreaWidget && dockAreaWidget->isAutoHide())
|
if (dockAreaWidget && dockAreaWidget->isAutoHide())
|
||||||
visibleDockAreas++;
|
visibleDockAreas++;
|
||||||
|
|
||||||
containerOverlay->setAllowedAreas(visibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
|
DockWidgetAreas allowedContainerAreas = (visibleDockAreas > 1) ? OuterDockAreas : AllDockAreas;
|
||||||
|
|
||||||
auto dockArea = topContainer->dockAreaAt(globalPosition);
|
auto dockArea = topContainer->dockAreaAt(globalPosition);
|
||||||
|
// If the dock container contains only one single DockArea, then we need
|
||||||
|
// to respect the allowed areas - only the center area is relevant here because
|
||||||
|
// all other allowed areas are from the container
|
||||||
|
if (visibleDockAreas == 1 && dockArea)
|
||||||
|
allowedContainerAreas.setFlag(CenterDockWidgetArea,
|
||||||
|
dockArea->allowedAreas().testFlag(CenterDockWidgetArea));
|
||||||
|
|
||||||
|
if (isContentPinnable())
|
||||||
|
allowedContainerAreas |= AutoHideDockAreas;
|
||||||
|
|
||||||
|
containerOverlay->setAllowedAreas(allowedContainerAreas);
|
||||||
|
containerOverlay->enableDropPreview(containerDropArea != InvalidDockWidgetArea);
|
||||||
|
|
||||||
if (dockArea && dockArea->isVisible() && visibleDockAreas >= 0
|
if (dockArea && dockArea->isVisible() && visibleDockAreas >= 0
|
||||||
&& dockArea != m_contentSourceArea) {
|
&& dockArea != m_contentSourceArea) {
|
||||||
dockAreaOverlay->enableDropPreview(true);
|
dockAreaOverlay->enableDropPreview(true);
|
||||||
@@ -149,10 +182,10 @@ void FloatingDragPreviewPrivate::updateDropOverlays(const QPoint &globalPosition
|
|||||||
dockAreaOverlay->hideOverlay();
|
dockAreaOverlay->hideOverlay();
|
||||||
// If there is only one single visible dock area in a container, then it does not make
|
// If there is only one single visible dock area in a container, then it does not make
|
||||||
// sense to show a dock overlay because the dock area would be removed and inserted at
|
// sense to show a dock overlay because the dock area would be removed and inserted at
|
||||||
// the same position.
|
// the same position. Only auto hide area is allowed.
|
||||||
if (visibleDockAreas == 1)
|
if (visibleDockAreas == 1)
|
||||||
containerOverlay->hideOverlay();
|
containerOverlay->setAllowedAreas(AutoHideDockAreas);
|
||||||
else
|
|
||||||
containerOverlay->showOverlay(topContainer);
|
containerOverlay->showOverlay(topContainer);
|
||||||
|
|
||||||
if (dockArea == m_contentSourceArea && InvalidDockWidgetArea == containerDropArea)
|
if (dockArea == m_contentSourceArea && InvalidDockWidgetArea == containerDropArea)
|
||||||
@@ -199,6 +232,7 @@ FloatingDragPreview::FloatingDragPreview(QWidget *content, QWidget *parent)
|
|||||||
, d(new FloatingDragPreviewPrivate(this))
|
, d(new FloatingDragPreviewPrivate(this))
|
||||||
{
|
{
|
||||||
d->m_content = content;
|
d->m_content = content;
|
||||||
|
d->m_contentFeatures = d->contentFeatures();
|
||||||
setAttribute(Qt::WA_DeleteOnClose);
|
setAttribute(Qt::WA_DeleteOnClose);
|
||||||
if (DockManager::testConfigFlag(DockManager::DragPreviewHasWindowFrame)) {
|
if (DockManager::testConfigFlag(DockManager::DragPreviewHasWindowFrame)) {
|
||||||
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
||||||
@@ -288,22 +322,25 @@ void FloatingDragPreview::finishDragging()
|
|||||||
// Non floatable auto hide widgets should stay in its current auto hide state if they are
|
// Non floatable auto hide widgets should stay in its current auto hide state if they are
|
||||||
// dragged into a floating window.
|
// dragged into a floating window.
|
||||||
if (validDropArea || d->isContentFloatable())
|
if (validDropArea || d->isContentFloatable())
|
||||||
cleanupAutoHideContainerWidget();
|
cleanupAutoHideContainerWidget(containerDropArea);
|
||||||
|
|
||||||
if (!d->m_dropContainer) {
|
if (!d->m_dropContainer) {
|
||||||
d->createFloatingWidget();
|
d->createFloatingWidget();
|
||||||
} else if (dockDropArea != InvalidDockWidgetArea) {
|
} else if (dockDropArea != InvalidDockWidgetArea) {
|
||||||
d->m_dropContainer->dropWidget(d->m_content,
|
d->m_dropContainer->dropWidget(d->m_content,
|
||||||
dockDropArea,
|
dockDropArea,
|
||||||
d->m_dropContainer->dockAreaAt(QCursor::pos()));
|
d->m_dropContainer->dockAreaAt(QCursor::pos()),
|
||||||
|
d->m_dockManager->dockAreaOverlay()->tabIndexUnderCursor());
|
||||||
} else if (containerDropArea != InvalidDockWidgetArea) {
|
} else if (containerDropArea != InvalidDockWidgetArea) {
|
||||||
// If there is only one single dock area, and we drop into the center then we tabify the
|
// If there is only one single dock area, and we drop into the center then we tabify the
|
||||||
// dropped widget into the only visible dock area.
|
// dropped widget into the only visible dock area.
|
||||||
if (d->m_dropContainer->visibleDockAreaCount() <= 1
|
if (d->m_dropContainer->visibleDockAreaCount() <= 1
|
||||||
&& CenterDockWidgetArea == containerDropArea)
|
&& CenterDockWidgetArea == containerDropArea)
|
||||||
d->m_dropContainer->dropWidget(d->m_content,
|
d->m_dropContainer
|
||||||
|
->dropWidget(d->m_content,
|
||||||
containerDropArea,
|
containerDropArea,
|
||||||
d->m_dropContainer->dockAreaAt(QCursor::pos()));
|
d->m_dropContainer->dockAreaAt(QCursor::pos()),
|
||||||
|
d->m_dockManager->containerOverlay()->tabIndexUnderCursor());
|
||||||
else
|
else
|
||||||
d->m_dropContainer->dropWidget(d->m_content, containerDropArea, nullptr);
|
d->m_dropContainer->dropWidget(d->m_content, containerDropArea, nullptr);
|
||||||
} else {
|
} else {
|
||||||
@@ -315,15 +352,24 @@ void FloatingDragPreview::finishDragging()
|
|||||||
d->m_dockManager->dockAreaOverlay()->hideOverlay();
|
d->m_dockManager->dockAreaOverlay()->hideOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatingDragPreview::cleanupAutoHideContainerWidget()
|
void FloatingDragPreview::cleanupAutoHideContainerWidget(DockWidgetArea containerDropArea)
|
||||||
{
|
{
|
||||||
auto droppedDockWidget = qobject_cast<DockWidget *>(d->m_content);
|
auto droppedDockWidget = qobject_cast<DockWidget *>(d->m_content);
|
||||||
if (droppedDockWidget && droppedDockWidget->autoHideDockContainer())
|
|
||||||
droppedDockWidget->autoHideDockContainer()->cleanupAndDelete();
|
|
||||||
|
|
||||||
auto droppedArea = qobject_cast<DockAreaWidget *>(d->m_content);
|
auto droppedArea = qobject_cast<DockAreaWidget *>(d->m_content);
|
||||||
if (droppedArea && droppedArea->autoHideDockContainer())
|
|
||||||
droppedArea->autoHideDockContainer()->cleanupAndDelete();
|
auto autoHideContainer = droppedDockWidget ? droppedDockWidget->autoHideDockContainer()
|
||||||
|
: droppedArea->autoHideDockContainer();
|
||||||
|
|
||||||
|
if (!autoHideContainer)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If the dropped widget is already an auto hide widget and if it is moved to a new side bar
|
||||||
|
// location in the same container, then we do not need to cleanup.
|
||||||
|
if (internal::isSideBarArea(containerDropArea)
|
||||||
|
&& (d->m_dropContainer == autoHideContainer->dockContainer()))
|
||||||
|
return;
|
||||||
|
|
||||||
|
autoHideContainer->cleanupAndDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatingDragPreview::paintEvent(QPaintEvent *event)
|
void FloatingDragPreview::paintEvent(QPaintEvent *event)
|
||||||
@@ -333,6 +379,7 @@ void FloatingDragPreview::paintEvent(QPaintEvent *event)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
QPainter painter(this);
|
QPainter painter(this);
|
||||||
|
painter.setOpacity(0.6);
|
||||||
if (DockManager::testConfigFlag(DockManager::DragPreviewShowsContentPixmap))
|
if (DockManager::testConfigFlag(DockManager::DragPreviewShowsContentPixmap))
|
||||||
painter.drawPixmap(QPoint(0, 0), d->m_contentPreviewPixmap);
|
painter.drawPixmap(QPoint(0, 0), d->m_contentPreviewPixmap);
|
||||||
|
|
||||||
|
@@ -89,7 +89,7 @@ public: // implements AbstractFloatingWidget
|
|||||||
/**
|
/**
|
||||||
* Cleanup auto hide container if the dragged widget has one.
|
* Cleanup auto hide container if the dragged widget has one.
|
||||||
*/
|
*/
|
||||||
void cleanupAutoHideContainerWidget();
|
void cleanupAutoHideContainerWidget(DockWidgetArea containerDropArea);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user