Compare commits

..

1 Commits
3.8.0 ... 3.7.0

Author SHA1 Message Date
Uwe Kindler
cbdf3211d6 Improved documentation for Linux support 2021-01-03 17:27:01 +01:00
83 changed files with 462 additions and 3404 deletions

View File

@@ -10,52 +10,19 @@ environment:
# Appveyor doesn't have Qt 12 yet
LatestQtVersion: 5.13
matrix:
# 32 bit builds
# MSVC 2015 builds
# Dynamic Library builds
# LTS version of Qt, dll, 32bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "false"
use_cmake: "false"
# LTS version of Qt, dll, 32bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "false"
use_cmake: "true"
# end Dynamic Library builds
# Static Library builds
# LTS version of Qt, static, 32bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "true"
use_cmake: "false"
# LTS version of Qt, static, 32bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "true"
use_cmake: "true"
# end Static Library builds
# end MSVC 2015 builds
# MinGW builds
# Dynamic Library builds
# LTS version of Qt, dll, 32bit, MinGW, qmake
- QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- QT: C:\Qt\%LatestQtVersion%\mingw73_32
COMPILER: C:\Qt\Tools\mingw730_32
targetPlatform: x86
use_mingw: "true"
use_static: "false"
use_cmake: "false"
# LTS version of Qt, dll, 32bit, MinGW, cmake
- QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- QT: C:\Qt\%LatestQtVersion%\mingw73_32
COMPILER: C:\Qt\Tools\mingw730_32
targetPlatform: x86
use_mingw: "true"
@@ -64,14 +31,14 @@ environment:
# end Dynamic Library builds
# Static Library builds
# LTS version of Qt, static, 32bit, MinGW, qmake
- QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- QT: C:\Qt\%LatestQtVersion%\mingw73_32
COMPILER: C:\Qt\Tools\mingw730_32
targetPlatform: x86
use_mingw: "true"
use_static: "true"
use_cmake: "false"
# LTS version of Qt, static, 32bit, MinGW, cmake
- QT5: C:\Qt\%LatestQtVersion%\mingw73_32
- QT: C:\Qt\%LatestQtVersion%\mingw73_32
COMPILER: C:\Qt\Tools\mingw730_32
targetPlatform: x86
use_mingw: "true"
@@ -79,19 +46,54 @@ environment:
use_cmake: "true"
# end Static Library builds
# end MinGW builds
# end 32 bit builds
# 64 bit builds
# MSVC 2015 builds
# MSVC 2017 builds
# Dynamic Library builds
# LTS version of Qt, dll, 64bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
# LTS version of Qt, dll, 32bit, MSVC 2017, qmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "false"
use_cmake: "false"
# LTS version of Qt, dll, 32bit, MSVC 2017, cmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "false"
use_cmake: "true"
# end Dynamic Library builds
# Static Library builds
# LTS version of Qt, static, 32bit, MSVC 2017, qmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "true"
use_cmake: "false"
# LTS version of Qt, static, 32bit, MSVC 2017, cmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: x86
use_mingw: "false"
use_static: "true"
use_cmake: "true"
# end Static Library builds
# end MSVC 2017 builds
# end 32 bit builds
# 64 bit builds
# MSVC 2017 builds
# Dynamic Library builds
# LTS version of Qt, dll, 64bit, MSVC 2017, qmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: amd64
use_mingw: "false"
use_static: "false"
use_cmake: "false"
# LTS version of Qt, dll, 64bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
# LTS version of Qt, dll, 64bit, MSVC 2017, cmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: amd64
use_mingw: "false"
@@ -99,38 +101,40 @@ environment:
use_cmake: "true"
# end Dynamic Library builds
# Static Library builds
# LTS version of Qt, static, 64bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
# LTS version of Qt, static, 64bit, MSVC 2017, qmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: amd64
use_mingw: "false"
use_static: "true"
use_cmake: "false"
# LTS version of Qt, static, 64bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2017_64
# LTS version of Qt, static, 64bit, MSVC 2017, cmake
- QT: C:\Qt\%LatestQtVersion%\msvc2017_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build
targetPlatform: amd64
use_mingw: "false"
use_static: "true"
use_cmake: "true"
# end Static Library builds
# end MSVC 2015 builds
# end MSVC 2017 builds
# end 64 bit builds
matrix:
fast_finish: true
before_build:
- set originalWD=%CD%
- call "%QT5%\bin\qtenv2.bat"
- call "%QT%\bin\qtenv2.bat"
- cd /D %originalWD%
- if %use_mingw%==false call "%COMPILER%\vcvarsall.bat" %targetPlatform%
- if %use_static%==true (set USESTATIC=ON) else (set USESTATIC=OFF)
- if %use_mingw%==true (set CMAKEGENERATOR="MinGW Makefiles") else (set CMAKEGENERATOR="NMake Makefiles")
- if %use_mingw%==true (set MAKEENGINE=mingw32-make) else (set MAKEENGINE=nmake)
- if %use_mingw%==true set PATH=%PATH:C:\Program Files\Git\usr\bin;=%
- if %use_mingw%==true set PATH=%PATH%:C:\Program Files\Git\usr\bin;=%
build_script:
- echo %PATH%
- if %use_cmake%==true mkdir build
- if %use_cmake%==true cd build
- if %use_cmake%==true cmake --version

View File

@@ -6,7 +6,7 @@ jobs:
build:
strategy:
matrix:
os: [ubuntu-latest, ubuntu-20.04, ubuntu-18.04]
os: [ubuntu-latest, ubuntu-18.04, ubuntu-16.04]
runs-on: ${{ matrix.os }}
@@ -16,7 +16,7 @@ jobs:
run: |
sudo apt-get update --fix-missing
sudo apt-get install qt5-default
sudo apt-get install qtbase5-private-dev
sudo apt-get install libqt5x11extras5-dev
- name: qmake
run: qmake
- name: make

1
.gitignore vendored
View File

@@ -383,4 +383,3 @@ FodyWeavers.xsd
/ build
/Settings.ini
.vscode/settings.json
/.settings

View File

@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project>
<configuration id="cdt.managedbuild.toolchain.gnu.mingw.base.1119687795" name="Default">
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
<provider copy-of="extension" id="org.eclipse.cdt.ui.UserLanguageSettingsProvider"/>
<provider-reference id="org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider" ref="shared-provider"/>
<provider class="org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuildCommandParser" id="org.eclipse.cdt.managedbuilder.core.GCCBuildCommandParser" keep-relative-paths="false" name="CDT GCC Build Output Parser" parameter="(g?cc)|([gc]\+\+)|(clang)" prefer-non-shared="true"/>
<provider class="org.eclipse.cdt.managedbuilder.internal.language.settings.providers.GCCBuiltinSpecsDetectorMinGW" console="false" env-hash="-1242828358748104657" id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" keep-relative-paths="false" name="CDT GCC Built-in Compiler Settings MinGW" parameter="${COMMAND} ${FLAGS} -E -P -v -dD &quot;${INPUTS}&quot;" prefer-non-shared="true">
<language-scope id="org.eclipse.cdt.core.gcc"/>
<language-scope id="org.eclipse.cdt.core.g++"/>
</provider>
<provider-reference id="org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider" ref="shared-provider"/>
</extension>
</configuration>
</project>

View File

@@ -9,6 +9,8 @@ matrix:
os: linux
dist: trusty
group: stable
before_install:
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@@ -18,6 +20,8 @@ matrix:
packages:
- qt55base
- qt55tools
- qt55x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
script:
@@ -35,6 +39,8 @@ matrix:
services:
- xvfb
compiler: gcc
before_install:
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@@ -44,6 +50,8 @@ matrix:
packages:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386
@@ -65,6 +73,8 @@ matrix:
services:
- xvfb
compiler: gcc
before_install:
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@@ -74,6 +84,8 @@ matrix:
packages:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386
@@ -95,6 +107,8 @@ matrix:
services:
- xvfb
compiler: gcc
before_install:
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@@ -104,6 +118,8 @@ matrix:
packages:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386
@@ -131,6 +147,8 @@ matrix:
services:
- xvfb
compiler: gcc
before_install:
- sudo apt-get -y install libqt5x11extras5-dev
addons:
apt:
sources:
@@ -140,6 +158,8 @@ matrix:
packages:
- qt514base
- qt514tools
- qt514x11extras
- libqt5x11extras5-dev
- gcc-9
- g++-9
- libc6-i386

View File

