mirror of
https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System.git
synced 2024-11-15 21:25:44 +08:00
commit
84b501205a
18
.cproject
18
.cproject
@ -71,15 +71,6 @@
|
|||||||
</storageModule>
|
</storageModule>
|
||||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||||
<storageModule moduleId="refreshScope"/>
|
<storageModule moduleId="refreshScope"/>
|
||||||
<storageModule moduleId="scannerConfiguration">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.mingw.base.1119687795;cdt.managedbuild.toolchain.gnu.mingw.base.1119687795.1949777584;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.base.1947822681;cdt.managedbuild.tool.gnu.cpp.compiler.input.1318830536">
|
|
||||||
<autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.mingw.base.1119687795;cdt.managedbuild.toolchain.gnu.mingw.base.1119687795.1949777584;cdt.managedbuild.tool.gnu.c.compiler.mingw.base.389117097;cdt.managedbuild.tool.gnu.c.compiler.input.1568363924">
|
|
||||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
|
||||||
</scannerConfigBuildInfo>
|
|
||||||
</storageModule>
|
|
||||||
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
|
<storageModule moduleId="org.eclipse.cdt.make.core.buildtargets">
|
||||||
<buildTargets>
|
<buildTargets>
|
||||||
<target name="Build all" path=" build" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
<target name="Build all" path=" build" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
|
||||||
@ -356,4 +347,13 @@
|
|||||||
</target>
|
</target>
|
||||||
</buildTargets>
|
</buildTargets>
|
||||||
</storageModule>
|
</storageModule>
|
||||||
|
<storageModule moduleId="scannerConfiguration">
|
||||||
|
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||||
|
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.mingw.base.1119687795;cdt.managedbuild.toolchain.gnu.mingw.base.1119687795.1949777584;cdt.managedbuild.tool.gnu.cpp.compiler.mingw.base.1947822681;cdt.managedbuild.tool.gnu.cpp.compiler.input.1318830536">
|
||||||
|
<autodiscovery enabled="false" problemReportingEnabled="true" selectedProfileId="org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile"/>
|
||||||
|
</scannerConfigBuildInfo>
|
||||||
|
<scannerConfigBuildInfo instanceId="cdt.managedbuild.toolchain.gnu.mingw.base.1119687795;cdt.managedbuild.toolchain.gnu.mingw.base.1119687795.1949777584;cdt.managedbuild.tool.gnu.c.compiler.mingw.base.389117097;cdt.managedbuild.tool.gnu.c.compiler.input.1568363924">
|
||||||
|
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||||
|
</scannerConfigBuildInfo>
|
||||||
|
</storageModule>
|
||||||
</cproject>
|
</cproject>
|
||||||
|
2
.gitignore
vendored
2
.gitignore
vendored
@ -8,3 +8,5 @@ moc_*
|
|||||||
ui_*
|
ui_*
|
||||||
Makefile
|
Makefile
|
||||||
|
|
||||||
|
# IDEs
|
||||||
|
.idea
|
||||||
|
@ -40,6 +40,7 @@ set(ads_SRCS
|
|||||||
src/ElidingLabel.cpp
|
src/ElidingLabel.cpp
|
||||||
src/FloatingDockContainer.cpp
|
src/FloatingDockContainer.cpp
|
||||||
src/ads.qrc
|
src/ads.qrc
|
||||||
|
src/linux/FloatingWidgetTitleBar.cpp
|
||||||
)
|
)
|
||||||
set(ads_INSTALL_INCLUDE
|
set(ads_INSTALL_INCLUDE
|
||||||
src/ads_globals.h
|
src/ads_globals.h
|
||||||
@ -54,6 +55,7 @@ set(ads_INSTALL_INCLUDE
|
|||||||
src/DockWidgetTab.h
|
src/DockWidgetTab.h
|
||||||
src/ElidingLabel.h
|
src/ElidingLabel.h
|
||||||
src/FloatingDockContainer.h
|
src/FloatingDockContainer.h
|
||||||
|
src/linux/FloatingWidgetTitleBar.h
|
||||||
)
|
)
|
||||||
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
|
||||||
set(ads_PlatformDir "x86")
|
set(ads_PlatformDir "x86")
|
||||||
@ -84,7 +86,7 @@ install(TARGETS qtadvanceddocking
|
|||||||
ARCHIVE DESTINATION lib COMPONENT library
|
ARCHIVE DESTINATION lib COMPONENT library
|
||||||
)
|
)
|
||||||
target_include_directories(qtadvanceddocking PUBLIC
|
target_include_directories(qtadvanceddocking PUBLIC
|
||||||
$<BUILD_INTERFACE:${ads_INCLUDE}>
|
"$<BUILD_INTERFACE:${ads_INCLUDE}>"
|
||||||
$<INSTALL_INTERFACE:include>
|
$<INSTALL_INTERFACE:include>
|
||||||
)
|
)
|
||||||
target_link_libraries(qtadvanceddocking PUBLIC ${ads_LIBS})
|
target_link_libraries(qtadvanceddocking PUBLIC ${ads_LIBS})
|
||||||
|
23
README.md
23
README.md
@ -1,6 +1,7 @@
|
|||||||
# Advanced Docking System for Qt
|
# Advanced Docking System for Qt
|
||||||
[![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
[![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
||||||
[![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
|
[![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
|
||||||
|
[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](gnu-lgpl-v2.1.md)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -8,7 +9,7 @@ Qt Advanced Docking System lets you create customizable layouts using a full
|
|||||||
featured window docking system similar to what is found in many popular
|
featured window docking system similar to what is found in many popular
|
||||||
integrated development environements (IDEs) such as Visual Studio.
|
integrated development environements (IDEs) such as Visual Studio.
|
||||||
Everything is implemented with standard Qt functionality without any
|
Everything is implemented with standard Qt functionality without any
|
||||||
platform specific code. Basic usage of QWidgets an QLayouts and using basic
|
platform specific code. Basic usage of QWidgets and QLayouts and using basic
|
||||||
styles as much as possible.
|
styles as much as possible.
|
||||||
|
|
||||||
This work is based on and inspired by the
|
This work is based on and inspired by the
|
||||||
@ -60,9 +61,22 @@ main window layout.
|
|||||||
![Perspective](doc/perspectives_dark.png)
|
![Perspective](doc/perspectives_dark.png)
|
||||||
|
|
||||||
## Tested Compatible Environments
|
## Tested Compatible Environments
|
||||||
- Windows 10 [![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
|
### Windows
|
||||||
- Ubuntu [![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
Windows 10 [![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
|
||||||
- macOS [![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
|
||||||
|
The library was developed on and for Windows. It is used in a commercial Windows application and is therefore constantly tested.
|
||||||
|
|
||||||
|
### macOS
|
||||||
|
macOS [![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
||||||
|
|
||||||
|
The application can be compiled for macOS. A user reported, that the library works on macOS. If have not tested it.
|
||||||
|
|
||||||
|
### Linux
|
||||||
|
Ubuntu [![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
||||||
|
|
||||||
|
The application can be compiled for Linux and has been developed and tested with **Kubuntu 18.04**.
|
||||||
|
|
||||||
|
![Advanced Docking on Linux](doc/linux_kubuntu_1804.png)
|
||||||
|
|
||||||
## Build
|
## Build
|
||||||
Open the `ads.pro` with QtCreator and start the build, that's it.
|
Open the `ads.pro` with QtCreator and start the build, that's it.
|
||||||
@ -144,5 +158,6 @@ MainWindow::~MainWindow()
|
|||||||
- Manuel Freiholz
|
- Manuel Freiholz
|
||||||
|
|
||||||
## License information
|
## License information
|
||||||
|
[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](gnu-lgpl-v2.1.md)
|
||||||
This project uses the [LGPLv2.1 license](gnu-lgpl-v2.1.md)
|
This project uses the [LGPLv2.1 license](gnu-lgpl-v2.1.md)
|
||||||
|
|
||||||
|
@ -23,8 +23,7 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
|||||||
set(ads_demo_SRCS
|
set(ads_demo_SRCS
|
||||||
main.cpp
|
main.cpp
|
||||||
MainWindow.cpp
|
MainWindow.cpp
|
||||||
MainWindow.ui
|
mainwindow.ui
|
||||||
main.qrc
|
|
||||||
)
|
)
|
||||||
add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS})
|
add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS})
|
||||||
if(BUILD_STATIC)
|
if(BUILD_STATIC)
|
||||||
|
@ -88,6 +88,32 @@ static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function returns a features string with closable (c), movable (m) and floatable (f)
|
||||||
|
* features. i.e. The following string is for a not closable but movable and floatable
|
||||||
|
* widget: c- m+ f+
|
||||||
|
*/
|
||||||
|
static QString featuresString(ads::CDockWidget* DockWidget)
|
||||||
|
{
|
||||||
|
auto f = DockWidget->features();
|
||||||
|
return QString("c%1 m%2 f%3")
|
||||||
|
.arg(f.testFlag(ads::CDockWidget::DockWidgetClosable) ? "+" : "-")
|
||||||
|
.arg(f.testFlag(ads::CDockWidget::DockWidgetMovable) ? "+" : "-")
|
||||||
|
.arg(f.testFlag(ads::CDockWidget::DockWidgetFloatable) ? "+" : "-");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the string returned by featuresString() to the window title of
|
||||||
|
* the given DockWidget
|
||||||
|
*/
|
||||||
|
static void appendFeaturStringToWindowTitle(ads::CDockWidget* DockWidget)
|
||||||
|
{
|
||||||
|
DockWidget->setWindowTitle(DockWidget->windowTitle()
|
||||||
|
+ QString(" (%1)").arg(featuresString(DockWidget)));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu)
|
static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu)
|
||||||
{
|
{
|
||||||
@ -110,7 +136,8 @@ static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu)
|
|||||||
QFileSystemModel* m = new QFileSystemModel(w);
|
QFileSystemModel* m = new QFileSystemModel(w);
|
||||||
m->setRootPath(QDir::currentPath());
|
m->setRootPath(QDir::currentPath());
|
||||||
w->setModel(m);
|
w->setModel(m);
|
||||||
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++));
|
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1")
|
||||||
|
.arg(FileSystemCount++));
|
||||||
DockWidget->setWidget(w);
|
DockWidget->setWidget(w);
|
||||||
ViewMenu->addAction(DockWidget->toggleViewAction());
|
ViewMenu->addAction(DockWidget->toggleViewAction());
|
||||||
return DockWidget;
|
return DockWidget;
|
||||||
@ -185,6 +212,8 @@ void MainWindowPrivate::createContent()
|
|||||||
ToolBar->addAction(ui.actionSaveState);
|
ToolBar->addAction(ui.actionSaveState);
|
||||||
ToolBar->addAction(ui.actionRestoreState);
|
ToolBar->addAction(ui.actionRestoreState);
|
||||||
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false);
|
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false);
|
||||||
|
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetFloatable, false);
|
||||||
|
appendFeaturStringToWindowTitle(FileSystemWidget);
|
||||||
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
|
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
|
||||||
DockWidget = createCalendarDockWidget(ViewMenu);
|
DockWidget = createCalendarDockWidget(ViewMenu);
|
||||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false);
|
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false);
|
||||||
@ -270,19 +299,27 @@ CMainWindow::CMainWindow(QWidget *parent) :
|
|||||||
d->ui.setupUi(this);
|
d->ui.setupUi(this);
|
||||||
d->createActions();
|
d->createActions();
|
||||||
|
|
||||||
|
// uncomment the following line if the tab close button should be
|
||||||
|
// a QToolButton instead of a QPushButton
|
||||||
|
// CDockManager::setConfigFlags(CDockManager::configFlags() | CDockManager::TabCloseButtonIsToolButton);
|
||||||
|
|
||||||
|
// uncomment the following line if you wand a fixed tab width that does
|
||||||
|
// not change if the visibility of the close button changes
|
||||||
|
// CDockManager::setConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden, true);
|
||||||
|
|
||||||
// Now create the dock manager and its content
|
// Now create the dock manager and its content
|
||||||
d->DockManager = new CDockManager(this);
|
d->DockManager = new CDockManager(this);
|
||||||
|
|
||||||
// Uncomment the following line to have the old style where the dock
|
// Uncomment the following line to have the old style where the dock
|
||||||
// area close button closes the active tab
|
// area close button closes the active tab
|
||||||
//d->DockManager->setConfigFlags({
|
// CDockManager::setConfigFlags({CDockManager::DockAreaHasCloseButton
|
||||||
// CDockManager::DockAreaHasCloseButton | CDockManager::DockAreaCloseButtonClosesTab});
|
// | CDockManager::DockAreaCloseButtonClosesTab});
|
||||||
connect(d->PerspectiveComboBox, SIGNAL(activated(const QString&)),
|
connect(d->PerspectiveComboBox, SIGNAL(activated(const QString&)),
|
||||||
d->DockManager, SLOT(openPerspective(const QString&)));
|
d->DockManager, SLOT(openPerspective(const QString&)));
|
||||||
|
|
||||||
d->createContent();
|
d->createContent();
|
||||||
// Default window geometry
|
// Default window geometry
|
||||||
resize(800, 600);
|
resize(1280, 720);
|
||||||
|
|
||||||
d->restoreState();
|
d->restoreState();
|
||||||
d->restorePerspectives();
|
d->restorePerspectives();
|
||||||
|
@ -21,7 +21,6 @@ HEADERS += \
|
|||||||
FORMS += \
|
FORMS += \
|
||||||
mainwindow.ui
|
mainwindow.ui
|
||||||
|
|
||||||
RESOURCES += main.qrc
|
|
||||||
|
|
||||||
LIBS += -L$${ADS_OUT_ROOT}/lib
|
LIBS += -L$${ADS_OUT_ROOT}/lib
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/main"/>
|
|
||||||
</RCC>
|
|
BIN
doc/linux_kubuntu_1804.png
Normal file
BIN
doc/linux_kubuntu_1804.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 232 KiB |
@ -23,7 +23,6 @@ HEADERS += \
|
|||||||
FORMS += \
|
FORMS += \
|
||||||
MainWindow.ui
|
MainWindow.ui
|
||||||
|
|
||||||
#RESOURCES += main.qrc
|
|
||||||
|
|
||||||
LIBS += -L$${ADS_OUT_ROOT}/lib
|
LIBS += -L$${ADS_OUT_ROOT}/lib
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ CDockAreaTabBar::CDockAreaTabBar(CDockAreaWidget* parent) :
|
|||||||
d(new DockAreaTabBarPrivate(this))
|
d(new DockAreaTabBarPrivate(this))
|
||||||
{
|
{
|
||||||
d->DockArea = parent;
|
d->DockArea = parent;
|
||||||
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Ignored);
|
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||||
setFrameStyle(QFrame::NoFrame);
|
setFrameStyle(QFrame::NoFrame);
|
||||||
setWidgetResizable(true);
|
setWidgetResizable(true);
|
||||||
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||||
@ -171,7 +171,7 @@ void CDockAreaTabBar::mouseReleaseEvent(QMouseEvent* ev)
|
|||||||
{
|
{
|
||||||
if (ev->button() == Qt::LeftButton)
|
if (ev->button() == Qt::LeftButton)
|
||||||
{
|
{
|
||||||
qDebug() << "CTabsScrollArea::mouseReleaseEvent";
|
ADS_PRINT("CTabsScrollArea::mouseReleaseEvent");
|
||||||
ev->accept();
|
ev->accept();
|
||||||
d->FloatingWidget = nullptr;
|
d->FloatingWidget = nullptr;
|
||||||
d->DragStartMousePos = QPoint();
|
d->DragStartMousePos = QPoint();
|
||||||
@ -205,10 +205,17 @@ void CDockAreaTabBar::mouseMoveEvent(QMouseEvent* ev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If one single dock widget in this area is not floatable then the whole
|
||||||
|
// area is not floatable
|
||||||
|
if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength();
|
int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength();
|
||||||
if (DragDistance >= CDockManager::startDragDistance())
|
if (DragDistance >= CDockManager::startDragDistance())
|
||||||
{
|
{
|
||||||
qDebug() << "CTabsScrollArea::startFloating";
|
ADS_PRINT("CTabsScrollArea::startFloating");
|
||||||
startFloating(d->DragStartMousePos);
|
startFloating(d->DragStartMousePos);
|
||||||
auto Overlay = d->DockArea->dockManager()->containerOverlay();
|
auto Overlay = d->DockArea->dockManager()->containerOverlay();
|
||||||
Overlay->setAllowedAreas(OuterDockAreas);
|
Overlay->setAllowedAreas(OuterDockAreas);
|
||||||
@ -228,6 +235,11 @@ void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
makeAreaFloating(event->pos(), DraggingInactive);
|
makeAreaFloating(event->pos(), DraggingInactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +250,7 @@ CFloatingDockContainer* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset,
|
|||||||
{
|
{
|
||||||
QSize Size = d->DockArea->size();
|
QSize Size = d->DockArea->size();
|
||||||
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea);
|
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea);
|
||||||
FloatingWidget->startFloating(Offset, Size, DragState);
|
FloatingWidget->startFloating(Offset, Size, DragState, nullptr);
|
||||||
auto TopLevelDockWidget = FloatingWidget->topLevelDockWidget();
|
auto TopLevelDockWidget = FloatingWidget->topLevelDockWidget();
|
||||||
if (TopLevelDockWidget)
|
if (TopLevelDockWidget)
|
||||||
{
|
{
|
||||||
@ -309,7 +321,7 @@ void CDockAreaTabBar::removeTab(CDockWidgetTab* Tab)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
qDebug() << "CDockAreaTabBar::removeTab ";
|
ADS_PRINT("CDockAreaTabBar::removeTab ");
|
||||||
int NewCurrentIndex = currentIndex();
|
int NewCurrentIndex = currentIndex();
|
||||||
int RemoveIndex = d->TabsLayout->indexOf(Tab);
|
int RemoveIndex = d->TabsLayout->indexOf(Tab);
|
||||||
if (count() == 1)
|
if (count() == 1)
|
||||||
@ -352,7 +364,7 @@ void CDockAreaTabBar::removeTab(CDockWidgetTab* Tab)
|
|||||||
d->TabsLayout->removeWidget(Tab);
|
d->TabsLayout->removeWidget(Tab);
|
||||||
Tab->disconnect(this);
|
Tab->disconnect(this);
|
||||||
Tab->removeEventFilter(this);
|
Tab->removeEventFilter(this);
|
||||||
qDebug() << "NewCurrentIndex " << NewCurrentIndex;
|
ADS_PRINT("NewCurrentIndex " << NewCurrentIndex);
|
||||||
if (NewCurrentIndex != d->CurrentIndex)
|
if (NewCurrentIndex != d->CurrentIndex)
|
||||||
{
|
{
|
||||||
setCurrentIndex(NewCurrentIndex);
|
setCurrentIndex(NewCurrentIndex);
|
||||||
@ -480,7 +492,7 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
|
|||||||
{
|
{
|
||||||
if (MousePos.x() > tab(count() - 1)->geometry().right())
|
if (MousePos.x() > tab(count() - 1)->geometry().right())
|
||||||
{
|
{
|
||||||
qDebug() << "after all tabs";
|
ADS_PRINT("after all tabs");
|
||||||
toIndex = count() - 1;
|
toIndex = count() - 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -493,7 +505,7 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
|
|||||||
d->TabsLayout->insertWidget(toIndex, MovingTab);
|
d->TabsLayout->insertWidget(toIndex, MovingTab);
|
||||||
if (toIndex >= 0)
|
if (toIndex >= 0)
|
||||||
{
|
{
|
||||||
qDebug() << "tabMoved from " << fromIndex << " to " << toIndex;
|
ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex);
|
||||||
emit tabMoved(fromIndex, toIndex);
|
emit tabMoved(fromIndex, toIndex);
|
||||||
setCurrentIndex(toIndex);
|
setCurrentIndex(toIndex);
|
||||||
}
|
}
|
||||||
@ -553,6 +565,23 @@ bool CDockAreaTabBar::isTabOpen(int Index) const
|
|||||||
return !tab(Index)->isHidden();
|
return !tab(Index)->isHidden();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
QSize CDockAreaTabBar::minimumSizeHint() const
|
||||||
|
{
|
||||||
|
QSize Size = sizeHint();
|
||||||
|
Size.setWidth(Super::minimumSizeHint().width());// this defines the minimum width of a dock area
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
QSize CDockAreaTabBar::sizeHint() const
|
||||||
|
{
|
||||||
|
QSize Size = Super::sizeHint();
|
||||||
|
Size.setHeight(d->TabsContainerWidget->sizeHint().height());
|
||||||
|
return Size;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ads
|
} // namespace ads
|
||||||
|
|
||||||
//---------------------------------------------------------------------------
|
//---------------------------------------------------------------------------
|
||||||
|
@ -44,6 +44,10 @@ class CFloatingDockContainer;
|
|||||||
* Custom tabbar implementation for tab area that is shown on top of a
|
* Custom tabbar implementation for tab area that is shown on top of a
|
||||||
* dock area widget.
|
* dock area widget.
|
||||||
* The tabbar displays the tab widgets of the contained dock widgets.
|
* The tabbar displays the tab widgets of the contained dock widgets.
|
||||||
|
* We cannot use QTabBar here because it does a lot of fancy animations
|
||||||
|
* that will crash the application if a tab is removed while the animation
|
||||||
|
* has not finished. And we need to remove a tab, if the user drags a
|
||||||
|
* a dock widget out of a group of tabbed widgets
|
||||||
*/
|
*/
|
||||||
class CDockAreaTabBar : public QScrollArea
|
class CDockAreaTabBar : public QScrollArea
|
||||||
{
|
{
|
||||||
@ -61,6 +65,7 @@ private slots:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void wheelEvent(QWheelEvent* Event) override;
|
virtual void wheelEvent(QWheelEvent* Event) override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stores mouse position to detect dragging
|
* Stores mouse position to detect dragging
|
||||||
*/
|
*/
|
||||||
@ -96,6 +101,7 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
using Super = QScrollArea;
|
using Super = QScrollArea;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default Constructor
|
* Default Constructor
|
||||||
*/
|
*/
|
||||||
@ -150,6 +156,21 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isTabOpen(int Index) const;
|
bool isTabOpen(int Index) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overrides the minimumSizeHint() function of QScrollArea
|
||||||
|
* The minimumSizeHint() is bigger than the sizeHint () for the scroll
|
||||||
|
* area because even if the scrollbars are invisible, the required speace
|
||||||
|
* is reserved in the minimumSizeHint(). This override simply returns
|
||||||
|
* sizeHint();
|
||||||
|
*/
|
||||||
|
virtual QSize minimumSizeHint() const override;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function provides a sizeHint that matches the height of the
|
||||||
|
* internal viewport.
|
||||||
|
*/
|
||||||
|
virtual QSize sizeHint() const override;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
/**
|
/**
|
||||||
* This property sets the index of the tab bar's visible tab
|
* This property sets the index of the tab bar's visible tab
|
||||||
|
@ -95,7 +95,25 @@ struct DockAreaTitleBarPrivate
|
|||||||
*/
|
*/
|
||||||
bool testConfigFlag(CDockManager::eConfigFlag Flag) const
|
bool testConfigFlag(CDockManager::eConfigFlag Flag) const
|
||||||
{
|
{
|
||||||
return DockArea->dockManager()->configFlags().testFlag(Flag);
|
return CDockManager::configFlags().testFlag(Flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function to set title bar button icons depending on operating
|
||||||
|
* system and to avoid duplicated code. On windows the standard icons
|
||||||
|
* are blurry since Qt 5.11 so we need to do some additional steps
|
||||||
|
*/
|
||||||
|
void setTitleBarButtonIcon(tTileBarButton* Button, QStyle::StandardPixmap StandarPixmap)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
Button->setIcon(_this->style()->standardIcon(StandarPixmap));
|
||||||
|
#else
|
||||||
|
QIcon Icon;
|
||||||
|
QPixmap normalPixmap = _this->style()->standardPixmap(StandarPixmap, 0, Button);
|
||||||
|
Icon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
|
||||||
|
Icon.addPixmap(normalPixmap, QIcon::Normal);
|
||||||
|
Button->setIcon(Icon);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
};// struct DockAreaTitleBarPrivate
|
};// struct DockAreaTitleBarPrivate
|
||||||
|
|
||||||
@ -112,50 +130,47 @@ DockAreaTitleBarPrivate::DockAreaTitleBarPrivate(CDockAreaTitleBar* _public) :
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void DockAreaTitleBarPrivate::createButtons()
|
void DockAreaTitleBarPrivate::createButtons()
|
||||||
{
|
{
|
||||||
|
QSizePolicy ButtonSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
||||||
|
// Tabs menu button
|
||||||
TabsMenuButton = new tTileBarButton();
|
TabsMenuButton = new tTileBarButton();
|
||||||
TabsMenuButton->setObjectName("tabsMenuButton");
|
TabsMenuButton->setObjectName("tabsMenuButton");
|
||||||
TabsMenuButton->setAutoRaise(true);
|
TabsMenuButton->setAutoRaise(true);
|
||||||
TabsMenuButton->setPopupMode(QToolButton::InstantPopup);
|
TabsMenuButton->setPopupMode(QToolButton::InstantPopup);
|
||||||
TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
|
setTitleBarButtonIcon(TabsMenuButton, QStyle::SP_TitleBarUnshadeButton);
|
||||||
|
|
||||||
QMenu* TabsMenu = new QMenu(TabsMenuButton);
|
QMenu* TabsMenu = new QMenu(TabsMenuButton);
|
||||||
#ifndef QT_NO_TOOLTIP
|
#ifndef QT_NO_TOOLTIP
|
||||||
TabsMenu->setToolTipsVisible(true);
|
TabsMenu->setToolTipsVisible(true);
|
||||||
#endif
|
#endif
|
||||||
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
|
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
|
||||||
TabsMenuButton->setMenu(TabsMenu);
|
TabsMenuButton->setMenu(TabsMenu);
|
||||||
#ifndef QT_NO_TOOLTIP
|
#ifndef QT_NO_TOOLTIP
|
||||||
TabsMenuButton->setToolTip(QObject::tr("List all tabs"));
|
TabsMenuButton->setToolTip(QObject::tr("List all tabs"));
|
||||||
#endif
|
#endif
|
||||||
TabsMenuButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
TabsMenuButton->setSizePolicy(ButtonSizePolicy);
|
||||||
TopLayout->addWidget(TabsMenuButton, 0);
|
TopLayout->addWidget(TabsMenuButton, 0);
|
||||||
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
|
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
|
||||||
SLOT(onTabsMenuActionTriggered(QAction*)));
|
SLOT(onTabsMenuActionTriggered(QAction*)));
|
||||||
|
|
||||||
|
|
||||||
// Undock button
|
// Undock button
|
||||||
UndockButton = new tTileBarButton();
|
UndockButton = new tTileBarButton();
|
||||||
UndockButton->setObjectName("undockButton");
|
UndockButton->setObjectName("undockButton");
|
||||||
UndockButton->setAutoRaise(true);
|
UndockButton->setAutoRaise(true);
|
||||||
#ifndef QT_NO_TOOLTIP
|
#ifndef QT_NO_TOOLTIP
|
||||||
UndockButton->setToolTip(QObject::tr("Detach Group"));
|
UndockButton->setToolTip(QObject::tr("Detach Group"));
|
||||||
#endif
|
#endif
|
||||||
UndockButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarNormalButton));
|
setTitleBarButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton);
|
||||||
UndockButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
UndockButton->setSizePolicy(ButtonSizePolicy);
|
||||||
TopLayout->addWidget(UndockButton, 0);
|
TopLayout->addWidget(UndockButton, 0);
|
||||||
_this->connect(UndockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked()));
|
_this->connect(UndockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked()));
|
||||||
|
|
||||||
|
|
||||||
|
// Close button
|
||||||
CloseButton = new tTileBarButton();
|
CloseButton = new tTileBarButton();
|
||||||
CloseButton->setObjectName("closeButton");
|
CloseButton->setObjectName("closeButton");
|
||||||
CloseButton->setAutoRaise(true);
|
CloseButton->setAutoRaise(true);
|
||||||
|
setTitleBarButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton);
|
||||||
// The standard icons do not look good on high DPI screens
|
#ifndef QT_NO_TOOLTIP
|
||||||
QIcon CloseIcon = _this->style()->standardIcon(QStyle::SP_TitleBarCloseButton);
|
|
||||||
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
|
|
||||||
QPixmap disabledPixmap = internal::createTransparentPixmap(normalPixmap, 0.25);
|
|
||||||
CloseIcon.addPixmap(disabledPixmap, QIcon::Disabled);
|
|
||||||
|
|
||||||
CloseButton->setIcon(CloseIcon);
|
|
||||||
#ifndef QT_NO_TOOLTIP
|
|
||||||
if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
|
if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
|
||||||
{
|
{
|
||||||
CloseButton->setToolTip(QObject::tr("Close Active Tab"));
|
CloseButton->setToolTip(QObject::tr("Close Active Tab"));
|
||||||
@ -164,9 +179,13 @@ void DockAreaTitleBarPrivate::createButtons()
|
|||||||
{
|
{
|
||||||
CloseButton->setToolTip(QObject::tr("Close Group"));
|
CloseButton->setToolTip(QObject::tr("Close Group"));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
|
CloseButton->setSizePolicy(ButtonSizePolicy);
|
||||||
|
CloseButton->setIconSize(QSize(16, 16));
|
||||||
|
if (testConfigFlag(CDockManager::DockAreaHasCloseButton))
|
||||||
|
{
|
||||||
TopLayout->addWidget(CloseButton, 0);
|
TopLayout->addWidget(CloseButton, 0);
|
||||||
|
}
|
||||||
_this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
|
_this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -262,7 +281,7 @@ void CDockAreaTitleBar::onTabsMenuAboutToShow()
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockAreaTitleBar::onCloseButtonClicked()
|
void CDockAreaTitleBar::onCloseButtonClicked()
|
||||||
{
|
{
|
||||||
qDebug() << "CDockAreaTitleBar::onCloseButtonClicked";
|
ADS_PRINT("CDockAreaTitleBar::onCloseButtonClicked");
|
||||||
if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
|
if (d->testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
|
||||||
{
|
{
|
||||||
d->TabBar->closeTab(d->TabBar->currentIndex());
|
d->TabBar->closeTab(d->TabBar->currentIndex());
|
||||||
@ -277,7 +296,10 @@ void CDockAreaTitleBar::onCloseButtonClicked()
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockAreaTitleBar::onUndockButtonClicked()
|
void CDockAreaTitleBar::onUndockButtonClicked()
|
||||||
{
|
{
|
||||||
|
if (d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||||
|
{
|
||||||
d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
|
d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -332,9 +354,10 @@ void CDockAreaTitleBar::setVisible(bool Visible)
|
|||||||
void CDockAreaTitleBar::showContextMenu(const QPoint& pos)
|
void CDockAreaTitleBar::showContextMenu(const QPoint& pos)
|
||||||
{
|
{
|
||||||
QMenu Menu(this);
|
QMenu Menu(this);
|
||||||
Menu.addAction(tr("Detach Area"), this, SLOT(onUndockButtonClicked()));
|
auto Action = Menu.addAction(tr("Detach Area"), this, SLOT(onUndockButtonClicked()));
|
||||||
|
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
|
||||||
Menu.addSeparator();
|
Menu.addSeparator();
|
||||||
auto Action = Menu.addAction(tr("Close Area"), this, SLOT(onCloseButtonClicked()));
|
Action = Menu.addAction(tr("Close Area"), this, SLOT(onCloseButtonClicked()));
|
||||||
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
|
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
|
||||||
Menu.addAction(tr("Close Other Areas"), d->DockArea, SLOT(closeOtherAreas()));
|
Menu.addAction(tr("Close Other Areas"), d->DockArea, SLOT(closeOtherAreas()));
|
||||||
Menu.exec(mapToGlobal(pos));
|
Menu.exec(mapToGlobal(pos));
|
||||||
|
@ -43,7 +43,9 @@ class CDockAreaWidget;
|
|||||||
struct DockAreaTitleBarPrivate;
|
struct DockAreaTitleBarPrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Title bar of a dock area
|
* Title bar of a dock area.
|
||||||
|
* The title bar contains a tabbar with all tabs for a dock widget group and
|
||||||
|
* with a tabs menu button, a undock button and a close button.
|
||||||
*/
|
*/
|
||||||
class CDockAreaTitleBar : public QFrame
|
class CDockAreaTitleBar : public QFrame
|
||||||
{
|
{
|
||||||
@ -61,6 +63,10 @@ private slots:
|
|||||||
void showContextMenu(const QPoint& pos);
|
void showContextMenu(const QPoint& pos);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
/**
|
||||||
|
* Call this slot to tell the title bar that it should update the tabs menu
|
||||||
|
* the next time it is shown.
|
||||||
|
*/
|
||||||
void markTabsMenuOutdated();
|
void markTabsMenuOutdated();
|
||||||
|
|
||||||
|
|
||||||
@ -87,7 +93,8 @@ public:
|
|||||||
QAbstractButton* button(TitleBarButton which) const;
|
QAbstractButton* button(TitleBarButton which) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function is here for debug reasons
|
* Marks the tabs menu outdated before it calls its base class
|
||||||
|
* implementation
|
||||||
*/
|
*/
|
||||||
virtual void setVisible(bool Visible) override;
|
virtual void setVisible(bool Visible) override;
|
||||||
|
|
||||||
|
@ -63,8 +63,11 @@ static const char* const INDEX_PROPERTY = "index";
|
|||||||
static const char* const ACTION_PROPERTY = "action";
|
static const char* const ACTION_PROPERTY = "action";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* New dock area layout mimics stack layout but only inserts the current
|
* Internal dock area layout mimics stack layout but only inserts the current
|
||||||
* widget into the internal QLayout object
|
* widget into the internal QLayout object.
|
||||||
|
* \warning Only the current widget has a parent. All other widgets
|
||||||
|
* do not have a parent. That means, a widget that is in this layout may
|
||||||
|
* return nullptr for its parent() function if it is not the current widget.
|
||||||
*/
|
*/
|
||||||
class CDockAreaLayout
|
class CDockAreaLayout
|
||||||
{
|
{
|
||||||
@ -118,7 +121,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes the given widget from the lyout
|
* Removes the given widget from the layout
|
||||||
*/
|
*/
|
||||||
void removeWidget(QWidget* Widget)
|
void removeWidget(QWidget* Widget)
|
||||||
{
|
{
|
||||||
@ -241,7 +244,7 @@ struct DockAreaWidgetPrivate
|
|||||||
DockAreaLayout* ContentsLayout = nullptr;
|
DockAreaLayout* ContentsLayout = nullptr;
|
||||||
CDockAreaTitleBar* TitleBar = nullptr;
|
CDockAreaTitleBar* TitleBar = nullptr;
|
||||||
CDockManager* DockManager = nullptr;
|
CDockManager* DockManager = nullptr;
|
||||||
bool UpdateCloseButton = false;
|
bool UpdateTitleBarButtons = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
@ -295,9 +298,9 @@ struct DockAreaWidgetPrivate
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Udpates the enable state of the close button
|
* Udpates the enable state of the close and detach button
|
||||||
*/
|
*/
|
||||||
void updateCloseButtonState();
|
void updateTitleBarButtonStates();
|
||||||
};
|
};
|
||||||
// struct DockAreaWidgetPrivate
|
// struct DockAreaWidgetPrivate
|
||||||
|
|
||||||
@ -322,17 +325,19 @@ void DockAreaWidgetPrivate::createTitleBar()
|
|||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void DockAreaWidgetPrivate::updateCloseButtonState()
|
void DockAreaWidgetPrivate::updateTitleBarButtonStates()
|
||||||
{
|
{
|
||||||
if (_this->isHidden())
|
if (_this->isHidden())
|
||||||
{
|
{
|
||||||
UpdateCloseButton = true;
|
UpdateTitleBarButtons = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBar->button(TitleBarButtonClose)->setEnabled(
|
TitleBar->button(TitleBarButtonClose)->setEnabled(
|
||||||
_this->features().testFlag(CDockWidget::DockWidgetClosable));
|
_this->features().testFlag(CDockWidget::DockWidgetClosable));
|
||||||
UpdateCloseButton = false;
|
TitleBar->button(TitleBarButtonUndock)->setEnabled(
|
||||||
|
_this->features().testFlag(CDockWidget::DockWidgetFloatable));
|
||||||
|
UpdateTitleBarButtons = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,7 +359,7 @@ CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
CDockAreaWidget::~CDockAreaWidget()
|
CDockAreaWidget::~CDockAreaWidget()
|
||||||
{
|
{
|
||||||
qDebug() << "~CDockAreaWidget()";
|
ADS_PRINT("~CDockAreaWidget()");
|
||||||
delete d->ContentsLayout;
|
delete d->ContentsLayout;
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
@ -400,28 +405,29 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
|||||||
setCurrentIndex(index);
|
setCurrentIndex(index);
|
||||||
}
|
}
|
||||||
DockWidget->setDockArea(this);
|
DockWidget->setDockArea(this);
|
||||||
d->updateCloseButtonState();
|
d->updateTitleBarButtonStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
||||||
{
|
{
|
||||||
qDebug() << "CDockAreaWidget::removeDockWidget";
|
ADS_PRINT("CDockAreaWidget::removeDockWidget");
|
||||||
auto NextOpenDockWidget = nextOpenDockWidget(DockWidget);
|
auto NextOpenDockWidget = nextOpenDockWidget(DockWidget);
|
||||||
|
|
||||||
d->ContentsLayout->removeWidget(DockWidget);
|
d->ContentsLayout->removeWidget(DockWidget);
|
||||||
auto TabWidget = DockWidget->tabWidget();
|
auto TabWidget = DockWidget->tabWidget();
|
||||||
TabWidget->hide();
|
TabWidget->hide();
|
||||||
d->tabBar()->removeTab(TabWidget);
|
d->tabBar()->removeTab(TabWidget);
|
||||||
|
CDockContainerWidget* DockContainer = dockContainer();
|
||||||
if (NextOpenDockWidget)
|
if (NextOpenDockWidget)
|
||||||
{
|
{
|
||||||
setCurrentDockWidget(NextOpenDockWidget);
|
setCurrentDockWidget(NextOpenDockWidget);
|
||||||
}
|
}
|
||||||
else if (d->ContentsLayout->isEmpty())
|
else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() > 1)
|
||||||
{
|
{
|
||||||
qDebug() << "Dock Area empty";
|
ADS_PRINT("Dock Area empty");
|
||||||
dockContainer()->removeDockArea(this);
|
DockContainer->removeDockArea(this);
|
||||||
this->deleteLater();
|
this->deleteLater();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -432,16 +438,15 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
|||||||
hideAreaWithNoVisibleContent();
|
hideAreaWithNoVisibleContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
d->updateCloseButtonState();
|
d->updateTitleBarButtonStates();
|
||||||
updateTitleBarVisibility();
|
updateTitleBarVisibility();
|
||||||
auto TopLevelDockWidget = dockContainer()->topLevelDockWidget();
|
auto TopLevelDockWidget = DockContainer->topLevelDockWidget();
|
||||||
if (TopLevelDockWidget)
|
if (TopLevelDockWidget)
|
||||||
{
|
{
|
||||||
TopLevelDockWidget->emitTopLevelChanged(true);
|
TopLevelDockWidget->emitTopLevelChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if (ADS_DEBUG_LEVEL > 0)
|
#if (ADS_DEBUG_LEVEL > 0)
|
||||||
CDockContainerWidget* DockContainer = dockContainer();
|
|
||||||
DockContainer->dumpLayout();
|
DockContainer->dumpLayout();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -481,7 +486,7 @@ void CDockAreaWidget::hideAreaWithNoVisibleContent()
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockAreaWidget::onTabCloseRequested(int Index)
|
void CDockAreaWidget::onTabCloseRequested(int Index)
|
||||||
{
|
{
|
||||||
qDebug() << "CDockAreaWidget::onTabCloseRequested " << Index;
|
ADS_PRINT("CDockAreaWidget::onTabCloseRequested " << Index);
|
||||||
dockWidget(Index)->toggleView(false);
|
dockWidget(Index)->toggleView(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -644,11 +649,11 @@ CDockWidget* CDockAreaWidget::dockWidget(int Index) const
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
|
void CDockAreaWidget::reorderDockWidget(int fromIndex, int toIndex)
|
||||||
{
|
{
|
||||||
qDebug() << "CDockAreaWidget::reorderDockWidget";
|
ADS_PRINT("CDockAreaWidget::reorderDockWidget");
|
||||||
if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
|
if (fromIndex >= d->ContentsLayout->count() || fromIndex < 0
|
||||||
|| toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
|
|| toIndex >= d->ContentsLayout->count() || toIndex < 0 || fromIndex == toIndex)
|
||||||
{
|
{
|
||||||
qDebug() << "Invalid index for tab movement" << fromIndex << toIndex;
|
ADS_PRINT("Invalid index for tab movement" << fromIndex << toIndex);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -703,8 +708,8 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
|
|||||||
auto CurrentDockWidget = currentDockWidget();
|
auto CurrentDockWidget = currentDockWidget();
|
||||||
QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
|
QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
|
||||||
s.writeAttribute("Current", Name);
|
s.writeAttribute("Current", Name);
|
||||||
qDebug() << "CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
|
ADS_PRINT("CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
|
||||||
<< " Current: " << Name;
|
<< " Current: " << Name);
|
||||||
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
||||||
{
|
{
|
||||||
dockWidget(i)->saveState(s);
|
dockWidget(i)->saveState(s);
|
||||||
@ -765,9 +770,9 @@ void CDockAreaWidget::toggleView(bool Open)
|
|||||||
void CDockAreaWidget::setVisible(bool Visible)
|
void CDockAreaWidget::setVisible(bool Visible)
|
||||||
{
|
{
|
||||||
Super::setVisible(Visible);
|
Super::setVisible(Visible);
|
||||||
if (d->UpdateCloseButton)
|
if (d->UpdateTitleBarButtons)
|
||||||
{
|
{
|
||||||
d->updateCloseButtonState();
|
d->updateTitleBarButtonStates();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,12 +185,12 @@ public:
|
|||||||
QList<CDockWidget*> dockWidgets() const;
|
QList<CDockWidget*> dockWidgets() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of dock widgets in this area
|
* Returns the number of open dock widgets in this area
|
||||||
*/
|
*/
|
||||||
int openDockWidgetsCount() const;
|
int openDockWidgetsCount() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a list of dock widgets that are not closed
|
* Returns a list of dock widgets that are not closed.
|
||||||
*/
|
*/
|
||||||
QList<CDockWidget*> openedDockWidgets() const;
|
QList<CDockWidget*> openedDockWidgets() const;
|
||||||
|
|
||||||
@ -236,8 +236,10 @@ public:
|
|||||||
* This functions returns the dock widget features of all dock widget in
|
* This functions returns the dock widget features of all dock widget in
|
||||||
* this area.
|
* this area.
|
||||||
* A bitwise and is used to combine the flags of all dock widgets. That
|
* A bitwise and is used to combine the flags of all dock widgets. That
|
||||||
* means, if only dock widget does not support a certain flag, the whole
|
* means, if only one single dock widget does not support a certain flag,
|
||||||
* dock are does not support the flag.
|
* the whole dock are does not support the flag. I.e. if one single
|
||||||
|
* dock widget in this area is not closabe, the whole dock are is not
|
||||||
|
* closable.
|
||||||
*/
|
*/
|
||||||
CDockWidget::DockWidgetFeatures features() const;
|
CDockWidget::DockWidgetFeatures features() const;
|
||||||
|
|
||||||
|
@ -269,7 +269,7 @@ public:
|
|||||||
CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = nullptr)
|
CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = nullptr)
|
||||||
{
|
{
|
||||||
CDockSplitter* s = new CDockSplitter(orientation, parent);
|
CDockSplitter* s = new CDockSplitter(orientation, parent);
|
||||||
s->setOpaqueResize(DockManager->configFlags().testFlag(CDockManager::OpaqueSplitterResize));
|
s->setOpaqueResize(CDockManager::configFlags().testFlag(CDockManager::OpaqueSplitterResize));
|
||||||
s->setChildrenCollapsible(false);
|
s->setChildrenCollapsible(false);
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -557,8 +557,8 @@ void DockContainerWidgetPrivate::saveChildNodesState(QXmlStreamWriter& s, QWidge
|
|||||||
s.writeStartElement("Splitter");
|
s.writeStartElement("Splitter");
|
||||||
s.writeAttribute("Orientation", (Splitter->orientation() == Qt::Horizontal) ? "-" : "|");
|
s.writeAttribute("Orientation", (Splitter->orientation() == Qt::Horizontal) ? "-" : "|");
|
||||||
s.writeAttribute("Count", QString::number(Splitter->count()));
|
s.writeAttribute("Count", QString::number(Splitter->count()));
|
||||||
qDebug() << "NodeSplitter orient: " << Splitter->orientation()
|
ADS_PRINT("NodeSplitter orient: " << Splitter->orientation()
|
||||||
<< " WidgetCont: " << Splitter->count();
|
<< " WidgetCont: " << Splitter->count());
|
||||||
for (int i = 0; i < Splitter->count(); ++i)
|
for (int i = 0; i < Splitter->count(); ++i)
|
||||||
{
|
{
|
||||||
saveChildNodesState(s, Splitter->widget(i));
|
saveChildNodesState(s, Splitter->widget(i));
|
||||||
@ -608,8 +608,8 @@ bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
qDebug() << "Restore NodeSplitter Orientation: " << Orientation <<
|
ADS_PRINT("Restore NodeSplitter Orientation: " << Orientation <<
|
||||||
" WidgetCount: " << WidgetCount;
|
" WidgetCount: " << WidgetCount);
|
||||||
QSplitter* Splitter = nullptr;
|
QSplitter* Splitter = nullptr;
|
||||||
if (!Testing)
|
if (!Testing)
|
||||||
{
|
{
|
||||||
@ -632,7 +632,7 @@ bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
|
|||||||
else if (s.name() == "Sizes")
|
else if (s.name() == "Sizes")
|
||||||
{
|
{
|
||||||
QString sSizes = s.readElementText().trimmed();
|
QString sSizes = s.readElementText().trimmed();
|
||||||
qDebug() << "Sizes: " << sSizes;
|
ADS_PRINT("Sizes: " << sSizes);
|
||||||
QTextStream TextStream(&sSizes);
|
QTextStream TextStream(&sSizes);
|
||||||
while (!TextStream.atEnd())
|
while (!TextStream.atEnd())
|
||||||
{
|
{
|
||||||
@ -656,8 +656,8 @@ bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "ChildNode isVisible " << ChildNode->isVisible()
|
ADS_PRINT("ChildNode isVisible " << ChildNode->isVisible()
|
||||||
<< " isVisibleTo " << ChildNode->isVisibleTo(Splitter);
|
<< " isVisibleTo " << ChildNode->isVisibleTo(Splitter));
|
||||||
Splitter->addWidget(ChildNode);
|
Splitter->addWidget(ChildNode);
|
||||||
Visible |= ChildNode->isVisibleTo(Splitter);
|
Visible |= ChildNode->isVisibleTo(Splitter);
|
||||||
}
|
}
|
||||||
@ -703,8 +703,8 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s,
|
|||||||
|
|
||||||
|
|
||||||
QString CurrentDockWidget = s.attributes().value("Current").toString();
|
QString CurrentDockWidget = s.attributes().value("Current").toString();
|
||||||
qDebug() << "Restore NodeDockArea Tabs: " << Tabs << " Current: "
|
ADS_PRINT("Restore NodeDockArea Tabs: " << Tabs << " Current: "
|
||||||
<< CurrentDockWidget;
|
<< CurrentDockWidget);
|
||||||
|
|
||||||
CDockAreaWidget* DockArea = nullptr;
|
CDockAreaWidget* DockArea = nullptr;
|
||||||
if (!Testing)
|
if (!Testing)
|
||||||
@ -738,7 +738,7 @@ bool DockContainerWidgetPrivate::restoreDockArea(QXmlStreamReader& s,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "Dock Widget found - parent " << DockWidget->parent();
|
ADS_PRINT("Dock Widget found - parent " << DockWidget->parent());
|
||||||
// We hide the DockArea here to prevent the short display (the flashing)
|
// We hide the DockArea here to prevent the short display (the flashing)
|
||||||
// of the dock areas during application startup
|
// of the dock areas during application startup
|
||||||
DockArea->hide();
|
DockArea->hide();
|
||||||
@ -780,17 +780,17 @@ bool DockContainerWidgetPrivate::restoreChildNodes(QXmlStreamReader& s,
|
|||||||
if (s.name() == "Splitter")
|
if (s.name() == "Splitter")
|
||||||
{
|
{
|
||||||
Result = restoreSplitter(s, CreatedWidget, Testing);
|
Result = restoreSplitter(s, CreatedWidget, Testing);
|
||||||
qDebug() << "Splitter";
|
ADS_PRINT("Splitter");
|
||||||
}
|
}
|
||||||
else if (s.name() == "Area")
|
else if (s.name() == "Area")
|
||||||
{
|
{
|
||||||
Result = restoreDockArea(s, CreatedWidget, Testing);
|
Result = restoreDockArea(s, CreatedWidget, Testing);
|
||||||
qDebug() << "DockAreaWidget";
|
ADS_PRINT("DockAreaWidget");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s.skipCurrentElement();
|
s.skipCurrentElement();
|
||||||
qDebug() << "Unknown element";
|
ADS_PRINT("Unknown element");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -862,6 +862,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
|||||||
buf.fill(' ', level * 4);
|
buf.fill(' ', level * 4);
|
||||||
if (Splitter)
|
if (Splitter)
|
||||||
{
|
{
|
||||||
|
#ifdef ADS_DEBUG_PRINT
|
||||||
qDebug("%sSplitter %s v: %s c: %s",
|
qDebug("%sSplitter %s v: %s c: %s",
|
||||||
(const char*)buf,
|
(const char*)buf,
|
||||||
(Splitter->orientation() == Qt::Vertical) ? "--" : "|",
|
(Splitter->orientation() == Qt::Vertical) ? "--" : "|",
|
||||||
@ -871,6 +872,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
|||||||
<< ((Splitter->orientation() == Qt::Vertical) ? "--" : "|") << " "
|
<< ((Splitter->orientation() == Qt::Vertical) ? "--" : "|") << " "
|
||||||
<< (Splitter->isHidden() ? " " : "v") << " "
|
<< (Splitter->isHidden() ? " " : "v") << " "
|
||||||
<< QString::number(Splitter->count()).toStdString() << std::endl;
|
<< QString::number(Splitter->count()).toStdString() << std::endl;
|
||||||
|
#endif
|
||||||
for (int i = 0; i < Splitter->count(); ++i)
|
for (int i = 0; i < Splitter->count(); ++i)
|
||||||
{
|
{
|
||||||
dumpRecursive(level + 1, Splitter->widget(i));
|
dumpRecursive(level + 1, Splitter->widget(i));
|
||||||
@ -883,6 +885,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
|||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
#ifdef ADS_DEBUG_PRINT
|
||||||
qDebug("%sDockArea", (const char*)buf);
|
qDebug("%sDockArea", (const char*)buf);
|
||||||
std::cout << (const char*)buf
|
std::cout << (const char*)buf
|
||||||
<< (DockArea->isHidden() ? " " : "v")
|
<< (DockArea->isHidden() ? " " : "v")
|
||||||
@ -897,6 +900,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
|||||||
std::cout << (DockWidget->isClosed() ? "c" : " ") << " ";
|
std::cout << (DockWidget->isClosed() ? "c" : " ") << " ";
|
||||||
std::cout << DockWidget->windowTitle().toStdString() << std::endl;
|
std::cout << DockWidget->windowTitle().toStdString() << std::endl;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
Q_UNUSED(level);
|
Q_UNUSED(level);
|
||||||
@ -923,12 +927,12 @@ CDockAreaWidget* DockContainerWidgetPrivate::dockWidgetIntoDockArea(DockWidgetAr
|
|||||||
int index = TargetAreaSplitter ->indexOf(TargetDockArea);
|
int index = TargetAreaSplitter ->indexOf(TargetDockArea);
|
||||||
if (TargetAreaSplitter->orientation() == InsertParam.orientation())
|
if (TargetAreaSplitter->orientation() == InsertParam.orientation())
|
||||||
{
|
{
|
||||||
qDebug() << "TargetAreaSplitter->orientation() == InsertParam.orientation()";
|
ADS_PRINT("TargetAreaSplitter->orientation() == InsertParam.orientation()");
|
||||||
TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea);
|
TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "TargetAreaSplitter->orientation() != InsertParam.orientation()";
|
ADS_PRINT("TargetAreaSplitter->orientation() != InsertParam.orientation()");
|
||||||
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
|
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
|
||||||
NewSplitter->addWidget(TargetDockArea);
|
NewSplitter->addWidget(TargetDockArea);
|
||||||
insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
|
insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
|
||||||
@ -998,6 +1002,15 @@ CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockW
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CDockContainerWidget::removeDockWidget(CDockWidget* Dockwidget)
|
||||||
|
{
|
||||||
|
CDockAreaWidget* Area = Dockwidget->dockAreaWidget();
|
||||||
|
if (Area)
|
||||||
|
{
|
||||||
|
Area->removeDockWidget(Dockwidget);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
unsigned int CDockContainerWidget::zOrderIndex() const
|
unsigned int CDockContainerWidget::zOrderIndex() const
|
||||||
@ -1047,7 +1060,7 @@ void CDockContainerWidget::addDockArea(CDockAreaWidget* DockAreaWidget,
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
||||||
{
|
{
|
||||||
qDebug() << "CDockContainerWidget::removeDockArea";
|
ADS_PRINT("CDockContainerWidget::removeDockArea");
|
||||||
area->disconnect(this);
|
area->disconnect(this);
|
||||||
d->DockAreas.removeAll(area);
|
d->DockAreas.removeAll(area);
|
||||||
CDockSplitter* Splitter = internal::findParent<CDockSplitter*>(area);
|
CDockSplitter* Splitter = internal::findParent<CDockSplitter*>(area);
|
||||||
@ -1057,6 +1070,12 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
|||||||
area->setParent(nullptr);
|
area->setParent(nullptr);
|
||||||
internal::hideEmptyParentSplitters(Splitter);
|
internal::hideEmptyParentSplitters(Splitter);
|
||||||
|
|
||||||
|
// Remove this area from cached areas
|
||||||
|
const auto& cache = d->LastAddedAreaCache;
|
||||||
|
if (auto p = std::find(cache, cache+sizeof(cache)/sizeof(cache[0]), area)) {
|
||||||
|
d->LastAddedAreaCache[std::distance(cache, p)] = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
// If splitter has more than 1 widgets, we are finished and can leave
|
// If splitter has more than 1 widgets, we are finished and can leave
|
||||||
if (Splitter->count() > 1)
|
if (Splitter->count() > 1)
|
||||||
{
|
{
|
||||||
@ -1067,7 +1086,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
|||||||
// avoid too many empty splitters
|
// avoid too many empty splitters
|
||||||
if (Splitter == d->RootSplitter)
|
if (Splitter == d->RootSplitter)
|
||||||
{
|
{
|
||||||
qDebug() << "Removed from RootSplitter";
|
ADS_PRINT("Removed from RootSplitter");
|
||||||
// If splitter is empty, we are finished
|
// If splitter is empty, we are finished
|
||||||
if (!Splitter->count())
|
if (!Splitter->count())
|
||||||
{
|
{
|
||||||
@ -1089,11 +1108,11 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
|||||||
QLayoutItem* li = d->Layout->replaceWidget(Splitter, ChildSplitter);
|
QLayoutItem* li = d->Layout->replaceWidget(Splitter, ChildSplitter);
|
||||||
d->RootSplitter = ChildSplitter;
|
d->RootSplitter = ChildSplitter;
|
||||||
delete li;
|
delete li;
|
||||||
qDebug() << "RootSplitter replaced by child splitter";
|
ADS_PRINT("RootSplitter replaced by child splitter");
|
||||||
}
|
}
|
||||||
else if (Splitter->count() == 1)
|
else if (Splitter->count() == 1)
|
||||||
{
|
{
|
||||||
qDebug() << "Replacing splitter with content";
|
ADS_PRINT("Replacing splitter with content");
|
||||||
QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
|
QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
|
||||||
auto Sizes = ParentSplitter->sizes();
|
auto Sizes = ParentSplitter->sizes();
|
||||||
QWidget* widget = Splitter->widget(0);
|
QWidget* widget = Splitter->widget(0);
|
||||||
@ -1172,7 +1191,7 @@ int CDockContainerWidget::visibleDockAreaCount() const
|
|||||||
void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget,
|
void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWidget,
|
||||||
const QPoint& TargetPos)
|
const QPoint& TargetPos)
|
||||||
{
|
{
|
||||||
qDebug() << "CDockContainerWidget::dropFloatingWidget";
|
ADS_PRINT("CDockContainerWidget::dropFloatingWidget");
|
||||||
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
|
CDockAreaWidget* DockArea = dockAreaAt(TargetPos);
|
||||||
auto dropArea = InvalidDockWidgetArea;
|
auto dropArea = InvalidDockWidgetArea;
|
||||||
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
auto ContainerDropArea = d->DockManager->containerOverlay()->dropAreaUnderCursor();
|
||||||
@ -1192,7 +1211,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
|
|||||||
|
|
||||||
if (dropArea != InvalidDockWidgetArea)
|
if (dropArea != InvalidDockWidgetArea)
|
||||||
{
|
{
|
||||||
qDebug() << "Dock Area Drop Content: " << dropArea;
|
ADS_PRINT("Dock Area Drop Content: " << dropArea);
|
||||||
d->dropIntoSection(FloatingWidget, DockArea, dropArea);
|
d->dropIntoSection(FloatingWidget, DockArea, dropArea);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1201,7 +1220,7 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
|
|||||||
if (InvalidDockWidgetArea == dropArea)
|
if (InvalidDockWidgetArea == dropArea)
|
||||||
{
|
{
|
||||||
dropArea = ContainerDropArea;
|
dropArea = ContainerDropArea;
|
||||||
qDebug() << "Container Drop Content: " << dropArea;
|
ADS_PRINT("Container Drop Content: " << dropArea);
|
||||||
if (dropArea != InvalidDockWidgetArea)
|
if (dropArea != InvalidDockWidgetArea)
|
||||||
{
|
{
|
||||||
d->dropIntoContainer(FloatingWidget, dropArea);
|
d->dropIntoContainer(FloatingWidget, dropArea);
|
||||||
@ -1243,8 +1262,8 @@ QList<CDockAreaWidget*> CDockContainerWidget::openedDockAreas() const
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
|
void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
|
||||||
{
|
{
|
||||||
qDebug() << "CDockContainerWidget::saveState isFloating "
|
ADS_PRINT("CDockContainerWidget::saveState isFloating "
|
||||||
<< isFloating();
|
<< isFloating());
|
||||||
|
|
||||||
s.writeStartElement("Container");
|
s.writeStartElement("Container");
|
||||||
s.writeAttribute("Floating", QString::number(isFloating() ? 1 : 0));
|
s.writeAttribute("Floating", QString::number(isFloating() ? 1 : 0));
|
||||||
@ -1267,18 +1286,19 @@ void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
|
|||||||
bool CDockContainerWidget::restoreState(QXmlStreamReader& s, bool Testing)
|
bool CDockContainerWidget::restoreState(QXmlStreamReader& s, bool Testing)
|
||||||
{
|
{
|
||||||
bool IsFloating = s.attributes().value("Floating").toInt();
|
bool IsFloating = s.attributes().value("Floating").toInt();
|
||||||
qDebug() << "Restore CDockContainerWidget Floating" << IsFloating;
|
ADS_PRINT("Restore CDockContainerWidget Floating" << IsFloating);
|
||||||
|
|
||||||
QWidget*NewRootSplitter {};
|
QWidget*NewRootSplitter {};
|
||||||
if (!Testing)
|
if (!Testing)
|
||||||
{
|
{
|
||||||
d->VisibleDockAreaCount = -1;// invalidate the dock area count
|
d->VisibleDockAreaCount = -1;// invalidate the dock area count
|
||||||
d->DockAreas.clear();
|
d->DockAreas.clear();
|
||||||
|
std::fill(std::begin(d->LastAddedAreaCache),std::end(d->LastAddedAreaCache), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsFloating)
|
if (IsFloating)
|
||||||
{
|
{
|
||||||
qDebug() << "Restore floating widget";
|
ADS_PRINT("Restore floating widget");
|
||||||
if (!s.readNextStartElement() || s.name() != "Geometry")
|
if (!s.readNextStartElement() || s.name() != "Geometry")
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
|
@ -50,7 +50,10 @@ struct FloatingDockContainerPrivate;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Container that manages a number of dock areas with single dock widgets
|
* Container that manages a number of dock areas with single dock widgets
|
||||||
* or tabyfied dock widgets in each area
|
* or tabyfied dock widgets in each area.
|
||||||
|
* Each window that support docking has a DockContainerWidget. That means
|
||||||
|
* the main application window and all floating windows are ore contain
|
||||||
|
* an DockContainerWidget.
|
||||||
*/
|
*/
|
||||||
class ADS_EXPORT CDockContainerWidget : public QFrame
|
class ADS_EXPORT CDockContainerWidget : public QFrame
|
||||||
{
|
{
|
||||||
@ -166,6 +169,11 @@ public:
|
|||||||
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
|
||||||
CDockAreaWidget* DockAreaWidget = nullptr);
|
CDockAreaWidget* DockAreaWidget = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes dockwidget
|
||||||
|
*/
|
||||||
|
void removeDockWidget(CDockWidget* Dockwidget);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the current zOrderIndex
|
* Returns the current zOrderIndex
|
||||||
*/
|
*/
|
||||||
|
@ -56,6 +56,8 @@
|
|||||||
|
|
||||||
namespace ads
|
namespace ads
|
||||||
{
|
{
|
||||||
|
static CDockManager::ConfigFlags StaticConfigFlags = CDockManager::DefaultConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data class of CDockManager class (pimpl)
|
* Private data class of CDockManager class (pimpl)
|
||||||
*/
|
*/
|
||||||
@ -72,7 +74,6 @@ struct DockManagerPrivate
|
|||||||
QMenu* ViewMenu;
|
QMenu* ViewMenu;
|
||||||
CDockManager::eViewMenuInsertionOrder MenuInsertionOrder = CDockManager::MenuAlphabeticallySorted;
|
CDockManager::eViewMenuInsertionOrder MenuInsertionOrder = CDockManager::MenuAlphabeticallySorted;
|
||||||
bool RestoringState = false;
|
bool RestoringState = false;
|
||||||
CDockManager::ConfigFlags ConfigFlags = CDockManager::DefaultConfig;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
@ -145,7 +146,11 @@ DockManagerPrivate::DockManagerPrivate(CDockManager* _public) :
|
|||||||
void DockManagerPrivate::loadStylesheet()
|
void DockManagerPrivate::loadStylesheet()
|
||||||
{
|
{
|
||||||
QString Result;
|
QString Result;
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
QFile StyleSheetFile(":ads/stylesheets/default_linux.css");
|
||||||
|
#else
|
||||||
QFile StyleSheetFile(":ads/stylesheets/default.css");
|
QFile StyleSheetFile(":ads/stylesheets/default.css");
|
||||||
|
#endif
|
||||||
StyleSheetFile.open(QIODevice::ReadOnly);
|
StyleSheetFile.open(QIODevice::ReadOnly);
|
||||||
QTextStream StyleSheetStream(&StyleSheetFile);
|
QTextStream StyleSheetStream(&StyleSheetFile);
|
||||||
Result = StyleSheetStream.readAll();
|
Result = StyleSheetStream.readAll();
|
||||||
@ -170,7 +175,7 @@ bool DockManagerPrivate::restoreContainer(int Index, QXmlStreamReader& stream, b
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
qDebug() << "d->Containers[i]->restoreState ";
|
ADS_PRINT("d->Containers[i]->restoreState ");
|
||||||
auto Container = Containers[Index];
|
auto Container = Containers[Index];
|
||||||
if (Container->isFloating())
|
if (Container->isFloating())
|
||||||
{
|
{
|
||||||
@ -207,7 +212,7 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
|
|||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
qDebug() << s.attributes().value("Version");
|
ADS_PRINT(s.attributes().value("Version"));
|
||||||
bool ok;
|
bool ok;
|
||||||
int v = s.attributes().value("Version").toInt(&ok);
|
int v = s.attributes().value("Version").toInt(&ok);
|
||||||
if (!ok || v != version)
|
if (!ok || v != version)
|
||||||
@ -217,7 +222,7 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
|
|||||||
|
|
||||||
bool Result = true;
|
bool Result = true;
|
||||||
int DockContainers = s.attributes().value("Containers").toInt();
|
int DockContainers = s.attributes().value("Containers").toInt();
|
||||||
qDebug() << DockContainers;
|
ADS_PRINT(DockContainers);
|
||||||
int DockContainerCount = 0;
|
int DockContainerCount = 0;
|
||||||
while (s.readNextStartElement())
|
while (s.readNextStartElement())
|
||||||
{
|
{
|
||||||
@ -336,11 +341,12 @@ void DockManagerPrivate::emitTopLevelEvents()
|
|||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
|
bool DockManagerPrivate::restoreState(const QByteArray& State, int version)
|
||||||
{
|
{
|
||||||
|
QByteArray state = State.startsWith("<?xml") ? State : qUncompress(State);
|
||||||
if (!checkFormat(state, version))
|
if (!checkFormat(state, version))
|
||||||
{
|
{
|
||||||
qDebug() << "checkFormat: Error checking format!!!!!!!";
|
ADS_PRINT("checkFormat: Error checking format!!!!!!!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -350,7 +356,7 @@ bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
|
|||||||
|
|
||||||
if (!restoreStateFromXml(state, version))
|
if (!restoreStateFromXml(state, version))
|
||||||
{
|
{
|
||||||
qDebug() << "restoreState: Error restoring state!!!!!!!";
|
ADS_PRINT("restoreState: Error restoring state!!!!!!!");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -425,7 +431,7 @@ CDockManager::~CDockManager()
|
|||||||
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
||||||
{
|
{
|
||||||
d->FloatingWidgets.append(FloatingWidget);
|
d->FloatingWidgets.append(FloatingWidget);
|
||||||
qDebug() << "d->FloatingWidgets.count() " << d->FloatingWidgets.count();
|
ADS_PRINT("d->FloatingWidgets.count() " << d->FloatingWidgets.count());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -489,11 +495,12 @@ unsigned int CDockManager::zOrderIndex() const
|
|||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
QByteArray CDockManager::saveState(eXmlMode XmlMode, int version) const
|
QByteArray CDockManager::saveState(int version) const
|
||||||
{
|
{
|
||||||
QByteArray xmldata;
|
QByteArray xmldata;
|
||||||
QXmlStreamWriter s(&xmldata);
|
QXmlStreamWriter s(&xmldata);
|
||||||
s.setAutoFormatting(XmlAutoFormattingEnabled == XmlMode);
|
auto ConfigFlags = CDockManager::configFlags();
|
||||||
|
s.setAutoFormatting(ConfigFlags.testFlag(XmlAutoFormattingEnabled));
|
||||||
s.writeStartDocument();
|
s.writeStartDocument();
|
||||||
s.writeStartElement("QtAdvancedDockingSystem");
|
s.writeStartElement("QtAdvancedDockingSystem");
|
||||||
s.writeAttribute("Version", QString::number(version));
|
s.writeAttribute("Version", QString::number(version));
|
||||||
@ -506,7 +513,8 @@ QByteArray CDockManager::saveState(eXmlMode XmlMode, int version) const
|
|||||||
s.writeEndElement();
|
s.writeEndElement();
|
||||||
s.writeEndDocument();
|
s.writeEndDocument();
|
||||||
|
|
||||||
return xmldata;
|
return ConfigFlags.testFlag(XmlCompressionEnabled)
|
||||||
|
? qCompress(xmldata, 9) : xmldata;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -565,9 +573,13 @@ CDockAreaWidget* CDockManager::addDockWidgetTab(DockWidgetArea area,
|
|||||||
{
|
{
|
||||||
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, AreaWidget);
|
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, AreaWidget);
|
||||||
}
|
}
|
||||||
|
else if (!openedDockAreas().isEmpty())
|
||||||
|
{
|
||||||
|
return addDockWidget(area, Dockwidget, openedDockAreas().last());
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return addDockWidget(area, Dockwidget, AreaWidget);
|
return addDockWidget(area, Dockwidget, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -586,6 +598,12 @@ CDockWidget* CDockManager::findDockWidget(const QString& ObjectName) const
|
|||||||
return d->DockWidgetsMap.value(ObjectName, nullptr);
|
return d->DockWidgetsMap.value(ObjectName, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CDockManager::removeDockWidget(CDockWidget* Dockwidget)
|
||||||
|
{
|
||||||
|
d->DockWidgetsMap.remove(Dockwidget->objectName());
|
||||||
|
CDockContainerWidget::removeDockWidget(Dockwidget);
|
||||||
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
QMap<QString, CDockWidget*> CDockManager::dockWidgetsMap() const
|
QMap<QString, CDockWidget*> CDockManager::dockWidgetsMap() const
|
||||||
@ -747,16 +765,23 @@ int CDockManager::startDragDistance()
|
|||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
CDockManager::ConfigFlags CDockManager::configFlags() const
|
CDockManager::ConfigFlags CDockManager::configFlags()
|
||||||
{
|
{
|
||||||
return d->ConfigFlags;
|
return StaticConfigFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
void CDockManager::setConfigFlags(const ConfigFlags Flags)
|
void CDockManager::setConfigFlags(const ConfigFlags Flags)
|
||||||
{
|
{
|
||||||
d->ConfigFlags = Flags;
|
StaticConfigFlags = Flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//===========================================================================
|
||||||
|
void CDockManager::setConfigFlag(eConfigFlag Flag, bool On)
|
||||||
|
{
|
||||||
|
internal::setFlag(StaticConfigFlags, Flag, On);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -51,7 +51,16 @@ struct DockWidgetTabPrivate;
|
|||||||
struct DockAreaWidgetPrivate;
|
struct DockAreaWidgetPrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The central dock manager that maintains the complete docking system
|
* The central dock manager that maintains the complete docking system.
|
||||||
|
* With the configuration flags you can globally control the functionality
|
||||||
|
* of the docking system. The dock manager uses an internal stylesheet to
|
||||||
|
* style its components like splitters, tabs and buttons. If you want to
|
||||||
|
* disable this stylesheet because your application uses its own,
|
||||||
|
* just call the function for settings the stylesheet with an empty
|
||||||
|
* string.
|
||||||
|
* \code
|
||||||
|
* DockManager->setStyleSheet("");
|
||||||
|
* \endcode
|
||||||
**/
|
**/
|
||||||
class ADS_EXPORT CDockManager : public CDockContainerWidget
|
class ADS_EXPORT CDockManager : public CDockContainerWidget
|
||||||
{
|
{
|
||||||
@ -108,23 +117,22 @@ public:
|
|||||||
MenuAlphabeticallySorted
|
MenuAlphabeticallySorted
|
||||||
};
|
};
|
||||||
|
|
||||||
enum eXmlMode
|
|
||||||
{
|
|
||||||
XmlAutoFormattingDisabled,
|
|
||||||
XmlAutoFormattingEnabled
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* These global configuration flags configure some global dock manager
|
* These global configuration flags configure some global dock manager
|
||||||
* settings.
|
* settings.
|
||||||
*/
|
*/
|
||||||
enum eConfigFlag
|
enum eConfigFlag
|
||||||
{
|
{
|
||||||
ActiveTabHasCloseButton = 0x01, //!< If this flag is set, the active tab in a tab area has a close button
|
ActiveTabHasCloseButton = 0x0001, //!< If this flag is set, the active tab in a tab area has a close button
|
||||||
DockAreaHasCloseButton = 0x02, //!< If the flag is set each dock area has a close button
|
DockAreaHasCloseButton = 0x0002, //!< If the flag is set each dock area has a close button
|
||||||
DockAreaCloseButtonClosesTab = 0x04,//!< If the flag is set, the dock area close button closes the active tab, if not set, it closes the complete cock area
|
DockAreaCloseButtonClosesTab = 0x0004,//!< If the flag is set, the dock area close button closes the active tab, if not set, it closes the complete cock area
|
||||||
OpaqueSplitterResize = 0x08, //!< See QSplitter::setOpaqueResize() documentation
|
OpaqueSplitterResize = 0x0008, //!< See QSplitter::setOpaqueResize() documentation
|
||||||
DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize, ///< the default configuration
|
XmlAutoFormattingEnabled = 0x0010,//!< If enabled, the XML writer automatically adds line-breaks and indentation to empty sections between elements (ignorable whitespace).
|
||||||
|
XmlCompressionEnabled = 0x0020,//!< If enabled, the XML output will be compressed and is not human readable anymore
|
||||||
|
TabCloseButtonIsToolButton = 0x0040,//! If enabled the tab close buttons will be QToolButtons instead of QPushButtons - disabled by default
|
||||||
|
AllTabsHaveCloseButton = 0x0080, //!< if this flag is set, then all tabs that are closable show a close button
|
||||||
|
RetainTabSizeWhenCloseButtonHidden = 0x0100, //!< if this flag is set, the space for the close button is reserved even if the close button is not visible
|
||||||
|
DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize | XmlCompressionEnabled, ///< the default configuration
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag)
|
Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag)
|
||||||
|
|
||||||
@ -133,7 +141,7 @@ public:
|
|||||||
* If the given parent is a QMainWindow, the dock manager sets itself as the
|
* If the given parent is a QMainWindow, the dock manager sets itself as the
|
||||||
* central widget.
|
* central widget.
|
||||||
* Before you create any dock widgets, you should properly setup the
|
* Before you create any dock widgets, you should properly setup the
|
||||||
* configuration flags via setConfigFlags()
|
* configuration flags via setConfigFlags().
|
||||||
*/
|
*/
|
||||||
CDockManager(QWidget* parent = 0);
|
CDockManager(QWidget* parent = 0);
|
||||||
|
|
||||||
@ -145,13 +153,18 @@ public:
|
|||||||
/**
|
/**
|
||||||
* This function returns the global configuration flags
|
* This function returns the global configuration flags
|
||||||
*/
|
*/
|
||||||
ConfigFlags configFlags() const;
|
static ConfigFlags configFlags();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the global configuration flags for the whole docking system.
|
* Sets the global configuration flags for the whole docking system.
|
||||||
* Call this function before you create your first dock widget.
|
* Call this function before you create your first dock widget.
|
||||||
*/
|
*/
|
||||||
void setConfigFlags(const ConfigFlags Flags);
|
static void setConfigFlags(const ConfigFlags Flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a certain config flag
|
||||||
|
*/
|
||||||
|
static void setConfigFlag(eConfigFlag Flag, bool On = true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds dockwidget into the given area.
|
* Adds dockwidget into the given area.
|
||||||
@ -192,6 +205,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
CDockWidget* findDockWidget(const QString& ObjectName) const;
|
CDockWidget* findDockWidget(const QString& ObjectName) const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the given Dock from the dock manager
|
||||||
|
*/
|
||||||
|
void removeDockWidget(CDockWidget* Dockwidget);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function returns a readable reference to the internal dock
|
* This function returns a readable reference to the internal dock
|
||||||
* widgets map so that it is possible to iterate over all dock widgets
|
* widgets map so that it is possible to iterate over all dock widgets
|
||||||
@ -223,7 +241,7 @@ public:
|
|||||||
* The XmlMode XmlAutoFormattingDisabled is better if you would like to have
|
* The XmlMode XmlAutoFormattingDisabled is better if you would like to have
|
||||||
* a more compact XML output - i.e. for storage in ini files.
|
* a more compact XML output - i.e. for storage in ini files.
|
||||||
*/
|
*/
|
||||||
QByteArray saveState(eXmlMode XmlMode = XmlAutoFormattingDisabled, int version = 0) const;
|
QByteArray saveState(int version = 0) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Restores the state of this dockmanagers dockwidgets.
|
* Restores the state of this dockmanagers dockwidgets.
|
||||||
|
@ -132,6 +132,21 @@ struct DockOverlayCrossPrivate
|
|||||||
return Color;
|
return Color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
/**
|
||||||
|
* Helper function that returns the drop indicator width depending on the
|
||||||
|
* operating system
|
||||||
|
*/
|
||||||
|
qreal dropIndicatiorWidth(QLabel* l) const
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
Q_UNUSED(l)
|
||||||
|
return 40;
|
||||||
|
#else
|
||||||
|
return static_cast<qreal>(l->fontMetrics().height()) * 3.f;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
|
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
|
||||||
@ -140,7 +155,7 @@ struct DockOverlayCrossPrivate
|
|||||||
QLabel* l = new QLabel();
|
QLabel* l = new QLabel();
|
||||||
l->setObjectName("DockWidgetAreaLabel");
|
l->setObjectName("DockWidgetAreaLabel");
|
||||||
|
|
||||||
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
|
const qreal metric = dropIndicatiorWidth(l);
|
||||||
const QSizeF size(metric, metric);
|
const QSizeF size(metric, metric);
|
||||||
|
|
||||||
l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode));
|
l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode));
|
||||||
@ -154,7 +169,7 @@ struct DockOverlayCrossPrivate
|
|||||||
void updateDropIndicatorIcon(QWidget* DropIndicatorWidget)
|
void updateDropIndicatorIcon(QWidget* DropIndicatorWidget)
|
||||||
{
|
{
|
||||||
QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
|
QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
|
||||||
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
|
const qreal metric = dropIndicatiorWidth(l);
|
||||||
const QSizeF size(metric, metric);
|
const QSizeF size(metric, metric);
|
||||||
|
|
||||||
int Area = l->property("dockWidgetArea").toInt();
|
int Area = l->property("dockWidgetArea").toInt();
|
||||||
|
@ -245,9 +245,6 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
virtual void showEvent(QShowEvent* e) override;
|
virtual void showEvent(QShowEvent* e) override;
|
||||||
void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);
|
void setAreaWidgets(const QHash<DockWidgetArea, QWidget*>& widgets);
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
}; // CDockOverlayCross
|
}; // CDockOverlayCross
|
||||||
|
|
||||||
} // namespace ads
|
} // namespace ads
|
||||||
|
@ -68,7 +68,7 @@ CDockSplitter::CDockSplitter(Qt::Orientation orientation, QWidget *parent)
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
CDockSplitter::~CDockSplitter()
|
CDockSplitter::~CDockSplitter()
|
||||||
{
|
{
|
||||||
qDebug() << "~CDockSplitter";
|
ADS_PRINT("~CDockSplitter");
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,8 @@ namespace ads
|
|||||||
struct DockSplitterPrivate;
|
struct DockSplitterPrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Splitter used internally instead of QSplitter
|
* Splitter used internally instead of QSplitter with some additional
|
||||||
|
* fuctionality.
|
||||||
*/
|
*/
|
||||||
class ADS_EXPORT CDockSplitter : public QSplitter
|
class ADS_EXPORT CDockSplitter : public QSplitter
|
||||||
{
|
{
|
||||||
|
@ -214,7 +214,7 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
|
|||||||
setObjectName(title);
|
setObjectName(title);
|
||||||
|
|
||||||
d->TabWidget = new CDockWidgetTab(this);
|
d->TabWidget = new CDockWidgetTab(this);
|
||||||
d->ToggleViewAction = new QAction(title, nullptr);
|
d->ToggleViewAction = new QAction(title, this);
|
||||||
d->ToggleViewAction->setCheckable(true);
|
d->ToggleViewAction->setCheckable(true);
|
||||||
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
|
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
|
||||||
SLOT(toggleView(bool)));
|
SLOT(toggleView(bool)));
|
||||||
@ -224,7 +224,7 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
CDockWidget::~CDockWidget()
|
CDockWidget::~CDockWidget()
|
||||||
{
|
{
|
||||||
qDebug() << "~CDockWidget()";
|
ADS_PRINT("~CDockWidget()");
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -243,21 +243,35 @@ void CDockWidget::setToggleViewActionChecked(bool Checked)
|
|||||||
void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
|
void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
|
||||||
{
|
{
|
||||||
QScrollArea* ScrollAreaWidget = qobject_cast<QScrollArea*>(widget);
|
QScrollArea* ScrollAreaWidget = qobject_cast<QScrollArea*>(widget);
|
||||||
if (ScrollAreaWidget || ForceNoScrollArea != InsertMode)
|
if (ScrollAreaWidget || ForceNoScrollArea == InsertMode)
|
||||||
|
{
|
||||||
|
d->Layout->addWidget(widget);
|
||||||
|
if (ScrollAreaWidget && ScrollAreaWidget->viewport())
|
||||||
|
{
|
||||||
|
ScrollAreaWidget->viewport()->setProperty("dockWidgetContent", true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
d->setupScrollArea();
|
d->setupScrollArea();
|
||||||
d->ScrollArea->setWidget(widget);
|
d->ScrollArea->setWidget(widget);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
d->Layout->addWidget(widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
d->Widget = widget;
|
d->Widget = widget;
|
||||||
d->Widget->setProperty("dockWidgetContent", true);
|
d->Widget->setProperty("dockWidgetContent", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
QWidget* CDockWidget::takeWidget()
|
||||||
|
{
|
||||||
|
d->ScrollArea->takeWidget();
|
||||||
|
d->Layout->removeWidget(d->Widget);
|
||||||
|
d->Widget->setParent(nullptr);
|
||||||
|
return d->Widget;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
QWidget* CDockWidget::widget() const
|
QWidget* CDockWidget::widget() const
|
||||||
{
|
{
|
||||||
@ -275,25 +289,21 @@ CDockWidgetTab* CDockWidget::tabWidget() const
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockWidget::setFeatures(DockWidgetFeatures features)
|
void CDockWidget::setFeatures(DockWidgetFeatures features)
|
||||||
{
|
{
|
||||||
|
if (d->Features == features)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
d->Features = features;
|
d->Features = features;
|
||||||
|
d->TabWidget->onDockWidgetFeaturesChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
|
void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
|
||||||
{
|
{
|
||||||
#if QT_VERSION >= 0x050700
|
auto Features = features();
|
||||||
d->Features.setFlag(flag, on);
|
internal::setFlag(Features, flag, on);
|
||||||
#else
|
setFeatures(Features);
|
||||||
if(on)
|
|
||||||
{
|
|
||||||
d->Features |= flag;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
d->Features &= ~flag;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -141,7 +141,7 @@ public:
|
|||||||
enum DockWidgetFeature
|
enum DockWidgetFeature
|
||||||
{
|
{
|
||||||
DockWidgetClosable = 0x01,
|
DockWidgetClosable = 0x01,
|
||||||
DockWidgetMovable = 0x02,
|
DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored
|
||||||
DockWidgetFloatable = 0x04,
|
DockWidgetFloatable = 0x04,
|
||||||
AllDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable,
|
AllDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable,
|
||||||
NoDockWidgetFeatures = 0x00
|
NoDockWidgetFeatures = 0x00
|
||||||
@ -238,6 +238,11 @@ public:
|
|||||||
*/
|
*/
|
||||||
void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
|
void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the widget from the dock and give ownership back to the caller
|
||||||
|
*/
|
||||||
|
QWidget* takeWidget();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the widget for the dock widget. This function returns zero if
|
* Returns the widget for the dock widget. This function returns zero if
|
||||||
* the widget has not been set.
|
* the widget has not been set.
|
||||||
|
@ -55,7 +55,6 @@ namespace ads
|
|||||||
{
|
{
|
||||||
|
|
||||||
using tTabLabel = CElidingLabel;
|
using tTabLabel = CElidingLabel;
|
||||||
using tCloseButton = QPushButton;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data class of CDockWidgetTab class (pimpl)
|
* Private data class of CDockWidgetTab class (pimpl)
|
||||||
@ -72,7 +71,7 @@ struct DockWidgetTabPrivate
|
|||||||
eDragState DragState = DraggingInactive;
|
eDragState DragState = DraggingInactive;
|
||||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||||
QIcon Icon;
|
QIcon Icon;
|
||||||
tCloseButton* CloseButton = nullptr;
|
QAbstractButton* CloseButton = nullptr;
|
||||||
QSpacerItem* IconTextSpacer;
|
QSpacerItem* IconTextSpacer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -120,7 +119,24 @@ struct DockWidgetTabPrivate
|
|||||||
*/
|
*/
|
||||||
bool testConfigFlag(CDockManager::eConfigFlag Flag) const
|
bool testConfigFlag(CDockManager::eConfigFlag Flag) const
|
||||||
{
|
{
|
||||||
return DockArea->dockManager()->configFlags().testFlag(Flag);
|
return CDockManager::configFlags().testFlag(Flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the close button as QPushButton or as QToolButton
|
||||||
|
*/
|
||||||
|
QAbstractButton* createCloseButton() const
|
||||||
|
{
|
||||||
|
if (testConfigFlag(CDockManager::TabCloseButtonIsToolButton))
|
||||||
|
{
|
||||||
|
auto Button = new QToolButton();
|
||||||
|
Button->setAutoRaise(true);
|
||||||
|
return Button;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return new QPushButton();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// struct DockWidgetTabPrivate
|
// struct DockWidgetTabPrivate
|
||||||
@ -143,19 +159,19 @@ void DockWidgetTabPrivate::createLayout()
|
|||||||
TitleLabel->setObjectName("dockWidgetTabLabel");
|
TitleLabel->setObjectName("dockWidgetTabLabel");
|
||||||
TitleLabel->setAlignment(Qt::AlignCenter);
|
TitleLabel->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
CloseButton = new tCloseButton();
|
CloseButton = createCloseButton();
|
||||||
CloseButton->setObjectName("tabCloseButton");
|
CloseButton->setObjectName("tabCloseButton");
|
||||||
// The standard icons do does not look good on high DPI screens
|
// The standard icons do does not look good on high DPI screens
|
||||||
QIcon CloseIcon = _this->style()->standardIcon(QStyle::SP_TitleBarCloseButton);
|
QIcon CloseIcon;
|
||||||
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
|
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
|
||||||
QPixmap disabledPixmap = internal::createTransparentPixmap(normalPixmap, 0.25);
|
CloseIcon.addPixmap(normalPixmap, QIcon::Normal);
|
||||||
CloseIcon.addPixmap(disabledPixmap, QIcon::Disabled);
|
CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
|
||||||
CloseButton->setIcon(CloseIcon);
|
CloseButton->setIcon(CloseIcon);
|
||||||
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||||
CloseButton->setVisible(false);
|
_this->onDockWidgetFeaturesChanged();
|
||||||
#ifndef QT_NO_TOOLTIP
|
#ifndef QT_NO_TOOLTIP
|
||||||
CloseButton->setToolTip(QObject::tr("Close Tab"));
|
CloseButton->setToolTip(QObject::tr("Close Tab"));
|
||||||
#endif
|
#endif
|
||||||
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
|
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
|
||||||
|
|
||||||
QFontMetrics fm(TitleLabel->font());
|
QFontMetrics fm(TitleLabel->font());
|
||||||
@ -192,9 +208,9 @@ void DockWidgetTabPrivate::moveTab(QMouseEvent* ev)
|
|||||||
bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
|
bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
|
||||||
{
|
{
|
||||||
auto dockContainer = DockWidget->dockContainer();
|
auto dockContainer = DockWidget->dockContainer();
|
||||||
qDebug() << "isFloating " << dockContainer->isFloating();
|
ADS_PRINT("isFloating " << dockContainer->isFloating());
|
||||||
qDebug() << "areaCount " << dockContainer->dockAreaCount();
|
ADS_PRINT("areaCount " << dockContainer->dockAreaCount());
|
||||||
qDebug() << "widgetCount " << DockWidget->dockAreaWidget()->dockWidgetsCount();
|
ADS_PRINT("widgetCount " << DockWidget->dockAreaWidget()->dockWidgetsCount());
|
||||||
// if this is the last dock widget inside of this floating widget,
|
// if this is the last dock widget inside of this floating widget,
|
||||||
// then it does not make any sense, to make it floating because
|
// then it does not make any sense, to make it floating because
|
||||||
// it is already floating
|
// it is already floating
|
||||||
@ -205,7 +221,7 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
qDebug() << "startFloating";
|
ADS_PRINT("startFloating");
|
||||||
DragState = DraggingState;
|
DragState = DraggingState;
|
||||||
QSize Size = DockArea->size();
|
QSize Size = DockArea->size();
|
||||||
CFloatingDockContainer* FloatingWidget = nullptr;
|
CFloatingDockContainer* FloatingWidget = nullptr;
|
||||||
@ -223,7 +239,7 @@ bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
|
|||||||
|
|
||||||
if (DraggingFloatingWidget == DraggingState)
|
if (DraggingFloatingWidget == DraggingState)
|
||||||
{
|
{
|
||||||
FloatingWidget->startDragging(DragStartMousePosition, Size);
|
FloatingWidget->startDragging(DragStartMousePosition, Size, _this);
|
||||||
auto Overlay = DockWidget->dockManager()->containerOverlay();
|
auto Overlay = DockWidget->dockManager()->containerOverlay();
|
||||||
Overlay->setAllowedAreas(OuterDockAreas);
|
Overlay->setAllowedAreas(OuterDockAreas);
|
||||||
this->FloatingWidget = FloatingWidget;
|
this->FloatingWidget = FloatingWidget;
|
||||||
@ -250,7 +266,7 @@ CDockWidgetTab::CDockWidgetTab(CDockWidget* DockWidget, QWidget *parent) :
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
CDockWidgetTab::~CDockWidgetTab()
|
CDockWidgetTab::~CDockWidgetTab()
|
||||||
{
|
{
|
||||||
qDebug() << "~CDockWidgetTab()";
|
ADS_PRINT("~CDockWidgetTab()");
|
||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -327,7 +343,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Floating is only allowed for widgets that are movable
|
// Floating is only allowed for widgets that are movable
|
||||||
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetMovable))
|
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||||
{
|
{
|
||||||
d->startFloating();
|
d->startFloating();
|
||||||
}
|
}
|
||||||
@ -351,9 +367,10 @@ void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
|
|||||||
|
|
||||||
d->DragStartMousePosition = ev->pos();
|
d->DragStartMousePosition = ev->pos();
|
||||||
QMenu Menu(this);
|
QMenu Menu(this);
|
||||||
Menu.addAction(tr("Detach"), this, SLOT(onDetachActionTriggered()));
|
auto Action = Menu.addAction(tr("Detach"), this, SLOT(onDetachActionTriggered()));
|
||||||
|
Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable));
|
||||||
Menu.addSeparator();
|
Menu.addSeparator();
|
||||||
auto Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
|
Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
|
||||||
Action->setEnabled(isClosable());
|
Action->setEnabled(isClosable());
|
||||||
Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
|
Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
|
||||||
Menu.exec(mapToGlobal(ev->pos()));
|
Menu.exec(mapToGlobal(ev->pos()));
|
||||||
@ -371,8 +388,10 @@ bool CDockWidgetTab::isActiveTab() const
|
|||||||
void CDockWidgetTab::setActiveTab(bool active)
|
void CDockWidgetTab::setActiveTab(bool active)
|
||||||
{
|
{
|
||||||
bool DockWidgetClosable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable);
|
bool DockWidgetClosable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable);
|
||||||
bool TabHasCloseButton = d->testConfigFlag(CDockManager::ActiveTabHasCloseButton);
|
bool ActiveTabHasCloseButton = d->testConfigFlag(CDockManager::ActiveTabHasCloseButton);
|
||||||
d->CloseButton->setVisible(active && DockWidgetClosable && TabHasCloseButton);
|
bool AllTabsHaveCloseButton = d->testConfigFlag(CDockManager::AllTabsHaveCloseButton);
|
||||||
|
bool TabHasCloseButton = (ActiveTabHasCloseButton && active) | AllTabsHaveCloseButton;
|
||||||
|
d->CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton);
|
||||||
if (d->IsActiveTab == active)
|
if (d->IsActiveTab == active)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -442,7 +461,7 @@ void CDockWidgetTab::setIcon(const QIcon& Icon)
|
|||||||
d->Icon = Icon;
|
d->Icon = Icon;
|
||||||
if (d->IconLabel)
|
if (d->IconLabel)
|
||||||
{
|
{
|
||||||
d->IconLabel->setPixmap(Icon.pixmap(this->windowHandle(), QSize(16, 16)));
|
d->IconLabel->setPixmap(Icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this)));
|
||||||
d->IconLabel->setVisible(true);
|
d->IconLabel->setVisible(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -468,7 +487,8 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
|
|||||||
// If this is the last dock area in a dock container it does not make
|
// 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
|
// sense to move it to a new floating widget and leave this one
|
||||||
// empty
|
// empty
|
||||||
if (!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
|
if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
|
||||||
|
&& d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||||
{
|
{
|
||||||
d->DragStartMousePosition = event->pos();
|
d->DragStartMousePosition = event->pos();
|
||||||
d->startFloating(DraggingInactive);
|
d->startFloating(DraggingInactive);
|
||||||
@ -504,13 +524,15 @@ bool CDockWidgetTab::isClosable() const
|
|||||||
//===========================================================================
|
//===========================================================================
|
||||||
void CDockWidgetTab::onDetachActionTriggered()
|
void CDockWidgetTab::onDetachActionTriggered()
|
||||||
{
|
{
|
||||||
|
if (!d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
d->DragStartMousePosition = mapFromGlobal(QCursor::pos());
|
d->DragStartMousePosition = mapFromGlobal(QCursor::pos());
|
||||||
d->startFloating(DraggingInactive);
|
d->startFloating(DraggingInactive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
bool CDockWidgetTab::event(QEvent *e)
|
bool CDockWidgetTab::event(QEvent *e)
|
||||||
{
|
{
|
||||||
@ -525,6 +547,17 @@ bool CDockWidgetTab::event(QEvent *e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CDockWidgetTab::onDockWidgetFeaturesChanged()
|
||||||
|
{
|
||||||
|
auto Features = d->DockWidget->features();
|
||||||
|
auto SizePolicy = d->CloseButton->sizePolicy();
|
||||||
|
SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable)
|
||||||
|
&& d->testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden));
|
||||||
|
d->CloseButton->setSizePolicy(SizePolicy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace ads
|
} // namespace ads
|
||||||
|
@ -53,6 +53,8 @@ class ADS_EXPORT CDockWidgetTab : public QFrame
|
|||||||
private:
|
private:
|
||||||
DockWidgetTabPrivate* d; ///< private data (pimpl)
|
DockWidgetTabPrivate* d; ///< private data (pimpl)
|
||||||
friend struct DockWidgetTabPrivate;
|
friend struct DockWidgetTabPrivate;
|
||||||
|
friend class CDockWidget;
|
||||||
|
void onDockWidgetFeaturesChanged();
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onDetachActionTriggered();
|
void onDetachActionTriggered();
|
||||||
@ -125,7 +127,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
QString text() const;
|
QString text() const;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the tab text
|
* Sets the tab text
|
||||||
*/
|
*/
|
||||||
@ -136,17 +137,15 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isClosable() const;
|
bool isClosable() const;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Track event ToolTipChange and set child ToolTip
|
* Track event ToolTipChange and set child ToolTip
|
||||||
*/
|
*/
|
||||||
virtual bool event(QEvent *e) override;
|
virtual bool event(QEvent *e) override;
|
||||||
|
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
||||||
virtual void setVisible(bool visible) override;
|
virtual void setVisible(bool visible) override;
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void activeTabChanged();
|
void activeTabChanged();
|
||||||
void clicked();
|
void clicked();
|
||||||
|
@ -157,7 +157,11 @@ QSize CElidingLabel::minimumSizeHint() const
|
|||||||
return QLabel::minimumSizeHint();
|
return QLabel::minimumSizeHint();
|
||||||
}
|
}
|
||||||
const QFontMetrics &fm = fontMetrics();
|
const QFontMetrics &fm = fontMetrics();
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
||||||
|
QSize size(fm.horizontalAdvance(d->Text.left(2) + "…"), fm.height());
|
||||||
|
#else
|
||||||
QSize size(fm.width(d->Text.left(2) + "…"), fm.height());
|
QSize size(fm.width(d->Text.left(2) + "…"), fm.height());
|
||||||
|
#endif
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -170,7 +174,11 @@ QSize CElidingLabel::sizeHint() const
|
|||||||
return QLabel::sizeHint();
|
return QLabel::sizeHint();
|
||||||
}
|
}
|
||||||
const QFontMetrics& fm = fontMetrics();
|
const QFontMetrics& fm = fontMetrics();
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 11, 0))
|
||||||
|
QSize size(fm.horizontalAdvance(d->Text), QLabel::sizeHint().height());
|
||||||
|
#else
|
||||||
QSize size(fm.width(d->Text), QLabel::sizeHint().height());
|
QSize size(fm.width(d->Text), QLabel::sizeHint().height());
|
||||||
|
#endif
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,21 +1,20 @@
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Qt Advanced Docking System
|
** Qt Advanced Docking System
|
||||||
** Copyright (C) 2017 Uwe Kindler
|
** Copyright (C) 2017 Uwe Kindler
|
||||||
**
|
**
|
||||||
** This library is free software; you can redistribute it and/or
|
** This library is free software; you can redistribute it and/or
|
||||||
** modify it under the terms of the GNU Lesser General Public
|
** modify it under the terms of the GNU Lesser General Public
|
||||||
** License as published by the Free Software Foundation; either
|
** License as published by the Free Software Foundation; either
|
||||||
** version 2.1 of the License, or (at your option) any later version.
|
** version 2.1 of the License, or (at your option) any later version.
|
||||||
**
|
**
|
||||||
** This library is distributed in the hope that it will be useful,
|
** This library is distributed in the hope that it will be useful,
|
||||||
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
** Lesser General Public License for more details.
|
** Lesser General Public License for more details.
|
||||||
**
|
**
|
||||||
** You should have received a copy of the GNU Lesser General Public
|
** You should have received a copy of the GNU Lesser General Public
|
||||||
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
/// \file FloatingDockContainer.cpp
|
/// \file FloatingDockContainer.cpp
|
||||||
@ -24,7 +23,6 @@
|
|||||||
/// \brief Implementation of CFloatingDockContainer class
|
/// \brief Implementation of CFloatingDockContainer class
|
||||||
//============================================================================
|
//============================================================================
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
// INCLUDES
|
// INCLUDES
|
||||||
//============================================================================
|
//============================================================================
|
||||||
@ -45,7 +43,10 @@
|
|||||||
#include "DockWidget.h"
|
#include "DockWidget.h"
|
||||||
#include "DockOverlay.h"
|
#include "DockOverlay.h"
|
||||||
|
|
||||||
#include <iostream>
|
#ifdef Q_OS_LINUX
|
||||||
|
#include "linux/FloatingWidgetTitleBar.h"
|
||||||
|
#include <xcb/xcb.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace ads
|
namespace ads
|
||||||
{
|
{
|
||||||
@ -55,22 +56,26 @@ static unsigned int zOrderCounter = 0;
|
|||||||
*/
|
*/
|
||||||
struct FloatingDockContainerPrivate
|
struct FloatingDockContainerPrivate
|
||||||
{
|
{
|
||||||
CFloatingDockContainer* _this;
|
CFloatingDockContainer *_this;
|
||||||
CDockContainerWidget* DockContainer;
|
CDockContainerWidget *DockContainer;
|
||||||
unsigned int zOrderIndex = ++zOrderCounter;
|
unsigned int zOrderIndex = ++zOrderCounter;
|
||||||
QPointer<CDockManager> DockManager;
|
QPointer<CDockManager> DockManager;
|
||||||
eDragState DraggingState = DraggingInactive;
|
eDragState DraggingState = DraggingInactive;
|
||||||
QPoint DragStartMousePosition;
|
QPoint DragStartMousePosition;
|
||||||
CDockContainerWidget* DropContainer = nullptr;
|
CDockContainerWidget *DropContainer = nullptr;
|
||||||
CDockAreaWidget* SingleDockArea = nullptr;
|
CDockAreaWidget *SingleDockArea = nullptr;
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
QWidget* MouseEventHandler = nullptr;
|
||||||
|
CFloatingWidgetTitleBar* TitleBar = nullptr;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Private data constructor
|
* Private data constructor
|
||||||
*/
|
*/
|
||||||
FloatingDockContainerPrivate(CFloatingDockContainer* _public);
|
FloatingDockContainerPrivate(CFloatingDockContainer *_public);
|
||||||
|
|
||||||
void titleMouseReleaseEvent();
|
void titleMouseReleaseEvent();
|
||||||
void updateDropOverlays(const QPoint& GlobalPos);
|
void updateDropOverlays(const QPoint &GlobalPos);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests is a certain state is active
|
* Tests is a certain state is active
|
||||||
@ -84,20 +89,26 @@ struct FloatingDockContainerPrivate
|
|||||||
{
|
{
|
||||||
DraggingState = StateId;
|
DraggingState = StateId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setWindowTitle(const QString &Text)
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
TitleBar->setTitle(Text);
|
||||||
|
#else
|
||||||
|
_this->setWindowTitle(Text);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
};
|
};
|
||||||
// struct FloatingDockContainerPrivate
|
// struct FloatingDockContainerPrivate
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
FloatingDockContainerPrivate::FloatingDockContainerPrivate(CFloatingDockContainer* _public) :
|
FloatingDockContainerPrivate::FloatingDockContainerPrivate(
|
||||||
|
CFloatingDockContainer *_public) :
|
||||||
_this(_public)
|
_this(_public)
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
||||||
{
|
{
|
||||||
@ -107,25 +118,31 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (DockManager->dockAreaOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea
|
if (DockManager->dockAreaOverlay()->dropAreaUnderCursor()
|
||||||
|| DockManager->containerOverlay()->dropAreaUnderCursor() != InvalidDockWidgetArea)
|
!= InvalidDockWidgetArea
|
||||||
|
|| DockManager->containerOverlay()->dropAreaUnderCursor()
|
||||||
|
!= InvalidDockWidgetArea)
|
||||||
{
|
{
|
||||||
// Resize the floating widget to the size of the highlighted drop area
|
// Resize the floating widget to the size of the highlighted drop area
|
||||||
// rectangle
|
// rectangle
|
||||||
CDockOverlay* Overlay = DockManager->containerOverlay();
|
CDockOverlay *Overlay = DockManager->containerOverlay();
|
||||||
if (!Overlay->dropOverlayRect().isValid())
|
if (!Overlay->dropOverlayRect().isValid())
|
||||||
{
|
{
|
||||||
Overlay = DockManager->dockAreaOverlay();
|
Overlay = DockManager->dockAreaOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect Rect = Overlay->dropOverlayRect();
|
QRect Rect = Overlay->dropOverlayRect();
|
||||||
int FrameWidth = (_this->frameSize().width() - _this->rect().width()) / 2;
|
int FrameWidth = (_this->frameSize().width() - _this->rect().width())
|
||||||
int TitleBarHeight = _this->frameSize().height() - _this->rect().height() - FrameWidth;
|
/ 2;
|
||||||
|
int TitleBarHeight = _this->frameSize().height()
|
||||||
|
- _this->rect().height() - FrameWidth;
|
||||||
if (Rect.isValid())
|
if (Rect.isValid())
|
||||||
{
|
{
|
||||||
QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft());
|
QPoint TopLeft = Overlay->mapToGlobal(Rect.topLeft());
|
||||||
TopLeft.ry() += TitleBarHeight;
|
TopLeft.ry() += TitleBarHeight;
|
||||||
_this->setGeometry(QRect(TopLeft, QSize(Rect.width(), Rect.height() - TitleBarHeight)));
|
_this->setGeometry(
|
||||||
|
QRect(TopLeft,
|
||||||
|
QSize(Rect.width(), Rect.height() - TitleBarHeight)));
|
||||||
QApplication::processEvents();
|
QApplication::processEvents();
|
||||||
}
|
}
|
||||||
DropContainer->dropFloatingWidget(_this, QCursor::pos());
|
DropContainer->dropFloatingWidget(_this, QCursor::pos());
|
||||||
@ -135,10 +152,8 @@ void FloatingDockContainerPrivate::titleMouseReleaseEvent()
|
|||||||
DockManager->dockAreaOverlay()->hideOverlay();
|
DockManager->dockAreaOverlay()->hideOverlay();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
|
void FloatingDockContainerPrivate::updateDropOverlays(const QPoint &GlobalPos)
|
||||||
{
|
{
|
||||||
if (!_this->isVisible() || !DockManager)
|
if (!_this->isVisible() || !DockManager)
|
||||||
{
|
{
|
||||||
@ -146,7 +161,7 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto Containers = DockManager->dockContainers();
|
auto Containers = DockManager->dockContainers();
|
||||||
CDockContainerWidget* TopContainer = nullptr;
|
CDockContainerWidget *TopContainer = nullptr;
|
||||||
for (auto ContainerWidget : Containers)
|
for (auto ContainerWidget : Containers)
|
||||||
{
|
{
|
||||||
if (!ContainerWidget->isVisible())
|
if (!ContainerWidget->isVisible())
|
||||||
@ -181,23 +196,24 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
|
int VisibleDockAreas = TopContainer->visibleDockAreaCount();
|
||||||
ContainerOverlay->setAllowedAreas(VisibleDockAreas > 1 ?
|
ContainerOverlay->setAllowedAreas(
|
||||||
OuterDockAreas : AllDockAreas);
|
VisibleDockAreas > 1 ? OuterDockAreas : AllDockAreas);
|
||||||
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
|
DockWidgetArea ContainerArea = ContainerOverlay->showOverlay(TopContainer);
|
||||||
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
|
ContainerOverlay->enableDropPreview(ContainerArea != InvalidDockWidgetArea);
|
||||||
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
|
auto DockArea = TopContainer->dockAreaAt(GlobalPos);
|
||||||
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
|
if (DockArea && DockArea->isVisible() && VisibleDockAreas > 0)
|
||||||
{
|
{
|
||||||
DockAreaOverlay->enableDropPreview(true);
|
DockAreaOverlay->enableDropPreview(true);
|
||||||
DockAreaOverlay->setAllowedAreas((VisibleDockAreas == 1) ?
|
DockAreaOverlay->setAllowedAreas(
|
||||||
NoDockWidgetArea : AllDockAreas);
|
(VisibleDockAreas == 1) ? NoDockWidgetArea : AllDockAreas);
|
||||||
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
|
DockWidgetArea Area = DockAreaOverlay->showOverlay(DockArea);
|
||||||
|
|
||||||
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that
|
// A CenterDockWidgetArea for the dockAreaOverlay() indicates that
|
||||||
// the mouse is in the title bar. If the ContainerArea is valid
|
// the mouse is in the title bar. If the ContainerArea is valid
|
||||||
// then we ignore the dock area of the dockAreaOverlay() and disable
|
// then we ignore the dock area of the dockAreaOverlay() and disable
|
||||||
// the drop preview
|
// the drop preview
|
||||||
if ((Area == CenterDockWidgetArea) && (ContainerArea != InvalidDockWidgetArea))
|
if ((Area == CenterDockWidgetArea)
|
||||||
|
&& (ContainerArea != InvalidDockWidgetArea))
|
||||||
{
|
{
|
||||||
DockAreaOverlay->enableDropPreview(false);
|
DockAreaOverlay->enableDropPreview(false);
|
||||||
ContainerOverlay->enableDropPreview(true);
|
ContainerOverlay->enableDropPreview(true);
|
||||||
@ -213,22 +229,36 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
|
CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
|
||||||
QWidget(DockManager, Qt::Window),
|
tFloatingWidgetBase(DockManager),
|
||||||
d(new FloatingDockContainerPrivate(this))
|
d(new FloatingDockContainerPrivate(this))
|
||||||
{
|
{
|
||||||
d->DockManager = DockManager;
|
d->DockManager = DockManager;
|
||||||
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
|
d->DockContainer = new CDockContainerWidget(DockManager, this);
|
||||||
|
connect(d->DockContainer, SIGNAL(dockAreasAdded()), this,
|
||||||
|
SLOT(onDockAreasAddedOrRemoved()));
|
||||||
|
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this,
|
||||||
|
SLOT(onDockAreasAddedOrRemoved()));
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
d->TitleBar = new CFloatingWidgetTitleBar(this);
|
||||||
|
setWindowFlags(windowFlags() | Qt::Tool);
|
||||||
|
QDockWidget::setWidget(d->DockContainer);
|
||||||
|
QDockWidget::setFloating(true);
|
||||||
|
QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||||
|
setTitleBarWidget(d->TitleBar);
|
||||||
|
connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
|
||||||
|
#else
|
||||||
|
setWindowFlags(
|
||||||
|
Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
||||||
|
QBoxLayout *l = new QBoxLayout(QBoxLayout::TopToBottom);
|
||||||
l->setContentsMargins(0, 0, 0, 0);
|
l->setContentsMargins(0, 0, 0, 0);
|
||||||
l->setSpacing(0);
|
l->setSpacing(0);
|
||||||
setLayout(l);
|
setLayout(l);
|
||||||
|
|
||||||
d->DockContainer = new CDockContainerWidget(DockManager, this);
|
|
||||||
connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, SLOT(onDockAreasAddedOrRemoved()));
|
|
||||||
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, SLOT(onDockAreasAddedOrRemoved()));
|
|
||||||
l->addWidget(d->DockContainer);
|
l->addWidget(d->DockContainer);
|
||||||
|
#endif
|
||||||
|
|
||||||
DockManager->registerFloatingWidget(this);
|
DockManager->registerFloatingWidget(this);
|
||||||
|
|
||||||
// We install an event filter to detect mouse release events because we
|
// We install an event filter to detect mouse release events because we
|
||||||
@ -237,26 +267,30 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
|
|||||||
qApp->installEventFilter(this);
|
qApp->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) :
|
CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) :
|
||||||
CFloatingDockContainer(DockArea->dockManager())
|
CFloatingDockContainer(DockArea->dockManager())
|
||||||
{
|
{
|
||||||
d->DockContainer->addDockArea(DockArea);
|
d->DockContainer->addDockArea(DockArea);
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
d->TitleBar->enableCloseButton(isClosable());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
|
CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) :
|
||||||
CFloatingDockContainer(DockWidget->dockManager())
|
CFloatingDockContainer(DockWidget->dockManager())
|
||||||
{
|
{
|
||||||
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
|
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
d->TitleBar->enableCloseButton(isClosable());
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
CFloatingDockContainer::~CFloatingDockContainer()
|
CFloatingDockContainer::~CFloatingDockContainer()
|
||||||
{
|
{
|
||||||
qDebug() << "~CFloatingDockContainer";
|
ADS_PRINT("~CFloatingDockContainer");
|
||||||
if (d->DockManager)
|
if (d->DockManager)
|
||||||
{
|
{
|
||||||
d->DockManager->removeFloatingWidget(this);
|
d->DockManager->removeFloatingWidget(this);
|
||||||
@ -264,27 +298,24 @@ CFloatingDockContainer::~CFloatingDockContainer()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
CDockContainerWidget* CFloatingDockContainer::dockContainer() const
|
CDockContainerWidget* CFloatingDockContainer::dockContainer() const
|
||||||
{
|
{
|
||||||
return d->DockContainer;
|
return d->DockContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::changeEvent(QEvent *event)
|
void CFloatingDockContainer::changeEvent(QEvent *event)
|
||||||
{
|
{
|
||||||
QWidget::changeEvent(event);
|
QWidget::changeEvent(event);
|
||||||
if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
|
if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
|
||||||
{
|
{
|
||||||
qDebug() << "FloatingWidget::changeEvent QEvent::ActivationChange ";
|
ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
|
||||||
d->zOrderIndex = ++zOrderCounter;
|
d->zOrderIndex = ++zOrderCounter;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||||
{
|
{
|
||||||
@ -304,11 +335,10 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::closeEvent(QCloseEvent *event)
|
void CFloatingDockContainer::closeEvent(QCloseEvent *event)
|
||||||
{
|
{
|
||||||
qDebug() << "CFloatingDockContainer closeEvent";
|
ADS_PRINT("CFloatingDockContainer closeEvent");
|
||||||
d->setState(DraggingInactive);
|
d->setState(DraggingInactive);
|
||||||
|
|
||||||
if (isClosable())
|
if (isClosable())
|
||||||
@ -319,11 +349,18 @@ void CFloatingDockContainer::closeEvent(QCloseEvent *event)
|
|||||||
// https://bugreports.qt.io/browse/QTBUG-73295
|
// https://bugreports.qt.io/browse/QTBUG-73295
|
||||||
// The following code is a workaround for Qt versions > 5.9.2 that seems
|
// The following code is a workaround for Qt versions > 5.9.2 that seems
|
||||||
// to work
|
// to work
|
||||||
#if (QT_VERSION > 0x050902)
|
// Starting from Qt version 5.12.2 this seems to work again. But
|
||||||
|
// now the QEvent::NonClientAreaMouseButtonPress function returns always
|
||||||
|
// Qt::RightButton even if the left button was pressed
|
||||||
|
#ifndef Q_OS_LINUX
|
||||||
|
#if (QT_VERSION > QT_VERSION_CHECK(5, 9, 2) && QT_VERSION < QT_VERSION_CHECK(5, 12, 2))
|
||||||
event->ignore();
|
event->ignore();
|
||||||
this->hide();
|
this->hide();
|
||||||
#else
|
#else
|
||||||
Super::closeEvent(event);
|
Super::closeEvent(event);
|
||||||
|
#endif
|
||||||
|
#else // Q_OS_LINUX
|
||||||
|
Super::closeEvent(event);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -332,7 +369,6 @@ void CFloatingDockContainer::closeEvent(QCloseEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::hideEvent(QHideEvent *event)
|
void CFloatingDockContainer::hideEvent(QHideEvent *event)
|
||||||
{
|
{
|
||||||
@ -346,39 +382,48 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::showEvent(QShowEvent *event)
|
void CFloatingDockContainer::showEvent(QShowEvent *event)
|
||||||
{
|
{
|
||||||
Super::showEvent(event);
|
Super::showEvent(event);
|
||||||
/*for (auto DockArea : d->DockContainer->openedDockAreas())
|
|
||||||
{
|
|
||||||
for (auto DockWidget : DockArea->openedDockWidgets())
|
|
||||||
{
|
|
||||||
DockWidget->setToggleViewActionChecked(true);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
bool CFloatingDockContainer::event(QEvent *e)
|
bool CFloatingDockContainer::event(QEvent *e)
|
||||||
{
|
{
|
||||||
switch (d->DraggingState)
|
switch (d->DraggingState)
|
||||||
{
|
{
|
||||||
case DraggingInactive:
|
case DraggingInactive:
|
||||||
if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons() == Qt::LeftButton)
|
|
||||||
{
|
{
|
||||||
qDebug() << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type();
|
// Normally we would check here, if the left mouse button is pressed.
|
||||||
|
// But from QT version 5.12.2 on the mouse events from
|
||||||
|
// QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
|
||||||
|
// The event always returns Qt::RightButton even if the left button
|
||||||
|
// is clicked.
|
||||||
|
// It is really great to work around the whole NonClientMouseArea
|
||||||
|
// bugs
|
||||||
|
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
|
||||||
|
if (e->type()
|
||||||
|
== QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
|
||||||
|
{
|
||||||
|
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
|
||||||
d->setState(DraggingMousePressed);
|
d->setState(DraggingMousePressed);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
|
||||||
|
{
|
||||||
|
ADS_PRINT("FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type());
|
||||||
|
d->setState(DraggingMousePressed);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DraggingMousePressed:
|
case DraggingMousePressed:
|
||||||
switch (e->type())
|
switch (e->type())
|
||||||
{
|
{
|
||||||
case QEvent::NonClientAreaMouseButtonDblClick:
|
case QEvent::NonClientAreaMouseButtonDblClick:
|
||||||
qDebug() << "FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick";
|
ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick");
|
||||||
d->setState(DraggingInactive);
|
d->setState(DraggingInactive);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -405,7 +450,7 @@ bool CFloatingDockContainer::event(QEvent *e)
|
|||||||
case DraggingFloatingWidget:
|
case DraggingFloatingWidget:
|
||||||
if (e->type() == QEvent::NonClientAreaMouseButtonRelease)
|
if (e->type() == QEvent::NonClientAreaMouseButtonRelease)
|
||||||
{
|
{
|
||||||
qDebug() << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease";
|
ADS_PRINT("FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease");
|
||||||
d->titleMouseReleaseEvent();
|
d->titleMouseReleaseEvent();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -420,59 +465,81 @@ bool CFloatingDockContainer::event(QEvent *e)
|
|||||||
return QWidget::event(e);
|
return QWidget::event(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
|
bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
|
||||||
{
|
{
|
||||||
Q_UNUSED(watched);
|
Q_UNUSED(watched);
|
||||||
if (event->type() == QEvent::MouseButtonRelease && d->isState(DraggingFloatingWidget))
|
if (event->type() == QEvent::MouseButtonRelease
|
||||||
|
&& d->isState(DraggingFloatingWidget))
|
||||||
{
|
{
|
||||||
qDebug() << "FloatingWidget::eventFilter QEvent::MouseButtonRelease";
|
ADS_PRINT("FloatingWidget::eventFilter QEvent::MouseButtonRelease");
|
||||||
|
finishDragging();
|
||||||
d->titleMouseReleaseEvent();
|
d->titleMouseReleaseEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
|
||||||
eDragState DragState)
|
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
|
||||||
{
|
{
|
||||||
|
#ifndef Q_OS_LINUX
|
||||||
|
Q_UNUSED(MouseEventHandler)
|
||||||
|
#endif
|
||||||
resize(Size);
|
resize(Size);
|
||||||
d->setState(DragState);
|
d->setState(DragState);
|
||||||
d->DragStartMousePosition = DragStartMousePos;
|
d->DragStartMousePosition = DragStartMousePos;
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
// I have not found a way on Linux to display the floating widget behind the
|
||||||
|
// dock overlay. That means if the user drags this floating widget around,
|
||||||
|
// it is always painted in front of the dock overlay and dock overlay cross.
|
||||||
|
// and the user will not see the dock overlay. To work around this issue,
|
||||||
|
// the window opacity is set to 0.6 to make the dock overlay visible
|
||||||
|
// again. If someone has an idea, how to place the dragged floating widget
|
||||||
|
// behind the dock overlay, then a pull request would be welcome.
|
||||||
|
if (DraggingFloatingWidget == DragState)
|
||||||
|
{
|
||||||
|
setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
|
||||||
|
setWindowOpacity(0.6);
|
||||||
|
d->MouseEventHandler = MouseEventHandler;
|
||||||
|
if (d->MouseEventHandler)
|
||||||
|
{
|
||||||
|
d->MouseEventHandler->grabMouse();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
moveFloating();
|
moveFloating();
|
||||||
show();
|
show();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::moveFloating()
|
void CFloatingDockContainer::moveFloating()
|
||||||
{
|
{
|
||||||
int BorderSize = (frameSize().width() - size().width()) / 2;
|
int BorderSize = (frameSize().width() - size().width()) / 2;
|
||||||
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0);
|
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
|
||||||
|
- QPoint(BorderSize, 0);
|
||||||
move(moveToPos);
|
move(moveToPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
bool CFloatingDockContainer::isClosable() const
|
bool CFloatingDockContainer::isClosable() const
|
||||||
{
|
{
|
||||||
return d->DockContainer->features().testFlag(CDockWidget::DockWidgetClosable);
|
return d->DockContainer->features().testFlag(
|
||||||
|
CDockWidget::DockWidgetClosable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
||||||
{
|
{
|
||||||
qDebug() << "CFloatingDockContainer::onDockAreasAddedOrRemoved()";
|
ADS_PRINT("CFloatingDockContainer::onDockAreasAddedOrRemoved()");
|
||||||
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
|
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
|
||||||
if (TopLevelDockArea)
|
if (TopLevelDockArea)
|
||||||
{
|
{
|
||||||
d->SingleDockArea = TopLevelDockArea;
|
d->SingleDockArea = TopLevelDockArea;
|
||||||
this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
|
d->setWindowTitle(
|
||||||
|
d->SingleDockArea->currentDockWidget()->windowTitle());
|
||||||
connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
|
connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
|
||||||
SLOT(onDockAreaCurrentChanged(int)));
|
SLOT(onDockAreaCurrentChanged(int)));
|
||||||
}
|
}
|
||||||
@ -484,36 +551,34 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved()
|
|||||||
SLOT(onDockAreaCurrentChanged(int)));
|
SLOT(onDockAreaCurrentChanged(int)));
|
||||||
d->SingleDockArea = nullptr;
|
d->SingleDockArea = nullptr;
|
||||||
}
|
}
|
||||||
this->setWindowTitle(qApp->applicationDisplayName());
|
d->setWindowTitle(qApp->applicationDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::updateWindowTitle()
|
void CFloatingDockContainer::updateWindowTitle()
|
||||||
{
|
{
|
||||||
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
|
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
|
||||||
if (TopLevelDockArea)
|
if (TopLevelDockArea)
|
||||||
{
|
{
|
||||||
this->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle());
|
d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
this->setWindowTitle(qApp->applicationDisplayName());
|
d->setWindowTitle(qApp->applicationDisplayName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
|
void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
|
||||||
{
|
{
|
||||||
Q_UNUSED(Index);
|
Q_UNUSED(Index);
|
||||||
this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
|
d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing)
|
bool CFloatingDockContainer::restoreState(QXmlStreamReader &Stream,
|
||||||
|
bool Testing)
|
||||||
{
|
{
|
||||||
if (!d->DockContainer->restoreState(Stream, Testing))
|
if (!d->DockContainer->restoreState(Stream, Testing))
|
||||||
{
|
{
|
||||||
@ -524,27 +589,39 @@ bool CFloatingDockContainer::restoreState(QXmlStreamReader& Stream, bool Testing
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
bool CFloatingDockContainer::hasTopLevelDockWidget() const
|
bool CFloatingDockContainer::hasTopLevelDockWidget() const
|
||||||
{
|
{
|
||||||
return d->DockContainer->hasTopLevelDockWidget();
|
return d->DockContainer->hasTopLevelDockWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
CDockWidget* CFloatingDockContainer::topLevelDockWidget() const
|
CDockWidget* CFloatingDockContainer::topLevelDockWidget() const
|
||||||
{
|
{
|
||||||
return d->DockContainer->topLevelDockWidget();
|
return d->DockContainer->topLevelDockWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//============================================================================
|
//============================================================================
|
||||||
QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
|
QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
|
||||||
{
|
{
|
||||||
return d->DockContainer->dockWidgets();
|
return d->DockContainer->dockWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CFloatingDockContainer::finishDragging()
|
||||||
|
{
|
||||||
|
ADS_PRINT("CFloatingDockContainer::finishDragging");
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
|
||||||
|
setWindowOpacity(1);
|
||||||
|
activateWindow();
|
||||||
|
if (d->MouseEventHandler)
|
||||||
|
{
|
||||||
|
d->MouseEventHandler->releaseMouse();
|
||||||
|
d->MouseEventHandler = nullptr;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ads
|
} // namespace ads
|
||||||
|
|
||||||
|
@ -29,10 +29,16 @@
|
|||||||
//============================================================================
|
//============================================================================
|
||||||
// INCLUDES
|
// INCLUDES
|
||||||
//============================================================================
|
//============================================================================
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
#include "ads_globals.h"
|
#include "ads_globals.h"
|
||||||
|
|
||||||
|
#ifdef Q_OS_LINUX
|
||||||
|
#include <QDockWidget>
|
||||||
|
#define tFloatingWidgetBase QDockWidget
|
||||||
|
#else
|
||||||
|
#include <QWidget>
|
||||||
|
#define tFloatingWidgetBase QWidget
|
||||||
|
#endif
|
||||||
|
|
||||||
class QXmlStreamReader;
|
class QXmlStreamReader;
|
||||||
|
|
||||||
namespace ads
|
namespace ads
|
||||||
@ -49,13 +55,15 @@ class CDockWidgetTab;
|
|||||||
struct DockWidgetTabPrivate;
|
struct DockWidgetTabPrivate;
|
||||||
class CDockAreaTitleBar;
|
class CDockAreaTitleBar;
|
||||||
struct DockAreaTitleBarPrivate;
|
struct DockAreaTitleBarPrivate;
|
||||||
|
class CFloatingWidgetTitleBar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implements a floating widget that is a dock container that accepts
|
* This implements a floating widget that is a dock container that accepts
|
||||||
* docking of dock widgets like the main window and that can be docked into
|
* docking of dock widgets like the main window and that can be docked into
|
||||||
* another dock container
|
* another dock container.
|
||||||
|
* Every floating window of the docking system is a FloatingDockContainer.
|
||||||
*/
|
*/
|
||||||
class ADS_EXPORT CFloatingDockContainer : public QWidget
|
class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
private:
|
private:
|
||||||
@ -70,6 +78,7 @@ private:
|
|||||||
friend struct DockAreaTitleBarPrivate;
|
friend struct DockAreaTitleBarPrivate;
|
||||||
friend class CDockWidget;
|
friend class CDockWidget;
|
||||||
friend class CDockAreaWidget;
|
friend class CDockAreaWidget;
|
||||||
|
friend class CFloatingWidgetTitleBar;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void onDockAreasAddedOrRemoved();
|
void onDockAreasAddedOrRemoved();
|
||||||
@ -82,23 +91,30 @@ protected:
|
|||||||
* depending on the start position given in Pos parameter
|
* depending on the start position given in Pos parameter
|
||||||
*/
|
*/
|
||||||
void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
|
||||||
eDragState DragState);
|
eDragState DragState, QWidget* MouseEventHandler);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this function to start dragging the floating widget
|
* Call this function to start dragging the floating widget
|
||||||
*/
|
*/
|
||||||
void startDragging(const QPoint& DragStartMousePos, const QSize& Size)
|
void startDragging(const QPoint& DragStartMousePos, const QSize& Size,
|
||||||
|
QWidget* MouseEventHandler)
|
||||||
{
|
{
|
||||||
startFloating(DragStartMousePos, Size, DraggingFloatingWidget);
|
startFloating(DragStartMousePos, Size, DraggingFloatingWidget, MouseEventHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call this function if you explecitely want to signal that dragging has
|
||||||
|
* finished
|
||||||
|
*/
|
||||||
|
void finishDragging();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Call this function if you just want to initialize the position
|
* Call this function if you just want to initialize the position
|
||||||
* and size of the floating widget
|
* and size of the floating widget
|
||||||
*/
|
*/
|
||||||
void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size)
|
void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size)
|
||||||
{
|
{
|
||||||
startFloating(DragStartMousePos, Size, DraggingInactive);
|
startFloating(DragStartMousePos, Size, DraggingInactive, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -3,5 +3,6 @@
|
|||||||
<file>stylesheets/default.css</file>
|
<file>stylesheets/default.css</file>
|
||||||
<file>images/close-button.svg</file>
|
<file>images/close-button.svg</file>
|
||||||
<file>images/close-button-disabled.svg</file>
|
<file>images/close-button-disabled.svg</file>
|
||||||
|
<file>stylesheets/default_linux.css</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
|
@ -45,6 +45,15 @@
|
|||||||
#define ADS_EXPORT
|
#define ADS_EXPORT
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Define ADS_DEBUG_PRINT to enable a lot of debug output
|
||||||
|
#ifdef ADS_DEBUG_PRINT
|
||||||
|
#define ADS_PRINT(s) qDebug() << s
|
||||||
|
#else
|
||||||
|
#define ADS_PRINT(s)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
// Set ADS_DEBUG_LEVEL to enable additional debug output and to enable layout
|
||||||
|
// dumps to qDebug and std::cout after layout changes
|
||||||
#define ADS_DEBUG_LEVEL 0
|
#define ADS_DEBUG_LEVEL 0
|
||||||
|
|
||||||
class QSplitter;
|
class QSplitter;
|
||||||
@ -153,6 +162,27 @@ T findParent(const QWidget* w)
|
|||||||
*/
|
*/
|
||||||
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity);
|
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Helper function for settings flags in a QFlags instance.
|
||||||
|
*/
|
||||||
|
template <class T>
|
||||||
|
void setFlag(T& Flags, typename T::enum_type flag, bool on = true)
|
||||||
|
{
|
||||||
|
#if QT_VERSION >= 0x050700
|
||||||
|
Flags.setFlag(flag, on);
|
||||||
|
#else
|
||||||
|
if(on)
|
||||||
|
{
|
||||||
|
Flags |= flag;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Flags &= ~flag;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
} // namespace ads
|
} // namespace ads
|
||||||
|
|
||||||
|
183
src/linux/FloatingWidgetTitleBar.cpp
Normal file
183
src/linux/FloatingWidgetTitleBar.cpp
Normal file
@ -0,0 +1,183 @@
|
|||||||
|
/*******************************************************************************
|
||||||
|
** Qt Advanced Docking System
|
||||||
|
** Copyright (C) 2017 Uwe Kindler
|
||||||
|
**
|
||||||
|
** This library is free software; you can redistribute it and/or
|
||||||
|
** modify it under the terms of the GNU Lesser General Public
|
||||||
|
** License as published by the Free Software Foundation; either
|
||||||
|
** version 2.1 of the License, or (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This library is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
** Lesser General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU Lesser General Public
|
||||||
|
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
/// \file FloatingWidgetTitleBar.cpp
|
||||||
|
/// \author Uwe Kindler
|
||||||
|
/// \date 13.05.2019
|
||||||
|
/// \brief Implementation of CFloatingWidgetTitleBar class
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
// INCLUDES
|
||||||
|
//============================================================================
|
||||||
|
#include "FloatingWidgetTitleBar.h"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QPushButton>
|
||||||
|
#include <QToolButton>
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QStyle>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
#include "ads_globals.h"
|
||||||
|
#include "ElidingLabel.h"
|
||||||
|
#include "FloatingDockContainer.h"
|
||||||
|
|
||||||
|
namespace ads
|
||||||
|
{
|
||||||
|
|
||||||
|
using tTabLabel = CElidingLabel;
|
||||||
|
using tCloseButton = QPushButton;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Private data class of public interface CFloatingWidgetTitleBar
|
||||||
|
*/
|
||||||
|
struct FloatingWidgetTitleBarPrivate
|
||||||
|
{
|
||||||
|
CFloatingWidgetTitleBar *_this; ///< public interface class
|
||||||
|
QLabel *IconLabel = nullptr;
|
||||||
|
tTabLabel *TitleLabel;
|
||||||
|
tCloseButton *CloseButton = nullptr;
|
||||||
|
CFloatingDockContainer *FloatingWidget = nullptr;
|
||||||
|
eDragState DragState = DraggingInactive;
|
||||||
|
|
||||||
|
FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar *_public) :
|
||||||
|
_this(_public)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the complete layout including all controls
|
||||||
|
*/
|
||||||
|
void createLayout();
|
||||||
|
};
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void FloatingWidgetTitleBarPrivate::createLayout()
|
||||||
|
{
|
||||||
|
TitleLabel = new tTabLabel();
|
||||||
|
TitleLabel->setElideMode(Qt::ElideRight);
|
||||||
|
TitleLabel->setText("DockWidget->windowTitle()");
|
||||||
|
TitleLabel->setObjectName("floatingTitleLabel");
|
||||||
|
TitleLabel->setAlignment(Qt::AlignLeft);
|
||||||
|
|
||||||
|
CloseButton = new tCloseButton();
|
||||||
|
CloseButton->setObjectName("floatingTitleCloseButton");
|
||||||
|
CloseButton->setFlat(true);
|
||||||
|
|
||||||
|
// The standard icons do does not look good on high DPI screens
|
||||||
|
QIcon CloseIcon;
|
||||||
|
QPixmap normalPixmap = _this->style()->standardPixmap(
|
||||||
|
QStyle::SP_TitleBarCloseButton, 0, CloseButton);
|
||||||
|
CloseIcon.addPixmap(normalPixmap, QIcon::Normal);
|
||||||
|
CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25),
|
||||||
|
QIcon::Disabled);
|
||||||
|
CloseButton->setIcon(
|
||||||
|
_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
|
||||||
|
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||||
|
CloseButton->setVisible(true);
|
||||||
|
CloseButton->setFocusPolicy(Qt::NoFocus);
|
||||||
|
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
|
||||||
|
|
||||||
|
QFontMetrics fm(TitleLabel->font());
|
||||||
|
int Spacing = qRound(fm.height() / 4.0);
|
||||||
|
|
||||||
|
// Fill the layout
|
||||||
|
QBoxLayout *Layout = new QBoxLayout(QBoxLayout::LeftToRight);
|
||||||
|
Layout->setContentsMargins(6, 0, 0, 0);
|
||||||
|
Layout->setSpacing(0);
|
||||||
|
_this->setLayout(Layout);
|
||||||
|
Layout->addWidget(TitleLabel, 1);
|
||||||
|
Layout->addSpacing(Spacing);
|
||||||
|
Layout->addWidget(CloseButton);
|
||||||
|
Layout->setAlignment(Qt::AlignCenter);
|
||||||
|
|
||||||
|
TitleLabel->setVisible(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
CFloatingWidgetTitleBar::CFloatingWidgetTitleBar(CFloatingDockContainer *parent) :
|
||||||
|
QWidget(parent),
|
||||||
|
d(new FloatingWidgetTitleBarPrivate(this))
|
||||||
|
{
|
||||||
|
d->FloatingWidget = parent;
|
||||||
|
d->createLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
CFloatingWidgetTitleBar::~CFloatingWidgetTitleBar()
|
||||||
|
{
|
||||||
|
delete d;
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
if (ev->button() == Qt::LeftButton)
|
||||||
|
{
|
||||||
|
d->DragState = DraggingFloatingWidget;
|
||||||
|
d->FloatingWidget->startDragging(ev->pos(), d->FloatingWidget->size(),
|
||||||
|
this);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Super::mousePressEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
d->DragState = DraggingInactive;
|
||||||
|
Super::mouseReleaseEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
if (!(ev->buttons() & Qt::LeftButton) || DraggingInactive == d->DragState)
|
||||||
|
{
|
||||||
|
d->DragState = DraggingInactive;
|
||||||
|
Super::mouseMoveEvent(ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// move floating window
|
||||||
|
if (DraggingFloatingWidget == d->DragState)
|
||||||
|
{
|
||||||
|
d->FloatingWidget->moveFloating();
|
||||||
|
Super::mouseMoveEvent(ev);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Super::mouseMoveEvent(ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CFloatingWidgetTitleBar::enableCloseButton(bool Enable)
|
||||||
|
{
|
||||||
|
d->CloseButton->setEnabled(Enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
void CFloatingWidgetTitleBar::setTitle(const QString &Text)
|
||||||
|
{
|
||||||
|
d->TitleLabel->setText(Text);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ads
|
85
src/linux/FloatingWidgetTitleBar.h
Normal file
85
src/linux/FloatingWidgetTitleBar.h
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
#ifndef FLOATINGWIDGETTITLEBAR_H
|
||||||
|
#define FLOATINGWIDGETTITLEBAR_H
|
||||||
|
/*******************************************************************************
|
||||||
|
** Qt Advanced Docking System
|
||||||
|
** Copyright (C) 2017 Uwe Kindler
|
||||||
|
**
|
||||||
|
** This library is free software; you can redistribute it and/or
|
||||||
|
** modify it under the terms of the GNU Lesser General Public
|
||||||
|
** License as published by the Free Software Foundation; either
|
||||||
|
** version 2.1 of the License, or (at your option) any later version.
|
||||||
|
**
|
||||||
|
** This library is distributed in the hope that it will be useful,
|
||||||
|
** but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
** Lesser General Public License for more details.
|
||||||
|
**
|
||||||
|
** You should have received a copy of the GNU Lesser General Public
|
||||||
|
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
/// \file FloatingWidgetTitleBar.h
|
||||||
|
/// \author Uwe Kindler
|
||||||
|
/// \date 13.05.2019
|
||||||
|
/// \brief Declaration of CFloatingWidgetTitleBar class
|
||||||
|
//============================================================================
|
||||||
|
|
||||||
|
//============================================================================
|
||||||
|
// INCLUDES
|
||||||
|
//============================================================================
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
namespace ads
|
||||||
|
{
|
||||||
|
class CFloatingDockContainer;
|
||||||
|
|
||||||
|
struct FloatingWidgetTitleBarPrivate;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Titlebar for floating widgets to capture non client are mouse events.
|
||||||
|
* Linux does not support NonClieantArea mouse events like
|
||||||
|
* QEvent::NonClientAreaMouseButtonPress. Because these events are required
|
||||||
|
* for the docking system to work properly, we use our own titlebar here to
|
||||||
|
* capture the required mouse events.
|
||||||
|
*/
|
||||||
|
class CFloatingWidgetTitleBar : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
private:
|
||||||
|
FloatingWidgetTitleBarPrivate *d; ///< private data (pimpl)
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void mousePressEvent(QMouseEvent *ev) override;
|
||||||
|
virtual void mouseReleaseEvent(QMouseEvent *ev) override;
|
||||||
|
virtual void mouseMoveEvent(QMouseEvent *ev) override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using Super = QWidget;
|
||||||
|
explicit CFloatingWidgetTitleBar(CFloatingDockContainer *parent = nullptr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Virtual Destructor
|
||||||
|
*/
|
||||||
|
virtual ~CFloatingWidgetTitleBar();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables / disables the window close button.
|
||||||
|
*/
|
||||||
|
void enableCloseButton(bool Enable);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the window title, that means, the text of the internal tile label.
|
||||||
|
*/
|
||||||
|
void setTitle(const QString &Text);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* This signal is emitted, if the close button is clicked.
|
||||||
|
*/
|
||||||
|
void closeRequested();
|
||||||
|
};
|
||||||
|
} // namespace ads
|
||||||
|
#endif // FLOATINGWIDGETTITLEBAR_H
|
@ -43,7 +43,6 @@ HEADERS += \
|
|||||||
ElidingLabel.h
|
ElidingLabel.h
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
SOURCES += \
|
SOURCES += \
|
||||||
ads_globals.cpp \
|
ads_globals.cpp \
|
||||||
DockAreaWidget.cpp \
|
DockAreaWidget.cpp \
|
||||||
@ -58,6 +57,12 @@ SOURCES += \
|
|||||||
DockAreaTitleBar.cpp \
|
DockAreaTitleBar.cpp \
|
||||||
ElidingLabel.cpp
|
ElidingLabel.cpp
|
||||||
|
|
||||||
|
|
||||||
|
unix {
|
||||||
|
HEADERS += linux/FloatingWidgetTitleBar.h
|
||||||
|
SOURCES += linux/FloatingWidgetTitleBar.cpp
|
||||||
|
}
|
||||||
|
|
||||||
isEmpty(PREFIX){
|
isEmpty(PREFIX){
|
||||||
PREFIX=..\installed
|
PREFIX=..\installed
|
||||||
warning("Install Prefix not set")
|
warning("Install Prefix not set")
|
||||||
@ -66,3 +71,5 @@ headers.path=$$PREFIX/include
|
|||||||
headers.files=$$HEADERS
|
headers.files=$$HEADERS
|
||||||
target.path=$$PREFIX/lib
|
target.path=$$PREFIX/lib
|
||||||
INSTALLS += headers target
|
INSTALLS += headers target
|
||||||
|
|
||||||
|
DISTFILES +=
|
||||||
|
@ -63,7 +63,7 @@ ads--CDockWidget
|
|||||||
#closeButton,
|
#closeButton,
|
||||||
#undockButton
|
#undockButton
|
||||||
{
|
{
|
||||||
padding: 0 -2px;
|
padding: 0px -2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
96
src/stylesheets/default_linux.css
Normal file
96
src/stylesheets/default_linux.css
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
|
||||||
|
/*
|
||||||
|
* Default style sheet on Windows Platforms
|
||||||
|
* Note: Always use CSS-classes with and without "ads--" namespace to support Qt4 & Qt5
|
||||||
|
*/
|
||||||
|
|
||||||
|
ads--CDockContainerWidget
|
||||||
|
{
|
||||||
|
background: palette(dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
ads--CDockContainerWidget QSplitter::handle
|
||||||
|
{
|
||||||
|
background: palette(dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
ads--CDockAreaWidget
|
||||||
|
{
|
||||||
|
background: palette(window);
|
||||||
|
border: 1px solid white;
|
||||||
|
}
|
||||||
|
|
||||||
|
ads--CDockAreaWidget #tabsMenuButton::menu-indicator
|
||||||
|
{
|
||||||
|
image: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ads--CDockWidgetTab
|
||||||
|
{
|
||||||
|
background: palette(window);
|
||||||
|
border-color: palette(light);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 0 1px 0 0;
|
||||||
|
padding: 0 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
ads--CDockWidgetTab[activeTab="true"]
|
||||||
|
{
|
||||||
|
background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:0.5, stop:0 palette(window), stop:1 palette(light));
|
||||||
|
/*background: palette(highlight);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
ads--CDockWidgetTab QLabel
|
||||||
|
{
|
||||||
|
color: palette(dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
ads--CDockWidgetTab[activeTab="true"] QLabel
|
||||||
|
{
|
||||||
|
color: palette(foreground);
|
||||||
|
}
|
||||||
|
|
||||||
|
ads--CDockWidget
|
||||||
|
{
|
||||||
|
background: palette(light);
|
||||||
|
border-color: palette(light);
|
||||||
|
border-style: solid;
|
||||||
|
border-width: 1px 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabsMenuButton,
|
||||||
|
#closeButton,
|
||||||
|
#undockButton
|
||||||
|
{
|
||||||
|
padding: 0px -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QScrollArea#dockWidgetScrollArea
|
||||||
|
{
|
||||||
|
padding: 0px;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#tabCloseButton
|
||||||
|
{
|
||||||
|
margin-top: 2px;
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
padding: 0px -2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabCloseButton:hover
|
||||||
|
{
|
||||||
|
border: 1px solid rgba(0, 0, 0, 32);
|
||||||
|
background: rgba(0, 0, 0, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
#tabCloseButton:pressed
|
||||||
|
{
|
||||||
|
background: rgba(0, 0, 0, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user