@@ -15,13 +15,10 @@ integrated development environments (IDEs) such as Visual Studio.
## New and Noteworthy
The [release 3.7](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.7.0)
adds the following features:
The [release 3.7.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.7.0)
adds support for Qt6.
- support for **Qt6.**
- support for [empty dock area](doc/user-guide.md#empty-dock-area)
The [release 3.6](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.6.0)
The [release 3.6.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.6.0)
adds some nice new features:
- support for [central widget](doc/user-guide.md#central-widget) concept
@@ -35,7 +32,7 @@ adds some nice new features:
Both features are contributions from ADS users. Read the [documentation](doc/user-guide.md)
to learn more about both new features.
The [release 3.5](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.5.0)
The [release 3.5.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.5.0)
adds the new [focus highlighting](doc/user-guide.md#focushighlighting) feature.
This optional feature enables highlighting of the focused dock widget like you
know it from Visual Studio.
@@ -81,7 +78,6 @@ know it from Visual Studio.
- [ezEditor](#ezeditor)
- [D-Tect X](#d-tect-x)
- [HiveWE](#hivewe)
- [Ramses Composer](#ramses-composer)
### Docking everywhere - no central widget
@@ -220,13 +216,7 @@ Screenshot Ubuntu:
## Build
The Linux build requires private header files. Make sure that they are installed:
```bash
sudo apt install qtbase5-private-dev
```
Open the `ads.pro` file with QtCreator and start the build, that's it.
Open the `ads.pro` with QtCreator and start the build, that's it.
You can run the demo project and test it yourself.
## Getting started / Example
@@ -361,7 +351,7 @@ Taken from the [Qt Blog](https://www.qt.io/blog/qt-design-studio-1.5-beta-releas
> The most obvious change in [Qt Design Studio 1.5](https://www.qt.io/blog/qt-design-studio-1.5-beta-released) is the integration of dock widgets using the Qt Advanced Docking System. This allows the user to fully customize the workspace and also to undock any view into its own top level window. This especially improves the usability when using multiple screens.
[![Qt Design Studio](doc/showcase_qt_design_studio_video.png)](https://youtu.be/za9KBWcFXEw?t=84)
![Qt Design Studio](doc/showcase_qt_design_studio.png)
### [QmixElements](https://www.cetoni.com/products/qmixelements/)
@@ -398,18 +388,3 @@ of the open editor windows.
[learn more...](https://github.com/stijnherfst/HiveWE)
![HiveWE](doc/showcase_hivewe.png)
### [Ramses Composer](https://github.com/GENIVI/ramses-composer)
Ramses Composer is the authoring tool for the open source [RAMSES](https://github.com/GENIVI/ramses)
rendering ecosystem.
Ramses is a low-level rendering engine which is optimized for embedded hardware
mobile devices, automotive ECUs, IoT electronics. Ramses was initially developed
at the BMW Group and open-sourced in 2018 as part of a collaboration initiative
with the Genivi Alliance. It is an important part of the BMW infotainment cluster
and digital portfolio.
[learn more...](https://github.com/GENIVI/ramses-composer)
![RamsesComposer](doc/showcase_ramses_composer.png)

29
ads.pri
View File

@@ -1,25 +1,28 @@
CONFIG(debug, debug|release){
win32 {
versionAtLeast(QT_VERSION, 5.15.0) {
LIBS += -lqtadvanceddocking
}
else {
LIBS += -lqtadvanceddockingd
}
lessThan(QT_MAJOR_VERSION, 6) {
CONFIG(debug, debug|release){
win32 {
LIBS += -lqtadvanceddockingd
}
else:mac {
LIBS += -lqtadvanceddocking_debug
}
else {
LIBS += -lqtadvanceddocking
}
}
else:mac {
LIBS += -lqtadvanceddocking_debug
}
else {
else{
LIBS += -lqtadvanceddocking
}
}
else{
else {
# qt$$qtLibraryTarget(qtadvanceddocking) does not produce an advanceddockingd.dll file on Windows
# for Qt6 - I don't know if this is a bug and I have to investigate
LIBS += -lqtadvanceddocking
}
unix:!macx {
LIBS += -lxcb
QT += x11extras
}

View File

@@ -2,4 +2,7 @@ include(CMakeFindDependencyMacro)
find_dependency(Qt5Core ${REQUIRED_QT_VERSION} REQUIRED)
find_dependency(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED)
find_dependency(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED)
if(UNIX AND NOT APPLE)
find_dependency(Qt5X11Extras ${REQUIRED_QT_VERSION} REQUIRED)
endif()
include("${CMAKE_CURRENT_LIST_DIR}/adsTargets.cmake")

View File

@@ -1,10 +1,9 @@
cmake_minimum_required(VERSION 3.5)
project(ads_demo VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
if(WIN32 AND QT_VERSION_MAJOR LESS 6)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS AxContainer REQUIRED)
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
if(WIN32)
find_package(Qt5 5.5 COMPONENTS AxContainer REQUIRED)
endif()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(ads_demo_SRCS
@@ -17,11 +16,9 @@ set(ads_demo_SRCS
)
add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS})
target_include_directories(AdvancedDockingSystemDemo PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../src")
target_link_libraries(AdvancedDockingSystemDemo PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
if(WIN32 AND QT_VERSION_MAJOR LESS 6)
target_link_libraries(AdvancedDockingSystemDemo PUBLIC Qt${QT_VERSION_MAJOR}::AxContainer)
target_link_libraries(AdvancedDockingSystemDemo PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
if(WIN32)
target_link_libraries(AdvancedDockingSystemDemo PUBLIC Qt5::AxContainer)
endif()
target_link_libraries(AdvancedDockingSystemDemo PRIVATE qtadvanceddocking)
set_target_properties(AdvancedDockingSystemDemo PROPERTIES

View File

@@ -79,7 +79,7 @@
#include "FloatingDockContainer.h"
#include "DockComponentsFactory.h"
#include "StatusDialog.h"
#include "DockSplitter.h"
/**
@@ -417,22 +417,6 @@ void MainWindowPrivate::createContent()
DockWidget = createCalendarDockWidget();
DockWidget->setTabToolTip(QString("Tab ToolTip\nHodie est dies magna"));
auto DockArea = DockManager->addDockWidget(ads::CenterDockWidgetArea, DockWidget, TopDockArea);
// Now we create a action to test resizing of DockArea widget
auto Action = ui.menuTests->addAction(QString("Resize %1").arg(DockWidget->windowTitle()));
QObject::connect(Action, &QAction::triggered, [DockArea]()
{
// Resizing only works, if the Splitter is visible and has a valid
// sizes
auto Splitter = ads::internal::findParent<ads::CDockSplitter*>(DockArea);
if (!Splitter)
{
return;
}
// We change the sizes of the splitter that contains the Calendar 1 widget
// to resize the dock widget
int Width = Splitter->width();
Splitter->setSizes({Width * 2/3, Width * 1/3});
});
// Now we add a custom button to the dock area title bar that will create
// new editor widgets when clicked
@@ -459,14 +443,13 @@ void MainWindowPrivate::createContent()
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), RighDockArea);
DockManager->addDockWidget(ads::CenterDockWidgetArea, createLongTextLabelDockWidget(), BottomDockArea);
Action = ui.menuTests->addAction(QString("Set %1 Floating").arg(DockWidget->windowTitle()));
auto Action = ui.menuTests->addAction(QString("Set %1 Floating").arg(DockWidget->windowTitle()));
DockWidget->connect(Action, SIGNAL(triggered()), SLOT(setFloating()));
Action = ui.menuTests->addAction(QString("Set %1 As Current Tab").arg(DockWidget->windowTitle()));
DockWidget->connect(Action, SIGNAL(triggered()), SLOT(setAsCurrentTab()));
Action = ui.menuTests->addAction(QString("Raise %1").arg(DockWidget->windowTitle()));
DockWidget->connect(Action, SIGNAL(triggered()), SLOT(raise()));
#ifdef Q_OS_WIN
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
if (!ads::CDockManager::testConfigFlag(ads::CDockManager::OpaqueUndocking))
@@ -630,9 +613,6 @@ CMainWindow::CMainWindow(QWidget *parent) :
// uncomment if you would like to enable an equal distribution of the
// available size of a splitter to all contained dock widgets
// CDockManager::setConfigFlag(CDockManager::EqualSplitOnInsertion, true);
// uncomment if you would like to close tabs with the middle mouse button, web browser style
// CDockManager::setConfigFlag(CDockManager::MiddleMouseButtonClosesTab, true);
// Now create the dock manager and its content
d->DockManager = new CDockManager(this);

View File

@@ -215,17 +215,6 @@ class MainWindow(MainWindowUI, MainWindowBase):
dock_widget = self.create_calendar_dock_widget()
dock_widget.setTabToolTip("Tab ToolTip\nHodie est dies magna")
dock_area = self.dock_manager.addDockWidget(QtAds.CenterDockWidgetArea, dock_widget, top_dock_area)
# Now we create a action to test resizing of DockArea widget
action = self.menuTests.addAction("Resize {}".format(dock_widget.windowTitle()))
def action_triggered():
splitter = QtAds.internal.findParent(QtAds.CDockSplitter, dock_area)
if not splitter:
return
# We change the sizes of the splitter that contains the Calendar 1 widget
# to resize the dock widget
width = splitter.width()
splitter.setSizes([width * 2/3, width * 1/3])
action.triggered.connect(action_triggered)
# Now we add a custom button to the dock area title bar that will create
# new editor widgets when clicked
@@ -370,7 +359,6 @@ class MainWindow(MainWindowUI, MainWindowBase):
floating = sender.property("Floating")
dock_widget = self.create_editor_widget()
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetForceCloseWithArea, True)
dock_widget.closeRequested.connect(self.on_editor_close_requested)
if floating:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 816 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 450 KiB

View File

@@ -28,7 +28,6 @@
- [`FloatingContainerForceNativeTitleBar` (Linux only)](#floatingcontainerforcenativetitlebar-linux-only)
- [`FloatingContainerForceQWidgetTitleBar` (Linux only)](#floatingcontainerforceqwidgettitlebar-linux-only)
- [Central Widget](#central-widget)
- [Empty Dock Area](#empty-dock-area)
- [Custom Close Handling](#custom-close-handling)
- [Styling](#styling)
- [Disabling the Internal Style Sheet](#disabling-the-internal-style-sheet)
@@ -501,33 +500,6 @@ See the `centralwidget` example to learn how it works.
> are already other dock widgets registered. So `setCentralWidget` should be
> the first function that you call when adding dock widgets.
## Empty Dock Area
Some applications require a fixed DockArea that is always visible, even if it
does not contain any DockWidgets. I.e. the DockArea is in this case a kind
of central widget that is always visible (see this
[issue](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/199)).
Since version 3.7.1 the advanced docking system supports this feature. The
`emptydockarea` example shows how this can be implemented with the library. You
just need to create a dock widget and set the feature flag `CDockWidget::NoTab`.
This permanently hides the tab widget of this area and removes it from the tab
menu. For this special dock widget you should also disable all other features
(movable, closable and floatable) to prevent closing and moving of this widget.
If you use the `CDockManager::setCentralWidget` function like in the example
code below, then you don't need to disable these features because this is done
in the `setCentralWidget` function.
```c++
QLabel* label = new QLabel();
label->setText("This is a DockArea which is always visible, even if it does not contain any DockWidgets.");
label->setAlignment(Qt::AlignCenter);
CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget");
CentralDockWidget->setWidget(label);
CentralDockWidget->setFeature(ads::CDockWidget::NoTab, true);// set the flag before adding the widget to dock manager
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
```
## Custom Close Handling
Normally clicking the close button of a dock widget will just hide the widget and the user can show it again using the `toggleView()` action of the dock widget. This is meant for user interfaces with a static amount of widgets. But the advanced docking system also supports dynamic dock widgets that will get deleted on close. If you set the dock widget flag `DockWidgetDeleteOnClose` for a certain dock widget, then it will be deleted as soon as you close this dock widget. This enables the implementation of user interfaces with dynamically created editors, like in word processing applications or source code development tools.

View File

@@ -3,6 +3,4 @@ project(QtADSExamples LANGUAGES CXX VERSION ${VERSION_SHORT})
add_subdirectory(simple)
add_subdirectory(sidebar)
add_subdirectory(deleteonclose)
add_subdirectory(centralwidget)
add_subdirectory(emptydockarea)
add_subdirectory(dockindock)
add_subdirectory(centralwidget)

View File

@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_centralwidget VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(CentralWidgetExample WIN32
main.cpp
@@ -10,9 +9,7 @@ add_executable(CentralWidgetExample WIN32
)
target_include_directories(CentralWidgetExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(CentralWidgetExample PRIVATE qtadvanceddocking)
target_link_libraries(CentralWidgetExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(CentralWidgetExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
set_target_properties(CentralWidgetExample PROPERTIES
AUTOMOC ON
AUTORCC ON

View File

@@ -12,7 +12,19 @@ from PyQtAds import QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)
import demo_rc # pyrcc5 demo\demo.qrc -o examples\centralWidget\demo_rc.py
def svg_icon(filename: str):
'''Helper function to create an SVG icon'''
# This is a workaround, because because in item views SVG icons are not
# properly scaled and look blurry or pixelate
icon = QIcon(filename)
icon.addPixmap(icon.pixmap(92))
return icon
class MainWindow(MainWindowUI, MainWindowBase):
def __init__(self, parent=None):
@@ -34,26 +46,27 @@ class MainWindow(MainWindowUI, MainWindowBase):
central_dock_area.setAllowedAreas(QtAds.DockWidgetArea.OuterDockAreas)
# create other dock widgets
file_tree = QTreeView()
file_tree.setFrameShape(QFrame.NoFrame)
file_model = QFileSystemModel(file_tree)
file_model.setRootPath(QDir.currentPath())
file_tree.setModel(file_model)
data_dock_widget = QtAds.CDockWidget("File system")
data_dock_widget.setWidget(file_tree)
data_dock_widget.resize(150, 250)
data_dock_widget.setMinimumSize(100, 250)
file_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, data_dock_widget, central_dock_area)
self.menuView.addAction(data_dock_widget.toggleViewAction())
table = QTableWidget()
table.setColumnCount(3)
table.setRowCount(10)
table_dock_widget = QtAds.CDockWidget("Table 1")
table_dock_widget = QtAds.CDockWidget("Table")
table_dock_widget.setWidget(table)
table_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
table_dock_widget.resize(250, 150)
table_dock_widget.setMinimumSize(200, 150)
table_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, table_dock_widget)
self.menuView.addAction(table_dock_widget.toggleViewAction())
table = QTableWidget()
table.setColumnCount(5)
table.setRowCount(1020)
table_dock_widget = QtAds.CDockWidget("Table 2")
table_dock_widget.setWidget(table)
table_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
table_dock_widget.resize(250, 150)
table_dock_widget.setMinimumSize(200, 150)
table_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.BottomDockWidgetArea, table_dock_widget, table_area)
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.BottomDockWidgetArea, table_dock_widget, file_area)
self.menuView.addAction(table_dock_widget.toggleViewAction())
properties_table = QTableWidget()
@@ -63,7 +76,7 @@ class MainWindow(MainWindowUI, MainWindowBase):
properties_dock_widget.setWidget(properties_table)
properties_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
properties_dock_widget.resize(250, 150)
properties_dock_widget.setMinimumSize(200, 150)
properties_dock_widget.setMinimumSize(200,150)
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.RightDockWidgetArea, properties_dock_widget, central_dock_area)
self.menuView.addAction(properties_dock_widget.toggleViewAction())
@@ -71,6 +84,7 @@ class MainWindow(MainWindowUI, MainWindowBase):
def create_perspective_ui(self):
save_perspective_action = QAction("Create Perspective", self)
save_perspective_action.setIcon(svg_icon(":/adsdemo/images/picture_in_picture.svg"))
save_perspective_action.triggered.connect(self.save_perspective)
perspective_list_action = QWidgetAction(self)
self.perspective_combobox = QComboBox(self)
@@ -92,11 +106,6 @@ class MainWindow(MainWindowUI, MainWindowBase):
self.perspective_combobox.clear()
self.perspective_combobox.addItems(self.dock_manager.perspectiveNames())
self.perspective_combobox.setCurrentText(perspective_name)
def closeEvent(self, event: QCloseEvent):
self.dock_manager.deleteLater()
super().closeEvent(event)
if __name__ == '__main__':
app = QApplication(sys.argv)

View File

@@ -46,26 +46,27 @@ CMainWindow::CMainWindow(QWidget *parent)
CentralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas);
// create other dock widgets
QTreeView* fileTree = new QTreeView();
fileTree->setFrameShape(QFrame::NoFrame);
QFileSystemModel* fileModel = new QFileSystemModel(fileTree);
fileModel->setRootPath(QDir::currentPath());
fileTree->setModel(fileModel);
CDockWidget* DataDockWidget = new CDockWidget("File system");
DataDockWidget->setWidget(fileTree);
DataDockWidget->resize(150, 250);
DataDockWidget->setMinimumSize(100, 250);
auto* fileArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, DataDockWidget, CentralDockArea);
ui->menuView->addAction(DataDockWidget->toggleViewAction());
QTableWidget* table = new QTableWidget();
table->setColumnCount(3);
table->setRowCount(10);
CDockWidget* TableDockWidget = new CDockWidget("Table 1");
CDockWidget* TableDockWidget = new CDockWidget("Table");
TableDockWidget->setWidget(table);
TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
TableDockWidget->resize(250, 150);
TableDockWidget->setMinimumSize(200,150);
auto TableArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, TableDockWidget);
ui->menuView->addAction(TableDockWidget->toggleViewAction());
table = new QTableWidget();
table->setColumnCount(5);
table->setRowCount(1020);
TableDockWidget = new CDockWidget("Table 2");
TableDockWidget->setWidget(table);
TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
TableDockWidget->resize(250, 150);
TableDockWidget->setMinimumSize(200,150);
DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, TableArea);
DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, fileArea);
ui->menuView->addAction(TableDockWidget->toggleViewAction());
QTableWidget* propertiesTable = new QTableWidget();

View File

@@ -1,16 +1,13 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_deleteonclose VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(DeleteOnCloseTest WIN32
main.cpp
)
target_include_directories(DeleteOnCloseTest PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(DeleteOnCloseTest PRIVATE qtadvanceddocking)
target_link_libraries(DeleteOnCloseTest PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(DeleteOnCloseTest PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
set_target_properties(DeleteOnCloseTest PROPERTIES
AUTOMOC ON
CXX_STANDARD 14

View File

@@ -41,39 +41,19 @@ int main(int argc, char *argv[])
now->widget()->setFocus();
});
QAction *action = new QAction("New [DockWidgetDeleteOnClose]", &w);
QAction *action = new QAction("New Delete On Close", &w);
w.menuBar()->addAction(action);
int i = 0;
QObject::connect(action, &QAction::triggered, [&]() {
auto dw = new ads::CDockWidget(QStringLiteral("test %1 [DockWidgetDeleteOnClose]").arg(i++), &w);
auto dw = new ads::CDockWidget(QStringLiteral("test doc %1").arg(i++), &w);
auto editor = new QTextEdit(QStringLiteral("lorem ipsum..."), dw);
dw->setWidget(editor);
dw->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true);
auto area = dockManager->addDockWidgetTab(ads::CenterDockWidgetArea, dw);
qDebug() << "doc dock widget created!" << dw << area;
});
auto dw = new ads::CDockWidget(QStringLiteral("test %1 [DeleteContentOnClose]").arg(i++), &w);
auto editor = new QTextEdit(QStringLiteral("recreated lorem ipsum......"), dw);
dw->setWidget(editor);
dw->setFeature(ads::CDockWidget::DeleteContentOnClose, true);
dw->setWidgetFactory([](QWidget* dw)
{
static int timesRecreated = 0;
return new QTextEdit(QStringLiteral("recreated lorem ipsum... times %1").arg(++timesRecreated), dw);
});
auto area = dockManager->addDockWidgetTab(ads::CenterDockWidgetArea, dw);
qDebug() << "DeleteContentOnClose dock widget created!" << dw << area;
action = new QAction("Toggle [DeleteContentOnClose]", &w);
w.menuBar()->addAction(action);
QObject::connect(action, &QAction::triggered, [dw]() {
dw->toggleView(dw->isClosed());
qDebug() << QString("dock widget %1! contents widget %2!").arg(dw->isClosed() ? "closed" : "open", dw->widget() ? "created" : "deleted");
});
action = new QAction("New", &w);
w.menuBar()->addAction(action);
QObject::connect(action, &QAction::triggered, [&]() {

View File

@@ -1,31 +0,0 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_dockindock VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(DockInDockExample WIN32
dockindock.cpp
dockindockmanager.cpp
perspectiveactions.cpp
perspectives.cpp
main.cpp
mainframe.cpp
)
target_include_directories(DockInDockExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(DockInDockExample PRIVATE qtadvanceddocking)
target_link_libraries(DockInDockExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(DockInDockExample PROPERTIES
AUTOMOC ON
AUTORCC ON
AUTOUIC ON
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
EXPORT_NAME "Qt Advanced Docking System Simple Example"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
)

View File

@@ -1,296 +0,0 @@
#include "dockindock.h"
#include "perspectives.h"
#include "dockindockmanager.h"
#include "perspectiveactions.h"
#include <QMenu>
#include <QDir>
#include <QVBoxLayout>
#include <QMainWindow>
#include <QMessageBox>
#include <QInputDialog>
#include <set>
#include <assert.h>
using namespace QtAdsUtl;
DockInDockWidget::DockInDockWidget( QWidget* parent, bool canCreateNewGroups, PerspectivesManager* perspectivesManager ) :
DockInDockWidget( parent, (DockInDockWidget*)NULL, perspectivesManager )
{
m_canCreateNewGroups = canCreateNewGroups;
m_topLevelDockWidget = this;
}
DockInDockWidget::DockInDockWidget( QWidget* parent, DockInDockWidget* topLevelDockWidget, PerspectivesManager* perspectivesManager ) :
baseClass( parent ),
m_topLevelDockWidget( topLevelDockWidget ),
m_canCreateNewGroups( (topLevelDockWidget) ? topLevelDockWidget->m_canCreateNewGroups : false ),
m_perspectivesManager( perspectivesManager )
{
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins( 0,0,0,0 );
layout->addWidget( m_mgr = new DockInDockManager(*this) );
}
DockInDockWidget::~DockInDockWidget()
{
}
ads::CDockAreaWidget* DockInDockWidget::addTabWidget( QWidget* widget, const QString& name, ads::CDockAreaWidget* after )
{
return addTabWidget( widget, name, QIcon(), after );
}
ads::CDockAreaWidget* DockInDockWidget::addTabWidget( QWidget* widget, const QString& name, QIcon icon, ads::CDockAreaWidget* after )
{
for ( auto existing : getTopLevelDockWidget()->getManager()->allDockWidgets(true,true) )
{
if ( existing.second->objectName() == name )
{
QMessageBox::critical( this, "Error", "Name '" + name + "' already in use" );
return NULL;
}
}
ads::CDockWidget* DockWidget = new ads::CDockWidget(name);
DockWidget->setWidget(widget);
DockWidget->setIcon( icon );
// Add the dock widget to the top dock widget area
return m_mgr->addDockWidget(ads::CenterDockWidgetArea, DockWidget, after);
}
bool DockInDockWidget::isTopLevel()
{
return objectName().isEmpty();
}
QString DockInDockWidget::getGroupNameError( const QString& groupName )
{
if ( groupName.isEmpty() )
{
return "Group must have a non-empty name";
}
std::vector<DockInDockManager*> dockManagers = m_mgr->allManagers( true, true );
for ( auto mgr : dockManagers )
{
if ( mgr->getGroupName() == groupName )
return "Group name '" + groupName + "' already used";
}
return "";
}
DockInDockWidget* DockInDockWidget::createGroup( const QString& groupName, ads::CDockAreaWidget*& insertPos )
{
return createGroup( groupName, QIcon(), insertPos );
}
DockInDockWidget* DockInDockWidget::createGroup( const QString& groupName, QIcon icon, ads::CDockAreaWidget*& insertPos )
{
QString error = getGroupNameError( groupName );
if ( !error.isEmpty() )
{
QMessageBox::critical( NULL, "Error", error );
return NULL;
}
DockInDockWidget* child = new DockInDockWidget( this, m_topLevelDockWidget, m_perspectivesManager );
child->setObjectName( groupName );
ads::CDockWidget* DockWidget = new ads::CDockWidget(groupName);
DockWidget->setWidget(child);
DockWidget->setIcon(icon);
insertPos = m_mgr->addDockWidget(ads::CenterDockWidgetArea, DockWidget, insertPos);
return child;
}
void DockInDockWidget::destroyGroup( DockInDockWidget* widgetToRemove )
{
auto topLevelWidget = widgetToRemove->getTopLevelDockWidget();
if ( topLevelWidget && topLevelWidget != widgetToRemove )
{
// reaffect all child docks to top-level
for ( auto dockwidget : widgetToRemove->getManager()->getWidgetsInGUIOrder() ) // don't use allDockWidgets to preserve sub-groups
{
MoveDockWidgetAction::move( dockwidget, topLevelWidget->getManager() );
}
assert( widgetToRemove->getManager()->allDockWidgets( true, true ).empty() );
// find widget's parent:
for ( auto dockwidget : topLevelWidget->getManager()->allDockWidgets( true, true ) )
{
if ( dockwidget.second->widget() == widgetToRemove )
{
dockwidget.first->removeDockWidget( dockwidget.second );
delete dockwidget.second;
//delete widgetToRemove; automatically deleted when dockWidget is deleted
widgetToRemove = NULL;
break;
}
}
assert( widgetToRemove == NULL );
}
else
{
assert( false );
}
}
void DockInDockWidget::attachViewMenu( QMenu* menu )
{
connect( menu, SIGNAL(aboutToShow()), this, SLOT(autoFillAttachedViewMenu()) );
}
void DockInDockWidget::autoFillAttachedViewMenu()
{
QMenu* menu = dynamic_cast<QMenu*>( QObject::sender() );
if ( menu )
{
menu->clear();
setupViewMenu( menu );
}
else
{
assert( false );
}
}
void DockInDockWidget::setupViewMenu( QMenu* menu )
{
std::vector<DockInDockManager*> dockManagers = m_mgr->allManagers( true, true );
bool hasPerspectivesMenu = false;
if ( getTopLevelDockWidget() == this )
hasPerspectivesMenu = (m_perspectivesManager != NULL);
else
assert( false );
QMenu* organize = menu;
if ( hasPerspectivesMenu )
organize = menu->addMenu( "Organize" );
setupMenu( organize, dockManagers );
if ( hasPerspectivesMenu )
{
QMenu* perspectives = menu->addMenu( "Perspectives" );
fillPerspectivesMenu( perspectives );
}
}
void DockInDockWidget::setupMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo )
{
m_mgr->fillViewMenu( menu, moveTo );
menu->addSeparator();
auto moveMenu = menu->addMenu( "Move" );
m_mgr->fillMoveMenu( moveMenu, moveTo );
}
void DockInDockWidget::fillPerspectivesMenu( QMenu* menu )
{
menu->addAction( "Create perspective...", this, SLOT(createPerspective()) );
QStringList perspectiveNames;
if ( m_perspectivesManager )
perspectiveNames = m_perspectivesManager->perspectiveNames();
if ( !perspectiveNames.isEmpty() )
{
QMenu* load = menu->addMenu( "Load perspective" );
for ( auto name : perspectiveNames )
load->addAction( new LoadPerspectiveAction( load, name, *this ) );
QMenu* remove = menu->addMenu( "Remove perspective" );
for ( auto name : perspectiveNames )
remove->addAction( new RemovePerspectiveAction( remove, name, *this ) );
}
}
void DockInDockWidget::setNewPerspectiveDefaultName( const QString& defaultName )
{
m_newPerspectiveDefaultName = defaultName;
}
void DockInDockWidget::createPerspective()
{
if ( !m_perspectivesManager )
return;
QString name = m_newPerspectiveDefaultName;
if ( !m_newPerspectiveDefaultName.isEmpty() )
{
int index = 2;
while ( m_perspectivesManager->perspectiveNames().contains( name ) )
{
name = m_newPerspectiveDefaultName + " (" + QString::number(index) + ")";
++index;
}
}
while ( true )
{
bool ok = false;
name = QInputDialog::getText( NULL, "Create perspective", "Enter perspective name", QLineEdit::Normal, name, &ok );
if ( ok )
{
if ( name.isEmpty() )
{
QMessageBox::critical( NULL, "Error", "Perspective name cannot be empty" );
continue;
}
else if ( m_perspectivesManager->perspectiveNames().contains( name ) )
{
if ( QMessageBox::critical( NULL, "Error", "Perspective '" + name + "' already exists, overwrite it?", QMessageBox::Yes | QMessageBox::No, QMessageBox::No ) == QMessageBox::No )
continue;
}
m_perspectivesManager->addPerspective( name, *this );
break;
}
else
{
break;
}
}
}
static void dumpStatus( std::ostream& str, ads::CDockWidget* widget, const std::string& tab, std::string suffix )
{
DockInDockManager* asMgr = DockInDockManager::dockInAManager( widget );
if ( asMgr )
{
asMgr->parent().dumpStatus( str, tab );
}
else
{
str << tab << widget->objectName().toStdString() << suffix << std::endl;
}
}
void DockInDockWidget::dumpStatus( std::ostream& str, std::string tab )
{
str << tab << "Group: " << getManager()->getGroupName().toStdString() << std::endl;
tab += " ";
std::set<ads::CDockWidget*> visibleWidgets;
for ( auto widget : getManager()->getWidgetsInGUIOrder() )
{
visibleWidgets.insert( widget );
::dumpStatus( str, widget, tab, "" );
}
for ( auto closed : getManager()->dockWidgetsMap() )
{
if ( visibleWidgets.find( closed ) == visibleWidgets.end() )
{
::dumpStatus( str, closed, tab, " (closed)" );
}
}
}

View File

@@ -1,80 +0,0 @@
#pragma once
#include <QWidget>
#include <QMap>
#include <memory>
#include <ostream>
class QMenu;
namespace ads
{
class CDockAreaWidget;
}
namespace QtAdsUtl
{
class DockInDockManager;
class PerspectivesManager;
// tab of tab example for https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/306
class DockInDockWidget : public QWidget
{
typedef QWidget baseClass;
Q_OBJECT
public:
DockInDockWidget( QWidget* parent, bool canCreateNewGroups, PerspectivesManager* perspectivesManager );
~DockInDockWidget() override;
ads::CDockAreaWidget* addTabWidget( QWidget* widget, const QString& name, ads::CDockAreaWidget* after );
DockInDockWidget* createGroup( const QString& groupName, ads::CDockAreaWidget*& insertPos );
ads::CDockAreaWidget* addTabWidget( QWidget* widget, const QString& name, QIcon icon, ads::CDockAreaWidget* after );
DockInDockWidget* createGroup( const QString& groupName, QIcon icon, ads::CDockAreaWidget*& insertPos );
QString getGroupNameError( const QString& groupName );
void destroyGroup( DockInDockWidget* widget );
/** Manually fill a given view menu */
void setupViewMenu( QMenu* menu );
/** Attach a view menu that will be automatically fill */
void attachViewMenu( QMenu* menu );
bool isTopLevel();
void setupMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo );
inline DockInDockManager* getManager() { return m_mgr; }
inline DockInDockWidget* getTopLevelDockWidget() { return m_topLevelDockWidget; }
inline bool canCreateNewGroups() const { return m_canCreateNewGroups; }
void dumpStatus( std::ostream& str, std::string tab = "" );
inline PerspectivesManager* getPerspectivesManager() { return m_perspectivesManager; }
void setNewPerspectiveDefaultName( const QString& defaultName );
private slots:
void autoFillAttachedViewMenu();
void createPerspective();
private:
DockInDockManager* m_mgr;
DockInDockWidget* m_topLevelDockWidget;
bool m_canCreateNewGroups;
DockInDockWidget( QWidget* parent, DockInDockWidget* topLevelDockWidget, PerspectivesManager* perspectivesManager );
PerspectivesManager* m_perspectivesManager;
QString m_newPerspectiveDefaultName;
void fillPerspectivesMenu( QMenu* menu );
};
}

View File

@@ -1,35 +0,0 @@
ADS_OUT_ROOT = $${OUT_PWD}/../..
QT += core gui widgets
TARGET = DockInDock
DESTDIR = $${ADS_OUT_ROOT}/lib
TEMPLATE = app
CONFIG += c++14
CONFIG += debug_and_release
adsBuildStatic {
DEFINES += ADS_STATIC
}
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
dockindock.cpp \
dockindockmanager.cpp \
perspectiveactions.cpp \
perspectives.cpp \
main.cpp \
mainframe.cpp
HEADERS += \
dockindock.h \
dockindockmanager.h \
perspectiveactions.h \
perspectives.h \
mainframe.h
LIBS += -L$${ADS_OUT_ROOT}/lib
include(../../ads.pri)
INCLUDEPATH += ../../src
DEPENDPATH += ../../src

View File

@@ -1,203 +0,0 @@
import sys
from PyQt5.QtWidgets import (QApplication, QWidget, QVBoxLayout, QMessageBox,
QInputDialog, QMenu, QLineEdit)
from PyQt5.QtGui import QIcon
from PyQtAds import QtAds
from dockindockmanager import DockInDockManager
from perspectiveactions import LoadPerspectiveAction, RemovePerspectiveAction
class DockInDockWidget(QWidget):
def __init__(self, parent, perspectives_manager: 'PerspectivesManager', can_create_new_groups: bool = False, top_level_widget = None):
super().__init__(parent)
if top_level_widget is not None:
self.__can_create_new_groups = top_level_widget.can_create_new_groups
else:
self.__can_create_new_groups = can_create_new_groups
self.__top_level_dock_widget = top_level_widget if top_level_widget else self
self.__perspectives_manager = perspectives_manager
self.__new_perspective_default_name: str = ''
layout = QVBoxLayout(self)
layout.setContentsMargins(0,0,0,0)
self.__mgr = DockInDockManager(self)
layout.addWidget(self.__mgr)
def getManager(self) -> 'DockInDockManager':
return self.__mgr
def getTopLevelDockWidget(self) -> 'DockInDockWidget':
return self.__top_level_dock_widget
def canCreateNewGroups(self) -> bool:
return self.__can_create_new_groups
def getPerspectivesManager(self) -> 'PerspectivesManager':
return self.__perspectives_manager
def addTabWidget(self, widget: QWidget, name: str, after: QtAds.CDockAreaWidget, icon = QIcon()) -> QtAds.CDockAreaWidget:
for existing in self.getTopLevelDockWidget().getManager().allDockWidgets(True, True):
if existing[1].objectName() == name:
QMessageBox.critical(self, "Error", "Name '" + name + "' already in use")
return
dock_widget = QtAds.CDockWidget(name)
dock_widget.setWidget(widget)
dock_widget.setIcon(icon)
# Add the dock widget to the top dock widget area
return self.__mgr.addDockWidget(QtAds.CenterDockWidgetArea, dock_widget, after)
def isTopLevel(self) -> bool:
return not self.objectName()
def getGroupNameError(self, group_name: str) -> str:
if not group_name:
return "Group must have a non-empty name"
dock_managers = self.__mgr.allManagers(True, True)
for mgr in dock_managers:
if mgr.getGroupName() == group_name:
return "Group name '" + group_name + "' already used"
return ""
def createGroup(self, group_name: str, insert_pos: QtAds.CDockAreaWidget, icon = QIcon()) -> 'DockInDockWidget':
error = self.getGroupNameError(group_name)
if error:
QMessageBox.critical(None, "Error", error)
return
child = DockInDockWidget(self, self.__top_level_dock_widget, self.__perspectives_manager)
child.setObjectName(group_name)
dock_widget = QtAds.CDockWidget(group_name)
dock_widget.setWidget(child)
dock_widget.setIcon(icon)
insert_pos = self.__mgr.addDockWidget(QtAds.CenterDockWidgetArea, dock_widget, insert_pos)
return child, insert_pos
def destroyGroup(self, widget_to_remove: 'DockInDockWidget') -> None:
top_level_widget = widget_to_remove.getTopLevelDockWidget()
if top_level_widget and top_level_widget != widget_to_remove:
for dock_widget in widget_to_remove.getManager().getWidgetsInGUIOrder(): #don't use allDockWidgets to preserve sub-groups
MoveDockWidgetAction.move(dock_widget, top_level_widget.getManager())
assert not widget_to_remove.getManager().allDockWidgets(True, True)
# find widget's parent:
for dock_widget in top_level_widget.getManager().allDockWidgets(True, True):
if dockwidget[1].widget() == widget_to_remove:
dockwidget[0].removeDockWidget(dockwidget[1])
del dockwidget[1]
# delete widgetToRemove; automatically deleted when dockWidget is deleted
widget_to_remove = None
break
assert widget_to_remove == None
else:
assert False
def attachViewMenu(self, menu: QMenu) -> None:
menu.aboutToShow.connect(self.autoFillAttachedViewMenu)
def autoFillAttachedViewMenu(self) -> None:
menu = self.sender()
if menu:
menu.clear()
self.setupViewMenu(menu)
else:
assert False
def setupViewMenu(self, menu):
dock_managers = self.__mgr.allManagers(True, True)
has_perspectives_menu = False
if self.getTopLevelDockWidget() == self:
has_perspectives_menu = (self.__perspectives_manager != None)
else:
assert False
organize = menu
if has_perspectives_menu:
organize = menu.addMenu("Organize")
self.setupMenu(organize, dock_managers)
if has_perspectives_menu:
perspectives = menu.addMenu("Perspectives")
self.fillPerspectivesMenu(perspectives)
def setupMenu(self, menu: QMenu, move_to: 'list[DockInDockManager]') -> None:
self.__mgr.fillViewMenu(menu, move_to)
menu.addSeparator()
move_menu = menu.addMenu("Move")
self.__mgr.fillMoveMenu(move_menu, move_to)
def fillPerspectivesMenu(self, menu: QMenu):
menu.addAction("Create perspective...", self.createPerspective)
perspectives_names = []
if self.__perspectives_manager:
perspectives_names = self.__perspectives_manager.perspectiveNames()
if perspectives_names:
load = menu.addMenu("Load perspective")
for name in perspectives_names:
load.addAction(LoadPerspectiveAction(load, name, self))
remove = menu.addMenu("Remove perspective")
for name in perspectives_names:
remove.addAction(RemovePerspectiveAction(remove, name, self))
def setNewPerspectiveDefaultName(default_name: str) -> None:
self.__new_perspective_default_name = default_name
def createPerspective(self) -> None:
if not self.__perspectives_manager:
return
name = self.__new_perspective_default_name
if self.__new_perspective_default_name:
index = 2
while name in self.__perspectives_manager.perspectiveNames():
name = f"{self.__new_perspective_default_name}({index})"
index += 1
while True:
name, ok = QInputDialog.getText(None, "Create perspective", "Enter perspective name", QLineEdit.Normal, name)
if ok:
if not name:
QMessageBox.critical(None, "Error", "Perspective name cannot be empty")
continue
elif name in self.__perspectives_manager.perspectiveNames():
if QMessageBox.critical(None, "Error", f"Perspective '{name}' already exists, overwrite it?", QMessageBox.Yes | QMessageBox.No, QMessageBox.No) == QMessageBox.No:
continue
self.__perspectives_manager.addPerspective(name, self)
break
else:
break
def dumpStatus(self, echo: callable = print, widget: QtAds.CDockWidget = None, tab: str = '', suffix: str = '') -> str:
if widget is not None:
as_mgr = DockInDockManager.dockInAManager(widget)
if as_mgr:
as_mgr.parent().dumpStatus(tab=tab)
else:
echo(tab + widget.objectName() + suffix)
else:
echo(tab + "Group: " + self.getManager().getGroupName())
tab += " "
visible_widgets = set()
for widget in self.getManager().getWidgetsInGUIOrder():
visible_widgets.add(widget)
self.dumpStatus(widget=widget, tab=tab)
for closed in self.getManager().dockWidgetsMap().values():
if not closed in visible_widgets:
self.dumpStatus(widget=closed, tab=tab, suffix=" (closed)")

View File

@@ -1,334 +0,0 @@
#include "dockindockmanager.h"
#include "dockindock.h"
#include "DockAreaWidget.h"
#include <QMenu>
#include <QInputDialog>
#include <QSettings>
#include <QMessageBox>
#include <assert.h>
using namespace QtAdsUtl;
/////////////////////////////////////
// DockInDockManager
/////////////////////////////////////
DockInDockManager::DockInDockManager( DockInDockWidget& parent ) :
baseClass( &parent ),
m_parent( parent )
{
}
DockInDockManager::~DockInDockManager()
{
}
void DockInDockManager::fillViewMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo )
{
auto widgetsMap = dockWidgetsMap();
for ( auto iter = widgetsMap.begin(); iter != widgetsMap.end(); ++iter )
{
auto widget = iter.value()->widget();
auto action = iter.value()->toggleViewAction();
DockInDockWidget* asMgr = dynamic_cast<DockInDockWidget*>( widget );
if ( asMgr )
{
auto subMenu = menu->addMenu( iter.key() );
subMenu->addAction( action );
subMenu->addSeparator();
asMgr->setupMenu( subMenu, moveTo );
}
else
{
menu->addAction(action);
}
}
if ( parent().canCreateNewGroups() )
{
// see how this works, to create it in the right place,
// and also to have load perspective work when some groups are missing
menu->addSeparator();
menu->addAction( new QtAdsUtl::CreateChildDockAction( m_parent, menu ) );
if ( parent().getTopLevelDockWidget()->getManager() != this )
menu->addAction( new QtAdsUtl::DestroyGroupAction( &m_parent, menu ) );
}
}
void DockInDockManager::fillMoveMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo )
{
auto widgetsMap = dockWidgetsMap();
for ( auto iter = widgetsMap.begin(); iter != widgetsMap.end(); ++iter )
{
auto subMenu = menu->addMenu( iter.key() );
for ( auto mgr : moveTo )
{
// iterate over all possible target managers
if ( mgr == this )
{
// if dock is already in mgr, no reason to move it there
}
else if ( mgr == dockInAManager( iter.value() ) )
{
// if target is the group itself, can't move it there, would make no sense
}
else
{
subMenu->addAction( new MoveDockWidgetAction( iter.value(), mgr, subMenu ) );
}
}
}
}
void DockInDockManager::addPerspectiveRec( const QString& name )
{
std::vector<DockInDockManager*> managers = allManagers( true, true );
for ( auto child : managers )
child->addPerspective( name );
}
void DockInDockManager::openPerspectiveRec( const QString& name )
{
std::vector<DockInDockManager*> managers = allManagers( true, true );
for ( auto child : managers )
child->openPerspective( name );
}
QString DockInDockManager::getGroupName()
{
return parent().objectName();
}
#define CHILD_PREFIX QString("Child-")
QString DockInDockManager::getPersistGroupName()
{
QString group = "Top";
if ( !getGroupName().isEmpty() )
group = CHILD_PREFIX + getGroupName();
return group;
}
QString DockInDockManager::getGroupNameFromPersistGroupName( QString persistGroupName )
{
if ( persistGroupName.startsWith( CHILD_PREFIX ) )
{
persistGroupName = persistGroupName.mid( CHILD_PREFIX.size() );
}
else
{
assert( false );
}
return persistGroupName;
}
void DockInDockManager::loadPerspectivesRec(QSettings& Settings)
{
std::vector<DockInDockManager*> children = allManagers( true, true );
for ( auto mgr : children )
{
Settings.beginGroup(mgr->getPersistGroupName());
mgr->loadPerspectives( Settings );
Settings.endGroup();
}
}
void DockInDockManager::savePerspectivesRec(QSettings& Settings) const
{
std::vector<DockInDockManager*> children = allManagers( true, true );
for ( auto mgr : children )
{
Settings.beginGroup(mgr->getPersistGroupName());
mgr->savePerspectives( Settings );
Settings.endGroup();
}
}
void DockInDockManager::removePerspectivesRec()
{
std::vector<DockInDockManager*> managers = allManagers( true, true );
for ( auto child : managers )
child->removePerspectives( child->perspectiveNames() );
}
DockInDockManager* DockInDockManager::dockInAManager( ads::CDockWidget* widget )
{
DockInDockWidget* dockWidget = widget ? dynamic_cast<DockInDockWidget*>( widget->widget() ) : NULL;
return ( dockWidget ) ? dockWidget->getManager() : NULL;
}
void DockInDockManager::childManagers( std::vector<DockInDockManager*>& managers, bool rec ) const
{
auto widgets = getWidgetsInGUIOrder();
for ( auto widget : widgets )
{
DockInDockManager* asMgr = dockInAManager( widget );
if ( asMgr )
{
managers.push_back( asMgr );
if ( rec )
asMgr->childManagers( managers, rec );
}
}
}
std::vector<DockInDockManager*> DockInDockManager::allManagers( bool includeThis, bool rec ) const
{
std::vector<DockInDockManager*> managers;
if ( includeThis )
managers.push_back( const_cast<DockInDockManager*>(this) );
childManagers( managers, rec );
return managers;
}
std::vector<std::pair<DockInDockManager*,ads::CDockWidget*>> DockInDockManager::allDockWidgets( bool includeThis, bool rec ) const
{
std::vector<std::pair<DockInDockManager*,ads::CDockWidget*>> widgets;
for ( auto mgr : allManagers( includeThis, rec ) )
{
for ( auto widget : mgr->getWidgetsInGUIOrder() )
widgets.push_back( std::make_pair(mgr, widget) );
}
return widgets;
}
QMap<QString,QStringList> DockInDockManager::getGroupContents()
{
QMap<QString,QStringList> result;
std::vector<DockInDockManager*> managers = allManagers( true, true );
for ( auto mgr : managers )
{
result[mgr->getPersistGroupName()] = mgr->dockWidgetsMap().keys();
}
return result;
}
ads::CDockAreaWidget* DockInDockManager::getInsertDefaultPos()
{
ads::CDockAreaWidget* defaultPos = NULL;
if ( dockAreaCount() != 0 )
defaultPos = dockArea(dockAreaCount()-1);
return defaultPos;
}
std::vector<ads::CDockWidget*> DockInDockManager::getWidgetsInGUIOrder() const
{
std::vector<ads::CDockWidget*> result;
result.reserve( dockWidgetsMap().size() );
for ( int i = 0; i != dockAreaCount(); ++i )
{
for ( auto widget : dockArea(i)->dockWidgets() )
result.push_back( widget );
}
return result;
}
/////////////////////////////////////
// CreateChildDockAction
/////////////////////////////////////
CreateChildDockAction::CreateChildDockAction( DockInDockWidget& dockInDock, QMenu* menu ) :
QAction("New group...", menu),
m_dockInDock( dockInDock )
{
connect( this, SIGNAL(triggered()), this, SLOT(createGroup()) );
}
void CreateChildDockAction::createGroup()
{
QString name = "";
while ( true )
{
bool ok = false;
name = QInputDialog::getText( NULL, this->text(), "Enter group name", QLineEdit::Normal, name, &ok );
if ( ok )
{
QString error = "";
if ( m_dockInDock.getTopLevelDockWidget() )
error = m_dockInDock.getTopLevelDockWidget()->getGroupNameError( name );
else
assert( false );
if ( error.isEmpty() )
{
ads::CDockAreaWidget* insertPos = NULL;
m_dockInDock.createGroup( name, insertPos );
break;
}
else
{
QMessageBox::critical( NULL, "Error", error );
continue;
}
}
else
{
break;
}
}
}
/////////////////////////////////////
// DestroyGroupAction
/////////////////////////////////////
DestroyGroupAction::DestroyGroupAction( DockInDockWidget* widget, QMenu* menu ) :
QAction("Destroy " + widget->getManager()->getGroupName(), menu),
m_widget( widget )
{
connect( this, SIGNAL(triggered()), this, SLOT(destroyGroup()) );
}
void DestroyGroupAction::destroyGroup()
{
m_widget->getTopLevelDockWidget()->destroyGroup( m_widget );
}
/////////////////////////////////////
// MoveDockWidgetAction
/////////////////////////////////////
MoveDockWidgetAction::MoveDockWidgetAction( ads::CDockWidget* widget, DockInDockManager* moveTo, QMenu* menu ) :
QAction(menu),
m_widget( widget ),
m_moveTo( moveTo )
{
if ( moveTo->parent().isTopLevel() )
{
setText( "To top" );
}
else
{
setText( "To " + moveTo->parent().objectName() );
}
connect( this, SIGNAL(triggered()), this, SLOT(move()) );
}
void MoveDockWidgetAction::move()
{
move( m_widget, m_moveTo );
}
void MoveDockWidgetAction::move( ads::CDockWidget* widget, DockInDockManager* moveTo )
{
if ( widget && moveTo )
{
widget->dockManager()->removeDockWidget( widget );
moveTo->addDockWidget(ads::CenterDockWidgetArea, widget, moveTo->getInsertDefaultPos());
}
else
{
assert( false );
}
}

View File

@@ -1,96 +0,0 @@
#pragma once
#include "DockManager.h"
#include <QAction>
#include <QMap>
namespace QtAdsUtl
{
class DockInDockWidget;
class DockInDockManager : public ads::CDockManager
{
Q_OBJECT
typedef ads::CDockManager baseClass;
public:
DockInDockManager( DockInDockWidget& parent );
~DockInDockManager() override;
void fillViewMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo );
void fillMoveMenu( QMenu* menu, const std::vector<DockInDockManager*>& moveTo );
void addPerspectiveRec( const QString& name );
void openPerspectiveRec( const QString& name );
void removePerspectivesRec();
void loadPerspectivesRec(QSettings& Settings);
void savePerspectivesRec(QSettings& Settings) const;
static DockInDockManager* dockInAManager( ads::CDockWidget* widget );
inline DockInDockWidget& parent() { return m_parent; }
void childManagers( std::vector<DockInDockManager*>& managers, bool rec ) const;
std::vector<DockInDockManager*> allManagers( bool includeThis, bool rec ) const;
std::vector<std::pair<DockInDockManager*,ads::CDockWidget*>> allDockWidgets( bool includeThis, bool rec ) const;
QString getGroupName();
QString getPersistGroupName();
static QString getGroupNameFromPersistGroupName( QString persistGroupName );
QMap<QString,QStringList> getGroupContents();
ads::CDockAreaWidget* getInsertDefaultPos();
std::vector<ads::CDockWidget*> getWidgetsInGUIOrder() const;
private:
DockInDockWidget& m_parent;
};
class CreateChildDockAction : public QAction
{
Q_OBJECT
public:
CreateChildDockAction( DockInDockWidget& dockInDock, QMenu* menu );
public slots:
void createGroup();
private:
DockInDockWidget& m_dockInDock;
};
class DestroyGroupAction : public QAction
{
Q_OBJECT
public:
DestroyGroupAction( DockInDockWidget* widget, QMenu* menu );
public slots:
void destroyGroup();
private:
DockInDockWidget* m_widget;
};
class MoveDockWidgetAction : public QAction
{
Q_OBJECT
public:
MoveDockWidgetAction( ads::CDockWidget* widget, DockInDockManager* moveTo, QMenu* menu );
static void move( ads::CDockWidget* widget, DockInDockManager* moveTo );
public slots:
void move();
private:
ads::CDockWidget* m_widget;
DockInDockManager* m_moveTo;
};
}

View File

@@ -1,214 +0,0 @@
from PyQt5.QtWidgets import QAction, QMenu, QInputDialog, QLineEdit
from PyQt5.QtCore import QSettings
from PyQtAds import QtAds
CHILD_PREFIX = "Child-"
class DockInDockManager(QtAds.CDockManager):
def __init__(self, parent: 'DockInDockWidget'):
super().__init__()
self.__parent = parent
def parent(self) -> 'DockInDockWidget':
return self.__parent
def fillViewMenu(self, menu: QMenu, move_to: 'dict[DockInDockManager]') -> None:
from dockindock import DockInDockWidget # Prevent cyclic import
widgets_map = self.dockWidgetsMap()
for key, value in widgets_map.items():
widget = value.widget()
action = value.toggleViewAction()
if isinstance(widget, DockInDockWidget):
sub_menu = menu.addMenu(key)
sub_menu.addAction(action)
sub_menu.addSeparator()
widget.setupMenu(sub_menu, move_to)
else:
menu.addAction(action)
if self.parent().canCreateNewGroups():
# see how this works, to create it in the right place,
# and also to have load perspective work when some groups are missing
menu.addSeparator()
menu.addAction(CreateChildDockAction(self.__parent, menu))
if self.parent().getTopLevelDockWidget().getManager() != self:
menu.addAction(DestroyGroupAction( self.parent, menu))
def fillMoveMenu(self, menu: QMenu, move_to: 'list[DockInDockManager]') -> None:
widgets_map = self.dockWidgetsMap()
for key, value in widgets_map.items():
sub_menu = menu.addMenu(key)
for mgr in move_to:
# iterate over all possible target managers
if mgr == self:
pass # if dock is already in mgr, no reason to move it there
elif mgr == DockInDockManager.dockInAManager(value):
pass # if target is the group itself, can't move it there, would make no sense
else:
sub_menu.addAction(MoveDockWidgetAction(value, mgr, sub_menu))
def addPerspectiveRec(self, name: str) -> None:
managers = self.allManagers(True, True)
for child in managers:
child.addPerspective(name)
def openPerspectiveRec(self, name: str) -> None:
managers = self.allManagers(True, True)
for child in managers:
child.openPerspective(name)
def getGroupName(self) -> str:
return self.parent().objectName()
def getPersistGroupName(self) -> str:
group = "Top"
if self.getGroupName():
group = CHILD_PREFIX + self.getGroupName()
return group
def getGroupNameFromPersistGroupName(self, persist_group_name) -> str:
if persist_group_name.startswith(CHILD_PREFIX):
persist_group_name = persist_group_name[len(CHILD_PREFIX):]
else:
assert False
return persist_group_name
def loadPerspectivesRec(self, settings: QSettings) -> None:
children = self.allManagers(True, True)
for mgr in children:
settings.beginGroup(mgr.getPersistGroupName())
mgr.loadPerspectives(settings)
settings.endGroup()
def savePerspectivesRec(self, settings: QSettings) -> None:
children = self.allManagers(True, True)
for mgr in children:
settings.beginGroup(mgr.getPersistGroupName())
mgr.savePerspectives(settings)
settings.endGroup()
def removePerspectivesRec(self, settings: QSettings) -> None:
children = self.allManagers(True, True)
for mgr in children:
child.removePerspectives(child.perspectiveNames())
@staticmethod
def dockInAManager(widget) -> 'DockInDockManager':
from dockindock import DockInDockWidget # Prevent cyclic import
dock_widget = widget.widget() if widget else None
return dock_widget.getManager() if isinstance(dock_widget, DockInDockWidget) else None
def childManagers(self, managers: 'list[DockInDockManager]', rec: bool) -> None:
widgets = self.getWidgetsInGUIOrder()
for widget in widgets:
as_mgr = DockInDockManager.dockInAManager(widget)
if as_mgr:
managers.append(as_mgr)
if rec:
as_mgr.childManagers(managers, rec)
def allManagers(self, include_self: bool, rec: bool) -> 'list[DockInDockManager]':
managers = []
if include_self:
managers.append(self)
self.childManagers(managers, rec)
return managers
def allDockWidgets(self, include_self: bool, rec: bool) -> 'list[tuple[DockInDockManager, QtAds.CDockWidget]]':
widgets = []
for mgr in self.allManagers(include_self, rec):
for widget in mgr.getWidgetsInGUIOrder():
widgets.append((mgr, widget))
return widgets
def getGroupContents(self) -> 'dict[str, list[str]]':
result = {}
managers = self.allManagers(True, True)
for mgr in managers:
result[mgr.getPersistGroupName()] = mgr.dockWidgetsMap().keys()
return result
def getInsertDefaultPos(self) -> QtAds.CDockAreaWidget:
default_pos = None
if self.dockAreaCount() != 0:
default_pos = self.dockArea(self.dockAreaCount()-1)
return default_pos
def getWidgetsInGUIOrder(self) -> 'list[QtAds.CDockWidget]':
result = []
for i in range(self.dockAreaCount()):
for widget in self.dockArea(i).dockWidgets():
result.append(widget)
return result
class CreateChildDockAction(QAction):
def __init__(self, dock_in_dock: 'DockInDockWidget', menu: QMenu):
super().__init__("New group...", menu)
self.__dock_in_dock = dock_in_dock
self.triggered.connect(self.createGroup)
def createGroup(self) -> None:
name = ""
while True:
name, ok = QInputDialog.getText(None, self.text(), "Enter group name", QLineEdit.Normal, name)
if ok:
error = ""
if self.__dock_in_dock.getTopLevelDockWidget():
error = self.__dock_in_dock.getTopLevelDockWidget().getGroupNameError(name)
else:
assert False
if not error:
self.__dock_in_dock.createGroup(name, None)
break
else:
QMessageBox.critical(None, "Error", error)
continue
else:
break
class DestroyGroupAction(QAction):
def __init__(self, widget: 'DockInDockWidget', menu: QMenu):
super().__init__("Destroy" + widget.getManager().getGroupName(), menu)
self.__widget = widget
self.triggered.connect(self.destroyGroup)
def destroyGroup(self) -> None:
self.__widget.getTopLevelDockWidget().destroyGroup(self.__widget)
class MoveDockWidgetAction(QAction):
def __init__(self, widget: 'DockInDockWidget', move_to: DockInDockManager, menu: QMenu):
super().__init__(menu)
self.__widget = widget
self.__move_to = move_to
if move_to.parent().isTopLevel():
self.setText("To top")
else:
self.setText(f"To {move_to.parent().objectName()}")
self.triggered.connect(self._move)
def _move(self) -> None:
self.move(self.__widget, self.__move_to)
def move(self, widget: QtAds.CDockWidget, move_to: QtAds.CDockManager) -> None:
if widget and move_to:
widget.dockManager().removeDockWidget(widget)
move_to.addDockWidget(QtAds.CenterDockWidgetArea, widget, move_to.getInsertDefaultPos())
else:
assert False

View File

@@ -1,11 +0,0 @@
#include <QApplication>
#include "../../examples/simple/MainWindow.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}

View File

@@ -1,72 +0,0 @@
import sys
import os
import atexit
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
from PyQt5.QtCore import Qt
from PyQtAds import QtAds
from perspectives import PerspectivesManager
from dockindock import DockInDockWidget
class MainWindow(QMainWindow):
def __init__(self, parent=None):
super().__init__(parent)
self.perspectives_manager = PerspectivesManager("persist")
self.resize(400, 400)
self.dock_manager = DockInDockWidget(self, self.perspectives_manager, can_create_new_groups=True)
self.setCentralWidget(self.dock_manager)
self.dock_manager.attachViewMenu(self.menuBar().addMenu("View"))
previous_dock_widget = None
for i in range(3):
l = QLabel()
l.setWordWrap(True)
l.setAlignment(Qt.AlignTop | Qt.AlignLeft)
l.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ")
previous_dock_widget = self.dock_manager.addTabWidget(l, f"Top label {i}", previous_dock_widget)
last_top_level_dock = previous_dock_widget
for j in range(2):
group_manager, _ = self.dock_manager.createGroup(f"Group {j}", last_top_level_dock)
previous_dock_widget = None
for i in range(3):
# Create example content label - this can be any application specific widget
l = QLabel()
l.setWordWrap(True)
l.setAlignment(Qt.AlignTop | Qt.AlignLeft)
l.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ")
previous_dock_widget = group_manager.addTabWidget(l, f"ZInner {j}/{i}", previous_dock_widget)
# create sub-group
sub_group, _ = group_manager.createGroup(f"SubGroup {j}", previous_dock_widget)
previous_dock_widget = None
for i in range(3):
# Create example content label - this can be any application specific widget
l = QLabel()
l.setWordWrap(True)
l.setAlignment(Qt.AlignTop | Qt.AlignLeft)
l.setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ")
previous_dock_widget = sub_group.addTabWidget(l, f"SubInner {j}/{i}", previous_dock_widget)
self.perspectives_manager.loadPerspectives()
atexit.register(self.cleanup)
def cleanup(self):
self.perspectives_manager.savePerspectives()
if __name__ == '__main__':
app = QApplication(sys.argv)
w = MainWindow()
w.show()
app.exec_()

View File

@@ -1,76 +0,0 @@
#include "mainframe.h"
#include "dockindock.h"
#include "perspectives.h"
#include <QLabel>
#include <QMenuBar>
#include <QMessageBox>
#include <QSettings>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
m_perspectivesManager( new QtAdsUtl::PerspectivesManager( "persist" ) )
{
resize( 400, 400 );
setCentralWidget( m_dockManager = new QtAdsUtl::DockInDockWidget(this,true,m_perspectivesManager.get()) );
m_dockManager->attachViewMenu( menuBar()->addMenu( "View" ) );
ads::CDockAreaWidget* previousDockWidget = NULL;
for ( int i = 0; i != 3; ++i )
{
// Create example content label - this can be any application specific
// widget
QLabel* l = new QLabel();
l->setWordWrap(true);
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
previousDockWidget = m_dockManager->addTabWidget( l, "Top label " + QString::number(i), previousDockWidget );
}
auto lastTopLevelDock = previousDockWidget;
for ( int j = 0; j != 2; ++j )
{
QtAdsUtl::DockInDockWidget* groupManager = m_dockManager->createGroup( "Group " + QString::number(j), lastTopLevelDock );
previousDockWidget = NULL;
for ( int i = 0; i != 3; ++i )
{
// Create example content label - this can be any application specific
// widget
QLabel* l = new QLabel();
l->setWordWrap(true);
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
previousDockWidget = groupManager->addTabWidget( l, "ZInner " + QString::number(j) + "/" + QString::number(i), previousDockWidget );
}
// create sub-group
auto subGroup = groupManager->createGroup( "SubGroup " + QString::number(j), previousDockWidget );
previousDockWidget = NULL;
for ( int i = 0; i != 3; ++i )
{
// Create example content label - this can be any application specific
// widget
QLabel* l = new QLabel();
l->setWordWrap(true);
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
previousDockWidget = subGroup->addTabWidget( l, "SubInner " + QString::number(j) + "/" + QString::number(i), previousDockWidget );
}
}
m_perspectivesManager->loadPerspectives();
}
MainWindow::~MainWindow()
{
m_perspectivesManager->savePerspectives();
}

View File

@@ -1,30 +0,0 @@
#pragma once
#include <QMainWindow>
#include <QAction>
#include <QSettings>
#include <memory>
namespace QtAdsUtl
{
class DockInDockWidget;
class PerspectivesManager;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
QtAdsUtl::DockInDockWidget* m_dockManager;
std::unique_ptr<QtAdsUtl::PerspectivesManager> m_perspectivesManager;
};

View File

@@ -1,39 +0,0 @@
#include "perspectiveactions.h"
#include "dockindock.h"
#include "perspectives.h"
#include <QMenu>
using namespace QtAdsUtl;
//////////////////////////////
// LoadPerspectiveAction
//////////////////////////////
LoadPerspectiveAction::LoadPerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager ) :
QAction( name, parent ),
name( name ),
dockManager( dockManager )
{
connect( this, SIGNAL(triggered()), this, SLOT(load()) );
}
void LoadPerspectiveAction::load()
{
dockManager.getPerspectivesManager()->openPerspective( name, dockManager );
}
//////////////////////////////
// RemovePerspectiveAction
//////////////////////////////
RemovePerspectiveAction::RemovePerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager ) :
QAction( name, parent ),
name( name ),
dockManager( dockManager )
{
connect( this, SIGNAL(triggered()), this, SLOT(remove()) );
}
void RemovePerspectiveAction::remove()
{
dockManager.getPerspectivesManager()->removePerspective( name );
}

View File

@@ -1,38 +0,0 @@
#pragma once
#include <QAction>
namespace QtAdsUtl
{
class DockInDockWidget;
class LoadPerspectiveAction : public QAction
{
Q_OBJECT
public:
LoadPerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager );
public slots:
void load();
private:
QString name;
QtAdsUtl::DockInDockWidget& dockManager;
};
class RemovePerspectiveAction : public QAction
{
Q_OBJECT
public:
RemovePerspectiveAction( QMenu* parent, const QString& name, QtAdsUtl::DockInDockWidget& dockManager );
public slots:
void remove();
private:
QString name;
QtAdsUtl::DockInDockWidget& dockManager;
};
}

View File

@@ -1,25 +0,0 @@
from PyQt5.QtWidgets import QAction, QMenu
class LoadPerspectiveAction(QAction):
def __init__(self, parent: QMenu, name: str, dock_manager: 'DockInDockWidget'):
super().__init__(name, parent)
self.name = name
self.dock_manager = dock_manager
self.triggered.connect(self.load)
def load(self):
self.dock_manager.getPerspectivesManager().openPerspective(self.name, self.dock_manager)
class RemovePerspectiveAction(QAction):
def __init__(self, parent: QMenu, name: str, dock_manager: 'DockInDockWidget'):
super().__init__(name, parent)
self.name = name
self.dock_manager = dock_manager
self.triggered.connect(self.remove)
def remove(self):
self.dock_manager.getPerspectivesManager().removePerspective(self.name)

View File

@@ -1,278 +0,0 @@
#include "perspectives.h"
#include "dockindock.h"
#include "dockindockmanager.h"
#include <QSettings>
#include <QFile>
#include <QDir>
#include <assert.h>
#define GROUP_PREFIX QString("Group")
using namespace QtAdsUtl;
PerspectivesManager::PerspectivesManager( const QString& perspectivesFolder ) :
m_perspectivesFolder( perspectivesFolder )
{
}
PerspectivesManager::~PerspectivesManager()
{
// remove temp files:
for ( auto perspective : m_perspectives )
{
QString fileName = perspective.settings->fileName();
perspective.settings.reset();
QFile::remove(fileName);
}
}
QStringList PerspectivesManager::perspectiveNames() const
{
return m_perspectives.keys();
}
void PerspectivesManager::addPerspective( const QString& name, DockInDockWidget& widget )
{
if ( !m_perspectivesFolder.isEmpty() )
{
m_perspectives[name].settings = getSettingsObject( getSettingsFileName( name, true ) );
m_perspectives[name].groups = widget.getManager()->getGroupContents();
// save perspective internally
widget.getManager()->addPerspectiveRec( name );
// store it in QSettings object
widget.getManager()->savePerspectivesRec( *(m_perspectives[name].settings) );
// remove internal perspectives
widget.getManager()->removePerspectives( widget.getManager()->perspectiveNames() );
}
else
{
assert( false );
}
emit perspectivesListChanged();
}
ads::CDockWidget* findWidget( QString name, const std::vector<DockInDockManager*>& managers )
{
for ( auto mgr : managers )
{
auto widget = mgr->findDockWidget(name);
if ( widget )
return widget;
}
return NULL;
}
void PerspectivesManager::openPerspective( const QString& name, DockInDockWidget& widget )
{
assert( widget.getTopLevelDockWidget() == &widget );
if ( !m_perspectivesFolder.isEmpty() )
{
if ( m_perspectives.contains( name ) )
{
emit openingPerspective();
if ( widget.canCreateNewGroups() )
{
auto curGroups = widget.getManager()->allManagers(true,true);
for ( auto group : m_perspectives[name].groups.keys() )
{
bool found = false;
for ( auto curgroup : curGroups )
{
if ( curgroup->getPersistGroupName() == group )
{
found = true;
break;
}
}
if ( !found )
{
group = DockInDockManager::getGroupNameFromPersistGroupName( group );
// restore group in file but not in GUI yet
ads::CDockAreaWidget* insertPos = NULL;
widget.createGroup( group, insertPos );
}
}
curGroups = widget.getManager()->allManagers(false,true);
for ( auto curgroup : curGroups )
{
if ( !m_perspectives[name].groups.keys().contains( curgroup->getPersistGroupName() ) )
{
widget.destroyGroup( &curgroup->parent() );
}
}
}
auto managers = widget.getManager()->allManagers(true,true);
for ( auto group : m_perspectives[name].groups.keys() )
{
for ( auto mgr : managers )
{
if ( mgr->getPersistGroupName() == group )
{
for ( QString widgetName : m_perspectives[name].groups[group] )
{
ads::CDockWidget* widget = findWidget( widgetName, { mgr } );
if ( widget )
{
// OK, widget is already in the good manager!
}
else
{
widget = findWidget( widgetName, managers );
if ( widget )
{
// move dock widget in the same group as it used to be when perspective was saved
// this guarantee load/open perspectives will work smartly
MoveDockWidgetAction::move( widget, mgr );
}
}
}
}
}
}
// internally load perspectives from QSettings
widget.getManager()->loadPerspectivesRec( *(m_perspectives[name].settings) );
// load perspective (update GUI)
widget.getManager()->openPerspectiveRec( name );
// remove internal perspectives
widget.getManager()->removePerspectives( widget.getManager()->perspectiveNames() );
emit openedPerspective();
}
}
else
{
assert( false );
}
}
void PerspectivesManager::removePerspectives()
{
m_perspectives.clear();
emit perspectivesListChanged();
}
void PerspectivesManager::removePerspective( const QString& name )
{
m_perspectives.remove( name );
emit perspectivesListChanged();
}
QString PerspectivesManager::getSettingsFileName( const QString& perspective, bool temp ) const
{
auto name = ( perspective.isEmpty() ) ? "perspectives.ini" : "perspective_" + perspective + (temp?".tmp":".ini");
return m_perspectivesFolder + "/" + name;
}
std::shared_ptr<QSettings> PerspectivesManager::getSettingsObject( const QString& filePath ) const
{
return std::make_shared<QSettings>(filePath, QSettings::IniFormat);
}
void PerspectivesManager::loadPerspectives()
{
if ( !m_perspectivesFolder.isEmpty() )
{
QDir().mkpath( m_perspectivesFolder );
m_perspectives.clear();
auto mainSettings = getSettingsObject( getSettingsFileName( "", false ) );
std::string debug = mainSettings->fileName().toStdString();
int Size = mainSettings->beginReadArray("Perspectives");
for (int i = 0; i < Size; ++i)
{
mainSettings->setArrayIndex(i);
QString perspective = mainSettings->value("Name").toString();
if ( !perspective.isEmpty() )
{
// load perspective file:
auto toLoad = getSettingsFileName( perspective, false );
auto loaded = getSettingsFileName( perspective, true );
#ifdef _DEBUG
std::string debug1 = loaded.toStdString();
std::string debug2 = toLoad.toStdString();
#endif
QFile::remove( loaded );
if ( !QFile::copy( toLoad, loaded ) )
assert( false );
m_perspectives[perspective].settings = getSettingsObject( loaded );
// load group info:
mainSettings->beginGroup(GROUP_PREFIX);
for ( auto key : mainSettings->allKeys() )
m_perspectives[perspective].groups[key] = mainSettings->value( key ).toStringList();
mainSettings->endGroup();
}
else
{
assert( false );
}
}
mainSettings->endArray();
}
emit perspectivesListChanged();
}
void PerspectivesManager::savePerspectives() const
{
if ( !m_perspectivesFolder.isEmpty() )
{
auto mainSettings = getSettingsObject( getSettingsFileName( "", false ) );
// Save list of perspective and group organization
mainSettings->beginWriteArray("Perspectives", m_perspectives.size());
int i = 0;
for ( auto perspective : m_perspectives.keys() )
{
mainSettings->setArrayIndex(i);
mainSettings->setValue("Name", perspective);
mainSettings->beginGroup(GROUP_PREFIX);
for ( auto group : m_perspectives[perspective].groups.keys() )
{
mainSettings->setValue( group, m_perspectives[perspective].groups[group] );
}
mainSettings->endGroup();
++i;
}
mainSettings->endArray();
// Save perspectives themselves
for ( auto perspectiveName : m_perspectives.keys() )
{
auto toSave = getSettingsFileName( perspectiveName, false );
QSettings& settings = *(m_perspectives[perspectiveName].settings);
settings.sync();
#ifdef _DEBUG
std::string debug1 = settings.fileName().toStdString();
std::string debug2 = toSave.toStdString();
#endif
QFile::remove( toSave );
if ( !QFile::copy( settings.fileName(), toSave ) )
assert( false );
}
}
}

View File

@@ -1,59 +0,0 @@
#pragma once
#include <QObject>
#include <QMap>
#include <QString>
#include <memory>
class QMenu;
class QSettings;
namespace QtAdsUtl
{
class DockInDockWidget;
class PerspectivesManager : public QObject
{
Q_OBJECT
public:
PerspectivesManager( const QString& perspectivesFolder );
virtual ~PerspectivesManager();
QStringList perspectiveNames() const;
void addPerspective( const QString& name, DockInDockWidget& widget );
void openPerspective( const QString& name, DockInDockWidget& widget );
void removePerspectives();
void removePerspective( const QString& name );
void loadPerspectives();
void savePerspectives() const;
signals:
void perspectivesListChanged();
void openingPerspective();
void openedPerspective();
private:
// Partially bypass ADS perspective management, store list here
// and then ADS will only have one perspective loaded
// this is because all docking widgets must exist when a perspective is loaded
// we will guarantee that!
class PerspectiveInfo
{
public:
std::shared_ptr<QSettings> settings;
QMap<QString,QStringList> groups;
};
QMap<QString,PerspectiveInfo> m_perspectives;
QString m_perspectivesFolder;
QString getSettingsFileName( const QString& perspective, bool temp ) const;
std::shared_ptr<QSettings> getSettingsObject( const QString& filePath ) const;
};
}

View File

@@ -1,203 +0,0 @@
import os
import tempfile
import shutil
import atexit
from PyQt5.QtCore import pyqtSignal, QSettings, QObject
from PyQtAds import QtAds
from dockindockmanager import DockInDockManager
from dockindock import DockInDockWidget
GROUP_PREFIX = "Group"
def findWidget(name, managers: 'list[DockInDockManager]') -> QtAds.CDockWidget:
for mgr in managers:
widget = mgr.findDockWidget(name)
if widget:
return widget
class PerspectiveInfo:
# Partially bypass ADS perspective management, store list here
# and then ADS will only have one perspective loaded
# this is because all docking widgets must exist when a perspective is loaded
# we will guarantee that!
settings = QSettings()
groups: 'dict[str, list[str]]' = {}
class PerspectivesManager(QObject):
perspectivesListChanged = pyqtSignal()
openingPerspective = pyqtSignal()
openedPerspective = pyqtSignal()
def __init__(self, perspectives_folder):
super().__init__()
self.__perspectives_folder = perspectives_folder
self.__perspectives = {}
atexit.register(self.cleanup)
def cleanup(self):
for perspective in self.__perspectives.values():
filename = perspective.settings.fileName()
try:
os.remove(filename)
except FileNotFoundError:
pass
def perspectiveNames(self) -> 'list[str]':
return self.__perspectives.keys()
def addPerspective(self, name: str, widget: DockInDockWidget) -> None:
if self.__perspectives_folder:
self.__perspectives[name] = perspective = PerspectiveInfo()
perspective.settings = self.getSettingsObject(self.getSettingsFileName(name, True))
perspective.groups = widget.getManager().getGroupContents()
# save perspective internally
widget.getManager().addPerspectiveRec(name)
# store it in QSettings object
widget.getManager().savePerspectivesRec(perspective.settings)
# remove internal perspectives
widget.getManager().removePerspectives(widget.getManager().perspectiveNames())
self.perspectivesListChanged.emit()
def openPerspective(name: str, widget: DockInDockWidget) -> None:
assert widget.getTopLevelDockWidget() == widget
if self.__perspectives_folder:
if name in self.__perspectives:
self.openingPerspective.emit()
if widget.canCreateNewGroups():
cur_groups = widget.getManager().allManagers(True, True)
for group in self.__perspectives[name].groups.keys():
found = False
for curgroup in cur_groups:
if curgroup.getPerspectiveGroupName() == group:
found = True
break
if not found:
group = DockInDockManager.getGroupNameFromPersistGroupName(group)
# restore group in file but not in GUI yet
widget.createGroup(group, None)
cur_groups = widget.getManager().allManagers(False, True)
for curgroup in cur_groups:
if curgroup.getPersistGroupName() not in self.__perspectives[name].groups.keys():
widget.destroyGroup(curgroup.parent())
managers = widget.getManager().allManagers(True, True)
for group in self.__perspectives[name].groups().keys():
for mgr in managers:
if mgr.getPersistGroupName() == group:
for widget_name in self.__perspectives[name].groups[group]:
widget = findWidget(widget_name, [mgr])
if widget:
pass # OK, widget is already in the good manager!
else:
widget = findWidget(widget_name, managers)
if widget:
# move dock widget in the same group as it used to be when perspective was saved
# this guarantee load/open perspectives will work smartly
MoveDockWidgetAction.move(widget, mgr)
# internally load perspectives from QSettings
widget.getManager().loadPerspectivesRec(self.__perspectives[name].settings)
# load perspective (update GUI)
widget.getManager().openPerspectiveRec(name)
# remove internal perspectives
widget.getManager().removePerspectives(widget.getManager().perspectiveNames())
self.openedPerspective().emit()
else:
assert False
def removePerspectives(self) -> None:
self.__perspectives.clear()
self.perspectivesListChanged.emit()
def removePerspective(self, name: str) -> None:
del self.__perspectives[name]
self.perspectivesListChanged.emit()
def getSettingsFileName(self, perspective: str, temp: bool) -> str:
name = "perspectives.ini" if not perspective else f"perspectives_{perspective + '.tmp' if temp else perspective + '.ini'}"
return os.path.join(self.__perspectives_folder, name)
def getSettingsObject(self, file_path: str) -> QSettings:
return QSettings(file_path, QSettings.IniFormat)
def loadPerspectives(self) -> None:
if self.__perspectives_folder:
tempfile.mktemp(dir=self.__perspectives_folder)
self.__perspectives.clear()
main_settings = self.getSettingsObject(self.getSettingsFileName("", False))
debug = main_settings.fileName()
size = main_settings.beginReadArray("Perspectives")
for i in range(0, size):
main_settings.setArrayIndex(i)
perspective = main_settings.value("Name")
if perspective:
to_load = self.getSettingsFileName(perspective, False)
loaded = self.getSettingsFileName(perspective, True)
try:
os.remove(loaded)
except FileNotFoundError:
pass
if not shutil.copy(to_load, loaded):
assert False
self.__perspectives[perspective] = PerspectiveInfo()
self.__perspectives[perspective].settings = self.getSettingsObject(loaded)
# load group info:
main_settings.beginGroup(GROUP_PREFIX)
for key in main_settings.allKeys():
self.__perspectives[perspective].groups[key] = main_settings.value(key)
main_settings.endGroup()
else:
assert False
main_settings.endArray()
self.perspectivesListChanged.emit()
def savePerspectives(self) -> None:
if self.__perspectives_folder:
main_settings = self.getSettingsObject(self.getSettingsFileName("", False))
# Save list of perspective and group organization
main_settings.beginWriteArray("Perspectives", len(self.__perspectives))
for i, perspective in enumerate(self.__perspectives.keys()):
main_settings.setArrayIndex(i)
main_settings.setValue("Name", perspective)
main_settings.beginGroup(GROUP_PREFIX)
for group in self.__perspectives[perspective].groups.keys():
main_settings.setValue(group, list(self.__perspectives[perspective].groups[group]))
main_settings.endGroup()
main_settings.endArray()
# Save perspectives themselves
for perspective_name in self.__perspectives.keys():
to_save = self.getSettingsFileName(perspective_name, False)
settings = self.__perspectives[perspective_name].settings
settings.sync()
try:
os.remove(to_save)
except FileNotFoundError:
pass
if not shutil.copy(settings.fileName(), to_save):
assert False

View File

@@ -1,28 +0,0 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_centralwidget VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(EmptyDockAreaExample WIN32
main.cpp
mainwindow.cpp
mainwindow.ui
)
target_include_directories(EmptyDockAreaExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(EmptyDockAreaExample PRIVATE qtadvanceddocking)
target_link_libraries(EmptyDockAreaExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(EmptyDockAreaExample PROPERTIES
AUTOMOC ON
AUTORCC ON
AUTOUIC ON
CXX_STANDARD 14
CXX_STANDARD_REQUIRED ON
CXX_EXTENSIONS OFF
VERSION ${VERSION_SHORT}
EXPORT_NAME "Qt Advanced Docking System Empty Dock Area Example"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
)

View File

@@ -1,34 +0,0 @@
ADS_OUT_ROOT = $${OUT_PWD}/../..
QT += core gui widgets
TARGET = EmptyDockareaExample
DESTDIR = $${ADS_OUT_ROOT}/lib
TEMPLATE = app
CONFIG += c++14
CONFIG += debug_and_release
adsBuildStatic {
DEFINES += ADS_STATIC
}
# The following define makes your compiler emit warnings if you use
# any Qt feature that has been marked deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
mainwindow.cpp
HEADERS += \
mainwindow.h
FORMS += \
mainwindow.ui
LIBS += -L$${ADS_OUT_ROOT}/lib
include(../../ads.pri)
INCLUDEPATH += ../../src
DEPENDPATH += ../../src

View File

@@ -1,10 +0,0 @@
#include <mainwindow.h>
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
CMainWindow w;
w.show();
return a.exec();
}

View File

@@ -1,108 +0,0 @@
import sys
import os
from PyQt5 import uic
from PyQt5.QtCore import Qt, QSignalBlocker
from PyQt5.QtWidgets import (QApplication, QMainWindow, QLabel, QComboBox, QTableWidget,
QAction, QWidgetAction, QSizePolicy, QInputDialog)
from PyQt5.QtGui import QCloseEvent
from PyQtAds import QtAds
UI_FILE = os.path.join(os.path.dirname(__file__), 'mainwindow.ui')
MainWindowUI, MainWindowBase = uic.loadUiType(UI_FILE)
class CMainWindow(MainWindowUI, MainWindowBase):
def __init__(self, parent=None):
super().__init__(parent)
self.setupUi(self)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.OpaqueSplitterResize, True)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.XmlCompressionEnabled, False)
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FocusHighlighting, True)
self.dock_manager = QtAds.CDockManager(self)
# Set central widget
label = QLabel()
label.setText("This is a DockArea which is always visible, even if it does not contain any DockWidgets.")
label.setAlignment(Qt.AlignCenter)
central_dock_widget = QtAds.CDockWidget("CentralWidget")
central_dock_widget.setWidget(label)
central_dock_widget.setFeature(QtAds.CDockWidget.NoTab, True)
central_dock_area = self.dock_manager.setCentralWidget(central_dock_widget)
# create other dock widgets
table = QTableWidget()
table.setColumnCount(3)
table.setRowCount(10)
table_dock_widget = QtAds.CDockWidget("Table 1")
table_dock_widget.setWidget(table)
table_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
table_dock_widget.resize(250, 150)
table_dock_widget.setMinimumSize(200,150)
self.dock_manager.addDockWidgetTabToArea(table_dock_widget, central_dock_area)
table_area = self.dock_manager.addDockWidget(QtAds.DockWidgetArea.LeftDockWidgetArea, table_dock_widget)
self.menuView.addAction(table_dock_widget.toggleViewAction())
table = QTableWidget()
table.setColumnCount(5)
table.setRowCount(1020)
table_dock_widget = QtAds.CDockWidget("Table 2")
table_dock_widget.setWidget(table)
table_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
table_dock_widget.resize(250, 150)
table_dock_widget.setMinimumSize(200,150)
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.BottomDockWidgetArea, table_dock_widget, table_area)
self.menuView.addAction(table_dock_widget.toggleViewAction())
properties_table = QTableWidget()
properties_table.setColumnCount(3)
properties_table.setRowCount(10)
properties_dock_widget = QtAds.CDockWidget("Properties")
properties_dock_widget.setWidget(properties_table)
properties_dock_widget.setMinimumSizeHintMode(QtAds.CDockWidget.MinimumSizeHintFromDockWidget)
properties_dock_widget.resize(250, 150)
properties_dock_widget.setMinimumSize(200,150)
self.dock_manager.addDockWidget(QtAds.DockWidgetArea.RightDockWidgetArea, properties_dock_widget, central_dock_area)
self.menuView.addAction(properties_dock_widget.toggleViewAction())
self.createPerspectiveUi()
def createPerspectiveUi(self):
save_perspective_action = QAction("Create Perspective", self)
save_perspective_action.triggered.connect(self.savePerspective)
perspective_list_action = QWidgetAction(self)
self.perspective_combo_box = QComboBox(self)
self.perspective_combo_box.setSizeAdjustPolicy(QComboBox.AdjustToContents)
self.perspective_combo_box.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
self.perspective_combo_box.activated[str].connect(self.dock_manager.openPerspective)
perspective_list_action.setDefaultWidget(self.perspective_combo_box)
self.toolBar.addSeparator()
self.toolBar.addAction(perspective_list_action)
self.toolBar.addAction(save_perspective_action)
def savePerspective(self):
perspective_name, ok = QInputDialog.getText(self, "Save Perspective", "Enter unique name:")
if not perspective_name or not ok:
return
self.dock_manager.addPerspective(perspective_name)
blocker = QSignalBlocker(self.perspective_combo_box)
self.perspective_combo_box.clear()
self.perspective_combo_box.addItems(self.dock_manager.perspectiveNames())
self.perspective_combo_box.setCurrentText(perspective_name)
def closeEvent(self, event: QCloseEvent):
# Delete dock manager here to delete all floating widgets. This ensures
# that all top level windows of the dock manager are properly closed
self.dock_manager.deleteLater()
super().closeEvent(event)
if __name__ == '__main__':
app = QApplication(sys.argv)
w = CMainWindow()
w.show()
app.exec_()

View File

@@ -1,135 +0,0 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QWidgetAction>
#include <QLabel>
#include <QCalendarWidget>
#include <QTreeView>
#include <QFileSystemModel>
#include <QTableWidget>
#include <QHBoxLayout>
#include <QRadioButton>
#include <QPushButton>
#include <QInputDialog>
#include <QFileDialog>
#include <QSettings>
#include <QMessageBox>
#include <QPlainTextEdit>
#include <QToolBar>
#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
#include "DockAreaTabBar.h"
#include "FloatingDockContainer.h"
#include "DockComponentsFactory.h"
using namespace ads;
CMainWindow::CMainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::CMainWindow)
{
ui->setupUi(this);
CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true);
CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false);
CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
DockManager = new CDockManager(this);
// Set central widget
QLabel* label = new QLabel();
label->setText("This is a DockArea which is always visible, even if it does not contain any DockWidgets.");
label->setAlignment(Qt::AlignCenter);
CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget");
CentralDockWidget->setWidget(label);
CentralDockWidget->setFeature(ads::CDockWidget::NoTab, true);
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
// create other dock widgets
QTableWidget* table = new QTableWidget();
table->setColumnCount(3);
table->setRowCount(10);
CDockWidget* TableDockWidget = new CDockWidget("Table 1");
TableDockWidget->setWidget(table);
TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
TableDockWidget->resize(250, 150);
TableDockWidget->setMinimumSize(200,150);
DockManager->addDockWidgetTabToArea(TableDockWidget, CentralDockArea);
auto TableArea = DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, TableDockWidget);
ui->menuView->addAction(TableDockWidget->toggleViewAction());
table = new QTableWidget();
table->setColumnCount(5);
table->setRowCount(1020);
TableDockWidget = new CDockWidget("Table 2");
TableDockWidget->setWidget(table);
TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
TableDockWidget->resize(250, 150);
TableDockWidget->setMinimumSize(200,150);
DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, TableArea);
ui->menuView->addAction(TableDockWidget->toggleViewAction());
QTableWidget* propertiesTable = new QTableWidget();
propertiesTable->setColumnCount(3);
propertiesTable->setRowCount(10);
CDockWidget* PropertiesDockWidget = new CDockWidget("Properties");
PropertiesDockWidget->setWidget(propertiesTable);
PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
PropertiesDockWidget->resize(250, 150);
PropertiesDockWidget->setMinimumSize(200,150);
DockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, PropertiesDockWidget, CentralDockArea);
ui->menuView->addAction(PropertiesDockWidget->toggleViewAction());
createPerspectiveUi();
}
CMainWindow::~CMainWindow()
{
delete ui;
}
void CMainWindow::createPerspectiveUi()
{
SavePerspectiveAction = new QAction("Create Perspective", this);
connect(SavePerspectiveAction, SIGNAL(triggered()), SLOT(savePerspective()));
PerspectiveListAction = new QWidgetAction(this);
PerspectiveComboBox = new QComboBox(this);
PerspectiveComboBox->setSizeAdjustPolicy(QComboBox::AdjustToContents);
PerspectiveComboBox->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
connect(PerspectiveComboBox, SIGNAL(activated(const QString&)),
DockManager, SLOT(openPerspective(const QString&)));
PerspectiveListAction->setDefaultWidget(PerspectiveComboBox);
ui->toolBar->addSeparator();
ui->toolBar->addAction(PerspectiveListAction);
ui->toolBar->addAction(SavePerspectiveAction);
}
void CMainWindow::savePerspective()
{
QString PerspectiveName = QInputDialog::getText(this, "Save Perspective", "Enter unique name:");
if (PerspectiveName.isEmpty())
{
return;
}
DockManager->addPerspective(PerspectiveName);
QSignalBlocker Blocker(PerspectiveComboBox);
PerspectiveComboBox->clear();
PerspectiveComboBox->addItems(DockManager->perspectiveNames());
PerspectiveComboBox->setCurrentText(PerspectiveName);
}
//============================================================================
void CMainWindow::closeEvent(QCloseEvent* event)
{
// Delete dock manager here to delete all floating widgets. This ensures
// that all top level windows of the dock manager are properly closed
DockManager->deleteLater();
QMainWindow::closeEvent(event);
}

View File

@@ -1,43 +0,0 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QComboBox>
#include <QWidgetAction>
#include "DockManager.h"
#include "DockAreaWidget.h"
#include "DockWidget.h"
QT_BEGIN_NAMESPACE
namespace Ui { class CMainWindow; }
QT_END_NAMESPACE
class CMainWindow : public QMainWindow
{
Q_OBJECT
public:
CMainWindow(QWidget *parent = nullptr);
~CMainWindow();
protected:
virtual void closeEvent(QCloseEvent* event) override;
private:
QAction* SavePerspectiveAction = nullptr;
QWidgetAction* PerspectiveListAction = nullptr;
QComboBox* PerspectiveComboBox = nullptr;
Ui::CMainWindow *ui;
ads::CDockManager* DockManager;
ads::CDockAreaWidget* StatusDockArea;
ads::CDockWidget* TimelineDockWidget;
void createPerspectiveUi();
private slots:
void savePerspective();
};
#endif // MAINWINDOW_H

View File

@@ -1,47 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CMainWindow</class>
<widget class="QMainWindow" name="CMainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1284</width>
<height>757</height>
</rect>
</property>
<property name="windowTitle">
<string>MainWindow</string>
</property>
<widget class="QWidget" name="centralwidget"/>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1284</width>
<height>21</height>
</rect>
</property>
<widget class="QMenu" name="menuView">
<property name="title">
<string>View</string>
</property>
</widget>
<addaction name="menuView"/>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
</widget>
</widget>
<resources/>
<connections/>
</ui>

View File

@@ -4,6 +4,4 @@ SUBDIRS = \
centralwidget \
simple \
sidebar \
deleteonclose \
emptydockarea \
dockindock
deleteonclose

View File

@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_sidebar VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(SidebarExample WIN32
main.cpp
@@ -10,9 +9,7 @@ add_executable(SidebarExample WIN32
)
target_include_directories(SidebarExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(SidebarExample PRIVATE qtadvanceddocking)
target_link_libraries(SidebarExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(SidebarExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
set_target_properties(SidebarExample PROPERTIES
AUTOMOC ON
AUTORCC ON

View File

@@ -1,7 +1,6 @@
cmake_minimum_required(VERSION 3.5)
project(ads_example_simple VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_executable(SimpleExample WIN32
main.cpp
@@ -10,9 +9,7 @@ add_executable(SimpleExample WIN32
)
target_include_directories(SimpleExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
target_link_libraries(SimpleExample PRIVATE qtadvanceddocking)
target_link_libraries(SimpleExample PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
target_link_libraries(SimpleExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
set_target_properties(SimpleExample PROPERTIES
AUTOMOC ON
AUTORCC ON

View File

@@ -227,7 +227,9 @@ class build_ext(sipdistutils.build_ext):
extension.extra_link_args += ['-F' + self.qtconfig.QT_INSTALL_LIBS,
'-mmacosx-version-min=10.9']
elif sys.platform == 'linux':
extension.extra_compile_args += ['-std=c++11']
extension.extra_compile_args += ['-D', 'QT_X11EXTRAS_LIB', '-std=c++11']
extension.include_dirs += [os.path.join(self.qt_include_dir, 'QtX11Extras')]
extension.libraries += ['Qt5X11Extras' + self.qt_libinfix]
return super().swig_sources(sources, extension)

View File

@@ -21,7 +21,6 @@ public:
void notifyWidgetOrAreaRelocation(QWidget* RelocatedWidget);
void notifyFloatingWidgetDrop(ads::CFloatingDockContainer* FloatingWidget);
ads::CDockWidget* focusedDockWidget() const;
void setDockWidgetTabFocused(ads::CDockWidgetTab* Tab);
public slots:
void setDockWidgetFocused(ads::CDockWidget* focusedNow);

View File

@@ -135,6 +135,7 @@ protected:
ads::CDockOverlay* dockAreaOverlay() const;
void notifyWidgetOrAreaRelocation(QWidget* RelocatedWidget);
void notifyFloatingWidgetDrop(ads::CFloatingDockContainer* FloatingWidget);
ads::CDockWidget* focusedDockWidget() const;
virtual void showEvent(QShowEvent *event);
@@ -216,9 +217,6 @@ public:
void setViewMenuInsertionOrder(ads::CDockManager::eViewMenuInsertionOrder Order);
bool isRestoringState() const;
static int startDragDistance();
ads::CDockWidget* focusedDockWidget() const;
QList<int> splitterSizes(ads::CDockAreaWidget *ContainedArea) const;
void setSplitterSizes(ads::CDockAreaWidget *ContainedArea, const QList<int>& sizes);
public slots:
void openPerspective(const QString& PerspectiveName);

View File

@@ -33,10 +33,8 @@ public:
CustomCloseHandling,
DockWidgetFocusable,
DockWidgetForceCloseWithArea,
NoTab,
DefaultDockWidgetFeatures,
AllDockWidgetFeatures,
DockWidgetAlwaysCloseAndDelete,
NoDockWidgetFeatures
};
typedef QFlags<ads::CDockWidget::DockWidgetFeature> DockWidgetFeatures;

View File

@@ -35,8 +35,6 @@ public:
virtual bool event(QEvent *e);
void setElideMode(Qt::TextElideMode mode);
void updateStyle();
QSize iconSize() const;
void setIconSize(const QSize& Size);
public slots:
virtual void setVisible(bool visible);

View File

@@ -1,138 +1,60 @@
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
%ModuleHeaderCode
PyObject *qtads_FindParent(PyObject* type, const QWidget *child);
%End
%ModuleCode
PyObject *qtads_FindParent(PyObject* type, const QWidget *w)
{
// Check that the types checking was successful.
if (!type)
return 0;
QWidget* parentWidget = w->parentWidget();
while (parentWidget)
{
PyObject *ParentImpl = sipConvertFromType(parentWidget, sipType_QObject, 0);
if (!ParentImpl)
{
return 0;
}
if (PyObject_IsInstance(ParentImpl, type))
return ParentImpl;
Py_DECREF(ParentImpl);
parentWidget = parentWidget->parentWidget();
}
Py_INCREF(Py_None);
return Py_None;
}
%End
namespace ads
{
%TypeHeaderCode
#include <ads_globals.h>
%End
enum DockWidgetArea
{
NoDockWidgetArea,
LeftDockWidgetArea,
RightDockWidgetArea,
TopDockWidgetArea,
BottomDockWidgetArea,
CenterDockWidgetArea,
InvalidDockWidgetArea,
OuterDockAreas,
AllDockAreas
};
typedef QFlags<ads::DockWidgetArea> DockWidgetAreas;
enum TitleBarButton
{
TitleBarButtonTabsMenu,
TitleBarButtonUndock,
TitleBarButtonClose
};
enum eDragState
{
DraggingInactive,
DraggingMousePressed,
DraggingTab,
DraggingFloatingWidget
};
enum eIcon
{
TabCloseIcon,
DockAreaMenuIcon,
DockAreaUndockIcon,
DockAreaCloseIcon,
IconCount,
};
enum eBitwiseOperator
{
BitwiseAnd,
BitwiseOr
};
namespace internal
{
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To);
void hideEmptyParentSplitters(ads::CDockSplitter* FirstParentSplitter);
class CDockInsertParam
{
%TypeHeaderCode
#include <ads_globals.h>
%End
public:
Qt::Orientation orientation() const;
bool append() const;
int insertOffset() const;
};
ads::internal::CDockInsertParam dockAreaInsertParameters(ads::DockWidgetArea Area);
SIP_PYOBJECT findParent(SIP_PYTYPE type, const QWidget *w) const /TypeHint="QObject"/;
%MethodCode
sipRes = qtads_FindParent(a0, a1);
if (!sipRes)
{
sipIsErr = 1;
}
%End
QPixmap createTransparentPixmap(const QPixmap& Source, qreal Opacity);
QPoint globalPositionOf(QMouseEvent* ev);
void setButtonIcon(QAbstractButton* Button, QStyle::StandardPixmap StandarPixmap, ads::eIcon CustomIconId);
enum eRepolishChildOptions
{
RepolishIgnoreChildren,
RepolishDirectChildren,
RepolishChildrenRecursively
};
void repolishStyle(QWidget* w, ads::internal::eRepolishChildOptions Options = ads::internal::RepolishIgnoreChildren);
};
};
%End
%Import QtWidgets/QtWidgetsmod.sip
%If (Qt_5_0_0 -)
namespace ads
{
%TypeHeaderCode
#include <ads_globals.h>
%End
enum DockWidgetArea
{
NoDockWidgetArea,
LeftDockWidgetArea,
RightDockWidgetArea,
TopDockWidgetArea,
BottomDockWidgetArea,
CenterDockWidgetArea,
InvalidDockWidgetArea,
OuterDockAreas,
AllDockAreas
};
typedef QFlags<ads::DockWidgetArea> DockWidgetAreas;
enum TitleBarButton
{
TitleBarButtonTabsMenu,
TitleBarButtonUndock,
TitleBarButtonClose
};
enum eDragState
{
DraggingInactive,
DraggingMousePressed,
DraggingTab,
DraggingFloatingWidget
};
enum eIcon
{
TabCloseIcon,
DockAreaMenuIcon,
DockAreaUndockIcon,
DockAreaCloseIcon,
IconCount,
};
enum eBitwiseOperator
{
BitwiseAnd,
BitwiseOr
};
};
%End

View File

@@ -1,9 +1,8 @@
cmake_minimum_required(VERSION 3.5)
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} 5.5 COMPONENTS Core Gui Widgets REQUIRED)
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
if (UNIX AND NOT APPLE)
include_directories(${Qt${QT_VERSION_MAJOR}Gui_PRIVATE_INCLUDE_DIRS})
find_package(Qt5 5.5 COMPONENTS X11Extras REQUIRED)
endif()
set(CMAKE_INCLUDE_CURRENT_DIR ON)
if(BUILD_STATIC)
@@ -61,10 +60,12 @@ else()
add_library(qtadvanceddocking SHARED ${ads_SRCS} ${ads_HEADERS})
target_compile_definitions(qtadvanceddocking PRIVATE ADS_SHARED_EXPORT)
endif()
target_link_libraries(qtadvanceddocking PUBLIC Qt${QT_VERSION_MAJOR}::Core
Qt${QT_VERSION_MAJOR}::Gui
Qt${QT_VERSION_MAJOR}::Widgets)
set_target_properties(qtadvanceddocking PROPERTIES
target_link_libraries(qtadvanceddocking PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
if(UNIX AND NOT APPLE)
target_link_libraries(qtadvanceddocking PUBLIC Qt5::X11Extras)
target_link_libraries(qtadvanceddocking PRIVATE xcb)
endif()
set_target_properties(qtadvanceddocking PROPERTIES
AUTOMOC ON
AUTORCC ON
CXX_STANDARD 14
@@ -83,13 +84,13 @@ write_basic_package_version_file(
COMPATIBILITY SameMajorVersion
)
install(FILES ${ads_HEADERS}
DESTINATION include
DESTINATION include
COMPONENT headers
)
install(FILES
install(FILES
"${CMAKE_SOURCE_DIR}/LICENSE"
"${CMAKE_SOURCE_DIR}/gnu-lgpl-v2.1.md"
DESTINATION license
DESTINATION license
COMPONENT license
)
install(TARGETS qtadvanceddocking

View File

@@ -180,11 +180,11 @@ void CDockAreaTabBar::setCurrentIndex(int index)
return;
}
Q_EMIT currentChanging(index);
emit currentChanging(index);
d->CurrentIndex = index;
d->updateTabs();
updateGeometry();
Q_EMIT currentChanged(index);
emit currentChanged(index);
}
@@ -206,7 +206,7 @@ void CDockAreaTabBar::insertTab(int Index, CDockWidgetTab* Tab)
connect(Tab, SIGNAL(moved(const QPoint&)), this, SLOT(onTabWidgetMoved(const QPoint&)));
connect(Tab, SIGNAL(elidedChanged(bool)), this, SIGNAL(elidedChanged(bool)));
Tab->installEventFilter(this);
Q_EMIT tabInserted(Index);
emit tabInserted(Index);
if (Index <= d->CurrentIndex)
{
setCurrentIndex(d->CurrentIndex + 1);
@@ -266,7 +266,7 @@ void CDockAreaTabBar::removeTab(CDockWidgetTab* Tab)
}
}
Q_EMIT removingTab(RemoveIndex);
emit removingTab(RemoveIndex);
d->TabsLayout->removeWidget(Tab);
Tab->disconnect(this);
Tab->removeEventFilter(this);
@@ -320,7 +320,7 @@ void CDockAreaTabBar::onTabClicked()
return;
}
setCurrentIndex(index);
Q_EMIT tabBarClicked(index);
emit tabBarClicked(index);
}
@@ -409,7 +409,7 @@ void CDockAreaTabBar::onTabWidgetMoved(const QPoint& GlobalPos)
d->TabsLayout->removeWidget(MovingTab);
d->TabsLayout->insertWidget(toIndex, MovingTab);
ADS_PRINT("tabMoved from " << fromIndex << " to " << toIndex);
Q_EMIT tabMoved(fromIndex, toIndex);
emit tabMoved(fromIndex, toIndex);
setCurrentIndex(toIndex);
}
else
@@ -432,7 +432,7 @@ void CDockAreaTabBar::closeTab(int Index)
{
return;
}
Q_EMIT tabCloseRequested(Index);
emit tabCloseRequested(Index);
}
@@ -449,12 +449,12 @@ bool CDockAreaTabBar::eventFilter(QObject *watched, QEvent *event)
switch (event->type())
{
case QEvent::Hide:
Q_EMIT tabClosed(d->TabsLayout->indexOf(Tab));
emit tabClosed(d->TabsLayout->indexOf(Tab));
updateGeometry();
break;
case QEvent::Show:
Q_EMIT tabOpened(d->TabsLayout->indexOf(Tab));
emit tabOpened(d->TabsLayout->indexOf(Tab));
updateGeometry();
break;

View File

@@ -58,7 +58,7 @@ private:
friend struct DockAreaTabBarPrivate;
friend class CDockAreaTitleBar;
private Q_SLOTS:
private slots:
void onTabClicked();
void onTabCloseRequested();
void onCloseOtherTabsRequested();
@@ -140,7 +140,7 @@ public:
*/
virtual QSize sizeHint() const override;
public Q_SLOTS:
public slots:
/**
* This property sets the index of the tab bar's visible tab
*/
@@ -152,7 +152,7 @@ public Q_SLOTS:
*/
void closeTab(int Index);
Q_SIGNALS:
signals:
/**
* This signal is emitted when the tab bar's current tab is about to be changed. The new
* current has the given index, or -1 if there isn't a new one.

View File

@@ -51,7 +51,6 @@
#include "DockAreaTabBar.h"
#include "IconProvider.h"
#include "DockComponentsFactory.h"
#include "DockFocusController.h"
#include <iostream>
@@ -383,7 +382,7 @@ void CDockAreaTitleBar::onTabsMenuActionTriggered(QAction* Action)
{
int Index = Action->data().toInt();
d->TabBar->setCurrentIndex(Index);
Q_EMIT tabBarClicked(Index);
emit tabBarClicked(Index);
}
@@ -472,8 +471,7 @@ void CDockAreaTitleBar::mousePressEvent(QMouseEvent* ev)
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
//d->TabBar->currentTab()->setFocus(Qt::OtherFocusReason);
d->dockManager()->dockFocusController()->setDockWidgetTabFocused(d->TabBar->currentTab());
d->TabBar->currentTab()->setFocus(Qt::OtherFocusReason);
}
return;
}

View File

@@ -54,7 +54,7 @@ private:
DockAreaTitleBarPrivate* d; ///< private data (pimpl)
friend struct DockAreaTitleBarPrivate;
private Q_SLOTS:
private slots:
void onTabsMenuAboutToShow();
void onCloseButtonClicked();
void onUndockButtonClicked();
@@ -88,7 +88,7 @@ protected:
*/
virtual void contextMenuEvent(QContextMenuEvent *event) override;
public Q_SLOTS:
public slots:
/**
* Call this slot to tell the title bar that it should update the tabs menu
* the next time it is shown.
@@ -148,7 +148,7 @@ public:
*/
int indexOf(QWidget *widget) const;
Q_SIGNALS:
signals:
/**
* This signal is emitted if a tab in the tab bar is clicked by the user
* or if the user clicks on a tab item in the title bar tab menu.

View File

@@ -378,7 +378,7 @@ CDockAreaWidget::CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget
d->ContentsLayout = new DockAreaLayout(d->Layout);
if (d->DockManager)
{
Q_EMIT d->DockManager->dockAreaCreated(this);
emit d->DockManager->dockAreaCreated(this);
}
}
@@ -604,11 +604,11 @@ void CDockAreaWidget::setCurrentIndex(int index)
return;
}
Q_EMIT currentChanging(index);
emit currentChanging(index);
TabBar->setCurrentIndex(index);
d->ContentsLayout->setCurrentIndex(index);
d->ContentsLayout->currentWidget()->show();
Q_EMIT currentChanged(index);
emit currentChanged(index);
}
@@ -808,49 +808,18 @@ CDockWidget* CDockAreaWidget::nextOpenDockWidget(CDockWidget* DockWidget) const
auto OpenDockWidgets = openedDockWidgets();
if (OpenDockWidgets.count() > 1 || (OpenDockWidgets.count() == 1 && OpenDockWidgets[0] != DockWidget))
{
CDockWidget* NextDockWidget;
if (OpenDockWidgets.last() == DockWidget)
{
CDockWidget* NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
// search backwards for widget with tab
for (int i = OpenDockWidgets.count() - 2; i >= 0; --i)
{
auto dw = OpenDockWidgets[i];
if (!dw->features().testFlag(CDockWidget::NoTab))
{
return dw;
}
}
// return widget without tab
return NextDockWidget;
NextDockWidget = OpenDockWidgets[OpenDockWidgets.count() - 2];
}
else
{
int IndexOfDockWidget = OpenDockWidgets.indexOf(DockWidget);
CDockWidget* NextDockWidget = OpenDockWidgets[IndexOfDockWidget + 1];
// search forwards for widget with tab
for (int i = IndexOfDockWidget + 1; i < OpenDockWidgets.count(); ++i)
{
auto dw = OpenDockWidgets[i];
if (!dw->features().testFlag(CDockWidget::NoTab))
{
return dw;
}
}
// search backwards for widget with tab
for (int i = IndexOfDockWidget - 1; i >= 0; --i)
{
auto dw = OpenDockWidgets[i];
if (!dw->features().testFlag(CDockWidget::NoTab))
{
return dw;
}
}
// return widget without tab
return NextDockWidget;
int NextIndex = OpenDockWidgets.indexOf(DockWidget) + 1;
NextDockWidget = OpenDockWidgets[NextIndex];
}
return NextDockWidget;
}
else
{
@@ -888,7 +857,7 @@ void CDockAreaWidget::toggleView(bool Open)
{
setVisible(Open);
Q_EMIT viewToggled(Open);
emit viewToggled(Open);
}
@@ -1030,21 +999,6 @@ void CDockAreaWidget::onDockWidgetFeaturesChanged()
}
#ifdef Q_OS_WIN
//============================================================================
bool CDockAreaWidget::event(QEvent *e)
{
switch (e->type())
{
case QEvent::PlatformSurface: return true;
default:
break;
}
return Super::event(e);
}
#endif
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -67,7 +67,7 @@ private:
friend class CDockManager;
void onDockWidgetFeaturesChanged();
private Q_SLOTS:
private slots:
void onTabCloseRequested(int Index);
/**
@@ -77,17 +77,6 @@ private Q_SLOTS:
void reorderDockWidget(int fromIndex, int toIndex);
protected:
#ifdef Q_OS_WIN
/**
* Reimplements QWidget::event to handle QEvent::PlatformSurface
* This is here to fix issue #294 Tab refresh problem with a QGLWidget
* that exists since Qt version 5.12.7. So this function is here to
* work around a Qt issue.
*/
virtual bool event(QEvent *event) override;
#endif
/**
* Inserts a dock widget into dock area.
* All dockwidgets in the dock area tabified in a stacked layout with tabs.
@@ -149,7 +138,7 @@ protected:
*/
void markTitleBarMenuOutdated();
protected Q_SLOTS:
protected slots:
void toggleView(bool Open);
public:
@@ -323,7 +312,7 @@ public:
*/
bool isCentralWidgetArea() const;
public Q_SLOTS:
public slots:
/**
* This activates the tab for the given tab index.
* If the dock widget for the given tab is not visible, the this function
@@ -341,7 +330,7 @@ public Q_SLOTS:
*/
void closeOtherAreas();
Q_SIGNALS:
signals:
/**
* This signal is emitted when user clicks on a tab at an index.
*/

View File

@@ -284,13 +284,13 @@ public:
void emitDockAreasRemoved()
{
onVisibleDockAreaCountChanged();
Q_EMIT _this->dockAreasRemoved();
emit _this->dockAreasRemoved();
}
void emitDockAreasAdded()
{
onVisibleDockAreaCountChanged();
Q_EMIT _this->dockAreasAdded();
emit _this->dockAreasAdded();
}
/**
@@ -341,7 +341,7 @@ public:
CDockAreaWidget* DockArea = qobject_cast<CDockAreaWidget*>(_this->sender());
VisibleDockAreaCount += Visible ? 1 : -1;
onVisibleDockAreaCountChanged();
Q_EMIT _this->dockAreaViewToggled(DockArea, Visible);
emit _this->dockAreaViewToggled(DockArea, Visible);
}
}; // struct DockContainerWidgetPrivate
@@ -1565,9 +1565,8 @@ void CDockContainerWidget::dropFloatingWidget(CFloatingDockContainer* FloatingWi
}
if (Dropped)
{
// Fix https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351
FloatingWidget->hideAndDeleteLater();
{
FloatingWidget->deleteLater();
// If we dropped a floating widget with only one single dock widget, then we
// drop a top level widget that changes from floating to docked now

View File

@@ -265,7 +265,7 @@ public:
*/
void closeOtherAreas(CDockAreaWidget* KeepOpenArea);
Q_SIGNALS:
signals:
/**
* This signal is emitted if one or multiple dock areas has been added to
* the internal list of dock areas.

View File

@@ -16,7 +16,6 @@
#include <QPointer>
#include <QApplication>
#include <QAbstractButton>
#include <QWindow>
#include "DockWidget.h"
#include "DockAreaWidget.h"
@@ -116,17 +115,6 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
return;
}
QWindow* Window = nullptr;
auto DockContainer = DockWidget->dockContainer();
if (DockContainer)
{
Window = DockContainer->window()->windowHandle();
}
if (Window)
{
Window->setProperty("FocusedDockWidget", QVariant::fromValue<CDockWidget*>(DockWidget));
}
CDockAreaWidget* NewFocusedDockArea = nullptr;
if (FocusedDockWidget)
{
@@ -151,14 +139,7 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
}
CFloatingDockContainer* NewFloatingWidget = nullptr;
DockContainer = FocusedDockWidget->dockContainer();
if (DockContainer)
{
NewFloatingWidget = DockContainer->floatingWidget();
}
auto NewFloatingWidget = FocusedDockWidget->dockContainer()->floatingWidget();
if (NewFloatingWidget)
{
NewFloatingWidget->setProperty("FocusedDockWidget", QVariant::fromValue(DockWidget));
@@ -168,19 +149,21 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
#ifdef Q_OS_LINUX
// This code is required for styling the floating widget titlebar for linux
// depending on the current focus state
if (FloatingWidget != NewFloatingWidget)
{
if (FloatingWidget)
{
updateFloatingWidgetFocusStyle(FloatingWidget, false);
}
FloatingWidget = NewFloatingWidget;
if (FloatingWidget == NewFloatingWidget)
{
return;
}
if (FloatingWidget)
{
updateFloatingWidgetFocusStyle(FloatingWidget, true);
}
}
if (FloatingWidget)
{
updateFloatingWidgetFocusStyle(FloatingWidget, false);
}
FloatingWidget = NewFloatingWidget;
if (FloatingWidget)
{
updateFloatingWidgetFocusStyle(FloatingWidget, true);
}
#endif
if (old == DockWidget && !ForceFocusChangedSignal)
@@ -191,7 +174,7 @@ void DockFocusControllerPrivate::updateDockWidgetFocus(CDockWidget* DockWidget)
ForceFocusChangedSignal = false;
if (DockWidget->isVisible())
{
Q_EMIT DockManager->focusedDockWidgetChanged(old, DockWidget);
emit DockManager->focusedDockWidgetChanged(old, DockWidget);
}
else
{
@@ -210,7 +193,7 @@ void CDockFocusController::onDockWidgetVisibilityChanged(bool Visible)
disconnect(Sender, SIGNAL(visibilityChanged(bool)), this, SLOT(onDockWidgetVisibilityChanged(bool)));
if (DockWidget && Visible)
{
Q_EMIT d->DockManager->focusedDockWidgetChanged(d->OldFocusedDockWidget, DockWidget);
emit d->DockManager->focusedDockWidgetChanged(d->OldFocusedDockWidget, DockWidget);
}
}
@@ -223,8 +206,6 @@ CDockFocusController::CDockFocusController(CDockManager* DockManager) :
d->DockManager = DockManager;
connect(QApplication::instance(), SIGNAL(focusChanged(QWidget*, QWidget*)),
this, SLOT(onApplicationFocusChanged(QWidget*, QWidget*)));
connect(QApplication::instance(), SIGNAL(focusWindowChanged(QWindow*)),
this, SLOT(onFocusWindowChanged(QWindow*)));
connect(d->DockManager, SIGNAL(stateRestored()), SLOT(onStateRestored()));
}
@@ -235,35 +216,9 @@ CDockFocusController::~CDockFocusController()
}
//============================================================================
void CDockFocusController::onFocusWindowChanged(QWindow *focusWindow)
{
if (!focusWindow)
{
return;
}
auto vDockWidget = focusWindow->property("FocusedDockWidget");
if (!vDockWidget.isValid())
{
return;
}
auto DockWidget = vDockWidget.value<CDockWidget*>();
if (!DockWidget)
{
return;
}
d->updateDockWidgetFocus(DockWidget);
}
//===========================================================================
void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidget* focusedNow)
{
Q_UNUSED(focusedOld);
if (d->DockManager->isRestoringState())
{
return;
@@ -276,7 +231,47 @@ void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidge
return;
}
CDockWidget* DockWidget = qobject_cast<CDockWidget*>(focusedNow);
// If the close button in another tab steals the focus from the current
// active dock widget content, i.e. if the user clicks its close button,
// then we immediately give the focus back to the previous focused widget
// focusedOld
if (CDockManager::testConfigFlag(CDockManager::AllTabsHaveCloseButton))
{
auto OtherDockWidgetTab = internal::findParent<CDockWidgetTab*>(focusedNow);
if (OtherDockWidgetTab && focusedOld)
{
auto OldFocusedDockWidget = internal::findParent<CDockWidget*>(focusedOld);
if (OldFocusedDockWidget)
{
focusedOld->setFocus();
}
return;
}
}
CDockWidget* DockWidget = nullptr;
auto DockWidgetTab = qobject_cast<CDockWidgetTab*>(focusedNow);
if (DockWidgetTab)
{
DockWidget = DockWidgetTab->dockWidget();
// If the DockWidgetTab "steals" the focus from a widget in the same
// DockWidget, then we immediately give the focus back to the previous
// focused widget focusedOld
if (focusedOld)
{
auto OldFocusedDockWidget = internal::findParent<CDockWidget*>(focusedOld);
if (OldFocusedDockWidget && OldFocusedDockWidget == DockWidget)
{
focusedOld->setFocus();
}
}
}
if (!DockWidget)
{
DockWidget = qobject_cast<CDockWidget*>(focusedNow);
}
if (!DockWidget)
{
DockWidget = internal::findParent<CDockWidget*>(focusedNow);
@@ -298,17 +293,6 @@ void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidge
}
//===========================================================================
void CDockFocusController::setDockWidgetTabFocused(CDockWidgetTab* Tab)
{
auto DockWidget = Tab->dockWidget();
if (DockWidget)
{
d->updateDockWidgetFocus(DockWidget);
}
}
//===========================================================================
void CDockFocusController::setDockWidgetFocused(CDockWidget* focusedNow)
{
@@ -336,7 +320,7 @@ void CDockFocusController::onFocusedDockAreaViewToggled(bool Open)
return;
}
d->updateDockWidgetFocus(OpenedDockAreas[0]->currentDockWidget());
CDockManager::setWidgetFocus(OpenedDockAreas[0]->currentDockWidget()->tabWidget());
}
@@ -364,7 +348,7 @@ void CDockFocusController::notifyWidgetOrAreaRelocation(QWidget* DroppedWidget)
}
d->ForceFocusChangedSignal = true;
CDockManager::setWidgetFocus(DockWidget);
CDockManager::setWidgetFocus(DockWidget->tabWidget());
}
@@ -385,8 +369,9 @@ void CDockFocusController::notifyFloatingWidgetDrop(CFloatingDockContainer* Floa
auto DockWidget = vDockWidget.value<CDockWidget*>();
if (DockWidget)
{
d->FocusedDockWidget = nullptr;
DockWidget->dockAreaWidget()->setCurrentDockWidget(DockWidget);
CDockManager::setWidgetFocus(DockWidget);
CDockManager::setWidgetFocus(DockWidget->tabWidget());
}
}

View File

@@ -30,9 +30,8 @@ private:
DockFocusControllerPrivate* d; ///< private data (pimpl)
friend struct DockFocusControllerPrivate;
private Q_SLOTS:
private slots:
void onApplicationFocusChanged(QWidget *old, QWidget *now);
void onFocusWindowChanged(QWindow *focusWindow);
void onFocusedDockAreaViewToggled(bool Open);
void onStateRestored();
void onDockWidgetVisibilityChanged(bool Visible);
@@ -49,6 +48,21 @@ public:
*/
virtual ~CDockFocusController();
/**
* Helper function to set focus depending on the configuration of the
* FocusStyling flag
*/
template <class QWidgetPtr>
static void setWidgetFocus(QWidgetPtr widget)
{
if (!CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
return;
}
widget->setFocus(Qt::OtherFocusReason);
}
/**
* A container needs to call this function if a widget has been dropped
* into it
@@ -69,13 +83,7 @@ public:
*/
CDockWidget* focusedDockWidget() const;
/**
* Request focus highlighting for the given dock widget assigned to the tab
* given in Tab parameter
*/
void setDockWidgetTabFocused(CDockWidgetTab* Tab);
public Q_SLOTS:
public slots:
/**
* Request a focus change to the given dock widget
*/

View File

@@ -343,7 +343,7 @@ void DockManagerPrivate::restoreDockWidgetsOpenState()
if (DockWidget->property(internal::DirtyProperty).toBool())
{
DockWidget->flagAsUnassigned();
Q_EMIT DockWidget->viewToggled(false);
emit DockWidget->viewToggled(false);
}
else
{
@@ -505,20 +505,6 @@ CDockManager::CDockManager(QWidget *parent) :
//============================================================================
CDockManager::~CDockManager()
{
// fix memory leaks, see https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/307
std::vector<ads::CDockAreaWidget*> areas;
for ( int i = 0; i != dockAreaCount(); ++i )
{
areas.push_back( dockArea(i) );
}
for ( auto area : areas )
{
for ( auto widget : area->dockWidgets() )
delete widget;
delete area;
}
auto FloatingWidgets = d->FloatingWidgets;
for (auto FloatingWidget : FloatingWidgets)
{
@@ -596,7 +582,7 @@ bool CDockManager::eventFilter(QObject *obj, QEvent *e)
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
{
d->FloatingWidgets.append(FloatingWidget);
Q_EMIT floatingWidgetCreated(FloatingWidget);
emit floatingWidgetCreated(FloatingWidget);
ADS_PRINT("d->FloatingWidgets.count() " << d->FloatingWidgets.count());
}
@@ -713,14 +699,14 @@ bool CDockManager::restoreState(const QByteArray &state, int version)
hide();
}
d->RestoringState = true;
Q_EMIT restoringState();
emit restoringState();
bool Result = d->restoreState(state, version);
d->RestoringState = false;
if (!IsHidden)
{
show();
}
Q_EMIT stateRestored();
emit stateRestored();
return Result;
}
@@ -746,7 +732,7 @@ CFloatingDockContainer* CDockManager::addDockWidgetFloating(CDockWidget* Dockwid
{
d->UninitializedFloatingWidgets.append(FloatingWidget);
}
Q_EMIT dockWidgetAdded(Dockwidget);
emit dockWidgetAdded(Dockwidget);
return FloatingWidget;
}
@@ -775,7 +761,7 @@ CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
auto Container = DockAreaWidget ? DockAreaWidget->dockContainer(): this;
auto AreaOfAddedDockWidget = Container->addDockWidget(area, Dockwidget, DockAreaWidget);
Q_EMIT dockWidgetAdded(Dockwidget);
emit dockWidgetAdded(Dockwidget);
return AreaOfAddedDockWidget;
}
@@ -817,11 +803,11 @@ CDockWidget* CDockManager::findDockWidget(const QString& ObjectName) const
//============================================================================
void CDockManager::removeDockWidget(CDockWidget* Dockwidget)
{
Q_EMIT dockWidgetAboutToBeRemoved(Dockwidget);
emit dockWidgetAboutToBeRemoved(Dockwidget);
d->DockWidgetsMap.remove(Dockwidget->objectName());
CDockContainerWidget::removeDockWidget(Dockwidget);
Dockwidget->setDockManager(nullptr);
Q_EMIT dockWidgetRemoved(Dockwidget);
emit dockWidgetRemoved(Dockwidget);
}
//============================================================================
@@ -835,7 +821,7 @@ QMap<QString, CDockWidget*> CDockManager::dockWidgetsMap() const
void CDockManager::addPerspective(const QString& UniquePrespectiveName)
{
d->Perspectives.insert(UniquePrespectiveName, saveState());
Q_EMIT perspectiveListChanged();
emit perspectiveListChanged();
}
@@ -857,8 +843,8 @@ void CDockManager::removePerspectives(const QStringList& Names)
if (Count)
{
Q_EMIT perspectivesRemoved();
Q_EMIT perspectiveListChanged();
emit perspectivesRemoved();
emit perspectiveListChanged();
}
}
@@ -879,9 +865,9 @@ void CDockManager::openPerspective(const QString& PerspectiveName)
return;
}
Q_EMIT openingPerspective(PerspectiveName);
emit openingPerspective(PerspectiveName);
restoreState(Iterator.value());
Q_EMIT perspectiveOpened(PerspectiveName);
emit perspectiveOpened(PerspectiveName);
}
@@ -926,8 +912,6 @@ void CDockManager::loadPerspectives(QSettings& Settings)
}
Settings.endArray();
Q_EMIT perspectiveListChanged();
Q_EMIT perspectiveListLoaded();
}
@@ -1140,13 +1124,6 @@ void CDockManager::setSplitterSizes(CDockAreaWidget *ContainedArea, const QList<
}
}
//===========================================================================
CDockFocusController* CDockManager::dockFocusController() const
{
return d->FocusController;
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -53,7 +53,6 @@ struct DockWidgetTabPrivate;
struct DockAreaWidgetPrivate;
class CIconProvider;
class CDockComponentsFactory;
class CDockFocusController;
/**
* The central dock manager that maintains the complete docking system.
@@ -135,18 +134,12 @@ protected:
*/
void notifyFloatingWidgetDrop(CFloatingDockContainer* FloatingWidget);
/**
* Show the floating widgets that has been created floating
*/
virtual void showEvent(QShowEvent *event) override;
/**
* Acces for the internal dock focus controller.
* This function only returns a valid object, if the FocusHighlighting
* flag is set.
*/
CDockFocusController* dockFocusController() const;
public:
using Super = CDockContainerWidget;
@@ -195,7 +188,6 @@ public:
FloatingContainerForceQWidgetTitleBar = 0x1000000,//!< Linux only ! Forces all FloatingContainer to use a QWidget based title bar.
//!< If neither this nor FloatingContainerForceNativeTitleBar is set (the default) native titlebars are used except on known bad systems.
//! Users can overwrite this by setting the environment variable ADS_UseNativeTitle to "1" or "0".
MiddleMouseButtonClosesTab = 0x2000000, //! If the flag is set, the user can use the mouse middle button to close the tab under the mouse
DefaultDockAreaButtons = DockAreaHasCloseButton
| DockAreaHasUndockButton
@@ -514,7 +506,7 @@ public:
*/
void setSplitterSizes(CDockAreaWidget *ContainedArea, const QList<int>& sizes);
public Q_SLOTS:
public slots:
/**
* Opens the perspective with the given name.
*/
@@ -527,19 +519,12 @@ public Q_SLOTS:
*/
void setDockWidgetFocused(CDockWidget* DockWidget);
Q_SIGNALS:
signals:
/**
* This signal is emitted if the list of perspectives changed.
* The list of perspectives changes if perspectives are added, removed
* or if the perspective list has been loaded
* This signal is emitted if the list of perspectives changed
*/
void perspectiveListChanged();
/**
* This signal is emitted if the perspective list has been loaded
*/
void perspectiveListLoaded();
/**
* This signal is emitted if perspectives have been removed
*/

View File

@@ -806,7 +806,7 @@ void CDockOverlayCross::setIconColors(const QString& Colors)
{"Arrow", CDockOverlayCross::ArrowColor},
{"Shadow", CDockOverlayCross::ShadowColor}};
#if (QT_VERSION < QT_VERSION_CHECK(5, 14, 0))
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
auto SkipEmptyParts = QString::SkipEmptyParts;
#else
auto SkipEmptyParts = Qt::SkipEmptyParts;

View File

@@ -66,12 +66,6 @@ namespace ads
*/
struct DockWidgetPrivate
{
struct WidgetFactory
{
CDockWidget::FactoryFunc createWidget;
CDockWidget::eInsertMode insertMode;
};
CDockWidget* _this = nullptr;
QBoxLayout* Layout = nullptr;
QWidget* Widget = nullptr;
@@ -90,8 +84,7 @@ struct DockWidgetPrivate
bool IsFloatingTopLevel = false;
QList<QAction*> TitleBarActions;
CDockWidget::eMinimumSizeHintMode MinimumSizeHintMode = CDockWidget::MinimumSizeHintFromDockWidget;
WidgetFactory* Factory = nullptr;
/**
* Private data constructor
*/
@@ -123,12 +116,6 @@ struct DockWidgetPrivate
* Setup the main scroll area
*/
void setupScrollArea();
/**
* Creates the content widget with the registered widget factory and
* returns true on success.
*/
bool createWidgetFromFactory();
};
// struct DockWidgetPrivate
@@ -143,23 +130,10 @@ DockWidgetPrivate::DockWidgetPrivate(CDockWidget* _public) :
//============================================================================
void DockWidgetPrivate::showDockWidget()
{
if (!Widget)
{
if (!createWidgetFromFactory())
{
Q_ASSERT(!Features.testFlag(CDockWidget::DeleteContentOnClose)
&& "DeleteContentOnClose flag was set, but the widget "
"factory is missing or it doesn't return a valid QWidget.");
return;
}
}
if (!DockArea)
{
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(_this);
// We use the size hint of the content widget to provide a good
// initial size
FloatingWidget->resize(Widget ? Widget->sizeHint() : _this->sizeHint());
FloatingWidget->resize(_this->size());
TabWidget->show();
FloatingWidget->show();
}
@@ -191,12 +165,6 @@ void DockWidgetPrivate::hideDockWidget()
{
TabWidget->hide();
updateParentDockArea();
if (Features.testFlag(CDockWidget::DeleteContentOnClose))
{
Widget->deleteLater();
Widget = nullptr;
}
}
@@ -250,30 +218,6 @@ void DockWidgetPrivate::setupScrollArea()
}
//============================================================================
bool DockWidgetPrivate::createWidgetFromFactory()
{
if (!Features.testFlag(CDockWidget::DeleteContentOnClose))
{
return false;
}
if (!Factory)
{
return false;
}
QWidget* w = Factory->createWidget(_this);
if (!w)
{
return false;
}
_this->setWidget(w, Factory->insertMode);
return true;
}
//============================================================================
CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
QFrame(parent),
@@ -344,17 +288,6 @@ void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
d->Widget->setProperty("dockWidgetContent", true);
}
//============================================================================
void CDockWidget::setWidgetFactory(FactoryFunc createWidget, eInsertMode insertMode)
{
if (d->Factory)
{
delete d->Factory;
}
d->Factory = new DockWidgetPrivate::WidgetFactory { createWidget, insertMode };
}
//============================================================================
QWidget* CDockWidget::takeWidget()
@@ -405,7 +338,7 @@ void CDockWidget::setFeatures(DockWidgetFeatures features)
return;
}
d->Features = features;
Q_EMIT featuresChanged(d->Features);
emit featuresChanged(d->Features);
d->TabWidget->onDockWidgetFeaturesChanged();
if(CDockAreaWidget* DockArea = dockAreaWidget())
DockArea->onDockWidgetFeaturesChanged();
@@ -597,8 +530,7 @@ void CDockWidget::toggleViewInternal(bool Open)
CDockWidget* TopLevelDockWidgetAfter = DockContainer
? DockContainer->topLevelDockWidget() : nullptr;
CDockWidget::emitTopLevelEventForWidget(TopLevelDockWidgetAfter, true);
CFloatingDockContainer* FloatingContainer = DockContainer
? DockContainer->floatingWidget() : nullptr;
CFloatingDockContainer* FloatingContainer = DockContainer->floatingWidget();
if (FloatingContainer)
{
FloatingContainer->updateWindowTitle();
@@ -606,9 +538,9 @@ void CDockWidget::toggleViewInternal(bool Open)
if (!Open)
{
Q_EMIT closed();
emit closed();
}
Q_EMIT viewToggled(Open);
emit viewToggled(Open);
}
@@ -648,11 +580,11 @@ bool CDockWidget::event(QEvent *e)
switch (e->type())
{
case QEvent::Hide:
Q_EMIT visibilityChanged(false);
emit visibilityChanged(false);
break;
case QEvent::Show:
Q_EMIT visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0);
emit visibilityChanged(geometry().right() >= 0 && geometry().bottom() >= 0);
break;
case QEvent::WindowTitleChange :
@@ -670,7 +602,7 @@ bool CDockWidget::event(QEvent *e)
{
d->DockArea->markTitleBarMenuOutdated();//update tabs menu
}
Q_EMIT titleChanged(title);
emit titleChanged(title);
}
break;
@@ -853,7 +785,7 @@ void CDockWidget::emitTopLevelChanged(bool Floating)
if (Floating != d->IsFloatingTopLevel)
{
d->IsFloatingTopLevel = Floating;
Q_EMIT topLevelChanged(d->IsFloatingTopLevel);
emit topLevelChanged(d->IsFloatingTopLevel);
}
}
@@ -911,7 +843,7 @@ bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
{
if (!ForceClose)
{
Q_EMIT closeRequested();
emit closeRequested();
}
if (!ForceClose && features().testFlag(CDockWidget::CustomCloseHandling))
@@ -937,7 +869,7 @@ bool CDockWidget::closeDockWidgetInternal(bool ForceClose)
}
}
deleteDockWidget();
Q_EMIT closed();
emit closed();
}
else
{

View File

@@ -58,7 +58,7 @@ private:
DockWidgetPrivate* d; ///< private data (pimpl)
friend struct DockWidgetPrivate;
private Q_SLOTS:
private slots:
/**
* Adjusts the toolbar icon sizes according to the floating state
*/
@@ -147,19 +147,17 @@ public:
enum DockWidgetFeature
{
DockWidgetClosable = 0x001,///< dock widget has a close button
DockWidgetMovable = 0x002,///< dock widget is movable and can be moved to a new position in the current dock container
DockWidgetFloatable = 0x004,///< dock widget can be dragged into a floating window
DockWidgetDeleteOnClose = 0x008, ///< deletes the dock widget when it is closed
CustomCloseHandling = 0x010, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead
DockWidgetFocusable = 0x020, ///< if this is enabled, a dock widget can get focus highlighting
DockWidgetForceCloseWithArea = 0x040, ///< dock widget will be closed when the dock area hosting it is closed
NoTab = 0x080, ///< dock widget tab will never be shown if this flag is set
DeleteContentOnClose = 0x100, ///< deletes only the contained widget on close, keeping the dock widget intact and in place. Attempts to rebuild the contents widget on show if there is a widget factory set.
DockWidgetClosable = 0x01,///< dock widget has a close button
DockWidgetMovable = 0x02,///< dock widget is movable and can be moved to a new position in the current dock container
DockWidgetFloatable = 0x04,///< dock widget can be dragged into a floating window
DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed
CustomCloseHandling = 0x10, ///< clicking the close button will not close the dock widget but emits the closeRequested() signal instead
DockWidgetFocusable = 0x20, ///< if this is enabled, a dock widget can get focus highlighting
DockWidgetForceCloseWithArea = 0x40, ///< dock widget will be closed when the dock area hosting it is closed
DefaultDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable | DockWidgetFocusable,
AllDockWidgetFeatures = DefaultDockWidgetFeatures | DockWidgetDeleteOnClose | CustomCloseHandling,
DockWidgetAlwaysCloseAndDelete = DockWidgetForceCloseWithArea | DockWidgetDeleteOnClose,
NoDockWidgetFeatures = 0x000
NoDockWidgetFeatures = 0x00
};
Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
@@ -255,7 +253,7 @@ public:
/**
* Sets the widget for the dock widget to widget.
* The InsertMode defines how the widget is inserted into the dock widget.
* The content of a dock widget should be resizable to a very small size to
* The content of a dock widget should be resizable do a very small size to
* prevent the dock widget from blocking the resizing. To ensure, that a
* dock widget can be resized very well, it is better to insert the content+
* widget into a scroll area or to provide a widget that is already a scroll
@@ -270,19 +268,7 @@ public:
* provide the InsertMode ForceNoScrollArea
*/
void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
/**
* Only used when the feature flag DeleteContentOnClose is set.
* Using the flag and setting a widget factory allows to free the resources
* of the widget of your application while retaining the position the next
* time you want to show your widget, unlike the flag DockWidgetDeleteOnClose
* which deletes the dock widget itself. Since we keep the dock widget, all
* regular features of ADS should work as normal, including saving and
* restoring the state of the docking system and using perspectives.
*/
using FactoryFunc = std::function<QWidget*(QWidget*)>;
void setWidgetFactory(FactoryFunc createWidget, eInsertMode InsertMode = AutoScrollArea);
/**
* Remove the widget from the dock and give ownership back to the caller
*/
@@ -497,7 +483,7 @@ public: // reimplements QFrame -----------------------------------------------
*/
virtual bool event(QEvent *e) override;
public Q_SLOTS:
public slots:
/**
* This property controls whether the dock widget is open or closed.
* The toogleViewAction triggers this slot
@@ -558,7 +544,7 @@ public Q_SLOTS:
void showNormal();
Q_SIGNALS:
signals:
/**
* This signal is emitted if the dock widget is opened or closed
*/

View File

@@ -50,7 +50,6 @@
#include "DockOverlay.h"
#include "DockManager.h"
#include "IconProvider.h"
#include "DockFocusController.h"
namespace ads
@@ -208,14 +207,6 @@ struct DockWidgetTabPrivate
IconLabel->setVisible(true);
}
/**
* Convenience function for access to the dock manager dock focus controller
*/
CDockFocusController* focusController() const
{
return DockWidget->dockManager()->dockFocusController();
}
};
// struct DockWidgetTabPrivate
@@ -243,7 +234,6 @@ void DockWidgetTabPrivate::createLayout()
CloseButton->setObjectName("tabCloseButton");
internal::setButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, TabCloseIcon);
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
CloseButton->setFocusPolicy(Qt::NoFocus);
updateCloseButtonSizePolicy();
internal::setToolTip(CloseButton, QObject::tr("Close Tab"));
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
@@ -341,11 +331,10 @@ CDockWidgetTab::CDockWidgetTab(CDockWidget* DockWidget, QWidget *parent) :
setAttribute(Qt::WA_NoMousePropagation, true);
d->DockWidget = DockWidget;
d->createLayout();
setFocusPolicy(Qt::NoFocus);
/*if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
setFocusPolicy(Qt::ClickFocus);
}*/
}
}
//============================================================================
@@ -364,11 +353,7 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
ev->accept();
d->saveDragStartMousePosition(internal::globalPositionOf(ev));
d->DragState = DraggingMousePressed;
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting))
{
d->focusController()->setDockWidgetTabFocused(this);
}
Q_EMIT clicked();
emit clicked();
return;
}
Super::mousePressEvent(ev);
@@ -392,30 +377,16 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
// End of tab moving, emit signal
if (d->DockArea)
{
ev->accept();
Q_EMIT moved(internal::globalPositionOf(ev));
emit moved(internal::globalPositionOf(ev));
}
break;
case DraggingFloatingWidget:
ev->accept();
d->FloatingWidget->finishDragging();
break;
default:; // do nothing
}
}
else if (ev->button() == Qt::MiddleButton)
{
if (CDockManager::testConfigFlag(CDockManager::MiddleMouseButtonClosesTab))
{
// Only attempt to close if the mouse is still
// on top of the widget, to allow the user to cancel.
if (rect().contains(mapFromGlobal(QCursor::pos()))) {
ev->accept();
Q_EMIT closeRequested();
}
}
}
Super::mouseReleaseEvent(ev);
@@ -544,8 +515,7 @@ void CDockWidgetTab::setActiveTab(bool active)
bool UpdateFocusStyle = false;
if (active && !hasFocus())
{
//setFocus(Qt::OtherFocusReason);
d->focusController()->setDockWidgetTabFocused(this);
setFocus(Qt::OtherFocusReason);
UpdateFocusStyle = true;
}
@@ -568,7 +538,7 @@ void CDockWidgetTab::setActiveTab(bool active)
update();
updateGeometry();
Q_EMIT activeTabChanged();
emit activeTabChanged();
}
@@ -642,18 +612,14 @@ QString CDockWidgetTab::text() const
//============================================================================
void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
// If this is the last dock area in a dock container it does not make
// sense to move it to a new floating widget and leave this one
// empty
if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
&& d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
{
// If this is the last dock area in a dock container it does not make
// sense to move it to a new floating widget and leave this one
// empty
if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
&& d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
{
event->accept();
d->saveDragStartMousePosition(internal::globalPositionOf(event));
d->startFloating(DraggingInactive);
}
d->saveDragStartMousePosition(internal::globalPositionOf(event));
d->startFloating(DraggingInactive);
}
Super::mouseDoubleClickEvent(event);
@@ -663,7 +629,7 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
//============================================================================
void CDockWidgetTab::setVisible(bool visible)
{
visible &= !d->DockWidget->features().testFlag(CDockWidget::NoTab);
// Just here for debugging to insert debug output
Super::setVisible(visible);
}
@@ -711,9 +677,6 @@ bool CDockWidgetTab::event(QEvent *e)
{
const auto text = toolTip();
d->TitleLabel->setToolTip(text);
if (d->IconLabel) {
d->IconLabel->setToolTip(text);
}
}
#endif
return Super::event(e);

View File

@@ -60,7 +60,7 @@ private:
friend class CDockManager;
void onDockWidgetFeaturesChanged();
private Q_SLOTS:
private slots:
void detachDockWidget();
protected:
@@ -175,10 +175,10 @@ public:
*/
void setIconSize(const QSize& Size);
public Q_SLOTS:
public slots:
virtual void setVisible(bool visible) override;
Q_SIGNALS:
signals:
void activeTabChanged();
void clicked();
void closeRequested();

View File

@@ -74,7 +74,7 @@ void ElidingLabelPrivate::elideText(int Width)
IsElided = str != Text;
if(IsElided != WasElided)
{
Q_EMIT _this->elidedChanged(IsElided);
emit _this->elidedChanged(IsElided);
}
_this->QLabel::setText(str);
}
@@ -136,7 +136,7 @@ void CElidingLabel::mouseReleaseEvent(QMouseEvent* event)
return;
}
Q_EMIT clicked();
emit clicked();
}
@@ -144,7 +144,7 @@ void CElidingLabel::mouseReleaseEvent(QMouseEvent* event)
void CElidingLabel::mouseDoubleClickEvent( QMouseEvent *ev )
{
Q_UNUSED(ev)
Q_EMIT doubleClicked();
emit doubleClicked();
Super::mouseDoubleClickEvent(ev);
}

View File

@@ -84,7 +84,7 @@ public: // reimplements QLabel ----------------------------------------------
void setText(const QString &text);
QString text() const;
Q_SIGNALS:
signals:
/**
* This signal is emitted if the user clicks on the label (i.e. pressed
* down then released while the mouse cursor is inside the label)

View File

@@ -373,7 +373,6 @@ struct FloatingDockContainerPrivate
CDockAreaWidget *SingleDockArea = nullptr;
QPoint DragStartPos;
bool Hiding = false;
bool AutoHideChildren = true;
#ifdef Q_OS_LINUX
QWidget* MouseEventHandler = nullptr;
CFloatingWidgetTitleBar* TitleBar = nullptr;
@@ -610,8 +609,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
#ifdef Q_OS_LINUX
QDockWidget::setWidget(d->DockContainer);
QDockWidget::setFloating(true);
QDockWidget::setFeatures(QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable);
QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
bool native_window = true;
@@ -842,18 +840,15 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event)
return;
}
if ( d->AutoHideChildren )
d->Hiding = true;
for (auto DockArea : d->DockContainer->openedDockAreas())
{
d->Hiding = true;
for ( auto DockArea : d->DockContainer->openedDockAreas() )
for (auto DockWidget : DockArea->openedDockWidgets())
{
for ( auto DockWidget : DockArea->openedDockWidgets() )
{
DockWidget->toggleView( false );
}
DockWidget->toggleView(false);
}
d->Hiding = false;
}
d->Hiding = false;
}
@@ -1039,18 +1034,6 @@ QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
return d->DockContainer->dockWidgets();
}
//============================================================================
void CFloatingDockContainer::hideAndDeleteLater()
{
// Widget has been redocked, so it must be hidden right way (see
// https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/351)
// but AutoHideChildren must be set to false because "this" still contains
// dock widgets that shall not be toggled hidden.
d->AutoHideChildren = false;
hide();
deleteLater();
}
//============================================================================
void CFloatingDockContainer::finishDragging()
{

View File

@@ -65,7 +65,7 @@ class CDockingStateReader;
* This interface is used for opaque and non-opaque undocking. If opaque
* undocking is used, the a real CFloatingDockContainer widget will be created
*/
class ADS_EXPORT IFloatingWidget
class IFloatingWidget
{
public:
virtual ~IFloatingWidget() = default;
@@ -118,7 +118,7 @@ private:
friend class CDockAreaWidget;
friend class CFloatingWidgetTitleBar;
private Q_SLOTS:
private slots:
void onDockAreasAddedOrRemoved();
void onDockAreaCurrentChanged(int Index);
@@ -258,11 +258,6 @@ public:
*/
QList<CDockWidget*> dockWidgets() const;
/**
* This function hides the floating bar instantely and delete it later.
*/
void hideAndDeleteLater();
#ifdef Q_OS_LINUX
/**
* This is a function that responds to FloatingWidgetTitleBar::maximizeRequest()

View File

@@ -60,7 +60,7 @@ struct FloatingDragPreviewPrivate
void cancelDragging()
{
Canceled = true;
Q_EMIT _this->draggingCanceled();
emit _this->draggingCanceled();
DockManager->containerOverlay()->hideOverlay();
DockManager->dockAreaOverlay()->hideOverlay();
_this->close();

View File

@@ -32,7 +32,7 @@ private:
FloatingDragPreviewPrivate* d;
friend struct FloatingDragPreviewPrivate;
private Q_SLOTS:
private slots:
/**
* Cancel non opaque undocking if application becomes inactive
*/
@@ -92,7 +92,7 @@ public: // implements IFloatingWidget -----------------------------------------
*/
virtual void finishDragging() override;
Q_SIGNALS:
signals:
/**
* This signal is emitted, if dragging has been canceled by escape key
* or by active application switching via task manager

View File

@@ -39,12 +39,14 @@
#include "ads_globals.h"
#ifdef Q_OS_LINUX
#include <QX11Info>
#include <QSettings>
#include <QFile>
#include <QApplication>
#include <qpa/qplatformnativeinterface.h>
#endif
#include <QApplication>
namespace ads
{
@@ -55,31 +57,10 @@ static QString _window_manager;
static QHash<QString, xcb_atom_t> _xcb_atom_cache;
//============================================================================
bool is_platform_x11()
{
return QGuiApplication::platformName() == QLatin1String("xcb");
}
//============================================================================
xcb_connection_t* x11_connection()
{
if (!qApp)
return nullptr;
QPlatformNativeInterface *native = qApp->platformNativeInterface();
if (!native)
return nullptr;
void *connection = native->nativeResourceForIntegration(QByteArray("connection"));
return reinterpret_cast<xcb_connection_t *>(connection);
}
//============================================================================
xcb_atom_t xcb_get_atom(const char *name)
{
if (!is_platform_x11())
if (!QX11Info::isPlatformX11())
{
return XCB_ATOM_NONE;
}
@@ -88,7 +69,7 @@ xcb_atom_t xcb_get_atom(const char *name)
{
return _xcb_atom_cache[key];
}
xcb_connection_t *connection = x11_connection();
xcb_connection_t *connection = QX11Info::connection();
xcb_intern_atom_cookie_t request = xcb_intern_atom(connection, 1, strlen(name), name);
xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(connection, request, NULL);
if (!reply)
@@ -112,7 +93,7 @@ xcb_atom_t xcb_get_atom(const char *name)
//============================================================================
void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2)
{
auto connection = x11_connection();
auto connection = QX11Info::connection();
xcb_atom_t type_atom = xcb_get_atom(type);
xcb_atom_t prop_atom = xcb_get_atom(prop);
xcb_client_message_event_t event;
@@ -137,11 +118,11 @@ void xcb_update_prop(bool set, WId window, const char *type, const char *prop, c
//============================================================================
xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type)
{
if (!is_platform_x11())
if (!QX11Info::isPlatformX11())
{
return nullptr;
}
xcb_connection_t *connection = x11_connection();
xcb_connection_t *connection = QX11Info::connection();
xcb_atom_t type_atom = xcb_get_atom(type);
if (type_atom == XCB_ATOM_NONE)
{
@@ -210,7 +191,7 @@ bool xcb_dump_props(WId window, const char *type)
QVector<xcb_atom_t> atoms;
xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM);
qDebug() << "\n\n!!!" << type << " - " << atoms.length();
xcb_connection_t *connection = x11_connection();
xcb_connection_t *connection = QX11Info::connection();
for (auto atom : atoms)
{
auto foo = xcb_get_atom_name(connection, atom);
@@ -225,7 +206,7 @@ bool xcb_dump_props(WId window, const char *type)
//============================================================================
void xcb_add_prop(bool state, WId window, const char *type, const char *prop)
{
if (!is_platform_x11())
if (!QX11Info::isPlatformX11())
{
return;
}
@@ -246,7 +227,7 @@ void xcb_add_prop(bool state, WId window, const char *type, const char *prop)
{
atoms.remove(index);
}
xcb_connection_t *connection = x11_connection();
xcb_connection_t *connection = QX11Info::connection();
xcb_change_property(connection, XCB_PROP_MODE_REPLACE, window, type_atom, XCB_ATOM_ATOM, 32, atoms.count(), atoms.constData());
xcb_flush(connection);
}
@@ -257,11 +238,11 @@ QString detectWindowManagerX11()
{
// Tries to detect the windowmanager via X11.
// See: https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#idm46018259946000
if (!is_platform_x11())
if (!QX11Info::isPlatformX11())
{
return "UNKNOWN";
}
xcb_connection_t *connection = x11_connection();
xcb_connection_t *connection = QX11Info::connection();
xcb_screen_t *first_screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
if(!first_screen)
{

View File

@@ -73,8 +73,8 @@ SOURCES += \
unix:!macx {
HEADERS += linux/FloatingWidgetTitleBar.h
SOURCES += linux/FloatingWidgetTitleBar.cpp
QT += x11extras
LIBS += -lxcb
QT += gui-private
}
isEmpty(PREFIX){