Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbdf3211d6 | ||
|
|
6ee97e64d7 | ||
|
|
a1c4812619 | ||
|
|
b0c8edbd82 | ||
|
|
a4190ecbf0 | ||
|
|
d8c6efaada | ||
|
|
0312682e07 | ||
|
|
8d14068df7 | ||
|
|
fe1d9a493f | ||
|
|
e55ad49db8 | ||
|
|
018ce2001e | ||
|
|
c8fe4c46dd | ||
|
|
1781fa671d | ||
|
|
75910e910e | ||
|
|
899e06be1c | ||
|
|
66687dc8b6 | ||
|
|
b8fe620276 | ||
|
|
1a50ea9892 | ||
|
|
0a096869fe | ||
|
|
44dc76bd19 | ||
|
|
aedbaec497 | ||
|
|
04aa622111 | ||
|
|
3564229482 | ||
|
|
637db7f4f9 | ||
|
|
f6d3d6d34a | ||
|
|
92369bdb26 | ||
|
|
8f95447108 | ||
|
|
0e3c3bab45 | ||
|
|
3a5c965306 | ||
|
|
0c88457037 | ||
|
|
46fa22dc6a | ||
|
|
f3d32399e5 | ||
|
|
b320bb17d1 | ||
|
|
81afe2d3cb | ||
|
|
5fad43377b | ||
|
|
f543318232 | ||
|
|
ab385a782a | ||
|
|
c370875128 | ||
|
|
1c261515db | ||
|
|
37cbae84ca | ||
|
|
f5759716b4 | ||
|
|
f645fe725a | ||
|
|
fdedd7d92a | ||
|
|
044a43d793 | ||
|
|
6846c96146 | ||
|
|
8fe9461872 | ||
|
|
fbde4edcd2 | ||
|
|
68742681f7 | ||
|
|
bbb3f99bc3 | ||
|
|
e0f6f3013f | ||
|
|
6eb497fb64 | ||
|
|
ae15757765 | ||
|
|
be294b4867 | ||
|
|
70738f7549 | ||
|
|
42dc529ce1 | ||
|
|
65058d3a48 | ||
|
|
48c4106b7f | ||
|
|
175b48569f | ||
|
|
89c6abb5ce | ||
|
|
55f23799bc | ||
|
|
646211cc4c | ||
|
|
423bab9954 | ||
|
|
831d90ebf5 | ||
|
|
abdc0dc0dd | ||
|
|
175c836c93 | ||
|
|
76304172ab | ||
|
|
0eb3978aee | ||
|
|
73f42d55ca | ||
|
|
059a055483 | ||
|
|
dcf1ee393e | ||
|
|
04aecb3693 | ||
|
|
533d174abc | ||
|
|
48fb999bd0 | ||
|
|
5443e5f998 | ||
|
|
543d226ba3 | ||
|
|
03b1848b43 | ||
|
|
05ab8d2067 | ||
|
|
c28a27c81c | ||
|
|
1b42048135 | ||
|
|
bfe6b9bd26 | ||
|
|
08a8cee1c6 | ||
|
|
835a532e75 | ||
|
|
d383ade03c | ||
|
|
6d9c4cee02 | ||
|
|
a565239c4a | ||
|
|
ba69f3e6b9 | ||
|
|
14c29f695c | ||
|
|
703a9b3e12 | ||
|
|
0eca1b0433 | ||
|
|
691c9683ce | ||
|
|
1a11e5ddcd | ||
|
|
a4d281dbb6 | ||
|
|
8361f90dce | ||
|
|
04b4ff8b4b | ||
|
|
121248c3c5 | ||
|
|
c44d0c87e3 | ||
|
|
c6cf9487ba | ||
|
|
c78cc17730 | ||
|
|
81a0234b05 | ||
|
|
f72a8568c5 | ||
|
|
11aec65967 | ||
|
|
40636d1e05 | ||
|
|
75841415a3 | ||
|
|
edc799bc54 | ||
|
|
1d0b20337f | ||
|
|
4a6d2d3514 | ||
|
|
8443414ae3 |
108
.appveyor.yml
@@ -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
|
||||
|
||||
1
.github/workflows/linux-builds.yml
vendored
@@ -16,6 +16,7 @@ jobs:
|
||||
run: |
|
||||
sudo apt-get update --fix-missing
|
||||
sudo apt-get install qt5-default
|
||||
sudo apt-get install libqt5x11extras5-dev
|
||||
- name: qmake
|
||||
run: qmake
|
||||
- name: make
|
||||
|
||||
1
.gitignore
vendored
@@ -382,3 +382,4 @@ MigrationBackup/
|
||||
FodyWeavers.xsd
|
||||
/ build
|
||||
/Settings.ini
|
||||
.vscode/settings.json
|
||||
|
||||
@@ -2,10 +2,13 @@
|
||||
<project>
|
||||
<configuration id="cdt.managedbuild.toolchain.gnu.mingw.base.1119687795" name="Default">
|
||||
<extension point="org.eclipse.cdt.core.LanguageSettingsProvider">
|
||||
<provider-reference id="org.eclipse.cdt.managedbuilder.core.GCCBuiltinSpecsDetectorMinGW" ref="shared-provider"/>
|
||||
<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 "${INPUTS}"" 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>
|
||||
|
||||
22
.travis.yml
@@ -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,7 +73,9 @@ matrix:
|
||||
services:
|
||||
- xvfb
|
||||
compiler: gcc
|
||||
addons:
|
||||
before_install:
|
||||
- sudo apt-get -y install libqt5x11extras5-dev
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
@@ -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
|
||||
|
||||
90
README.md
@@ -1,6 +1,6 @@
|
||||
# Advanced Docking System for Qt
|
||||
|
||||
[](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
||||
[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/actions?query=workflow%3Alinux-builds)
|
||||
[](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
|
||||
[](gnu-lgpl-v2.1.md)
|
||||
|
||||
@@ -15,6 +15,23 @@ integrated development environments (IDEs) such as Visual Studio.
|
||||
|
||||
## New and Noteworthy
|
||||
|
||||
The [release 3.7.0](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.7.0)
|
||||
adds support for Qt6.
|
||||
|
||||
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
|
||||
|
||||

|
||||
|
||||
- support for [native floating widgets](doc/user-guide.md#floatingcontainerforcenativetitlebar-linux-only) on Linux
|
||||
|
||||

|
||||
|
||||
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.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
|
||||
@@ -42,6 +59,7 @@ know it from Visual Studio.
|
||||
- [Supports deletion of dynamically created dock widgets](#supports-deletion-of-dynamically-created-dock-widgets)
|
||||
- [Python PyQt5 Bindings](#python-pyqt5-bindings)
|
||||
- [Tested Compatible Environments](#tested-compatible-environments)
|
||||
- [Supported Qt Versions](#supported-qt-versions)
|
||||
- [Windows](#windows)
|
||||
- [macOS](#macos)
|
||||
- [Linux](#linux)
|
||||
@@ -58,6 +76,8 @@ know it from Visual Studio.
|
||||
- [Qt Design Studio](#qt-design-studio)
|
||||
- [QmixElements](#qmixelements)
|
||||
- [ezEditor](#ezeditor)
|
||||
- [D-Tect X](#d-tect-x)
|
||||
- [HiveWE](#hivewe)
|
||||
|
||||
### Docking everywhere - no central widget
|
||||
|
||||
@@ -65,8 +85,8 @@ There is no central widget like in the Qt docking system. You can dock on every
|
||||
border of the main window or you can dock into each dock area - so you are
|
||||
free to dock almost everywhere.
|
||||
|
||||
\
|
||||
\
|
||||

|
||||
|
||||

|
||||
|
||||
### Docking inside floating windows
|
||||
@@ -74,8 +94,8 @@ free to dock almost everywhere.
|
||||
There is no difference between the main window and a floating window. Docking
|
||||
into floating windows is supported.
|
||||
|
||||
\
|
||||
\
|
||||

|
||||
|
||||

|
||||
|
||||
### Grouped dragging
|
||||
@@ -84,8 +104,8 @@ When dragging the titlebar of a dock, all the tabs that are tabbed with it are
|
||||
going to be dragged. So you can move complete groups of tabbed widgets into
|
||||
a floating widget or from one dock area to another one.
|
||||
|
||||
\
|
||||
\
|
||||

|
||||
|
||||

|
||||
|
||||
### Perspectives for fast switching of the complete main window layout
|
||||
@@ -96,13 +116,13 @@ perspective to make your own custom perspective. Later you can simply
|
||||
select a perspective from the perspective list to quickly switch the complete
|
||||
main window layout.
|
||||
|
||||
\
|
||||
\
|
||||

|
||||
|
||||

|
||||
|
||||
### Opaque and non-opaque splitter resizing
|
||||
|
||||
The advanced docking system uses standard QSplitters as resize separators and thus supports opaque and non-opaque resizing functionality of QSplitter. In some rare cases, for very complex widgets or on slow machines resizing via separator on the fly may cause flicking and glaring of rendered content inside a widget. The global dock manager flag `OpaqueSplitterResize` configures the resizing behaviour of the splitters. If this flag is set, then widgets are resized dynamically (opaquely) while interactively moving the splitters.
|
||||
The advanced docking system uses standard QSplitters as resize separators and thus supports opaque and non-opaque resizing functionality of QSplitter. In some rare cases, for very complex widgets or on slow machines resizing via separator on the fly may cause flicking and glaring of rendered content inside a widget. The global dock manager flag `OpaqueSplitterResize` configures the resizing behaviour of the splitters. If this flag is set, then widgets are resized dynamically (opaquely) while interactively moving the splitters.
|
||||
|
||||

|
||||
|
||||
@@ -151,10 +171,14 @@ by the following people:
|
||||
- [Hugo Slepicka](https://github.com/hhslepicka)
|
||||
- [K Lauer](https://github.com/klauer)
|
||||
|
||||
Latest working version: [3.5.1](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.5.1)
|
||||
Latest working version: [3.5.2](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/releases/tag/3.5.2)
|
||||
|
||||
## Tested Compatible Environments
|
||||
|
||||
### Supported Qt Versions
|
||||
|
||||
The library supports **Qt5** and **Qt6**.
|
||||
|
||||
### Windows
|
||||
|
||||
Windows 10 [](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
|
||||
@@ -171,15 +195,23 @@ The application can be compiled for macOS. A user reported, that the library wor
|
||||
|
||||
### Linux
|
||||
|
||||
Ubuntu [](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
||||
[](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
|
||||
[](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/actions?query=workflow%3Alinux-builds)
|
||||
|
||||
The application can be compiled for Linux and has been developed and tested with **Kubuntu 18.04** and **Kubuntu 19.10**.
|
||||
Unfortunately, there is no such thing as a Linux operating system. Linux is a heterogeneous environment with a variety of different distributions. So it is not possible to support "Linux" like this is possible for Windows. It is only possible to support and test a small subset of Linux distributions. The library can be compiled for and has been developed and tested with the following Linux distributions:
|
||||
|
||||
- **Kubuntu 18.04 and 19.10**
|
||||
- **Ubuntu 18.04, 19.10 and 20.04**
|
||||
|
||||
There are some requirements for the Linux distribution that have to be met:
|
||||
|
||||
- an X server that supports ARGB visuals and a compositing window manager. This is required to display the translucent dock overlays ([https://doc.qt.io/qt-5/qwidget.html#creating-translucent-windows](https://doc.qt.io/qt-5/qwidget.html#creating-translucent-windows)). If your Linux distribution does not support this, or if you disable this feature, you will very likely see issue [#95](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/95).
|
||||
- Wayland is not properly supported by Qt yet. If you use Wayland, then you should set the session type to x11: `XDG_SESSION_TYPE=x11 ./AdvancedDockingSystemDemo`. You will find more details about this in issue [#288](https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System/issues/288).
|
||||
|
||||
Screenshot Kubuntu:
|
||||

|
||||
|
||||
and with **Ubuntu 19.10**
|
||||
|
||||
Screenshot Ubuntu:
|
||||

|
||||
|
||||
## Build
|
||||
@@ -311,7 +343,7 @@ If this project help you reduce time to develop or if you just like it, you can
|
||||
From version 4.12 on, Qt Creator uses the Advanced Docking Framework for its
|
||||
Qt Quick Designer. This improves the usability when using multiple screens.
|
||||
|
||||

|
||||

|
||||
|
||||
### [Qt Design Studio](https://www.qt.io/ui-design-tools)
|
||||
|
||||
@@ -319,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.
|
||||
|
||||

|
||||

|
||||
|
||||
### [QmixElements](https://www.cetoni.com/products/qmixelements/)
|
||||
|
||||
@@ -327,7 +359,7 @@ The QmixElements software from [CETONI](https://www.cetoni.com) is a comprehensi
|
||||
plugin-based and modular laboratory automation software for controlling CETONI devices using a joint graphical user interface. The software features a powerful script system to automate processes. This [blog post](https://www.cetoni.com/blog/qmixelements-advanced-docking-system/) gives a nice overview about the use of the Qt
|
||||
Advanced Docking System in the QmixElements sofware.
|
||||
|
||||

|
||||

|
||||
|
||||
### [ezEditor](https://github.com/ezEngine/ezEngine)
|
||||
|
||||
@@ -335,4 +367,24 @@ The ezEditor is a full blown graphical editor used for editing scenes and
|
||||
importing and authoring assets for the [ezEngine](https://github.com/ezEngine/ezEngine) -
|
||||
an open source C++ game engine in active development.
|
||||
|
||||

|
||||

|
||||
|
||||
### [D-Tect X](https://www.duerr-ndt.com/products/ndt-software/d-tect-xray-inspection-software.html)
|
||||
|
||||
D-Tect X is a X-ray inspection software for industrial radiography. It is a state-of-the-art 64-bit application which supports GPU (Graphics Processing Unit) acceleration and takes full advantage of computers with multiple CPU cores. A large set of tools assist the user in image analysis and evaluation. Thanks to the Qt Advanced Docking System the flexible and intuitive user interface can be completely customized to each user’s preference.
|
||||
|
||||
[learn more...](https://www.duerr-ndt.com/products/ndt-software/d-tect-xray-inspection-software.html)
|
||||
|
||||

|
||||
|
||||
### [HiveWE](https://github.com/stijnherfst/HiveWE)
|
||||
|
||||
HiveWE is a Warcraft III world editor. It focusses on speed and ease of use,
|
||||
especially for large maps where the regular World Editor is often too slow and clunky.
|
||||
It has a JASS editor with syntax hightlighting, tabs, code completion and more.
|
||||
The JASS editor uses the Qt Advanced Docking System for the management and layout
|
||||
of the open editor windows.
|
||||
|
||||
[learn more...](https://github.com/stijnherfst/HiveWE)
|
||||
|
||||

|
||||
|
||||
28
ads.pri
Normal file
@@ -0,0 +1,28 @@
|
||||
|
||||
lessThan(QT_MAJOR_VERSION, 6) {
|
||||
CONFIG(debug, debug|release){
|
||||
win32 {
|
||||
LIBS += -lqtadvanceddockingd
|
||||
}
|
||||
else:mac {
|
||||
LIBS += -lqtadvanceddocking_debug
|
||||
}
|
||||
else {
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
}
|
||||
else{
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
}
|
||||
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
|
||||
}
|
||||
@@ -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")
|
||||
@@ -58,11 +58,15 @@
|
||||
#include <QMessageBox>
|
||||
#include <QMenu>
|
||||
#include <QToolButton>
|
||||
#include <QToolBar>
|
||||
#include <QPointer>
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
#include <QAxWidget>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <QMap>
|
||||
#include <QElapsedTimer>
|
||||
@@ -109,7 +113,7 @@ static void appendFeaturStringToWindowTitle(ads::CDockWidget* DockWidget)
|
||||
static QIcon svgIcon(const QString& File)
|
||||
{
|
||||
// This is a workaround, because in item views SVG icons are not
|
||||
// properly scaled an look blurry or pixelate
|
||||
// properly scaled and look blurry or pixelate
|
||||
QIcon SvgIcon(File);
|
||||
SvgIcon.addPixmap(SvgIcon.pixmap(92));
|
||||
return SvgIcon;
|
||||
@@ -166,6 +170,8 @@ struct MainWindowPrivate
|
||||
QComboBox* PerspectiveComboBox = nullptr;
|
||||
ads::CDockManager* DockManager = nullptr;
|
||||
ads::CDockWidget* WindowTitleTestDockWidget = nullptr;
|
||||
QPointer<ads::CDockWidget> LastDockedEditor;
|
||||
QPointer<ads::CDockWidget> LastCreatedFloatingEditor;
|
||||
|
||||
MainWindowPrivate(CMainWindow* _public) : _this(_public) {}
|
||||
|
||||
@@ -352,6 +358,7 @@ struct MainWindowPrivate
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
/**
|
||||
* Creates an ActiveX widget on windows
|
||||
*/
|
||||
@@ -365,6 +372,7 @@ struct MainWindowPrivate
|
||||
return DockWidget;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
@@ -399,6 +407,9 @@ void MainWindowPrivate::createContent()
|
||||
// Test custom factory - we inject a help button into the title bar
|
||||
ads::CDockComponentsFactory::setFactory(new CCustomComponentsFactory());
|
||||
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
|
||||
// Uncomment the next line if you would like to test the
|
||||
// HideSingleWidgetTitleBar functionality
|
||||
// TopDockArea->setDockAreaFlag(ads::CDockAreaWidget::HideSingleWidgetTitleBar, true);
|
||||
ads::CDockComponentsFactory::resetDefaultFactory();
|
||||
|
||||
// We create a calendar widget and clear all flags to prevent the dock area
|
||||
@@ -440,10 +451,12 @@ void MainWindowPrivate::createContent()
|
||||
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))
|
||||
{
|
||||
DockManager->addDockWidget(ads::CenterDockWidgetArea, createActiveXWidget(), RighDockArea);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
for (auto DockWidget : DockManager->dockWidgetsMap())
|
||||
@@ -604,8 +617,13 @@ CMainWindow::CMainWindow(QWidget *parent) :
|
||||
// Now create the dock manager and its content
|
||||
d->DockManager = new CDockManager(this);
|
||||
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
connect(d->PerspectiveComboBox, SIGNAL(activated(const QString&)),
|
||||
d->DockManager, SLOT(openPerspective(const QString&)));
|
||||
#else
|
||||
connect(d->PerspectiveComboBox, SIGNAL(textActivated(const QString&)),
|
||||
d->DockManager, SLOT(openPerspective(const QString&)));
|
||||
#endif
|
||||
|
||||
d->createContent();
|
||||
// Default window geometry - center on screen
|
||||
@@ -631,6 +649,9 @@ CMainWindow::~CMainWindow()
|
||||
void CMainWindow::closeEvent(QCloseEvent* event)
|
||||
{
|
||||
d->saveState();
|
||||
// Delete dock manager here to delete all floating widgets. This ensures
|
||||
// that all top level windows of the dock manager are properly closed
|
||||
d->DockManager->deleteLater();
|
||||
QMainWindow::closeEvent(event);
|
||||
}
|
||||
|
||||
@@ -705,16 +726,39 @@ void CMainWindow::createEditor()
|
||||
bool Floating = vFloating.isValid() ? vFloating.toBool() : true;
|
||||
auto DockWidget = d->createEditorWidget();
|
||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetDeleteOnClose, true);
|
||||
DockWidget->setFeature(ads::CDockWidget::DockWidgetForceCloseWithArea, true);
|
||||
connect(DockWidget, SIGNAL(closeRequested()), SLOT(onEditorCloseRequested()));
|
||||
|
||||
if (Floating)
|
||||
{
|
||||
auto FloatingWidget = d->DockManager->addDockWidgetFloating(DockWidget);
|
||||
FloatingWidget->move(QPoint(20, 20));
|
||||
d->LastCreatedFloatingEditor = DockWidget;
|
||||
d->LastDockedEditor.clear();
|
||||
}
|
||||
else
|
||||
{
|
||||
d->DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
|
||||
ads::CDockAreaWidget* EditorArea = d->LastDockedEditor ? d->LastDockedEditor->dockAreaWidget() : nullptr;
|
||||
if (EditorArea)
|
||||
{
|
||||
std::cout << "DockAreaCount before: " << EditorArea->dockContainer()->dockAreaCount() << std::endl;
|
||||
d->DockManager->setConfigFlag(ads::CDockManager::EqualSplitOnInsertion, true);
|
||||
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
|
||||
std::cout << "DockAreaCount after: " << DockWidget->dockContainer()->dockAreaCount() << std::endl;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (d->LastCreatedFloatingEditor)
|
||||
{
|
||||
std::cout << "LastCreated" << std::endl;
|
||||
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, d->LastCreatedFloatingEditor->dockAreaWidget());
|
||||
}
|
||||
else
|
||||
{
|
||||
d->DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
|
||||
}
|
||||
}
|
||||
d->LastDockedEditor = DockWidget;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4,8 +4,12 @@ TARGET = AdvancedDockingSystemDemo
|
||||
DESTDIR = $${ADS_OUT_ROOT}/lib
|
||||
QT += core gui widgets
|
||||
|
||||
win32 {
|
||||
QT += axcontainer
|
||||
include(../ads.pri)
|
||||
|
||||
lessThan(QT_MAJOR_VERSION, 6) {
|
||||
win32 {
|
||||
QT += axcontainer
|
||||
}
|
||||
}
|
||||
|
||||
CONFIG += c++14
|
||||
@@ -34,21 +38,6 @@ RESOURCES += demo.qrc
|
||||
|
||||
LIBS += -L$${ADS_OUT_ROOT}/lib
|
||||
|
||||
# Dependency: AdvancedDockingSystem (shared)
|
||||
CONFIG(debug, debug|release){
|
||||
win32 {
|
||||
LIBS += -lqtadvanceddockingd
|
||||
}
|
||||
else:mac {
|
||||
LIBS += -lqtadvanceddocking_debug
|
||||
}
|
||||
else {
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
}
|
||||
else{
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
|
||||
INCLUDEPATH += ../src
|
||||
DEPENDPATH += ../src
|
||||
|
||||
28
demo/demo.py
@@ -65,7 +65,7 @@ def append_feature_string_to_window_title(dock_widget: QtAds.CDockWidget):
|
||||
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 an look blurry or pixelate
|
||||
# properly scaled and look blurry or pixelate
|
||||
icon = QIcon(filename)
|
||||
icon.addPixmap(icon.pixmap(92))
|
||||
return icon
|
||||
@@ -104,6 +104,8 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
self.perspective_list_action = None
|
||||
self.perspective_combo_box = None
|
||||
self.dock_manager = None
|
||||
self.window_title_test_dock_widget = None
|
||||
self.last_docked_editor = None
|
||||
|
||||
self.setupUi(self)
|
||||
self.create_actions()
|
||||
@@ -184,6 +186,7 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
# special_dock_area.setAllowedAreas(QtAds.LeftDockWidgetArea | QtAds.RightDockWidgetArea) # just for testing
|
||||
|
||||
dock_widget = self.create_long_text_label_dock_widget()
|
||||
self.window_title_test_dock_widget = dock_widget
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetFocusable, False)
|
||||
self.dock_manager.addDockWidget(QtAds.LeftDockWidgetArea, dock_widget)
|
||||
file_system_widget = self.create_file_system_tree_dock_widget()
|
||||
@@ -202,6 +205,9 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
# Test custom factory - we inject a help button into the title bar
|
||||
QtAds.CDockComponentsFactory.setFactory(CCustomComponentsFactory())
|
||||
top_dock_area = self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, file_system_widget)
|
||||
# Uncomment the next line if you would like to test the
|
||||
# HideSingleWidgetTitleBar functionality
|
||||
# top_dock_area.setDockAreaFlag(QtAds.CDockAreaWidget.HideSingleWidgetTitleBar, True)
|
||||
QtAds.CDockComponentsFactory.resetDefaultFactory()
|
||||
|
||||
# We create a calendar widget and clear all flags to prevent the dock area
|
||||
@@ -310,6 +316,7 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
|
||||
def closeEvent(self, event: QCloseEvent):
|
||||
self.save_state()
|
||||
self.dock_manager.deleteLater()
|
||||
super().closeEvent(event)
|
||||
|
||||
def on_actionSaveState_triggered(self, state: bool):
|
||||
@@ -350,7 +357,6 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
def create_editor(self):
|
||||
sender = self.sender()
|
||||
floating = sender.property("Floating")
|
||||
print("Floating:", floating)
|
||||
dock_widget = self.create_editor_widget()
|
||||
dock_widget.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
|
||||
dock_widget.closeRequested.connect(self.on_editor_close_requested)
|
||||
@@ -359,7 +365,13 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
floating_widget = self.dock_manager.addDockWidgetFloating(dock_widget)
|
||||
floating_widget.move(QPoint(20, 20))
|
||||
else:
|
||||
self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, dock_widget)
|
||||
editor_area = self.last_docked_editor.dockAreaWidget() if self.last_docked_editor is not None else None
|
||||
if editor_area is not None:
|
||||
self.dock_manager.setConfigFlag(QtAds.CDockManager.EqualSplitOnInsertion, True)
|
||||
self.dock_manager.addDockWidget(QtAds.RightDockWidgetArea, dock_widget, editor_area)
|
||||
else:
|
||||
self.dock_manager.addDockWidget(QtAds.TopDockWidgetArea, dock_widget)
|
||||
self.last_docked_editor = dock_widget
|
||||
|
||||
def on_editor_close_requested(self):
|
||||
dock_widget = self.sender()
|
||||
@@ -378,6 +390,16 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
dialog = CStatusDialog(self.dock_manager)
|
||||
dialog.exec_()
|
||||
|
||||
|
||||
def toggle_dock_widget_window_title(self):
|
||||
title = self.window_title_test_dock_widget.windowTitle()
|
||||
i = title.find(" (Test) ")
|
||||
if i == -1:
|
||||
title += " (Test) "
|
||||
else:
|
||||
title = title[i]
|
||||
self.window_title_test_dock_widget.setWindowTitle(title)
|
||||
|
||||
def save_state(self):
|
||||
'''
|
||||
Saves the dock manager state and the main window geometry
|
||||
|
||||
@@ -35,9 +35,11 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#if QT_VERSION >= 0x050600
|
||||
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
#endif
|
||||
#endif
|
||||
std::shared_ptr<int> b;
|
||||
QApplication a(argc, argv);
|
||||
|
||||
BIN
doc/central_widget.gif
Normal file
|
After Width: | Height: | Size: 572 KiB |
BIN
doc/cfg_flag_EqualSplitOnInsertion_false.png
Normal file
|
After Width: | Height: | Size: 5.2 KiB |
BIN
doc/cfg_flag_EqualSplitOnInsertion_true.png
Normal file
|
After Width: | Height: | Size: 5.1 KiB |
BIN
doc/cfg_flag_FloatingContainerForceNativeTitleBar_false.png
Normal file
|
After Width: | Height: | Size: 9.4 KiB |
BIN
doc/cfg_flag_FloatingContainerForceNativeTitleBar_true.png
Normal file
|
After Width: | Height: | Size: 9.3 KiB |
BIN
doc/showcase_d-tect-x.jpg
Normal file
|
After Width: | Height: | Size: 97 KiB |
|
Before Width: | Height: | Size: 385 KiB After Width: | Height: | Size: 385 KiB |
BIN
doc/showcase_hivewe.png
Normal file
|
After Width: | Height: | Size: 208 KiB |
|
Before Width: | Height: | Size: 539 KiB After Width: | Height: | Size: 539 KiB |
|
Before Width: | Height: | Size: 157 KiB After Width: | Height: | Size: 157 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
@@ -24,6 +24,11 @@
|
||||
- [`FloatingContainerHasWidgetIcon`](#floatingcontainerhaswidgeticon)
|
||||
- [`HideSingleCentralWidgetTitleBar`](#hidesinglecentralwidgettitlebar)
|
||||
- [`FocusHighlighting`](#focushighlighting)
|
||||
- [`EqualSplitOnInsertion`](#equalsplitoninsertion)
|
||||
- [`FloatingContainerForceNativeTitleBar` (Linux only)](#floatingcontainerforcenativetitlebar-linux-only)
|
||||
- [`FloatingContainerForceQWidgetTitleBar` (Linux only)](#floatingcontainerforceqwidgettitlebar-linux-only)
|
||||
- [Central Widget](#central-widget)
|
||||
- [Custom Close Handling](#custom-close-handling)
|
||||
- [Styling](#styling)
|
||||
- [Disabling the Internal Style Sheet](#disabling-the-internal-style-sheet)
|
||||
|
||||
@@ -409,6 +414,98 @@ bool CMainWindow::eventFilter(QObject *watched, QEvent *event)
|
||||
}
|
||||
```
|
||||
|
||||
### `EqualSplitOnInsertion`
|
||||
|
||||
This flag configures how the space is distributed if a new dock widget is
|
||||
inserted into an existing dock area. The flag is disabled by default. If 3
|
||||
dock widgets are inserted with the following code
|
||||
|
||||
```c++
|
||||
d->DockManager->addDockWidget(ads::RightDockWidgetArea, DockWidget, EditorArea);
|
||||
```
|
||||
|
||||
then this is the result, if the flag is disabled:
|
||||
|
||||

|
||||
|
||||
If the flag is enabled, then the space is equally distributed to all widgets
|
||||
in a splitter:
|
||||
|
||||

|
||||
|
||||
|
||||
### `FloatingContainerForceNativeTitleBar` (Linux only)
|
||||
|
||||
Since release 3.6 the library supports native title bars and window decorations
|
||||
for floating widgets on Linux (thanks to a user contribution).
|
||||
Native title bars and window decorations are supported by most Linux window
|
||||
managers, such as Compiz or Xfwm. Some window managers like KWin do not properly
|
||||
support this feature. Native floating widgets look better because of the native
|
||||
styling and the support all window manager features like snapping to window
|
||||
borders or maximizing. The library tries to detect the window manager during
|
||||
runtime and activates native window decorations if possible:
|
||||
|
||||

|
||||
|
||||
If you would like to overwrite this autodetection, then you can activate this
|
||||
flag to force native window titlebars. You can overwrite autodetection and this
|
||||
flag, if you set the environment variable `ADS_UseNativeTitle` to 0 or 1.
|
||||
|
||||
### `FloatingContainerForceQWidgetTitleBar` (Linux only)
|
||||
|
||||
If your window manager (i.e. KWin) does not properly support native floating
|
||||
windows, the docking library falls back to QWidget based floating widget
|
||||
title bars.
|
||||
|
||||

|
||||
|
||||
If you would like to overwrite autodetection, then you can activate this flag
|
||||
to force QWidget based title bars. You can overwrite autodetection and this
|
||||
flag, if you set the environment variable `ADS_UseNativeTitle` to 0 or 1.
|
||||
|
||||
## Central Widget
|
||||
|
||||
The Advanced Docking System has been developed to overcome the limitations of
|
||||
the native Qt docking system with its central widget concept. This was the
|
||||
reason that until version 3.6 of the library, there was no support for such
|
||||
thing like a central widget. Thanks to the contribution of a user the library
|
||||
now supports a central widget.
|
||||
|
||||
In the Advanced Docking System a central widget is a docking widget that is
|
||||
neither closable nor movable or floatable. A central widget has no title bar
|
||||
and so it is not possible for the user to hide, close or drag the central
|
||||
widget. If there is a central widget, then also the distribution of the sizes
|
||||
for the dock widgets around the central widget is different:
|
||||
|
||||
- **no central widget (default)** - on resizing the available space is
|
||||
distributed to all dock widgets - the size of all dock widgets
|
||||
shrinks or grows
|
||||
- **with central widget** - on resizing only the central widget is resized - the
|
||||
dock widgets around the central widget keep their size (see the animation below)
|
||||
|
||||

|
||||
|
||||
To set a central widget, you just need to pass your central dock widget
|
||||
to the dock manager `setCentralWidget` function:
|
||||
|
||||
```c++
|
||||
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
|
||||
```
|
||||
|
||||
See the `centralwidget` example to learn how it works.
|
||||
|
||||
> ##### Note
|
||||
> The central widget needs to be the first dock widget that is added to the
|
||||
> dock manager. The function does not work and returns a `nullptr` if there
|
||||
> are already other dock widgets registered. So `setCentralWidget` should be
|
||||
> the first function that you call when adding dock widgets.
|
||||
|
||||
## 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.
|
||||
|
||||
When an entire area is closed, the default behavior is to hide the dock widgets it contains regardless of the `DockWidgetDeleteOnClose` flag except if there is only one dock widget. In this special case, the `DockWidgetDeleteOnClose` flag is followed. This behavior can be changed by setting the `DockWidgetForceCloseWithArea` flag to all the dock widgets that needs to be closed with their area.
|
||||
|
||||
## Styling
|
||||
|
||||
The Advanced Docking System supports styling via [Qt Style Sheets](https://doc.qt.io/qt-5/stylesheet.html). All components like splitters, tabs, buttons, titlebar and
|
||||
|
||||
@@ -2,4 +2,5 @@ cmake_minimum_required(VERSION 3.5)
|
||||
project(QtADSExamples LANGUAGES CXX VERSION ${VERSION_SHORT})
|
||||
add_subdirectory(simple)
|
||||
add_subdirectory(sidebar)
|
||||
add_subdirectory(deleteonclose)
|
||||
add_subdirectory(deleteonclose)
|
||||
add_subdirectory(centralwidget)
|
||||
25
examples/centralwidget/CMakeLists.txt
Normal file
@@ -0,0 +1,25 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(ads_example_centralwidget VERSION ${VERSION_SHORT})
|
||||
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
add_executable(CentralWidgetExample WIN32
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
mainwindow.ui
|
||||
)
|
||||
target_include_directories(CentralWidgetExample PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../../src")
|
||||
target_link_libraries(CentralWidgetExample PRIVATE qtadvanceddocking)
|
||||
target_link_libraries(CentralWidgetExample PUBLIC Qt5::Core Qt5::Gui Qt5::Widgets)
|
||||
set_target_properties(CentralWidgetExample 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 Central Widget 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"
|
||||
)
|
||||
115
examples/centralwidget/centralWidget.py
Normal file
@@ -0,0 +1,115 @@
|
||||
import os
|
||||
import sys
|
||||
|
||||
from PyQt5 import uic
|
||||
from PyQt5.QtCore import Qt, QTimer, QDir, QSignalBlocker
|
||||
from PyQt5.QtGui import QCloseEvent, QIcon
|
||||
from PyQt5.QtWidgets import (QApplication, QLabel, QCalendarWidget, QFrame, QTreeView,
|
||||
QTableWidget, QFileSystemModel, QPlainTextEdit, QToolBar,
|
||||
QWidgetAction, QComboBox, QAction, QSizePolicy, QInputDialog)
|
||||
|
||||
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):
|
||||
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
|
||||
text_edit = QPlainTextEdit()
|
||||
text_edit.setPlaceholderText("This is the central editor. Enter your text here.")
|
||||
central_dock_widget = QtAds.CDockWidget("CentralWidget")
|
||||
central_dock_widget.setWidget(text_edit)
|
||||
central_dock_area = self.dock_manager.setCentralWidget(central_dock_widget)
|
||||
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")
|
||||
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, file_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.create_perspective_ui()
|
||||
|
||||
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)
|
||||
self.perspective_combobox.setSizeAdjustPolicy(QComboBox.AdjustToContents)
|
||||
self.perspective_combobox.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Preferred)
|
||||
self.perspective_combobox.activated[str].connect(self.dock_manager.openPerspective)
|
||||
perspective_list_action.setDefaultWidget(self.perspective_combobox)
|
||||
self.toolBar.addSeparator()
|
||||
self.toolBar.addAction(perspective_list_action)
|
||||
self.toolBar.addAction(save_perspective_action)
|
||||
|
||||
def save_perspective(self):
|
||||
perspective_name, ok = QInputDialog.getText(self, "Save Perspective", "Enter Unique name:")
|
||||
if not ok or not perspective_name:
|
||||
return
|
||||
|
||||
self.dock_manager.addPerspective(perspective_name)
|
||||
blocker = QSignalBlocker(self.perspective_combobox)
|
||||
self.perspective_combobox.clear()
|
||||
self.perspective_combobox.addItems(self.dock_manager.perspectiveNames())
|
||||
self.perspective_combobox.setCurrentText(perspective_name)
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
|
||||
w = MainWindow()
|
||||
w.show()
|
||||
app.exec_()
|
||||
34
examples/centralwidget/centralwidget.pro
Normal file
@@ -0,0 +1,34 @@
|
||||
ADS_OUT_ROOT = $${OUT_PWD}/../..
|
||||
|
||||
QT += core gui widgets
|
||||
|
||||
TARGET = CentralWidgetExample
|
||||
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
|
||||
|
||||
10
examples/centralwidget/main.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include <mainwindow.h>
|
||||
#include <QApplication>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
CMainWindow w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
||||
134
examples/centralwidget/mainwindow.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#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
|
||||
QPlainTextEdit* w = new QPlainTextEdit();
|
||||
w->setPlaceholderText("This is the central editor. Enter your text here.");
|
||||
CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget");
|
||||
CentralDockWidget->setWidget(w);
|
||||
auto* CentralDockArea = DockManager->setCentralWidget(CentralDockWidget);
|
||||
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");
|
||||
TableDockWidget->setWidget(table);
|
||||
TableDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
|
||||
TableDockWidget->resize(250, 150);
|
||||
TableDockWidget->setMinimumSize(200,150);
|
||||
DockManager->addDockWidget(DockWidgetArea::BottomDockWidgetArea, TableDockWidget, fileArea);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
43
examples/centralwidget/mainwindow.h
Normal file
@@ -0,0 +1,43 @@
|
||||
#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
|
||||
47
examples/centralwidget/mainwindow.ui
Normal file
@@ -0,0 +1,47 @@
|
||||
<?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>
|
||||
@@ -17,23 +17,7 @@ SOURCES += main.cpp
|
||||
|
||||
|
||||
LIBS += -L$${ADS_OUT_ROOT}/lib
|
||||
|
||||
# Dependency: AdvancedDockingSystem (shared)
|
||||
CONFIG(debug, debug|release){
|
||||
win32 {
|
||||
LIBS += -lqtadvanceddockingd
|
||||
}
|
||||
else:mac {
|
||||
LIBS += -lqtadvanceddocking_debug
|
||||
}
|
||||
else {
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
}
|
||||
else{
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
|
||||
include(../../ads.pri)
|
||||
INCLUDEPATH += ../../src
|
||||
DEPENDPATH += ../../src
|
||||
|
||||
|
||||
73
examples/deleteonclose/deleteonclose.py
Normal file
@@ -0,0 +1,73 @@
|
||||
import sys
|
||||
|
||||
from PyQtAds import QtAds
|
||||
from PyQt5.QtGui import QCloseEvent
|
||||
from PyQt5.QtCore import (qDebug, pyqtSlot, QObject, pyqtSignal)
|
||||
from PyQt5.QtWidgets import (QMainWindow, QAction, QTextEdit, QApplication,
|
||||
QMenuBar)
|
||||
|
||||
|
||||
class MainWindow(QMainWindow):
|
||||
dock_manager = None
|
||||
|
||||
def closeEvent(self, event: QCloseEvent):
|
||||
super().closeEvent(event)
|
||||
if self.dock_manager is not None:
|
||||
self.dock_manager.deleteLater()
|
||||
|
||||
def setDockManager(self, dock_manager: QtAds.CDockManager):
|
||||
self.dock_manager = dock_manager
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
app = QApplication(sys.argv)
|
||||
w = MainWindow()
|
||||
|
||||
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.FocusHighlighting, True)
|
||||
QtAds.CDockManager.setConfigFlag(QtAds.CDockManager.AllTabsHaveCloseButton, True)
|
||||
dock_manager = QtAds.CDockManager(w)
|
||||
w.setDockManager(dock_manager)
|
||||
|
||||
count = 0
|
||||
|
||||
def on_focused_dock_widget_changed(old: QtAds.CDockWidget, now: QtAds.CDockWidget):
|
||||
global count
|
||||
qDebug( "{:d} CDockManager::focusedDockWidgetChanged old: {} now: {} visible: {}".format(
|
||||
count,
|
||||
old.objectName() if old else "-",
|
||||
now.objectName(),
|
||||
now.isVisible()))
|
||||
count += 1
|
||||
now.widget().setFocus()
|
||||
|
||||
dock_manager.focusedDockWidgetChanged.connect(on_focused_dock_widget_changed)
|
||||
|
||||
action = QAction("New Delete On Close", w)
|
||||
w.menuBar().addAction(action)
|
||||
|
||||
i = 0
|
||||
def on_action_triggered():
|
||||
global i
|
||||
dw = QtAds.CDockWidget("test doc {:d}".format(i))
|
||||
i += 1
|
||||
editor = QTextEdit("lorem ipsum...", dw)
|
||||
dw.setWidget(editor)
|
||||
dw.setFeature(QtAds.CDockWidget.DockWidgetDeleteOnClose, True)
|
||||
area = dock_manager.addDockWidgetTab(QtAds.CenterDockWidgetArea, dw)
|
||||
qDebug("doc dock widget created! {} {}".format(dw, area))
|
||||
action.triggered.connect(on_action_triggered)
|
||||
|
||||
action = QAction("New", w)
|
||||
w.menuBar().addAction(action)
|
||||
def on_action2_triggered():
|
||||
global i
|
||||
dw = QtAds.CDockWidget("test {:d}".format(i))
|
||||
i += 1
|
||||
editor = QTextEdit("lorem ipsum...", dw)
|
||||
dw.setWidget(editor)
|
||||
area = dock_manager.addDockWidgetTab(QtAds.CenterDockWidgetArea, dw)
|
||||
qDebug("dock widget created! {} {}".format(dw, area))
|
||||
action.triggered.connect(on_action2_triggered)
|
||||
|
||||
w.show()
|
||||
app.exec_()
|
||||
@@ -5,14 +5,36 @@
|
||||
#include <QMenuBar>
|
||||
#include "DockManager.h"
|
||||
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
private:
|
||||
ads::CDockManager* m_DockManager = nullptr;
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *event) override
|
||||
{
|
||||
QMainWindow::closeEvent(event);
|
||||
if (m_DockManager)
|
||||
{
|
||||
m_DockManager->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
void setDockManager(ads::CDockManager* DockManager) {m_DockManager = DockManager;}
|
||||
};
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QApplication a(argc, argv);
|
||||
QMainWindow w;
|
||||
MainWindow w;
|
||||
|
||||
ads::CDockManager::setConfigFlag(ads::CDockManager::FocusHighlighting, true);
|
||||
ads::CDockManager::setConfigFlag(ads::CDockManager::AllTabsHaveCloseButton, true);
|
||||
auto dockManager = new ads::CDockManager(&w);
|
||||
w.setDockManager(dockManager);
|
||||
QObject::connect(dockManager, &ads::CDockManager::focusedDockWidgetChanged, [] (ads::CDockWidget* old, ads::CDockWidget* now) {
|
||||
static int Count = 0;
|
||||
qDebug() << Count++ << " CDockManager::focusedDockWidgetChanged old: " << (old ? old->objectName() : "-") << " now: " << now->objectName() << " visible: " << now->isVisible();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
TEMPLATE = subdirs
|
||||
|
||||
SUBDIRS = \
|
||||
centralwidget \
|
||||
simple \
|
||||
sidebar \
|
||||
deleteonclose
|
||||
|
||||
@@ -51,3 +51,13 @@ MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
void MainWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
QMainWindow::closeEvent(event);
|
||||
if (m_DockManager)
|
||||
{
|
||||
m_DockManager->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,9 @@ public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
|
||||
protected:
|
||||
virtual void closeEvent(QCloseEvent *event) override;
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
ads::CDockManager* m_DockManager;
|
||||
|
||||
@@ -25,23 +25,7 @@ FORMS += \
|
||||
|
||||
|
||||
LIBS += -L$${ADS_OUT_ROOT}/lib
|
||||
|
||||
# Dependency: AdvancedDockingSystem (shared)
|
||||
CONFIG(debug, debug|release){
|
||||
win32 {
|
||||
LIBS += -lqtadvanceddockingd
|
||||
}
|
||||
else:mac {
|
||||
LIBS += -lqtadvanceddocking_debug
|
||||
}
|
||||
else {
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
}
|
||||
else{
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
|
||||
include(../../ads.pri)
|
||||
INCLUDEPATH += ../../src
|
||||
DEPENDPATH += ../../src
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
/*ui->setupUi(this);
|
||||
ui->setupUi(this);
|
||||
|
||||
// Create the dock manager. Because the parent parameter is a QMainWindow
|
||||
// the dock manager registers itself as the central widget.
|
||||
@@ -32,70 +32,11 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
ui->menuView->addAction(DockWidget->toggleViewAction());
|
||||
|
||||
// Add the dock widget to the top dock widget area
|
||||
m_DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);*/
|
||||
|
||||
ui->setupUi(this);
|
||||
|
||||
// Create the dock manager. Because the parent parameter is a QMainWindow
|
||||
// the dock manager registers itself as the central widget.
|
||||
m_DockManager1 = new ads::CDockManager(this);
|
||||
|
||||
// Create example content label - this can be any application specific
|
||||
// widget
|
||||
ads::CDockWidget* DockWidget;
|
||||
{
|
||||
QLabel* l = new QLabel();
|
||||
l->setWordWrap(true);
|
||||
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
|
||||
|
||||
// Create a dock widget with the title Label 1 and set the created label
|
||||
// as the dock widget content
|
||||
DockWidget = new ads::CDockWidget("Label 1");
|
||||
DockWidget->setWidget(l);
|
||||
}
|
||||
|
||||
ads::CDockWidget* DockWidget2;
|
||||
{
|
||||
QLabel* l = new QLabel();
|
||||
l->setWordWrap(true);
|
||||
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
|
||||
|
||||
// Create a dock widget with the title Label 1 and set the created label
|
||||
// as the dock widget content
|
||||
DockWidget2 = new ads::CDockWidget("Label 2");
|
||||
DockWidget2->setWidget(l);
|
||||
}
|
||||
|
||||
|
||||
// Add the toggleViewAction of the dock widget to the menu to give
|
||||
// the user the possibility to show the dock widget if it has been closed
|
||||
ui->menuView->addAction(DockWidget->toggleViewAction());
|
||||
|
||||
// Add the dock widget to the top dock widget area
|
||||
m_DockManager1->addDockWidget(ads::TopDockWidgetArea, DockWidget);
|
||||
|
||||
|
||||
auto funcRemoveFirstManager = [=]()
|
||||
{
|
||||
m_DockManager1->removeDockWidget(DockWidget);
|
||||
|
||||
delete m_DockManager1;
|
||||
m_DockManager1 = nullptr;
|
||||
};
|
||||
QTimer::singleShot(3000, funcRemoveFirstManager);
|
||||
|
||||
auto funcAddSecondManager = [=]()
|
||||
{
|
||||
m_DockManager2 = new ads::CDockManager(this);
|
||||
|
||||
m_DockManager2->addDockWidget(ads::TopDockWidgetArea, DockWidget);
|
||||
};
|
||||
QTimer::singleShot(5000, funcAddSecondManager);
|
||||
m_DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
@@ -20,8 +20,7 @@ public:
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
ads::CDockManager* m_DockManager1;
|
||||
ads::CDockManager* m_DockManager2;
|
||||
ads::CDockManager* m_DockManager;
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
|
||||
@@ -25,23 +25,7 @@ FORMS += \
|
||||
|
||||
|
||||
LIBS += -L$${ADS_OUT_ROOT}/lib
|
||||
|
||||
# Dependency: AdvancedDockingSystem (shared)
|
||||
CONFIG(debug, debug|release){
|
||||
win32 {
|
||||
LIBS += -lqtadvanceddockingd
|
||||
}
|
||||
else:mac {
|
||||
LIBS += -lqtadvanceddocking_debug
|
||||
}
|
||||
else {
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
}
|
||||
else{
|
||||
LIBS += -lqtadvanceddocking
|
||||
}
|
||||
|
||||
include(../../ads.pri)
|
||||
INCLUDEPATH += ../../src
|
||||
DEPENDPATH += ../../src
|
||||
|
||||
|
||||
@@ -2,7 +2,8 @@ import os
|
||||
import sys
|
||||
|
||||
from PyQt5 import uic
|
||||
from PyQt5.QtCore import Qt
|
||||
from PyQt5.QtCore import Qt, QTimer
|
||||
from PyQt5.QtGui import QCloseEvent
|
||||
from PyQt5.QtWidgets import QApplication, QLabel
|
||||
|
||||
from PyQtAds import QtAds
|
||||
@@ -33,6 +34,7 @@ class MainWindow(MainWindowUI, MainWindowBase):
|
||||
# as the dock widget content
|
||||
dock_widget = QtAds.CDockWidget("Label 1")
|
||||
dock_widget.setWidget(l)
|
||||
|
||||
|
||||
# Add the toggleViewAction of the dock widget to the menu to give
|
||||
# the user the possibility to show the dock widget if it has been closed
|
||||
|
||||
4
setup.py
@@ -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)
|
||||
|
||||
|
||||
@@ -28,6 +28,13 @@ protected slots:
|
||||
void toggleView(bool Open);
|
||||
|
||||
public:
|
||||
enum eDockAreaFlag
|
||||
{
|
||||
HideSingleWidgetTitleBar,
|
||||
DefaultFlags
|
||||
};
|
||||
typedef QFlags<ads::CDockAreaWidget::eDockAreaFlag> DockAreaFlags;
|
||||
|
||||
CDockAreaWidget(ads::CDockManager* DockManager /TransferThis/, ads::CDockContainerWidget* parent /TransferThis/);
|
||||
virtual ~CDockAreaWidget();
|
||||
ads::CDockManager* dockManager() const;
|
||||
@@ -52,6 +59,12 @@ public:
|
||||
void setAllowedAreas(DockWidgetAreas areas);
|
||||
DockWidgetAreas allowedAreas() const;
|
||||
CDockAreaTitleBar* titleBar() const;
|
||||
|
||||
DockAreaFlags dockAreaFlags() const;
|
||||
void setDockAreaFlags(DockAreaFlags Flags);
|
||||
void setDockAreaFlag(eDockAreaFlag Flag, bool On);
|
||||
|
||||
bool isCentralWidgetArea() const;
|
||||
|
||||
public slots:
|
||||
void setCurrentIndex(int index);
|
||||
|
||||
@@ -32,6 +32,7 @@ protected:
|
||||
ads::CDockWidget* topLevelDockWidget() const;
|
||||
ads::CDockAreaWidget* topLevelDockArea() const;
|
||||
QList<ads::CDockWidget*> dockWidgets() const;
|
||||
void updateSplitterHandles(QSplitter* splitter);
|
||||
|
||||
public:
|
||||
/**
|
||||
|
||||
@@ -20,6 +20,7 @@ public:
|
||||
|
||||
void notifyWidgetOrAreaRelocation(QWidget* RelocatedWidget);
|
||||
void notifyFloatingWidgetDrop(ads::CFloatingDockContainer* FloatingWidget);
|
||||
ads::CDockWidget* focusedDockWidget() const;
|
||||
|
||||
public slots:
|
||||
void setDockWidgetFocused(ads::CDockWidget* focusedNow);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
%Import QtWidgets/QtWidgetsmod.sip
|
||||
|
||||
%If (Qt_5_0_0 -)
|
||||
|
||||
|
||||
%MappedType QMap<QString, ads::CDockWidget*>
|
||||
/TypeHint="Dict[QString, CDockWidget*]", TypeHintValue="{}"/
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
@@ -170,6 +171,8 @@ public:
|
||||
HideSingleCentralWidgetTitleBar,
|
||||
FocusHighlighting,
|
||||
EqualSplitOnInsertion,
|
||||
FloatingContainerForceNativeTitleBar,
|
||||
FloatingContainerForceQWidgetTitleBar,
|
||||
DefaultDockAreaButtons,
|
||||
DefaultBaseConfig,
|
||||
DefaultOpaqueConfig,
|
||||
@@ -206,6 +209,8 @@ public:
|
||||
QStringList perspectiveNames() const;
|
||||
void savePerspectives(QSettings& Settings) const;
|
||||
void loadPerspectives(QSettings& Settings);
|
||||
CDockWidget* centralWidget() const;
|
||||
CDockAreaWidget* setCentralWidget(CDockWidget* widget /Transfer/);
|
||||
QAction* addToggleViewActionToMenu(QAction* ToggleViewAction /Transfer/,
|
||||
const QString& Group = QString(), const QIcon& GroupIcon = QIcon());
|
||||
QMenu* viewMenu() const;
|
||||
@@ -224,11 +229,12 @@ signals:
|
||||
void stateRestored();
|
||||
void openingPerspective(const QString& PerspectiveName);
|
||||
void perspectiveOpened(const QString& PerspectiveName);
|
||||
void floatingWidgetCreated(CFloatingDockContainer* FloatingWidget);
|
||||
void dockAreaCreated(ads::CDockAreaWidget* DockArea);
|
||||
void dockWidgetAboutToBeRemoved(ads::CDockWidget* DockWidget);
|
||||
void dockWidgetRemoved(ads::CDockWidget* DockWidget);
|
||||
void focusedDockWidgetChanged(ads::CDockWidget* old, ads::CDockWidget* now);
|
||||
void floatingWidgetCreated(ads::CFloatingDockContainer*);
|
||||
void dockAreaCreated(ads::CDockAreaWidget*);
|
||||
void dockWidgetAdded(ads::CDockWidget* DockWidget);
|
||||
void dockWidgetAboutToBeRemoved(ads::CDockWidget*);
|
||||
void dockWidgetRemoved(ads::CDockWidget*);
|
||||
void focusedDockWidgetChanged(ads::CDockWidget*, ads::CDockWidget*);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -18,6 +18,7 @@ public:
|
||||
bool hasVisibleContent() const;
|
||||
QWidget* firstWidget() const;
|
||||
QWidget* lastWidget() const;
|
||||
bool isResizingWithContainer() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ public:
|
||||
DockWidgetDeleteOnClose,
|
||||
CustomCloseHandling,
|
||||
DockWidgetFocusable,
|
||||
DockWidgetForceCloseWithArea,
|
||||
DefaultDockWidgetFeatures,
|
||||
AllDockWidgetFeatures,
|
||||
NoDockWidgetFeatures
|
||||
@@ -84,6 +85,7 @@ public:
|
||||
QAction* toggleViewAction() const;
|
||||
void setToggleViewActionMode(ads::CDockWidget::eToggleViewActionMode Mode);
|
||||
void setMinimumSizeHintMode(ads::CDockWidget::eMinimumSizeHintMode Mode);
|
||||
bool isCentralWidget() const;
|
||||
void setIcon(const QIcon& Icon);
|
||||
QIcon icon() const;
|
||||
QToolBar* toolBar() const;
|
||||
|
||||
@@ -52,11 +52,20 @@ protected:
|
||||
|
||||
protected:
|
||||
virtual void changeEvent(QEvent *event);
|
||||
virtual void moveEvent(QMoveEvent *event);
|
||||
virtual bool event(QEvent *e);
|
||||
virtual void closeEvent(QCloseEvent *event);
|
||||
virtual void hideEvent(QHideEvent *event);
|
||||
virtual void showEvent(QShowEvent *event);
|
||||
|
||||
%If (WS_MACX)
|
||||
virtual bool event(QEvent *e);
|
||||
virtual void moveEvent(QMoveEvent *event);
|
||||
%End
|
||||
|
||||
%If (WS_X11)
|
||||
virtual void moveEvent(QMoveEvent *event);
|
||||
virtual void resizeEvent(QResizeEvent *event);
|
||||
%End
|
||||
|
||||
%If (WS_WIN)
|
||||
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);
|
||||
%End
|
||||
@@ -72,6 +81,15 @@ public:
|
||||
bool hasTopLevelDockWidget() const;
|
||||
ads::CDockWidget* topLevelDockWidget() const;
|
||||
QList<ads::CDockWidget*> dockWidgets() const;
|
||||
|
||||
%If (WS_X11)
|
||||
void onMaximizeRequest();
|
||||
void showNormal(bool fixGeometry);
|
||||
void showMaximized();
|
||||
bool isMaximized() const;
|
||||
void show();
|
||||
bool hasNativeTitleBar();
|
||||
%End
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -15,15 +15,24 @@ protected:
|
||||
virtual void mousePressEvent(QMouseEvent *ev);
|
||||
virtual void mouseReleaseEvent(QMouseEvent *ev);
|
||||
virtual void mouseMoveEvent(QMouseEvent *ev);
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event);
|
||||
|
||||
void setMaximizeIcon(const QIcon& Icon);
|
||||
QIcon maximizeIcon() const;
|
||||
void setNormalIcon(const QIcon& Icon);
|
||||
QIcon normalIcon() const;
|
||||
|
||||
public:
|
||||
explicit CFloatingWidgetTitleBar(CFloatingDockContainer *parent /TransferThis/ = 0);
|
||||
virtual ~CFloatingWidgetTitleBar();
|
||||
void enableCloseButton(bool Enable);
|
||||
void setTitle(const QString &Text);
|
||||
void updateStyle();
|
||||
void setMaximizedIcon(bool maximized);
|
||||
|
||||
signals:
|
||||
void closeRequested();
|
||||
void maximizeRequested();
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
project(QtAdvancedDockingSystem LANGUAGES CXX VERSION ${VERSION_SHORT})
|
||||
find_package(Qt5 5.5 COMPONENTS Core Gui Widgets REQUIRED)
|
||||
if (UNIX AND NOT APPLE)
|
||||
find_package(Qt5 5.5 COMPONENTS X11Extras REQUIRED)
|
||||
endif()
|
||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||
if(BUILD_STATIC)
|
||||
set(CMAKE_STATIC_LIBRARY_SUFFIX "_static${CMAKE_STATIC_LIBRARY_SUFFIX}")
|
||||
@@ -45,7 +48,8 @@ set(ads_HEADERS
|
||||
IconProvider.h
|
||||
DockComponentsFactory.h
|
||||
)
|
||||
if (UNIX)
|
||||
add_compile_options("$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
if (UNIX AND NOT APPLE)
|
||||
set(ads_SRCS linux/FloatingWidgetTitleBar.cpp ${ads_SRCS})
|
||||
set(ads_HEADERS linux/FloatingWidgetTitleBar.h ${ads_HEADERS})
|
||||
endif()
|
||||
@@ -57,6 +61,10 @@ else()
|
||||
target_compile_definitions(qtadvanceddocking PRIVATE ADS_SHARED_EXPORT)
|
||||
endif()
|
||||
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
|
||||
|
||||
@@ -30,8 +30,6 @@
|
||||
//============================================================================
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <QStackedLayout>
|
||||
#include <QScrollBar>
|
||||
#include <QScrollArea>
|
||||
@@ -177,6 +175,7 @@ public:
|
||||
{
|
||||
LayoutItem->widget()->setParent(nullptr);
|
||||
}
|
||||
delete LayoutItem;
|
||||
|
||||
m_ParentLayout->addWidget(next);
|
||||
if (prev)
|
||||
@@ -237,6 +236,7 @@ public:
|
||||
|
||||
|
||||
using DockAreaLayout = CDockAreaLayout;
|
||||
static const DockWidgetAreas DefaultAllowedAreas = AllDockAreas;
|
||||
|
||||
|
||||
/**
|
||||
@@ -250,8 +250,9 @@ struct DockAreaWidgetPrivate
|
||||
CDockAreaTitleBar* TitleBar = nullptr;
|
||||
CDockManager* DockManager = nullptr;
|
||||
bool UpdateTitleBarButtons = false;
|
||||
DockWidgetAreas AllowedAreas = AllDockAreas;
|
||||
DockWidgetAreas AllowedAreas = DefaultAllowedAreas;
|
||||
QSize MinSizeHint;
|
||||
CDockAreaWidget::DockAreaFlags Flags{CDockAreaWidget::DefaultFlags};
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -323,7 +324,6 @@ struct DockAreaWidgetPrivate
|
||||
}
|
||||
}
|
||||
};
|
||||
// struct DockAreaWidgetPrivate
|
||||
|
||||
|
||||
//============================================================================
|
||||
@@ -440,6 +440,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
|
||||
DockWidget->toggleViewInternal(true);
|
||||
}
|
||||
d->updateTitleBarButtonStates();
|
||||
updateTitleBarVisibility();
|
||||
}
|
||||
|
||||
|
||||
@@ -466,6 +467,14 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
|
||||
ADS_PRINT("Dock Area empty");
|
||||
DockContainer->removeDockArea(this);
|
||||
this->deleteLater();
|
||||
if(DockContainer->dockAreaCount() == 0)
|
||||
{
|
||||
if(CFloatingDockContainer* FloatingDockContainer = DockContainer->floatingWidget())
|
||||
{
|
||||
FloatingDockContainer->hide();
|
||||
FloatingDockContainer->deleteLater();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (DockWidget == CurrentDockWidget)
|
||||
{
|
||||
@@ -747,6 +756,7 @@ void CDockAreaWidget::updateTitleBarVisibility()
|
||||
{
|
||||
bool Hidden = Container->hasTopLevelDockWidget() && (Container->isFloating()
|
||||
|| CDockManager::testConfigFlag(CDockManager::HideSingleCentralWidgetTitleBar));
|
||||
Hidden |= (d->Flags.testFlag(HideSingleWidgetTitleBar) && openDockWidgetsCount() == 1);
|
||||
d->TitleBar->setVisible(!Hidden);
|
||||
}
|
||||
}
|
||||
@@ -771,6 +781,17 @@ void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
|
||||
auto CurrentDockWidget = currentDockWidget();
|
||||
QString Name = CurrentDockWidget ? CurrentDockWidget->objectName() : "";
|
||||
s.writeAttribute("Current", Name);
|
||||
// To keep the saved XML data small, we only save the allowed areas and the
|
||||
// dock area flags if the values are different from the default values
|
||||
if (d->AllowedAreas != DefaultAllowedAreas)
|
||||
{
|
||||
s.writeAttribute("AllowedAreas", QString::number(d->AllowedAreas, 16));
|
||||
}
|
||||
|
||||
if (d->Flags != DefaultFlags)
|
||||
{
|
||||
s.writeAttribute("Flags", QString::number(d->Flags, 16));
|
||||
}
|
||||
ADS_PRINT("CDockAreaWidget::saveState TabCount: " << d->ContentsLayout->count()
|
||||
<< " Current: " << Name);
|
||||
for (int i = 0; i < d->ContentsLayout->count(); ++i)
|
||||
@@ -850,16 +871,49 @@ void CDockAreaWidget::setVisible(bool Visible)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaWidget::setAllowedAreas(DockWidgetAreas areas)
|
||||
{
|
||||
d->AllowedAreas = areas;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
DockWidgetAreas CDockAreaWidget::allowedAreas() const
|
||||
{
|
||||
return d->AllowedAreas;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockAreaWidget::DockAreaFlags CDockAreaWidget::dockAreaFlags() const
|
||||
{
|
||||
return d->Flags;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaWidget::setDockAreaFlags(DockAreaFlags Flags)
|
||||
{
|
||||
auto ChangedFlags = d->Flags ^ Flags;
|
||||
d->Flags = Flags;
|
||||
if (ChangedFlags.testFlag(HideSingleWidgetTitleBar))
|
||||
{
|
||||
updateTitleBarVisibility();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaWidget::setDockAreaFlag(eDockAreaFlag Flag, bool On)
|
||||
{
|
||||
auto flags = dockAreaFlags();
|
||||
internal::setFlag(flags, Flag, On);
|
||||
setDockAreaFlags(flags);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QAbstractButton* CDockAreaWidget::titleBarButton(TitleBarButton which) const
|
||||
{
|
||||
@@ -873,17 +927,20 @@ void CDockAreaWidget::closeArea()
|
||||
// If there is only one single dock widget and this widget has the
|
||||
// DeleteOnClose feature, then we delete the dock widget now
|
||||
auto OpenDockWidgets = openedDockWidgets();
|
||||
if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
|
||||
if (OpenDockWidgets.count() == 1 && OpenDockWidgets[0]->features().testFlag(CDockWidget::DockWidgetDeleteOnClose))
|
||||
{
|
||||
OpenDockWidgets[0]->closeDockWidgetInternal();
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
for (auto DockWidget : openedDockWidgets())
|
||||
{
|
||||
DockWidget->toggleView(false);
|
||||
}
|
||||
}
|
||||
for (auto DockWidget : openedDockWidgets())
|
||||
{
|
||||
if (DockWidget->features().testFlag(CDockWidget::DockWidgetDeleteOnClose) && DockWidget->features().testFlag(CDockWidget::DockWidgetForceCloseWithArea))
|
||||
DockWidget->closeDockWidgetInternal();
|
||||
else
|
||||
DockWidget->toggleView(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -901,11 +958,47 @@ CDockAreaTitleBar* CDockAreaWidget::titleBar() const
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CDockAreaWidget::isCentralWidgetArea() const
|
||||
{
|
||||
if (dockWidgetsCount()!= 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return dockManager()->centralWidget() == dockWidgets()[0];
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QSize CDockAreaWidget::minimumSizeHint() const
|
||||
{
|
||||
return d->MinSizeHint.isValid() ? d->MinSizeHint : Super::minimumSizeHint();
|
||||
if (!d->MinSizeHint.isValid())
|
||||
{
|
||||
return Super::minimumSizeHint();
|
||||
}
|
||||
|
||||
if (d->TitleBar->isVisible())
|
||||
{
|
||||
return d->MinSizeHint + QSize(0, d->TitleBar->minimumSizeHint().height());
|
||||
}
|
||||
else
|
||||
{
|
||||
return d->MinSizeHint;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockAreaWidget::onDockWidgetFeaturesChanged()
|
||||
{
|
||||
if (d->TitleBar)
|
||||
{
|
||||
d->updateTitleBarButtonStates();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -65,6 +65,7 @@ private:
|
||||
friend class CDockWidget;
|
||||
friend struct DockManagerPrivate;
|
||||
friend class CDockManager;
|
||||
void onDockWidgetFeaturesChanged();
|
||||
|
||||
private slots:
|
||||
void onTabCloseRequested(int Index);
|
||||
@@ -144,6 +145,16 @@ public:
|
||||
using Super = QFrame;
|
||||
|
||||
/**
|
||||
* Dock area related flags
|
||||
*/
|
||||
enum eDockAreaFlag
|
||||
{
|
||||
HideSingleWidgetTitleBar = 0x0001,
|
||||
DefaultFlags = 0x0000
|
||||
};
|
||||
Q_DECLARE_FLAGS(DockAreaFlags, eDockAreaFlag)
|
||||
|
||||
/**
|
||||
* Default Constructor
|
||||
*/
|
||||
CDockAreaWidget(CDockManager* DockManager, CDockContainerWidget* parent);
|
||||
@@ -277,6 +288,30 @@ public:
|
||||
*/
|
||||
CDockAreaTitleBar* titleBar() const;
|
||||
|
||||
/**
|
||||
* Returns the dock area flags - a combination of flags that configure the
|
||||
* appearance and features of the dock area.
|
||||
* \see setDockAreaFlasg()
|
||||
*/
|
||||
DockAreaFlags dockAreaFlags() const;
|
||||
|
||||
/**
|
||||
* Sets the dock area flags - a combination of flags that configure the
|
||||
* appearance and features of the dock area
|
||||
*/
|
||||
void setDockAreaFlags(DockAreaFlags Flags);
|
||||
|
||||
/**
|
||||
* Sets the dock area flag Flag on this widget if on is true; otherwise
|
||||
* clears the flag.
|
||||
*/
|
||||
void setDockAreaFlag(eDockAreaFlag Flag, bool On);
|
||||
|
||||
/**
|
||||
* Returns true if the area contains the central widget of it's manager.
|
||||
*/
|
||||
bool isCentralWidgetArea() const;
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* This activates the tab for the given tab index.
|
||||
|
||||
@@ -322,6 +322,18 @@ public:
|
||||
Splitter->setSizes(SplitterSizes);
|
||||
}
|
||||
|
||||
/**
|
||||
* This function forces the dock container widget to update handles of splitters
|
||||
* based if a central widget exists.
|
||||
*/
|
||||
void updateSplitterHandles(QSplitter* splitter);
|
||||
|
||||
/**
|
||||
* If no central widget exists, the widgets resize with the container.
|
||||
* If a central widget exists, the widgets surrounding the central widget
|
||||
* do not resize its height or width.
|
||||
*/
|
||||
bool widgetResizesWithContainer(QWidget* widget);
|
||||
|
||||
// private slots: ------------------------------------------------------------
|
||||
void onDockAreaViewToggled(bool Visible)
|
||||
@@ -421,7 +433,8 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
|
||||
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
|
||||
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
|
||||
NewSplitter->addWidget(Splitter);
|
||||
Splitter = NewSplitter;
|
||||
updateSplitterHandles(NewSplitter);
|
||||
Splitter = NewSplitter;
|
||||
delete li;
|
||||
}
|
||||
|
||||
@@ -430,19 +443,21 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
|
||||
if (FloatingSplitter->count() == 1)
|
||||
{
|
||||
insertWidgetIntoSplitter(Splitter, FloatingSplitter->widget(0), InsertParam.append());
|
||||
}
|
||||
updateSplitterHandles(Splitter);
|
||||
}
|
||||
else if (FloatingSplitter->orientation() == InsertParam.orientation())
|
||||
{
|
||||
int InsertIndex = InsertParam.append() ? Splitter->count() : 0;
|
||||
while (FloatingSplitter->count())
|
||||
{
|
||||
Splitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
|
||||
}
|
||||
}
|
||||
updateSplitterHandles(Splitter);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
insertWidgetIntoSplitter(Splitter, FloatingSplitter, InsertParam.append());
|
||||
}
|
||||
}
|
||||
|
||||
RootSplitter = Splitter;
|
||||
addDockAreasToList(NewDockAreas);
|
||||
@@ -453,7 +468,7 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
|
||||
if (!Splitter->isVisible())
|
||||
{
|
||||
Splitter->show();
|
||||
}
|
||||
}
|
||||
_this->dumpLayout();
|
||||
}
|
||||
|
||||
@@ -515,7 +530,8 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
|
||||
QSplitter* Splitter = newSplitter(InsertParam.orientation());
|
||||
Layout->replaceWidget(TargetArea, Splitter);
|
||||
Splitter->addWidget(TargetArea);
|
||||
TargetAreaSplitter = Splitter;
|
||||
updateSplitterHandles(Splitter);
|
||||
TargetAreaSplitter = Splitter;
|
||||
}
|
||||
int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
|
||||
auto Widget = FloatingWidget->dockContainer()->findChild<QWidget*>(QString(), Qt::FindDirectChildrenOnly);
|
||||
@@ -529,7 +545,8 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
|
||||
if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
|
||||
{
|
||||
TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget);
|
||||
}
|
||||
updateSplitterHandles(TargetAreaSplitter);
|
||||
}
|
||||
else
|
||||
{
|
||||
AdjustSplitterSizes = (FloatingSplitter->count() == 1);
|
||||
@@ -537,8 +554,9 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
|
||||
while (FloatingSplitter->count())
|
||||
{
|
||||
TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
|
||||
}
|
||||
}
|
||||
updateSplitterHandles(TargetAreaSplitter);
|
||||
}
|
||||
}
|
||||
|
||||
if (AdjustSplitterSizes)
|
||||
{
|
||||
@@ -557,28 +575,32 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
|
||||
if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
|
||||
{
|
||||
NewSplitter->addWidget(Widget);
|
||||
}
|
||||
updateSplitterHandles(NewSplitter);
|
||||
}
|
||||
else
|
||||
{
|
||||
AdjustSplitterSizes = (FloatingSplitter->count() == 1);
|
||||
while (FloatingSplitter->count())
|
||||
{
|
||||
NewSplitter->addWidget(FloatingSplitter->widget(0));
|
||||
}
|
||||
}
|
||||
updateSplitterHandles(NewSplitter);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the sizes before insertion and restore it later to prevent
|
||||
// shrinking of existing area
|
||||
auto Sizes = TargetAreaSplitter->sizes();
|
||||
insertWidgetIntoSplitter(NewSplitter, TargetArea, !InsertParam.append());
|
||||
if (AdjustSplitterSizes)
|
||||
updateSplitterHandles(NewSplitter);
|
||||
if (AdjustSplitterSizes)
|
||||
{
|
||||
int Size = TargetAreaSize / 2;
|
||||
NewSplitter->setSizes({Size, Size});
|
||||
}
|
||||
TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
|
||||
TargetAreaSplitter->setSizes(Sizes);
|
||||
}
|
||||
updateSplitterHandles(TargetAreaSplitter);
|
||||
}
|
||||
|
||||
addDockAreasToList(NewDockAreas);
|
||||
_this->dumpLayout();
|
||||
@@ -663,7 +685,8 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg
|
||||
{
|
||||
int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
|
||||
TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), NewDockArea);
|
||||
int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2;
|
||||
updateSplitterHandles(TargetAreaSplitter);
|
||||
int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2;
|
||||
Sizes[AreaIndex] = Size;
|
||||
Sizes.insert(AreaIndex, Size);
|
||||
}
|
||||
@@ -674,16 +697,58 @@ void DockContainerWidgetPrivate::moveToNewSection(QWidget* Widget, CDockAreaWidg
|
||||
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
|
||||
NewSplitter->addWidget(TargetArea);
|
||||
insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
|
||||
int Size = TargetAreaSize / 2;
|
||||
updateSplitterHandles(NewSplitter);
|
||||
int Size = TargetAreaSize / 2;
|
||||
NewSplitter->setSizes({Size, Size});
|
||||
TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
|
||||
}
|
||||
updateSplitterHandles(TargetAreaSplitter);
|
||||
}
|
||||
TargetAreaSplitter->setSizes(Sizes);
|
||||
|
||||
addDockAreasToList({NewDockArea});
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockContainerWidgetPrivate::updateSplitterHandles( QSplitter* splitter )
|
||||
{
|
||||
if (!DockManager->centralWidget() || !splitter)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (int i = 0; i < splitter->count(); ++i)
|
||||
{
|
||||
splitter->setStretchFactor(i, widgetResizesWithContainer(splitter->widget(i)) ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool DockContainerWidgetPrivate::widgetResizesWithContainer(QWidget* widget)
|
||||
{
|
||||
if (!DockManager->centralWidget())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
auto Area = qobject_cast<CDockAreaWidget*>(widget);
|
||||
if(Area)
|
||||
{
|
||||
return Area->isCentralWidgetArea();
|
||||
}
|
||||
|
||||
auto innerSplitter = qobject_cast<CDockSplitter*>(widget);
|
||||
if (innerSplitter)
|
||||
{
|
||||
return innerSplitter->isResizingWithContainer();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockContainerWidgetPrivate::moveToContainer(QWidget* Widget, DockWidgetArea area)
|
||||
{
|
||||
@@ -852,15 +917,15 @@ bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s,
|
||||
{
|
||||
QWidget* ChildNode = nullptr;
|
||||
bool Result = true;
|
||||
if (s.name() == "Splitter")
|
||||
if (s.name() == QLatin1String("Splitter"))
|
||||
{
|
||||
Result = restoreSplitter(s, ChildNode, Testing);
|
||||
}
|
||||
else if (s.name() == "Area")
|
||||
else if (s.name() == QLatin1String("Area"))
|
||||
{
|
||||
Result = restoreDockArea(s, ChildNode, Testing);
|
||||
}
|
||||
else if (s.name() == "Sizes")
|
||||
else if (s.name() == QLatin1String("Sizes"))
|
||||
{
|
||||
QString sSizes = s.readElementText().trimmed();
|
||||
ADS_PRINT("Sizes: " << sSizes);
|
||||
@@ -892,6 +957,10 @@ bool DockContainerWidgetPrivate::restoreSplitter(CDockingStateReader& s,
|
||||
Splitter->addWidget(ChildNode);
|
||||
Visible |= ChildNode->isVisibleTo(Splitter);
|
||||
}
|
||||
if(!Testing)
|
||||
{
|
||||
updateSplitterHandles(Splitter);
|
||||
}
|
||||
|
||||
if (Sizes.count() != WidgetCount)
|
||||
{
|
||||
@@ -942,11 +1011,22 @@ bool DockContainerWidgetPrivate::restoreDockArea(CDockingStateReader& s,
|
||||
if (!Testing)
|
||||
{
|
||||
DockArea = new CDockAreaWidget(DockManager, _this);
|
||||
const auto AllowedAreasAttribute = s.attributes().value("AllowedAreas");
|
||||
if (!AllowedAreasAttribute.isEmpty())
|
||||
{
|
||||
DockArea->setAllowedAreas((DockWidgetArea)AllowedAreasAttribute.toInt(nullptr, 16));
|
||||
}
|
||||
|
||||
const auto FlagsAttribute = s.attributes().value("Flags");
|
||||
if (!FlagsAttribute.isEmpty())
|
||||
{
|
||||
DockArea->setDockAreaFlags((CDockAreaWidget::DockAreaFlags)FlagsAttribute.toInt(nullptr, 16));
|
||||
}
|
||||
}
|
||||
|
||||
while (s.readNextStartElement())
|
||||
{
|
||||
if (s.name() != "Widget")
|
||||
if (s.name() != QLatin1String("Widget"))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
@@ -1009,12 +1089,12 @@ bool DockContainerWidgetPrivate::restoreChildNodes(CDockingStateReader& s,
|
||||
bool Result = true;
|
||||
while (s.readNextStartElement())
|
||||
{
|
||||
if (s.name() == "Splitter")
|
||||
if (s.name() == QLatin1String("Splitter"))
|
||||
{
|
||||
Result = restoreSplitter(s, CreatedWidget, Testing);
|
||||
ADS_PRINT("Splitter");
|
||||
}
|
||||
else if (s.name() == "Area")
|
||||
else if (s.name() == QLatin1String("Area"))
|
||||
{
|
||||
Result = restoreDockArea(s, CreatedWidget, Testing);
|
||||
ADS_PRINT("DockAreaWidget");
|
||||
@@ -1058,7 +1138,8 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW
|
||||
if (Splitter->orientation() == InsertParam.orientation())
|
||||
{
|
||||
insertWidgetIntoSplitter(Splitter, NewDockArea, InsertParam.append());
|
||||
if (Splitter->isHidden())
|
||||
updateSplitterHandles(Splitter);
|
||||
if (Splitter->isHidden())
|
||||
{
|
||||
Splitter->show();
|
||||
}
|
||||
@@ -1071,14 +1152,16 @@ void DockContainerWidgetPrivate::addDockArea(CDockAreaWidget* NewDockArea, DockW
|
||||
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
|
||||
NewSplitter->addWidget(Splitter);
|
||||
NewSplitter->addWidget(NewDockArea);
|
||||
delete li;
|
||||
updateSplitterHandles(NewSplitter);
|
||||
delete li;
|
||||
}
|
||||
else
|
||||
{
|
||||
NewSplitter->addWidget(NewDockArea);
|
||||
QLayoutItem* li = Layout->replaceWidget(Splitter, NewSplitter);
|
||||
NewSplitter->addWidget(Splitter);
|
||||
delete li;
|
||||
updateSplitterHandles(NewSplitter);
|
||||
delete li;
|
||||
}
|
||||
RootSplitter = NewSplitter;
|
||||
}
|
||||
@@ -1124,7 +1207,7 @@ void DockContainerWidgetPrivate::dumpRecursive(int level, QWidget* widget)
|
||||
std::cout << (const char*)buf
|
||||
<< (DockArea->isHidden() ? " " : "v")
|
||||
<< (DockArea->openDockWidgetsCount() > 0 ? " " : "c")
|
||||
<< " DockArea" << std::endl;
|
||||
<< " DockArea " << "[hs: " << DockArea->sizePolicy().horizontalStretch() << ", vs: " << DockArea->sizePolicy().verticalStretch() << "]" << std::endl;
|
||||
buf.fill(' ', (level + 1) * 4);
|
||||
for (int i = 0; i < DockArea->dockWidgetsCount(); ++i)
|
||||
{
|
||||
@@ -1164,12 +1247,12 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA
|
||||
{
|
||||
ADS_PRINT("TargetAreaSplitter->orientation() == InsertParam.orientation()");
|
||||
TargetAreaSplitter->insertWidget(index + InsertParam.insertOffset(), NewDockArea);
|
||||
// do nothing, if flag is not enabled
|
||||
updateSplitterHandles(TargetAreaSplitter);
|
||||
// do nothing, if flag is not enabled
|
||||
if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion))
|
||||
{
|
||||
adjustSplitterSizesOnInsertion(TargetAreaSplitter);
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1179,16 +1262,17 @@ CDockAreaWidget* DockContainerWidgetPrivate::addDockWidgetToDockArea(DockWidgetA
|
||||
NewSplitter->addWidget(TargetDockArea);
|
||||
|
||||
insertWidgetIntoSplitter(NewSplitter, NewDockArea, InsertParam.append());
|
||||
TargetAreaSplitter->insertWidget(index, NewSplitter);
|
||||
if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion))
|
||||
{
|
||||
updateSplitterHandles(NewSplitter);
|
||||
TargetAreaSplitter->insertWidget(index, NewSplitter);
|
||||
updateSplitterHandles(TargetAreaSplitter);
|
||||
if (CDockManager::testConfigFlag(CDockManager::EqualSplitOnInsertion))
|
||||
{
|
||||
TargetAreaSplitter->setSizes(TargetAreaSizes);
|
||||
adjustSplitterSizesOnInsertion(NewSplitter);
|
||||
}
|
||||
}
|
||||
|
||||
appendDockAreas({NewDockArea});
|
||||
emitDockAreasAdded();
|
||||
addDockAreasToList({NewDockArea});
|
||||
return NewDockArea;
|
||||
}
|
||||
|
||||
@@ -1370,9 +1454,11 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
|
||||
}
|
||||
|
||||
delete Splitter;
|
||||
Splitter = nullptr;
|
||||
|
||||
emitAndExit:
|
||||
CDockWidget* TopLevelWidget = topLevelDockWidget();
|
||||
updateSplitterHandles(Splitter);
|
||||
CDockWidget* TopLevelWidget = topLevelDockWidget();
|
||||
|
||||
// Updated the title bar visibility of the dock widget if there is only
|
||||
// one single visible dock widget
|
||||
@@ -1578,7 +1664,7 @@ bool CDockContainerWidget::restoreState(CDockingStateReader& s, bool Testing)
|
||||
if (IsFloating)
|
||||
{
|
||||
ADS_PRINT("Restore floating widget");
|
||||
if (!s.readNextStartElement() || s.name() != "Geometry")
|
||||
if (!s.readNextStartElement() || s.name() != QLatin1String("Geometry"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1721,6 +1807,13 @@ QList<CDockWidget*> CDockContainerWidget::dockWidgets() const
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockContainerWidget::updateSplitterHandles(QSplitter* splitter)
|
||||
{
|
||||
d->updateSplitterHandles(splitter);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockWidget::DockWidgetFeatures CDockContainerWidget::features() const
|
||||
{
|
||||
|
||||
@@ -155,6 +155,12 @@ protected:
|
||||
*/
|
||||
QList<CDockWidget*> dockWidgets() const;
|
||||
|
||||
/**
|
||||
* This function forces the dock container widget to update handles of splitters
|
||||
* based on resize modes of dock widgets contained in the container.
|
||||
*/
|
||||
void updateSplitterHandles(QSplitter* splitter);
|
||||
|
||||
public:
|
||||
/**
|
||||
* Default Constructor
|
||||
@@ -276,7 +282,7 @@ signals:
|
||||
* This signal is emitted if a dock area is opened or closed via
|
||||
* toggleView() function
|
||||
*/
|
||||
void dockAreaViewToggled(CDockAreaWidget* DockArea, bool Open);
|
||||
void dockAreaViewToggled(ads::CDockAreaWidget* DockArea, bool Open);
|
||||
}; // class DockContainerWidget
|
||||
} // namespace ads
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -83,6 +83,10 @@ static void updateDockAreaFocusStyle(CDockAreaWidget* DockArea, bool Focused)
|
||||
#ifdef Q_OS_LINUX
|
||||
static void updateFloatingWidgetFocusStyle(CFloatingDockContainer* FloatingWidget, bool Focused)
|
||||
{
|
||||
if (FloatingWidget->hasNativeTitleBar())
|
||||
{
|
||||
return;
|
||||
}
|
||||
auto TitleBar = qobject_cast<CFloatingWidgetTitleBar*>(FloatingWidget->titleBarWidget());
|
||||
if (!TitleBar)
|
||||
{
|
||||
@@ -236,7 +240,11 @@ void CDockFocusController::onApplicationFocusChanged(QWidget* focusedOld, QWidge
|
||||
auto OtherDockWidgetTab = internal::findParent<CDockWidgetTab*>(focusedNow);
|
||||
if (OtherDockWidgetTab && focusedOld)
|
||||
{
|
||||
focusedOld->setFocus();
|
||||
auto OldFocusedDockWidget = internal::findParent<CDockWidget*>(focusedOld);
|
||||
if (OldFocusedDockWidget)
|
||||
{
|
||||
focusedOld->setFocus();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -377,6 +385,13 @@ void CDockFocusController::onStateRestored()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
CDockWidget* CDockFocusController::focusedDockWidget() const
|
||||
{
|
||||
return d->FocusedDockWidget.data();
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -77,6 +77,12 @@ public:
|
||||
*/
|
||||
void notifyFloatingWidgetDrop(CFloatingDockContainer* FloatingWidget);
|
||||
|
||||
/**
|
||||
* Returns the dock widget that has focus style in the ui or a nullptr if
|
||||
* not dock widget is painted focused.
|
||||
*/
|
||||
CDockWidget* focusedDockWidget() const;
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Request a focus change to the given dock widget
|
||||
|
||||
@@ -55,6 +55,7 @@
|
||||
#include "DockingStateReader.h"
|
||||
#include "DockAreaTitleBar.h"
|
||||
#include "DockFocusController.h"
|
||||
#include "DockSplitter.h"
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "linux/FloatingWidgetTitleBar.h"
|
||||
@@ -108,6 +109,7 @@ struct DockManagerPrivate
|
||||
bool RestoringState = false;
|
||||
QVector<CFloatingDockContainer*> UninitializedFloatingWidgets;
|
||||
CDockFocusController* FocusController = nullptr;
|
||||
CDockWidget* CentralWidget = nullptr;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -248,7 +250,7 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
|
||||
}
|
||||
CDockingStateReader s(state);
|
||||
s.readNextStartElement();
|
||||
if (s.name() != "QtAdvancedDockingSystem")
|
||||
if (s.name() != QLatin1String("QtAdvancedDockingSystem"))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -278,10 +280,31 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
|
||||
int DockContainers = s.attributes().value("Containers").toInt();
|
||||
#endif
|
||||
ADS_PRINT(DockContainers);
|
||||
|
||||
if (CentralWidget)
|
||||
{
|
||||
const auto CentralWidgetAttribute = s.attributes().value("CentralWidget");
|
||||
// If we have a central widget but a state without central widget, then
|
||||
// something is wrong.
|
||||
if (CentralWidgetAttribute.isEmpty())
|
||||
{
|
||||
qWarning() << "Dock manager has central widget but saved state does not have central widget.";
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the object name of the central widget does not match the name of the
|
||||
// saved central widget, the something is wrong
|
||||
if (CentralWidget->objectName() != CentralWidgetAttribute.toString())
|
||||
{
|
||||
qWarning() << "Object name of central widget does not match name of central widget in saved state.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
int DockContainerCount = 0;
|
||||
while (s.readNextStartElement())
|
||||
{
|
||||
if (s.name() == "Container")
|
||||
if (s.name() == QLatin1String("Container"))
|
||||
{
|
||||
Result = restoreContainer(DockContainerCount, s, Testing);
|
||||
if (!Result)
|
||||
@@ -296,11 +319,11 @@ bool DockManagerPrivate::restoreStateFromXml(const QByteArray &state, int versi
|
||||
{
|
||||
// Delete remaining empty floating widgets
|
||||
int FloatingWidgetIndex = DockContainerCount - 1;
|
||||
int DeleteCount = FloatingWidgets.count() - FloatingWidgetIndex;
|
||||
for (int i = 0; i < DeleteCount; ++i)
|
||||
for (int i = FloatingWidgetIndex; i < FloatingWidgets.count(); ++i)
|
||||
{
|
||||
FloatingWidgets[FloatingWidgetIndex + i]->deleteLater();
|
||||
_this->removeDockContainer(FloatingWidgets[FloatingWidgetIndex + i]->dockContainer());
|
||||
auto* floatingWidget = FloatingWidgets[i];
|
||||
_this->removeDockContainer(floatingWidget->dockContainer());
|
||||
floatingWidget->deleteLater();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,8 +390,6 @@ void DockManagerPrivate::restoreDockAreasIndices()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
void DockManagerPrivate::emitTopLevelEvents()
|
||||
{
|
||||
@@ -419,6 +440,7 @@ bool DockManagerPrivate::restoreState(const QByteArray& State, int version)
|
||||
restoreDockWidgetsOpenState();
|
||||
restoreDockAreasIndices();
|
||||
emitTopLevelEvents();
|
||||
_this->dumpLayout();
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -474,6 +496,10 @@ CDockManager::CDockManager(QWidget *parent) :
|
||||
{
|
||||
d->FocusController = new CDockFocusController(this);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
window()->installEventFilter(this);
|
||||
#endif
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
@@ -487,6 +513,70 @@ CDockManager::~CDockManager()
|
||||
delete d;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
#ifdef Q_OS_LINUX
|
||||
bool CDockManager::eventFilter(QObject *obj, QEvent *e)
|
||||
{
|
||||
// Emulate Qt:Tool behaviour.
|
||||
// Required because on some WMs Tool windows can't be maximized.
|
||||
|
||||
// Window always on top of the MainWindow.
|
||||
if (e->type() == QEvent::WindowActivate)
|
||||
{
|
||||
for (auto _window : floatingWidgets())
|
||||
{
|
||||
if (!_window->isVisible() || window()->isMinimized())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
// setWindowFlags(Qt::WindowStaysOnTopHint) will hide the window and thus requires a show call.
|
||||
// This then leads to flickering and a nasty endless loop (also buggy behaviour on Ubuntu).
|
||||
// So we just do it ourself.
|
||||
internal::xcb_update_prop(true, _window->window()->winId(),
|
||||
"_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP");
|
||||
}
|
||||
}
|
||||
else if (e->type() == QEvent::WindowDeactivate)
|
||||
{
|
||||
for (auto _window : floatingWidgets())
|
||||
{
|
||||
if (!_window->isVisible() || window()->isMinimized())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
internal::xcb_update_prop(false, _window->window()->winId(),
|
||||
"_NET_WM_STATE", "_NET_WM_STATE_ABOVE", "_NET_WM_STATE_STAYS_ON_TOP");
|
||||
_window->raise();
|
||||
}
|
||||
}
|
||||
|
||||
// Sync minimize with MainWindow
|
||||
if (e->type() == QEvent::WindowStateChange)
|
||||
{
|
||||
for (auto _window : floatingWidgets())
|
||||
{
|
||||
if (! _window->isVisible())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (window()->isMinimized())
|
||||
{
|
||||
_window->showMinimized();
|
||||
}
|
||||
else
|
||||
{
|
||||
_window->setWindowState(_window->windowState() & (~Qt::WindowMinimized));
|
||||
}
|
||||
}
|
||||
if (!window()->isMinimized())
|
||||
{
|
||||
QApplication::setActiveWindow(window());
|
||||
}
|
||||
}
|
||||
return Super::eventFilter(obj, e);
|
||||
}
|
||||
#endif
|
||||
|
||||
//============================================================================
|
||||
void CDockManager::registerFloatingWidget(CFloatingDockContainer* FloatingWidget)
|
||||
@@ -568,6 +658,10 @@ QByteArray CDockManager::saveState(int version) const
|
||||
s.writeAttribute("Version", QString::number(CurrentVersion));
|
||||
s.writeAttribute("UserVersion", QString::number(version));
|
||||
s.writeAttribute("Containers", QString::number(d->Containers.count()));
|
||||
if (d->CentralWidget)
|
||||
{
|
||||
s.writeAttribute("CentralWidget", d->CentralWidget->objectName());
|
||||
}
|
||||
for (auto Container : d->Containers)
|
||||
{
|
||||
Container->saveState(s);
|
||||
@@ -638,6 +732,7 @@ CFloatingDockContainer* CDockManager::addDockWidgetFloating(CDockWidget* Dockwid
|
||||
{
|
||||
d->UninitializedFloatingWidgets.append(FloatingWidget);
|
||||
}
|
||||
emit dockWidgetAdded(Dockwidget);
|
||||
return FloatingWidget;
|
||||
}
|
||||
|
||||
@@ -664,7 +759,10 @@ CDockAreaWidget* CDockManager::addDockWidget(DockWidgetArea area,
|
||||
CDockWidget* Dockwidget, CDockAreaWidget* DockAreaWidget)
|
||||
{
|
||||
d->DockWidgetsMap.insert(Dockwidget->objectName(), Dockwidget);
|
||||
return CDockContainerWidget::addDockWidget(area, Dockwidget, DockAreaWidget);
|
||||
auto Container = DockAreaWidget ? DockAreaWidget->dockContainer(): this;
|
||||
auto AreaOfAddedDockWidget = Container->addDockWidget(area, Dockwidget, DockAreaWidget);
|
||||
emit dockWidgetAdded(Dockwidget);
|
||||
return AreaOfAddedDockWidget;
|
||||
}
|
||||
|
||||
|
||||
@@ -816,6 +914,50 @@ void CDockManager::loadPerspectives(QSettings& Settings)
|
||||
Settings.endArray();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockWidget* CDockManager::centralWidget() const
|
||||
{
|
||||
return d->CentralWidget;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
CDockAreaWidget* CDockManager::setCentralWidget(CDockWidget* widget)
|
||||
{
|
||||
if (!widget)
|
||||
{
|
||||
d->CentralWidget = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Setting a new central widget is now allowed if there is already a central
|
||||
// widget or if there are already other dock widgets
|
||||
if (d->CentralWidget)
|
||||
{
|
||||
qWarning("Setting a central widget not possible because there is already a central widget.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// Setting a central widget is now allowed if there are already other
|
||||
// dock widgets.
|
||||
if (!d->DockWidgetsMap.isEmpty())
|
||||
{
|
||||
qWarning("Setting a central widget not possible - the central widget need to be the first "
|
||||
"dock widget that is added to the dock manager.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
widget->setFeature(CDockWidget::DockWidgetClosable, false);
|
||||
widget->setFeature(CDockWidget::DockWidgetMovable, false);
|
||||
widget->setFeature(CDockWidget::DockWidgetFloatable, false);
|
||||
d->CentralWidget = widget;
|
||||
CDockAreaWidget* CentralArea = addDockWidget(CenterDockWidgetArea, widget);
|
||||
CentralArea->setDockAreaFlag(CDockAreaWidget::eDockAreaFlag::HideSingleWidgetTitleBar, true);
|
||||
return CentralArea;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
QAction* CDockManager::addToggleViewActionToMenu(QAction* ToggleViewAction,
|
||||
const QString& Group, const QIcon& GroupIcon)
|
||||
@@ -940,6 +1082,48 @@ void CDockManager::setDockWidgetFocused(CDockWidget* DockWidget)
|
||||
}
|
||||
|
||||
|
||||
//===========================================================================
|
||||
CDockWidget* CDockManager::focusedDockWidget() const
|
||||
{
|
||||
if (!d->FocusController)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return d->FocusController->focusedDockWidget();
|
||||
}
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
QList<int> CDockManager::splitterSizes(CDockAreaWidget *ContainedArea) const
|
||||
{
|
||||
if (ContainedArea)
|
||||
{
|
||||
auto Splitter = internal::findParent<CDockSplitter*>(ContainedArea);
|
||||
if (Splitter)
|
||||
{
|
||||
return Splitter->sizes();
|
||||
}
|
||||
}
|
||||
return QList<int>();
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void CDockManager::setSplitterSizes(CDockAreaWidget *ContainedArea, const QList<int>& sizes)
|
||||
{
|
||||
if (!ContainedArea)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto Splitter = internal::findParent<CDockSplitter*>(ContainedArea);
|
||||
if (Splitter && Splitter->count() == sizes.count())
|
||||
{
|
||||
Splitter->setSizes(sizes);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -178,9 +178,17 @@ public:
|
||||
FloatingContainerHasWidgetIcon = 0x80000, //!< If set, the Floating Widget icon reflects the icon of the current dock widget otherwise it displays application icon
|
||||
HideSingleCentralWidgetTitleBar = 0x100000, //!< If there is only one single visible dock widget in the main dock container (the dock manager) and if this flag is set, then the titlebar of this dock widget will be hidden
|
||||
//!< this only makes sense for non draggable and non floatable widgets and enables the creation of some kind of "central" widget
|
||||
|
||||
FocusHighlighting = 0x200000, //!< enables styling of focused dock widget tabs or floating widget titlebar
|
||||
EqualSplitOnInsertion = 0x400000, ///!< if enabled, the space is equally distributed to all widgets in a splitter
|
||||
|
||||
FloatingContainerForceNativeTitleBar = 0x800000, //!< Linux only ! Forces all FloatingContainer to use the native title bar. This might break docking for FloatinContainer on some Window Managers (like Kwin/KDE).
|
||||
//!< If neither this nor FloatingContainerForceCustomTitleBar 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".
|
||||
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".
|
||||
|
||||
DefaultDockAreaButtons = DockAreaHasCloseButton
|
||||
| DockAreaHasUndockButton
|
||||
| DockAreaHasTabsMenuButton,///< default configuration of dock area title bar buttons
|
||||
@@ -378,7 +386,31 @@ public:
|
||||
*/
|
||||
void loadPerspectives(QSettings& Settings);
|
||||
|
||||
/**
|
||||
/**
|
||||
* This function returns managers central widget or nullptr if no central widget is set.
|
||||
*/
|
||||
CDockWidget* centralWidget() const;
|
||||
|
||||
/**
|
||||
* Adds dockwidget widget into the central area and marks it as central widget.
|
||||
* If central widget is set, it will be the only dock widget
|
||||
* that will resize with the dock container. A central widget if not
|
||||
* movable, floatable or closable and the titlebar of the central
|
||||
* dock area is not visible.
|
||||
* If the given widget could be set as central widget, the function returns
|
||||
* the created dock area. If the widget could not be set, because there
|
||||
* is already a central widget, this function returns a nullptr.
|
||||
* To clear the central widget, pass a nullptr to the function.
|
||||
* \note Setting a central widget is only possible if no other dock widgets
|
||||
* have been registered before. That means, this function should be the
|
||||
* first function that you call before you add other dock widgets.
|
||||
* \retval != 0 The dock area that contains the central widget
|
||||
* \retval nullptr Indicates that the given widget can not be set as central
|
||||
* widget because there is already a central widget.
|
||||
*/
|
||||
CDockAreaWidget* setCentralWidget(CDockWidget* widget);
|
||||
|
||||
/**
|
||||
* Adds a toggle view action to the the internal view menu.
|
||||
* You can either manage the insertion of the toggle view actions in your
|
||||
* application or you can add the actions to the internal view menu and
|
||||
@@ -443,6 +475,37 @@ public:
|
||||
widget->setFocus(Qt::OtherFocusReason);
|
||||
}
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
bool eventFilter(QObject *obj, QEvent *e) override;
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Returns the dock widget that has focus style in the ui or a nullptr if
|
||||
* not dock widget is painted focused.
|
||||
* If the flag FocusHighlighting is disabled, this function always returns
|
||||
* nullptr.
|
||||
*/
|
||||
CDockWidget* focusedDockWidget() const;
|
||||
|
||||
/**
|
||||
* Returns the sizes of the splitter that contains the dock area.
|
||||
*
|
||||
* If there is no splitter that contains the area, an empty list will be
|
||||
* returned.
|
||||
*/
|
||||
QList<int> splitterSizes(CDockAreaWidget *ContainedArea) const;
|
||||
|
||||
/**
|
||||
* Update the sizes of a splitter
|
||||
* Programmatically updates the sizes of a given splitter by calling
|
||||
* QSplitter::setSizes(). The splitter will be the splitter that
|
||||
* contains the supplied dock area widget. If there is not splitter
|
||||
* that contains the dock area, or the sizes supplied does not match
|
||||
* the number of children of the splitter, this method will have no
|
||||
* effect.
|
||||
*/
|
||||
void setSplitterSizes(CDockAreaWidget *ContainedArea, const QList<int>& sizes);
|
||||
|
||||
public slots:
|
||||
/**
|
||||
* Opens the perspective with the given name.
|
||||
@@ -502,20 +565,26 @@ signals:
|
||||
* An application can use this signal to e.g. subscribe to events of
|
||||
* the newly created window.
|
||||
*/
|
||||
void floatingWidgetCreated(CFloatingDockContainer* FloatingWidget);
|
||||
void floatingWidgetCreated(ads::CFloatingDockContainer* FloatingWidget);
|
||||
|
||||
/**
|
||||
* This signal is emitted, if a new DockArea has been created.
|
||||
* An application can use this signal to set custom icons or custom
|
||||
* tooltips for the DockArea buttons.
|
||||
*/
|
||||
void dockAreaCreated(CDockAreaWidget* DockArea);
|
||||
void dockAreaCreated(ads::CDockAreaWidget* DockArea);
|
||||
|
||||
/**
|
||||
* This signal is emitted if a dock widget has been added to this
|
||||
* dock manager instance.
|
||||
*/
|
||||
void dockWidgetAdded(ads::CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* This signal is emitted just before the given dock widget is removed
|
||||
* from the
|
||||
* from the dock manager
|
||||
*/
|
||||
void dockWidgetAboutToBeRemoved(CDockWidget* DockWidget);
|
||||
void dockWidgetAboutToBeRemoved(ads::CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* This signal is emitted if a dock widget has been removed with the remove
|
||||
@@ -523,14 +592,14 @@ signals:
|
||||
* If this signal is emitted, the dock widget has been removed from the
|
||||
* docking system but it is not deleted yet.
|
||||
*/
|
||||
void dockWidgetRemoved(CDockWidget* DockWidget);
|
||||
void dockWidgetRemoved(ads::CDockWidget* DockWidget);
|
||||
|
||||
/**
|
||||
* This signal is emitted if the focused dock widget changed.
|
||||
* Both old and now can be nullptr.
|
||||
* The focused dock widget is the one that is highlighted in the GUI
|
||||
*/
|
||||
void focusedDockWidgetChanged(CDockWidget* old, CDockWidget* now);
|
||||
void focusedDockWidgetChanged(ads::CDockWidget* old, ads::CDockWidget* now);
|
||||
}; // class DockManager
|
||||
} // namespace ads
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
@@ -806,10 +806,15 @@ void CDockOverlayCross::setIconColors(const QString& Colors)
|
||||
{"Arrow", CDockOverlayCross::ArrowColor},
|
||||
{"Shadow", CDockOverlayCross::ShadowColor}};
|
||||
|
||||
auto ColorList = Colors.split(' ', QString::SkipEmptyParts);
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
auto SkipEmptyParts = QString::SkipEmptyParts;
|
||||
#else
|
||||
auto SkipEmptyParts = Qt::SkipEmptyParts;
|
||||
#endif
|
||||
auto ColorList = Colors.split(' ', SkipEmptyParts);
|
||||
for (const auto& ColorListEntry : ColorList)
|
||||
{
|
||||
auto ComponentColor = ColorListEntry.split('=', QString::SkipEmptyParts);
|
||||
auto ComponentColor = ColorListEntry.split('=', SkipEmptyParts);
|
||||
int Component = ColorCompenentStringMap.value(ComponentColor[0], -1);
|
||||
if (Component < 0)
|
||||
{
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
#include <QDebug>
|
||||
#include <QChildEvent>
|
||||
|
||||
#include <QVariant>
|
||||
#include "DockAreaWidget.h"
|
||||
|
||||
namespace ads
|
||||
@@ -52,7 +52,7 @@ CDockSplitter::CDockSplitter(QWidget *parent)
|
||||
: QSplitter(parent),
|
||||
d(new DockSplitterPrivate(this))
|
||||
{
|
||||
setProperty("ads-splitter", true);
|
||||
setProperty("ads-splitter", QVariant(true));
|
||||
setChildrenCollapsible(false);
|
||||
}
|
||||
|
||||
@@ -102,6 +102,20 @@ QWidget* CDockSplitter::lastWidget() const
|
||||
return (count() > 0) ? widget(count() - 1) : nullptr;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
bool CDockSplitter::isResizingWithContainer() const
|
||||
{
|
||||
for (auto area : findChildren<CDockAreaWidget*>())
|
||||
{
|
||||
if(area->isCentralWidgetArea())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -71,6 +71,11 @@ public:
|
||||
* Returns last widget of nullptr is splitter is empty
|
||||
*/
|
||||
QWidget* lastWidget() const;
|
||||
|
||||
/**
|
||||
* Returns true if the splitter contains central widget of dock manager.
|
||||
*/
|
||||
bool isResizingWithContainer() const;
|
||||
}; // class CDockSplitter
|
||||
|
||||
} // namespace ads
|
||||
|
||||
@@ -340,6 +340,8 @@ void CDockWidget::setFeatures(DockWidgetFeatures features)
|
||||
d->Features = features;
|
||||
emit featuresChanged(d->Features);
|
||||
d->TabWidget->onDockWidgetFeaturesChanged();
|
||||
if(CDockAreaWidget* DockArea = dockAreaWidget())
|
||||
DockArea->onDockWidgetFeaturesChanged();
|
||||
}
|
||||
|
||||
|
||||
@@ -461,6 +463,13 @@ void CDockWidget::setMinimumSizeHintMode(eMinimumSizeHintMode Mode)
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CDockWidget::isCentralWidget() const
|
||||
{
|
||||
return dockManager()->centralWidget() == this;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidget::toggleView(bool Open)
|
||||
{
|
||||
@@ -540,6 +549,7 @@ void CDockWidget::setDockArea(CDockAreaWidget* DockArea)
|
||||
{
|
||||
d->DockArea = DockArea;
|
||||
d->ToggleViewAction->setChecked(DockArea != nullptr && !this->isClosed());
|
||||
setParent(DockArea);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -149,12 +149,14 @@ public:
|
||||
{
|
||||
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,
|
||||
DockWidgetFloatable = 0x04,///< dock widget can be dragged into a floating window
|
||||
DockWidgetDeleteOnClose = 0x08, ///< deletes the dock widget when it is closed
|
||||
CustomCloseHandling = 0x10,
|
||||
DockWidgetFocusable = 0x20,
|
||||
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 = 0x00
|
||||
};
|
||||
Q_DECLARE_FLAGS(DockWidgetFeatures, DockWidgetFeature)
|
||||
@@ -197,7 +199,7 @@ public:
|
||||
* To ensure, that a dock widget does not block resizing, the dock widget
|
||||
* reimplements minimumSizeHint() function to return a very small minimum
|
||||
* size hint. If you would like to adhere the minimumSizeHint() from the
|
||||
* content widget, the set the minimumSizeHintMode() to
|
||||
* content widget, then set the minimumSizeHintMode() to
|
||||
* MinimumSizeHintFromContent.
|
||||
*/
|
||||
enum eMinimumSizeHintMode
|
||||
@@ -360,6 +362,11 @@ public:
|
||||
*/
|
||||
void setMinimumSizeHintMode(eMinimumSizeHintMode Mode);
|
||||
|
||||
/**
|
||||
* Returns true if the dock widget is set as central widget of it's dock manager
|
||||
*/
|
||||
bool isCentralWidget() const;
|
||||
|
||||
/**
|
||||
* Sets the dock widget icon that is shown in tabs and in toggle view
|
||||
* actions
|
||||
@@ -577,7 +584,7 @@ signals:
|
||||
* This signal is emitted when the features property changes.
|
||||
* The features parameter gives the new value of the property.
|
||||
*/
|
||||
void featuresChanged(DockWidgetFeatures features);
|
||||
void featuresChanged(ads::CDockWidget::DockWidgetFeatures features);
|
||||
}; // class DockWidget
|
||||
}
|
||||
// namespace ads
|
||||
|
||||
@@ -51,7 +51,6 @@
|
||||
#include "DockManager.h"
|
||||
#include "IconProvider.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
@@ -77,6 +76,7 @@ struct DockWidgetTabPrivate
|
||||
QAbstractButton* CloseButton = nullptr;
|
||||
QSpacerItem* IconTextSpacer;
|
||||
QPoint TabDragStartPosition;
|
||||
QSize IconSize;
|
||||
|
||||
/**
|
||||
* Private data constructor
|
||||
@@ -134,6 +134,31 @@ struct DockWidgetTabPrivate
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the close button visibility from current feature/config
|
||||
*/
|
||||
void updateCloseButtonVisibility(bool active)
|
||||
{
|
||||
bool DockWidgetClosable = DockWidget->features().testFlag(CDockWidget::DockWidgetClosable);
|
||||
bool ActiveTabHasCloseButton = testConfigFlag(CDockManager::ActiveTabHasCloseButton);
|
||||
bool AllTabsHaveCloseButton = testConfigFlag(CDockManager::AllTabsHaveCloseButton);
|
||||
bool TabHasCloseButton = (ActiveTabHasCloseButton && active) | AllTabsHaveCloseButton;
|
||||
CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the size policy of the close button depending on the
|
||||
* RetainTabSizeWhenCloseButtonHidden feature
|
||||
*/
|
||||
void updateCloseButtonSizePolicy()
|
||||
{
|
||||
auto Features = DockWidget->features();
|
||||
auto SizePolicy = CloseButton->sizePolicy();
|
||||
SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable)
|
||||
&& testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden));
|
||||
CloseButton->setSizePolicy(SizePolicy);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
IFloatingWidget* createFloatingWidget(T* Widget, bool OpaqueUndocking)
|
||||
{
|
||||
@@ -161,6 +186,27 @@ struct DockWidgetTabPrivate
|
||||
DragStartMousePosition = _this->mapFromGlobal(GlobalPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the icon in case the icon size changed
|
||||
*/
|
||||
void updateIcon()
|
||||
{
|
||||
if (!IconLabel || Icon.isNull())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (IconSize.isValid())
|
||||
{
|
||||
IconLabel->setPixmap(Icon.pixmap(IconSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
IconLabel->setPixmap(Icon.pixmap(_this->style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, _this)));
|
||||
}
|
||||
IconLabel->setVisible(true);
|
||||
}
|
||||
|
||||
};
|
||||
// struct DockWidgetTabPrivate
|
||||
|
||||
@@ -188,7 +234,7 @@ void DockWidgetTabPrivate::createLayout()
|
||||
CloseButton->setObjectName("tabCloseButton");
|
||||
internal::setButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton, TabCloseIcon);
|
||||
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
_this->onDockWidgetFeaturesChanged();
|
||||
updateCloseButtonSizePolicy();
|
||||
internal::setToolTip(CloseButton, QObject::tr("Close Tab"));
|
||||
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
|
||||
|
||||
@@ -213,7 +259,7 @@ void DockWidgetTabPrivate::createLayout()
|
||||
void DockWidgetTabPrivate::moveTab(QMouseEvent* ev)
|
||||
{
|
||||
ev->accept();
|
||||
QPoint Distance = ev->globalPos() - GlobalDragStartMousePosition;
|
||||
QPoint Distance = internal::globalPositionOf(ev) - GlobalDragStartMousePosition;
|
||||
Distance.setY(0);
|
||||
auto TargetPos = Distance + TabDragStartPosition;
|
||||
TargetPos.rx() = qMax(TargetPos.x(), 0);
|
||||
@@ -305,7 +351,7 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
|
||||
if (ev->button() == Qt::LeftButton)
|
||||
{
|
||||
ev->accept();
|
||||
d->saveDragStartMousePosition(ev->globalPos());
|
||||
d->saveDragStartMousePosition(internal::globalPositionOf(ev));
|
||||
d->DragState = DraggingMousePressed;
|
||||
emit clicked();
|
||||
return;
|
||||
@@ -331,7 +377,7 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
|
||||
// End of tab moving, emit signal
|
||||
if (d->DockArea)
|
||||
{
|
||||
emit moved(ev->globalPos());
|
||||
emit moved(internal::globalPositionOf(ev));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -376,7 +422,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
||||
auto MappedPos = mapToParent(ev->pos());
|
||||
bool MouseOutsideBar = (MappedPos.x() < 0) || (MappedPos.x() > parentWidget()->rect().right());
|
||||
// Maybe a fixed drag distance is better here ?
|
||||
int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - ev->globalPos().y());
|
||||
int DragDistanceY = qAbs(d->GlobalDragStartMousePosition.y() - internal::globalPositionOf(ev).y());
|
||||
if (DragDistanceY >= CDockManager::startDragDistance() || MouseOutsideBar)
|
||||
{
|
||||
// If this is the last dock area in a dock container with only
|
||||
@@ -408,7 +454,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
|
||||
return;
|
||||
}
|
||||
else if (d->DockArea->openDockWidgetsCount() > 1
|
||||
&& (ev->globalPos() - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
|
||||
&& (internal::globalPositionOf(ev) - d->GlobalDragStartMousePosition).manhattanLength() >= QApplication::startDragDistance()) // Wait a few pixels before start moving
|
||||
{
|
||||
// If we start dragging the tab, we save its inital position to
|
||||
// restore it later
|
||||
@@ -461,11 +507,7 @@ bool CDockWidgetTab::isActiveTab() const
|
||||
//============================================================================
|
||||
void CDockWidgetTab::setActiveTab(bool active)
|
||||
{
|
||||
bool DockWidgetClosable = d->DockWidget->features().testFlag(CDockWidget::DockWidgetClosable);
|
||||
bool ActiveTabHasCloseButton = d->testConfigFlag(CDockManager::ActiveTabHasCloseButton);
|
||||
bool AllTabsHaveCloseButton = d->testConfigFlag(CDockManager::AllTabsHaveCloseButton);
|
||||
bool TabHasCloseButton = (ActiveTabHasCloseButton && active) | AllTabsHaveCloseButton;
|
||||
d->CloseButton->setVisible(DockWidgetClosable && TabHasCloseButton);
|
||||
d->updateCloseButtonVisibility(active);
|
||||
|
||||
// Focus related stuff
|
||||
if (CDockManager::testConfigFlag(CDockManager::FocusHighlighting) && !d->DockWidget->dockManager()->isRestoringState())
|
||||
@@ -549,11 +591,7 @@ void CDockWidgetTab::setIcon(const QIcon& Icon)
|
||||
}
|
||||
|
||||
d->Icon = Icon;
|
||||
if (d->IconLabel)
|
||||
{
|
||||
d->IconLabel->setPixmap(Icon.pixmap(style()->pixelMetric(QStyle::PM_SmallIconSize, nullptr, this)));
|
||||
d->IconLabel->setVisible(true);
|
||||
}
|
||||
d->updateIcon();
|
||||
}
|
||||
|
||||
|
||||
@@ -580,7 +618,7 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
|
||||
&& d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
|
||||
{
|
||||
d->saveDragStartMousePosition(event->globalPos());
|
||||
d->saveDragStartMousePosition(internal::globalPositionOf(event));
|
||||
d->startFloating(DraggingInactive);
|
||||
}
|
||||
|
||||
@@ -648,11 +686,8 @@ bool CDockWidgetTab::event(QEvent *e)
|
||||
//============================================================================
|
||||
void CDockWidgetTab::onDockWidgetFeaturesChanged()
|
||||
{
|
||||
auto Features = d->DockWidget->features();
|
||||
auto SizePolicy = d->CloseButton->sizePolicy();
|
||||
SizePolicy.setRetainSizeWhenHidden(Features.testFlag(CDockWidget::DockWidgetClosable)
|
||||
&& d->testConfigFlag(CDockManager::RetainTabSizeWhenCloseButtonHidden));
|
||||
d->CloseButton->setSizePolicy(SizePolicy);
|
||||
d->updateCloseButtonSizePolicy();
|
||||
d->updateCloseButtonVisibility(isActiveTab());
|
||||
}
|
||||
|
||||
|
||||
@@ -670,6 +705,21 @@ void CDockWidgetTab::updateStyle()
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QSize CDockWidgetTab::iconSize() const
|
||||
{
|
||||
return d->IconSize;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CDockWidgetTab::setIconSize(const QSize& Size)
|
||||
{
|
||||
d->IconSize = Size;
|
||||
d->updateIcon();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // namespace ads
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <QFrame>
|
||||
#include <QSize>
|
||||
|
||||
#include "ads_globals.h"
|
||||
|
||||
@@ -50,6 +51,7 @@ class ADS_EXPORT CDockWidgetTab : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool activeTab READ isActiveTab WRITE setActiveTab NOTIFY activeTabChanged)
|
||||
Q_PROPERTY(QSize iconSize READ iconSize WRITE setIconSize)
|
||||
|
||||
private:
|
||||
DockWidgetTabPrivate* d; ///< private data (pimpl)
|
||||
@@ -159,6 +161,20 @@ public:
|
||||
*/
|
||||
void updateStyle();
|
||||
|
||||
/**
|
||||
* Returns the icon size.
|
||||
* If no explicit icon size has been set, the function returns an invalid
|
||||
* QSize
|
||||
*/
|
||||
QSize iconSize() const;
|
||||
|
||||
/**
|
||||
* Set an explicit icon size.
|
||||
* If no icon size has been set explicitely, than the tab sets the icon size
|
||||
* depending on the style
|
||||
*/
|
||||
void setIconSize(const QSize& Size);
|
||||
|
||||
public slots:
|
||||
virtual void setVisible(bool visible) override;
|
||||
|
||||
|
||||
@@ -163,7 +163,12 @@ void CElidingLabel::resizeEvent(QResizeEvent *event)
|
||||
//============================================================================
|
||||
QSize CElidingLabel::minimumSizeHint() const
|
||||
{
|
||||
if (pixmap() != nullptr || d->isModeElideNone())
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
bool HasPixmap = !pixmap().isNull();
|
||||
#else
|
||||
bool HasPixmap = (pixmap() != nullptr);
|
||||
#endif
|
||||
if (HasPixmap || d->isModeElideNone())
|
||||
{
|
||||
return QLabel::minimumSizeHint();
|
||||
}
|
||||
@@ -180,7 +185,12 @@ QSize CElidingLabel::minimumSizeHint() const
|
||||
//============================================================================
|
||||
QSize CElidingLabel::sizeHint() const
|
||||
{
|
||||
if (pixmap() != nullptr || d->isModeElideNone())
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
bool HasPixmap = !pixmap().isNull();
|
||||
#else
|
||||
bool HasPixmap = (pixmap() != nullptr);
|
||||
#endif
|
||||
if (HasPixmap || d->isModeElideNone())
|
||||
{
|
||||
return QLabel::sizeHint();
|
||||
}
|
||||
|
||||
@@ -58,8 +58,8 @@ protected:
|
||||
public:
|
||||
using Super = QLabel;
|
||||
|
||||
CElidingLabel(QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||
CElidingLabel(const QString& text, QWidget* parent = 0, Qt::WindowFlags f = 0);
|
||||
CElidingLabel(QWidget* parent = 0, Qt::WindowFlags f = Qt::WindowFlags ());
|
||||
CElidingLabel(const QString& text, QWidget* parent = 0, Qt::WindowFlags f = Qt::WindowFlags ());
|
||||
virtual ~CElidingLabel();
|
||||
|
||||
/**
|
||||
|
||||
@@ -376,6 +376,7 @@ struct FloatingDockContainerPrivate
|
||||
#ifdef Q_OS_LINUX
|
||||
QWidget* MouseEventHandler = nullptr;
|
||||
CFloatingWidgetTitleBar* TitleBar = nullptr;
|
||||
bool IsResizing = false;
|
||||
#endif
|
||||
|
||||
/**
|
||||
@@ -410,10 +411,12 @@ struct FloatingDockContainerPrivate
|
||||
void setWindowTitle(const QString &Text)
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
TitleBar->setTitle(Text);
|
||||
#else
|
||||
_this->setWindowTitle(Text);
|
||||
if (TitleBar)
|
||||
{
|
||||
TitleBar->setTitle(Text);
|
||||
}
|
||||
#endif
|
||||
_this->setWindowTitle(Text);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -604,13 +607,52 @@ CFloatingDockContainer::CFloatingDockContainer(CDockManager *DockManager) :
|
||||
SLOT(onDockAreasAddedOrRemoved()));
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
d->TitleBar = new CFloatingWidgetTitleBar(this);
|
||||
setWindowFlags(windowFlags() | Qt::Tool);
|
||||
QDockWidget::setWidget(d->DockContainer);
|
||||
QDockWidget::setFloating(true);
|
||||
QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
setTitleBarWidget(d->TitleBar);
|
||||
connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
|
||||
QDockWidget::setWidget(d->DockContainer);
|
||||
QDockWidget::setFloating(true);
|
||||
QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
|
||||
|
||||
bool native_window = true;
|
||||
|
||||
// FloatingContainerForce*TitleBar is overwritten by the "ADS_UseNativeTitle" environment variable if set.
|
||||
auto env = qgetenv("ADS_UseNativeTitle").toUpper();
|
||||
if (env == "1")
|
||||
{
|
||||
native_window = true;
|
||||
}
|
||||
else if (env == "0")
|
||||
{
|
||||
native_window = false;
|
||||
}
|
||||
else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceNativeTitleBar))
|
||||
{
|
||||
native_window = true;
|
||||
}
|
||||
else if (DockManager->testConfigFlag(CDockManager::FloatingContainerForceQWidgetTitleBar))
|
||||
{
|
||||
native_window = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// KDE doesn't seem to fire MoveEvents while moving windows, so for now no native titlebar for everything using KWin.
|
||||
QString window_manager = internal::windowManager().toUpper().split(" ")[0];
|
||||
native_window = window_manager != "KWIN";
|
||||
}
|
||||
|
||||
if (native_window)
|
||||
{
|
||||
setTitleBarWidget(new QWidget());
|
||||
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint);
|
||||
}
|
||||
else
|
||||
{
|
||||
d->TitleBar = new CFloatingWidgetTitleBar(this);
|
||||
setTitleBarWidget(d->TitleBar);
|
||||
setWindowFlags(Qt::Window | Qt::WindowMinMaxButtonsHint | Qt::FramelessWindowHint);
|
||||
d->TitleBar->enableCloseButton(isClosable());
|
||||
connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
|
||||
connect(d->TitleBar, &CFloatingWidgetTitleBar::maximizeRequested,
|
||||
this, &CFloatingDockContainer::onMaximizeRequest);
|
||||
}
|
||||
#else
|
||||
setWindowFlags(
|
||||
Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
|
||||
@@ -629,9 +671,7 @@ CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget *DockArea) :
|
||||
CFloatingDockContainer(DockArea->dockManager())
|
||||
{
|
||||
d->DockContainer->addDockArea(DockArea);
|
||||
#ifdef Q_OS_LINUX
|
||||
d->TitleBar->enableCloseButton(isClosable());
|
||||
#endif
|
||||
|
||||
auto TopLevelDockWidget = topLevelDockWidget();
|
||||
if (TopLevelDockWidget)
|
||||
{
|
||||
@@ -646,9 +686,6 @@ CFloatingDockContainer::CFloatingDockContainer(CDockWidget *DockWidget) :
|
||||
CFloatingDockContainer(DockWidget->dockManager())
|
||||
{
|
||||
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
|
||||
#ifdef Q_OS_LINUX
|
||||
d->TitleBar->enableCloseButton(isClosable());
|
||||
#endif
|
||||
auto TopLevelDockWidget = topLevelDockWidget();
|
||||
if (TopLevelDockWidget)
|
||||
{
|
||||
@@ -678,19 +715,29 @@ CDockContainerWidget* CFloatingDockContainer::dockContainer() const
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::changeEvent(QEvent *event)
|
||||
{
|
||||
QWidget::changeEvent(event);
|
||||
Super::changeEvent(event);
|
||||
if ((event->type() == QEvent::ActivationChange) && isActiveWindow())
|
||||
{
|
||||
ADS_PRINT("FloatingWidget::changeEvent QEvent::ActivationChange ");
|
||||
d->zOrderIndex = ++zOrderCounter;
|
||||
return;
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
if (d->DraggingState == DraggingFloatingWidget)
|
||||
{
|
||||
d->titleMouseReleaseEvent();
|
||||
d->DraggingState = DraggingInactive;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
//============================================================================
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
||||
#else
|
||||
bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *message, qintptr *result)
|
||||
#endif
|
||||
{
|
||||
QWidget::nativeEvent(eventType, message, result);
|
||||
MSG *msg = static_cast<MSG*>(message);
|
||||
@@ -708,7 +755,7 @@ bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *mess
|
||||
case WM_NCLBUTTONDOWN:
|
||||
if (msg->wParam == HTCAPTION && d->isState(DraggingInactive))
|
||||
{
|
||||
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_NCLBUTTONDOWN" << e->type());
|
||||
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_NCLBUTTONDOWN");
|
||||
d->DragStartPos = pos();
|
||||
d->setState(DraggingMousePressed);
|
||||
}
|
||||
@@ -721,7 +768,7 @@ bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *mess
|
||||
case WM_ENTERSIZEMOVE:
|
||||
if (d->isState(DraggingMousePressed))
|
||||
{
|
||||
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_ENTERSIZEMOVE" << e->type());
|
||||
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_ENTERSIZEMOVE");
|
||||
d->setState(DraggingFloatingWidget);
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
@@ -730,7 +777,7 @@ bool CFloatingDockContainer::nativeEvent(const QByteArray &eventType, void *mess
|
||||
case WM_EXITSIZEMOVE:
|
||||
if (d->isState(DraggingFloatingWidget))
|
||||
{
|
||||
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_EXITSIZEMOVE" << e->type());
|
||||
ADS_PRINT("CFloatingDockContainer::nativeEvent WM_EXITSIZEMOVE");
|
||||
if (GetAsyncKeyState(VK_ESCAPE) & 0x8000)
|
||||
{
|
||||
d->handleEscapeKey();
|
||||
@@ -822,25 +869,35 @@ void CFloatingDockContainer::showEvent(QShowEvent *event)
|
||||
void CFloatingDockContainer::startFloating(const QPoint &DragStartMousePos,
|
||||
const QSize &Size, eDragState DragState, QWidget *MouseEventHandler)
|
||||
{
|
||||
#ifndef Q_OS_LINUX
|
||||
Q_UNUSED(MouseEventHandler)
|
||||
#endif
|
||||
resize(Size);
|
||||
d->setState(DragState);
|
||||
d->DragStartMousePosition = DragStartMousePos;
|
||||
#ifdef Q_OS_LINUX
|
||||
if (!isMaximized())
|
||||
{
|
||||
resize(Size);
|
||||
d->DragStartMousePosition = DragStartMousePos;
|
||||
}
|
||||
d->setState(DragState);
|
||||
if (DraggingFloatingWidget == DragState)
|
||||
{
|
||||
setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
|
||||
d->MouseEventHandler = MouseEventHandler;
|
||||
if (d->MouseEventHandler)
|
||||
{
|
||||
d->MouseEventHandler->grabMouse();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!isMaximized())
|
||||
{
|
||||
moveFloating();
|
||||
}
|
||||
show();
|
||||
#else
|
||||
Q_UNUSED(MouseEventHandler)
|
||||
resize(Size);
|
||||
d->DragStartMousePosition = DragStartMousePos;
|
||||
d->setState(DragState);
|
||||
moveFloating();
|
||||
show();
|
||||
#endif
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
@@ -850,7 +907,6 @@ void CFloatingDockContainer::moveFloating()
|
||||
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition
|
||||
- QPoint(BorderSize, 0);
|
||||
move(moveToPos);
|
||||
|
||||
switch (d->DraggingState)
|
||||
{
|
||||
case DraggingMousePressed:
|
||||
@@ -949,11 +1005,17 @@ bool CFloatingDockContainer::restoreState(CDockingStateReader &Stream,
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
onDockAreasAddedOrRemoved();
|
||||
#ifdef Q_OS_LINUX
|
||||
if(d->TitleBar)
|
||||
{
|
||||
d->TitleBar->setMaximizedIcon(windowState() == Qt::WindowMaximized);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::hasTopLevelDockWidget() const
|
||||
{
|
||||
@@ -977,19 +1039,17 @@ void CFloatingDockContainer::finishDragging()
|
||||
{
|
||||
ADS_PRINT("CFloatingDockContainer::finishDragging");
|
||||
#ifdef Q_OS_LINUX
|
||||
setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
|
||||
setWindowOpacity(1);
|
||||
activateWindow();
|
||||
if (d->MouseEventHandler)
|
||||
{
|
||||
d->MouseEventHandler->releaseMouse();
|
||||
d->MouseEventHandler = nullptr;
|
||||
}
|
||||
setWindowOpacity(1);
|
||||
activateWindow();
|
||||
if (d->MouseEventHandler)
|
||||
{
|
||||
d->MouseEventHandler->releaseMouse();
|
||||
d->MouseEventHandler = nullptr;
|
||||
}
|
||||
#endif
|
||||
d->titleMouseReleaseEvent();
|
||||
d->titleMouseReleaseEvent();
|
||||
}
|
||||
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::event(QEvent *e)
|
||||
@@ -1092,6 +1152,97 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::onMaximizeRequest()
|
||||
{
|
||||
if (windowState() == Qt::WindowMaximized)
|
||||
{
|
||||
showNormal();
|
||||
}
|
||||
else
|
||||
{
|
||||
showMaximized();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::showNormal(bool fixGeometry)
|
||||
{
|
||||
if (windowState() == Qt::WindowMaximized)
|
||||
{
|
||||
QRect oldNormal = normalGeometry();
|
||||
Super::showNormal();
|
||||
if(fixGeometry)
|
||||
{
|
||||
setGeometry(oldNormal);
|
||||
}
|
||||
}
|
||||
if(d->TitleBar)
|
||||
{
|
||||
d->TitleBar->setMaximizedIcon(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::showMaximized()
|
||||
{
|
||||
Super::showMaximized();
|
||||
if (d->TitleBar)
|
||||
{
|
||||
d->TitleBar->setMaximizedIcon(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::isMaximized() const
|
||||
{
|
||||
return windowState() == Qt::WindowMaximized;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::show()
|
||||
{
|
||||
// Prevent this window from showing in the taskbar and pager (alt+tab)
|
||||
internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_TASKBAR");
|
||||
internal::xcb_add_prop(true, winId(), "_NET_WM_STATE", "_NET_WM_STATE_SKIP_PAGER");
|
||||
Super::show();
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::resizeEvent(QResizeEvent *event)
|
||||
{
|
||||
d->IsResizing = true;
|
||||
Super::resizeEvent(event);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
|
||||
{
|
||||
Super::moveEvent(event);
|
||||
if (!d->IsResizing && event->spontaneous())
|
||||
{
|
||||
d->DraggingState = DraggingFloatingWidget;
|
||||
d->updateDropOverlays(QCursor::pos());
|
||||
}
|
||||
d->IsResizing = false;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
bool CFloatingDockContainer::hasNativeTitleBar()
|
||||
{
|
||||
return d->TitleBar == nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace ads
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
@@ -185,16 +185,25 @@ protected: // reimplements QWidget
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
virtual void moveEvent(QMoveEvent *event) override;
|
||||
virtual void resizeEvent(QResizeEvent *event) override;
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_WIN
|
||||
/**
|
||||
* Native event filter for handling WM_MOVING messages on Windows
|
||||
*/
|
||||
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||
#if (QT_VERSION < QT_VERSION_CHECK(6, 0, 0))
|
||||
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
||||
#else
|
||||
virtual bool nativeEvent(const QByteArray &eventType, void *message, qintptr *result) override;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
public:
|
||||
using Super = QWidget;
|
||||
using Super = tFloatingWidgetBase;
|
||||
|
||||
/**
|
||||
* Create empty floating widget - required for restore state
|
||||
@@ -248,6 +257,44 @@ public:
|
||||
* function of the internal container widget.
|
||||
*/
|
||||
QList<CDockWidget*> dockWidgets() const;
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
/**
|
||||
* This is a function that responds to FloatingWidgetTitleBar::maximizeRequest()
|
||||
* Maximize or normalize the container size.
|
||||
*/
|
||||
void onMaximizeRequest();
|
||||
|
||||
/**
|
||||
* Normalize (Unmaximize) the window.
|
||||
* fixGeometry parameter fixes a "bug" in QT where immediately after calling showNormal
|
||||
* geometry is not set properly.
|
||||
* Set this true when moving the window immediately after normalizing.
|
||||
*/
|
||||
void showNormal(bool fixGeometry=false);
|
||||
|
||||
/**
|
||||
* Maximizes the window.
|
||||
*/
|
||||
void showMaximized();
|
||||
|
||||
/**
|
||||
* Returns if the window is currently maximized or not.
|
||||
*/
|
||||
bool isMaximized() const;
|
||||
|
||||
/**
|
||||
* Patched show to prevent the window from appearing in the taskbar.
|
||||
*/
|
||||
void show();
|
||||
|
||||
/**
|
||||
* Returns true if the floating widget has a native titlebar or false if
|
||||
* the floating widget has a QWidget based title bar
|
||||
*/
|
||||
bool hasNativeTitleBar();
|
||||
#endif
|
||||
|
||||
}; // class FloatingDockContainer
|
||||
}
|
||||
// namespace ads
|
||||
|
||||
@@ -10,5 +10,9 @@
|
||||
<file>images/tabs-menu-button.svg</file>
|
||||
<file>images/detach-button.svg</file>
|
||||
<file>images/detach-button-disabled.svg</file>
|
||||
<file>images/maximize-button.svg</file>
|
||||
<file>images/maximize-button-focused.svg</file>
|
||||
<file>images/restore-button.svg</file>
|
||||
<file>images/restore-button-focused.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
@@ -38,12 +38,255 @@
|
||||
#include "IconProvider.h"
|
||||
#include "ads_globals.h"
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <QX11Info>
|
||||
#include <QSettings>
|
||||
#include <QFile>
|
||||
#endif
|
||||
|
||||
|
||||
#include <QApplication>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
|
||||
namespace internal
|
||||
{
|
||||
#ifdef Q_OS_LINUX
|
||||
static QString _window_manager;
|
||||
static QHash<QString, xcb_atom_t> _xcb_atom_cache;
|
||||
|
||||
|
||||
//============================================================================
|
||||
xcb_atom_t xcb_get_atom(const char *name)
|
||||
{
|
||||
if (!QX11Info::isPlatformX11())
|
||||
{
|
||||
return XCB_ATOM_NONE;
|
||||
}
|
||||
auto key = QString(name);
|
||||
if(_xcb_atom_cache.contains(key))
|
||||
{
|
||||
return _xcb_atom_cache[key];
|
||||
}
|
||||
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)
|
||||
{
|
||||
return XCB_ATOM_NONE;
|
||||
}
|
||||
xcb_atom_t atom = reply->atom;
|
||||
if(atom == XCB_ATOM_NONE)
|
||||
{
|
||||
ADS_PRINT("Unknown Atom response from XServer: " << name);
|
||||
}
|
||||
else
|
||||
{
|
||||
_xcb_atom_cache.insert(key, atom);
|
||||
}
|
||||
free(reply);
|
||||
return atom;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2)
|
||||
{
|
||||
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;
|
||||
event.response_type = XCB_CLIENT_MESSAGE;
|
||||
event.format = 32;
|
||||
event.sequence = 0;
|
||||
event.window = window;
|
||||
event.type = type_atom;
|
||||
event.data.data32[0] = set ? 1 : 0;
|
||||
event.data.data32[1] = prop_atom;
|
||||
event.data.data32[2] = prop2 ? xcb_get_atom(prop2) : 0;
|
||||
event.data.data32[3] = 0;
|
||||
event.data.data32[4] = 0;
|
||||
|
||||
xcb_send_event(connection, 0, window,
|
||||
XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT | XCB_EVENT_MASK_PROPERTY_CHANGE,
|
||||
(const char *)&event);
|
||||
xcb_flush(connection);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
xcb_get_property_reply_t* _xcb_get_props(WId window, const char *type, unsigned int atom_type)
|
||||
{
|
||||
if (!QX11Info::isPlatformX11())
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
xcb_connection_t *connection = QX11Info::connection();
|
||||
xcb_atom_t type_atom = xcb_get_atom(type);
|
||||
if (type_atom == XCB_ATOM_NONE)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
xcb_get_property_cookie_t request = xcb_get_property_unchecked(connection, 0, window, type_atom, atom_type, 0, 1024);
|
||||
xcb_get_property_reply_t *reply = xcb_get_property_reply(connection, request, nullptr);
|
||||
if(reply && reply->type != atom_type)
|
||||
{
|
||||
ADS_PRINT("ATOM TYPE MISMATCH (" << type <<"). Expected: " << atom_type << " but got " << reply->type);
|
||||
free(reply);
|
||||
return nullptr;
|
||||
}
|
||||
return reply;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
template <typename T>
|
||||
void xcb_get_prop_list(WId window, const char *type, QVector<T> &ret, unsigned int atom_type)
|
||||
{
|
||||
xcb_get_property_reply_t *reply = _xcb_get_props(window, type, atom_type);
|
||||
if (reply && reply->format == 32 && reply->type == atom_type && reply->value_len > 0)
|
||||
{
|
||||
const xcb_atom_t *data = static_cast<const T *>(xcb_get_property_value(reply));
|
||||
ret.resize(reply->value_len);
|
||||
memcpy((void *)&ret.first(), (void *)data, reply->value_len * sizeof(T));
|
||||
}
|
||||
free(reply);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QString xcb_get_prop_string(WId window, const char *type)
|
||||
{
|
||||
QString ret;
|
||||
// try utf8 first
|
||||
xcb_atom_t utf_atom = xcb_get_atom("UTF8_STRING");
|
||||
if(utf_atom != XCB_ATOM_NONE)
|
||||
{
|
||||
xcb_get_property_reply_t *reply = _xcb_get_props(window, type, utf_atom);
|
||||
if (reply && reply->format == 8 && reply->type == utf_atom)
|
||||
{
|
||||
const char *value = reinterpret_cast<const char *>(xcb_get_property_value(reply));
|
||||
ret = QString::fromUtf8(value, xcb_get_property_value_length(reply));
|
||||
free(reply);
|
||||
return ret;
|
||||
}
|
||||
free(reply);
|
||||
}
|
||||
// Fall back to XCB_ATOM_STRING
|
||||
xcb_get_property_reply_t *reply = _xcb_get_props(window, type, XCB_ATOM_STRING);
|
||||
if (reply && reply->format == 8 && reply->type == XCB_ATOM_STRING)
|
||||
{
|
||||
const char *value = reinterpret_cast<const char *>(xcb_get_property_value(reply));
|
||||
ret = QString::fromLatin1(value, xcb_get_property_value_length(reply));
|
||||
}
|
||||
free(reply);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
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 = QX11Info::connection();
|
||||
for (auto atom : atoms)
|
||||
{
|
||||
auto foo = xcb_get_atom_name(connection, atom);
|
||||
auto bar = xcb_get_atom_name_reply(connection, foo, nullptr);
|
||||
qDebug() << "\t" << xcb_get_atom_name_name(bar);
|
||||
free(bar);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void xcb_add_prop(bool state, WId window, const char *type, const char *prop)
|
||||
{
|
||||
if (!QX11Info::isPlatformX11())
|
||||
{
|
||||
return;
|
||||
}
|
||||
xcb_atom_t prop_atom = xcb_get_atom(prop);
|
||||
xcb_atom_t type_atom = xcb_get_atom(type);
|
||||
if (prop_atom == XCB_ATOM_NONE || type_atom == XCB_ATOM_NONE)
|
||||
{
|
||||
return;
|
||||
}
|
||||
QVector<xcb_atom_t> atoms;
|
||||
xcb_get_prop_list(window, type, atoms, XCB_ATOM_ATOM);
|
||||
int index = atoms.indexOf(prop_atom);
|
||||
if (state && index == -1)
|
||||
{
|
||||
atoms.push_back(prop_atom);
|
||||
}
|
||||
else if (!state && index >= 0)
|
||||
{
|
||||
atoms.remove(index);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QString detectWindowManagerX11()
|
||||
{
|
||||
// Tries to detect the windowmanager via X11.
|
||||
// See: https://specifications.freedesktop.org/wm-spec/1.3/ar01s03.html#idm46018259946000
|
||||
if (!QX11Info::isPlatformX11())
|
||||
{
|
||||
return "UNKNOWN";
|
||||
}
|
||||
xcb_connection_t *connection = QX11Info::connection();
|
||||
xcb_screen_t *first_screen = xcb_setup_roots_iterator (xcb_get_setup (connection)).data;
|
||||
if(!first_screen)
|
||||
{
|
||||
ADS_PRINT("No screen found via XCB.");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
// Get supporting window ()
|
||||
xcb_window_t root = first_screen->root;
|
||||
xcb_window_t support_win = 0;
|
||||
QVector<xcb_window_t> sup_windows;
|
||||
xcb_get_prop_list(root, "_NET_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_WINDOW);
|
||||
if(sup_windows.length() == 0)
|
||||
{
|
||||
// This doesn't seem to be in use anymore, but wmctrl does the same so lets play safe.
|
||||
// Both XCB_ATOM_CARDINAL and XCB_ATOM_WINDOW break down to a uint32_t, so reusing sup_windows should be fine.
|
||||
xcb_get_prop_list(root, "_WIN_SUPPORTING_WM_CHECK", sup_windows, XCB_ATOM_CARDINAL);
|
||||
}
|
||||
if(sup_windows.length() == 0)
|
||||
{
|
||||
ADS_PRINT("Failed to get the supporting window on non EWMH comform WM.");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
support_win = sup_windows[0];
|
||||
QString ret = xcb_get_prop_string(support_win, "_NET_WM_NAME");
|
||||
if(ret.length() == 0)
|
||||
{
|
||||
ADS_PRINT("Empty WM name occured.");
|
||||
return "UNKNOWN";
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
QString windowManager()
|
||||
{
|
||||
if(_window_manager.length() == 0)
|
||||
{
|
||||
_window_manager = detectWindowManagerX11();
|
||||
}
|
||||
return _window_manager;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
//============================================================================
|
||||
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,11 @@
|
||||
#include <QWidget>
|
||||
#include <QDebug>
|
||||
#include <QStyle>
|
||||
#include <QMouseEvent>
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include <xcb/xcb.h>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QAbstractButton)
|
||||
|
||||
@@ -122,6 +127,7 @@ enum eBitwiseOperator
|
||||
BitwiseOr
|
||||
};
|
||||
|
||||
|
||||
namespace internal
|
||||
{
|
||||
static const bool RestoreTesting = true;
|
||||
@@ -129,6 +135,33 @@ static const bool Restore = false;
|
||||
static const char* const ClosedProperty = "close";
|
||||
static const char* const DirtyProperty = "dirty";
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
// Utils to directly communicate with the X server
|
||||
/**
|
||||
* Get atom from cache or request it from the XServer.
|
||||
*/
|
||||
xcb_atom_t xcb_get_atom(const char *name);
|
||||
|
||||
/**
|
||||
* Add a property to a window. Only works on "hidden" windows.
|
||||
*/
|
||||
void xcb_add_prop(bool state, WId window, const char *type, const char *prop);
|
||||
/**
|
||||
* Updates up to two window properties. Can be set on a visible window.
|
||||
*/
|
||||
void xcb_update_prop(bool set, WId window, const char *type, const char *prop, const char *prop2 = nullptr);
|
||||
/**
|
||||
* Only for debugging purposes.
|
||||
*/
|
||||
bool xcb_dump_props(WId window, const char *type);
|
||||
/**
|
||||
* Gets the active window manager from the X11 Server.
|
||||
* Requires a EWMH conform window manager (Allmost all common used ones are).
|
||||
* Returns "UNKNOWN" otherwise.
|
||||
*/
|
||||
QString windowManager();
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Replace the from widget in the given splitter with the To widget
|
||||
*/
|
||||
@@ -147,7 +180,7 @@ void hideEmptyParentSplitters(CDockSplitter* FirstParentSplitter);
|
||||
class CDockInsertParam : public QPair<Qt::Orientation, bool>
|
||||
{
|
||||
public:
|
||||
using QPair::QPair;
|
||||
using QPair<Qt::Orientation, bool>::QPair;
|
||||
Qt::Orientation orientation() const {return this->first;}
|
||||
bool append() const {return this->second;}
|
||||
int insertOffset() const {return append() ? 1 : 0;}
|
||||
@@ -228,6 +261,19 @@ void setToolTip(QObjectPtr obj, const QString &tip)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function for access to mouse event global position in Qt5 and
|
||||
*/
|
||||
inline QPoint globalPositionOf(QMouseEvent* ev)
|
||||
{
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(6, 0, 0))
|
||||
return ev->globalPosition().toPoint();
|
||||
#else
|
||||
return ev->globalPos();
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Helper function to set the icon of a certain button.
|
||||
* Use this function to set the icons for the dock area and dock widget buttons.
|
||||
|
||||
145
src/images/maximize-button-focused.svg
Normal file
@@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="maximize-button-focused.svg">
|
||||
<style
|
||||
id="style2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-4" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-3" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-8" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="-7.4143106"
|
||||
inkscape:cy="6.591104"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g5228"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1848"
|
||||
inkscape:window-height="920"
|
||||
inkscape:window-x="72"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:document-rotation="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3336" />
|
||||
<sodipodi:guide
|
||||
position="4,10"
|
||||
orientation="1,0"
|
||||
id="guide883"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="10,12"
|
||||
orientation="0,-1"
|
||||
id="guide885"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="12,2"
|
||||
orientation="1,0"
|
||||
id="guide887"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="14,4"
|
||||
orientation="0,-1"
|
||||
id="guide889"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1036.3622)">
|
||||
<g
|
||||
transform="translate(628,-140.49998)"
|
||||
id="g5228">
|
||||
<rect
|
||||
id="rect4094"
|
||||
width="7"
|
||||
height="7"
|
||||
x="-623.5"
|
||||
y="1181.3622"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||
</g>
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<rdf:Description
|
||||
about="https://iconscout.com/legal#licenses"
|
||||
dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:publisher="Iconscout"
|
||||
dc:date="2016-12-14"
|
||||
dc:format="image/svg+xml"
|
||||
dc:language="en">
|
||||
<dc:creator>
|
||||
<rdf:Bag>
|
||||
<rdf:li>Jemis Mali</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:creator>
|
||||
</rdf:Description>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
145
src/images/maximize-button.svg
Normal file
@@ -0,0 +1,145 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="maximize-button.svg">
|
||||
<style
|
||||
id="style2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-4" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-3" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-8" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="-1.8674356"
|
||||
inkscape:cy="6.591104"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g5228"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1848"
|
||||
inkscape:window-height="920"
|
||||
inkscape:window-x="72"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:document-rotation="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3336" />
|
||||
<sodipodi:guide
|
||||
position="4,10"
|
||||
orientation="1,0"
|
||||
id="guide883"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="10,12"
|
||||
orientation="0,-1"
|
||||
id="guide885"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="12,2"
|
||||
orientation="1,0"
|
||||
id="guide887"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="14,4"
|
||||
orientation="0,-1"
|
||||
id="guide889"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1036.3622)">
|
||||
<g
|
||||
transform="translate(628,-140.49998)"
|
||||
id="g5228">
|
||||
<rect
|
||||
id="rect4094"
|
||||
width="7"
|
||||
height="7"
|
||||
x="-623.5"
|
||||
y="1181.3622"
|
||||
style="fill:none;stroke:#000000;stroke-width:0.99999994;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||
</g>
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<rdf:Description
|
||||
about="https://iconscout.com/legal#licenses"
|
||||
dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:publisher="Iconscout"
|
||||
dc:date="2016-12-14"
|
||||
dc:format="image/svg+xml"
|
||||
dc:language="en">
|
||||
<dc:creator>
|
||||
<rdf:Bag>
|
||||
<rdf:li>Jemis Mali</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:creator>
|
||||
</rdf:Description>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title />
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
150
src/images/restore-button-focused.svg
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="restore-button-focused.svg">
|
||||
<style
|
||||
id="style2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-4" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-3" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-8" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="3.6794394"
|
||||
inkscape:cy="7.841104"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g5228"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1848"
|
||||
inkscape:window-height="920"
|
||||
inkscape:window-x="72"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:document-rotation="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3336" />
|
||||
<sodipodi:guide
|
||||
position="4,10"
|
||||
orientation="1,0"
|
||||
id="guide883"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="10,12"
|
||||
orientation="0,-1"
|
||||
id="guide885"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="12,2"
|
||||
orientation="1,0"
|
||||
id="guide887"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="14,4"
|
||||
orientation="0,-1"
|
||||
id="guide889"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1036.3622)">
|
||||
<g
|
||||
transform="translate(628,-140.49998)"
|
||||
id="g5228">
|
||||
<rect
|
||||
id="rect4094"
|
||||
width="5.055603"
|
||||
height="5.0555329"
|
||||
x="-623.5556"
|
||||
y="1183.3622"
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||
<path
|
||||
style="fill:none;stroke:#ffffff;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -621.98958,1181.3414 h 5.51042 v 5.4999"
|
||||
id="path6127"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<rdf:Description
|
||||
about="https://iconscout.com/legal#licenses"
|
||||
dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:publisher="Iconscout"
|
||||
dc:date="2016-12-14"
|
||||
dc:format="image/svg+xml"
|
||||
dc:language="en">
|
||||
<dc:creator>
|
||||
<rdf:Bag>
|
||||
<rdf:li>Jemis Mali</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:creator>
|
||||
</rdf:Description>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
150
src/images/restore-button.svg
Normal file
@@ -0,0 +1,150 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="16px"
|
||||
height="16px"
|
||||
viewBox="0 0 16 16"
|
||||
id="svg2"
|
||||
version="1.1"
|
||||
inkscape:version="0.92.5 (2060ec1f9f, 2020-04-08)"
|
||||
sodipodi:docname="restore-button.svg">
|
||||
<style
|
||||
id="style2" />
|
||||
<defs
|
||||
id="defs4">
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-4" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-3" />
|
||||
<pattern
|
||||
y="0"
|
||||
x="0"
|
||||
height="6"
|
||||
width="6"
|
||||
patternUnits="userSpaceOnUse"
|
||||
id="EMFhbasepattern-8" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="32"
|
||||
inkscape:cx="3.6794394"
|
||||
inkscape:cy="7.841104"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="g5228"
|
||||
showgrid="true"
|
||||
units="px"
|
||||
inkscape:window-width="1848"
|
||||
inkscape:window-height="920"
|
||||
inkscape:window-x="72"
|
||||
inkscape:window-y="27"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:snap-bbox="true"
|
||||
inkscape:bbox-paths="true"
|
||||
inkscape:bbox-nodes="true"
|
||||
inkscape:snap-bbox-edge-midpoints="true"
|
||||
inkscape:snap-bbox-midpoints="true"
|
||||
inkscape:snap-global="true"
|
||||
inkscape:document-rotation="0"
|
||||
showguides="true"
|
||||
inkscape:guide-bbox="true">
|
||||
<inkscape:grid
|
||||
type="xygrid"
|
||||
id="grid3336" />
|
||||
<sodipodi:guide
|
||||
position="4,10"
|
||||
orientation="1,0"
|
||||
id="guide883"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="10,12"
|
||||
orientation="0,-1"
|
||||
id="guide885"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="12,2"
|
||||
orientation="1,0"
|
||||
id="guide887"
|
||||
inkscape:locked="false" />
|
||||
<sodipodi:guide
|
||||
position="14,4"
|
||||
orientation="0,-1"
|
||||
id="guide889"
|
||||
inkscape:locked="false" />
|
||||
</sodipodi:namedview>
|
||||
<g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-1036.3622)">
|
||||
<g
|
||||
transform="translate(628,-140.49998)"
|
||||
id="g5228">
|
||||
<rect
|
||||
id="rect4094"
|
||||
width="5.055603"
|
||||
height="5.0555329"
|
||||
x="-623.5556"
|
||||
y="1183.3622"
|
||||
style="fill:none;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" />
|
||||
<path
|
||||
style="fill:none;stroke:#000000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||
d="m -621.98958,1181.3414 h 5.51042 v 5.4999"
|
||||
id="path6127"
|
||||
inkscape:connector-curvature="0" />
|
||||
</g>
|
||||
</g>
|
||||
<metadata
|
||||
id="metadata12">
|
||||
<rdf:RDF>
|
||||
<rdf:Description
|
||||
about="https://iconscout.com/legal#licenses"
|
||||
dc:title="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:description="Menu, Bar, Lines, Option, List, Hamburger, Web"
|
||||
dc:publisher="Iconscout"
|
||||
dc:date="2016-12-14"
|
||||
dc:format="image/svg+xml"
|
||||
dc:language="en">
|
||||
<dc:creator>
|
||||
<rdf:Bag>
|
||||
<rdf:li>Jemis Mali</rdf:li>
|
||||
</rdf:Bag>
|
||||
</dc:creator>
|
||||
</rdf:Description>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.1 KiB |
@@ -46,6 +46,7 @@ namespace ads
|
||||
|
||||
using tTabLabel = CElidingLabel;
|
||||
using tCloseButton = QToolButton;
|
||||
using tMaximizeButton = QToolButton;
|
||||
|
||||
/**
|
||||
* @brief Private data class of public interface CFloatingWidgetTitleBar
|
||||
@@ -56,8 +57,12 @@ struct FloatingWidgetTitleBarPrivate
|
||||
QLabel *IconLabel = nullptr;
|
||||
tTabLabel *TitleLabel;
|
||||
tCloseButton *CloseButton = nullptr;
|
||||
tMaximizeButton* MaximizeButton = nullptr;
|
||||
CFloatingDockContainer *FloatingWidget = nullptr;
|
||||
eDragState DragState = DraggingInactive;
|
||||
QIcon MaximizeIcon;
|
||||
QIcon NormalIcon;
|
||||
bool Maximized = false;
|
||||
|
||||
FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar *_public) :
|
||||
_this(_public)
|
||||
@@ -83,6 +88,10 @@ void FloatingWidgetTitleBarPrivate::createLayout()
|
||||
CloseButton->setObjectName("floatingTitleCloseButton");
|
||||
CloseButton->setAutoRaise(true);
|
||||
|
||||
MaximizeButton = new tMaximizeButton();
|
||||
MaximizeButton->setObjectName("floatingTitleMaximizeButton");
|
||||
MaximizeButton->setAutoRaise(true);
|
||||
|
||||
// The standard icons do does not look good on high DPI screens
|
||||
QIcon CloseIcon;
|
||||
QPixmap normalPixmap = _this->style()->standardPixmap(
|
||||
@@ -97,6 +106,12 @@ void FloatingWidgetTitleBarPrivate::createLayout()
|
||||
CloseButton->setFocusPolicy(Qt::NoFocus);
|
||||
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
|
||||
|
||||
_this->setMaximizedIcon(false);
|
||||
MaximizeButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
MaximizeButton->setVisible(true);
|
||||
MaximizeButton->setFocusPolicy(Qt::NoFocus);
|
||||
_this->connect(MaximizeButton, &QPushButton::clicked, _this, &CFloatingWidgetTitleBar::maximizeRequested);
|
||||
|
||||
QFontMetrics fm(TitleLabel->font());
|
||||
int Spacing = qRound(fm.height() / 4.0);
|
||||
|
||||
@@ -107,6 +122,7 @@ void FloatingWidgetTitleBarPrivate::createLayout()
|
||||
_this->setLayout(Layout);
|
||||
Layout->addWidget(TitleLabel, 1);
|
||||
Layout->addSpacing(Spacing);
|
||||
Layout->addWidget(MaximizeButton);
|
||||
Layout->addWidget(CloseButton);
|
||||
Layout->setAlignment(Qt::AlignCenter);
|
||||
|
||||
@@ -120,6 +136,15 @@ CFloatingWidgetTitleBar::CFloatingWidgetTitleBar(CFloatingDockContainer *parent)
|
||||
{
|
||||
d->FloatingWidget = parent;
|
||||
d->createLayout();
|
||||
|
||||
auto normalPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarNormalButton, 0, d->MaximizeButton);
|
||||
d->NormalIcon.addPixmap(normalPixmap, QIcon::Normal);
|
||||
d->NormalIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
|
||||
|
||||
auto maxPixmap = this->style()->standardPixmap(QStyle::SP_TitleBarMaxButton, 0, d->MaximizeButton);
|
||||
d->MaximizeIcon.addPixmap(maxPixmap, QIcon::Normal);
|
||||
d->MaximizeIcon.addPixmap(internal::createTransparentPixmap(maxPixmap, 0.25), QIcon::Disabled);
|
||||
setMaximizedIcon(d->Maximized);
|
||||
}
|
||||
|
||||
//============================================================================
|
||||
@@ -141,17 +166,19 @@ void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent *ev)
|
||||
Super::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent *ev)
|
||||
{
|
||||
d->DragState = DraggingInactive;
|
||||
if (d->FloatingWidget)
|
||||
{
|
||||
d->FloatingWidget->finishDragging();
|
||||
d->FloatingWidget->finishDragging();
|
||||
}
|
||||
Super::mouseReleaseEvent(ev);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev)
|
||||
{
|
||||
@@ -165,6 +192,10 @@ void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent *ev)
|
||||
// move floating window
|
||||
if (DraggingFloatingWidget == d->DragState)
|
||||
{
|
||||
if(d->FloatingWidget->isMaximized())
|
||||
{
|
||||
d->FloatingWidget->showNormal(true);
|
||||
}
|
||||
d->FloatingWidget->moveFloating();
|
||||
Super::mouseMoveEvent(ev);
|
||||
return;
|
||||
@@ -186,11 +217,77 @@ void CFloatingWidgetTitleBar::setTitle(const QString &Text)
|
||||
d->TitleLabel->setText(Text);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingWidgetTitleBar::updateStyle()
|
||||
{
|
||||
internal::repolishStyle(this, internal::RepolishDirectChildren);
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingWidgetTitleBar::mouseDoubleClickEvent(QMouseEvent *event)
|
||||
{
|
||||
if (event->buttons() & Qt::LeftButton)
|
||||
{
|
||||
emit maximizeRequested();
|
||||
event->accept();
|
||||
}
|
||||
else
|
||||
{
|
||||
QWidget::mouseDoubleClickEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingWidgetTitleBar::setMaximizedIcon(bool maximized)
|
||||
{
|
||||
d->Maximized = maximized;
|
||||
if (maximized)
|
||||
{
|
||||
d->MaximizeButton->setIcon(d->NormalIcon);
|
||||
}
|
||||
else
|
||||
{
|
||||
d->MaximizeButton->setIcon(d->MaximizeIcon);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingWidgetTitleBar::setMaximizeIcon(const QIcon& Icon)
|
||||
{
|
||||
d->MaximizeIcon = Icon;
|
||||
if (d->Maximized)
|
||||
{
|
||||
setMaximizedIcon(d->Maximized);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
void CFloatingWidgetTitleBar::setNormalIcon(const QIcon& Icon)
|
||||
{
|
||||
d->NormalIcon = Icon;
|
||||
if (!d->Maximized)
|
||||
{
|
||||
setMaximizedIcon(d->Maximized);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QIcon CFloatingWidgetTitleBar::maximizeIcon() const
|
||||
{
|
||||
return d->MaximizeIcon;
|
||||
}
|
||||
|
||||
|
||||
//============================================================================
|
||||
QIcon CFloatingWidgetTitleBar::normalIcon() const
|
||||
{
|
||||
return d->NormalIcon;
|
||||
}
|
||||
|
||||
|
||||
} // namespace ads
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
// INCLUDES
|
||||
//============================================================================
|
||||
#include <QFrame>
|
||||
#include <QIcon>
|
||||
|
||||
namespace ads
|
||||
{
|
||||
@@ -48,6 +49,8 @@ struct FloatingWidgetTitleBarPrivate;
|
||||
class CFloatingWidgetTitleBar : public QFrame
|
||||
{
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(QIcon maximizeIcon READ maximizeIcon WRITE setMaximizeIcon)
|
||||
Q_PROPERTY(QIcon normalIcon READ normalIcon WRITE setNormalIcon)
|
||||
private:
|
||||
FloatingWidgetTitleBarPrivate *d; ///< private data (pimpl)
|
||||
|
||||
@@ -55,6 +58,12 @@ protected:
|
||||
virtual void mousePressEvent(QMouseEvent *ev) override;
|
||||
virtual void mouseReleaseEvent(QMouseEvent *ev) override;
|
||||
virtual void mouseMoveEvent(QMouseEvent *ev) override;
|
||||
virtual void mouseDoubleClickEvent(QMouseEvent *event) override;
|
||||
|
||||
void setMaximizeIcon(const QIcon& Icon);
|
||||
QIcon maximizeIcon() const;
|
||||
void setNormalIcon(const QIcon& Icon);
|
||||
QIcon normalIcon() const;
|
||||
|
||||
public:
|
||||
using Super = QWidget;
|
||||
@@ -80,11 +89,21 @@ public:
|
||||
*/
|
||||
void updateStyle();
|
||||
|
||||
/**
|
||||
* Change the maximize button icon according to current windows state
|
||||
*/
|
||||
void setMaximizedIcon(bool maximized);
|
||||
|
||||
signals:
|
||||
/**
|
||||
* This signal is emitted, if the close button is clicked.
|
||||
*/
|
||||
void closeRequested();
|
||||
|
||||
/**
|
||||
* This signal is emitted, if the maximize button is clicked.
|
||||
*/
|
||||
void maximizeRequested();
|
||||
};
|
||||
} // namespace ads
|
||||
#endif // FLOATINGWIDGETTITLEBAR_H
|
||||
|
||||
@@ -23,7 +23,8 @@ windows {
|
||||
}
|
||||
# MSVC
|
||||
*-msvc* {
|
||||
}
|
||||
QMAKE_CXXFLAGS += /utf-8
|
||||
}
|
||||
}
|
||||
|
||||
RESOURCES += ads.qrc
|
||||
@@ -69,9 +70,11 @@ SOURCES += \
|
||||
DockFocusController.cpp
|
||||
|
||||
|
||||
unix {
|
||||
unix:!macx {
|
||||
HEADERS += linux/FloatingWidgetTitleBar.h
|
||||
SOURCES += linux/FloatingWidgetTitleBar.cpp
|
||||
QT += x11extras
|
||||
LIBS += -lxcb
|
||||
}
|
||||
|
||||
isEmpty(PREFIX){
|
||||
|
||||
@@ -5,7 +5,7 @@ ads--CDockContainerWidget {
|
||||
background: palette(dark);
|
||||
}
|
||||
|
||||
ads--CDockContainerWidget QSplitter::handle {
|
||||
ads--CDockContainerWidget ads--CDockSplitter::handle {
|
||||
background: palette(dark);
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ ads--CDockContainerWidget {
|
||||
background: palette(dark);
|
||||
}
|
||||
|
||||
ads--CDockContainerWidget QSplitter::handle {
|
||||
ads--CDockContainerWidget ads--CDockSplitter::handle {
|
||||
background: palette(dark);
|
||||
}
|
||||
|
||||
@@ -92,13 +92,25 @@ QScrollArea#dockWidgetScrollArea {
|
||||
qproperty-iconSize: 16px;
|
||||
}
|
||||
|
||||
#floatingTitleCloseButton {
|
||||
qproperty-icon: url(:/ads/images/close-button.svg);
|
||||
|
||||
ads--CFloatingWidgetTitleBar {
|
||||
background: palette(midlight);
|
||||
qproperty-maximizeIcon: url(:/ads/images/maximize-button.svg);
|
||||
qproperty-normalIcon: url(:/ads/images/restore-button.svg);
|
||||
}
|
||||
|
||||
|
||||
#floatingTitleCloseButton, #floatingTitleMaximizeButton {
|
||||
qproperty-iconSize: 16px;
|
||||
border: none;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
|
||||
#floatingTitleCloseButton {
|
||||
qproperty-icon: url(:/ads/images/close-button.svg);
|
||||
}
|
||||
|
||||
#floatingTitleCloseButton:hover {
|
||||
background: rgba(0, 0, 0, 24);
|
||||
border: none;
|
||||
|
||||
@@ -16,6 +16,7 @@ ads--CDockWidgetTab {
|
||||
border-style: solid;
|
||||
border-width: 0 1px 0 0;
|
||||
padding: 0 0px;
|
||||
qproperty-iconSize: 16px 16px;/* this is optional in case you would like to change icon size*/
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab[activeTab="true"] {
|
||||
|
||||
@@ -2,89 +2,89 @@
|
||||
* Default style sheet on Linux Platforms with focus highlighting flag enabled
|
||||
*/
|
||||
ads--CDockContainerWidget {
|
||||
background: palette(dark);
|
||||
background: palette(dark);
|
||||
}
|
||||
|
||||
ads--CDockContainerWidget QSplitter::handle {
|
||||
background: palette(dark);
|
||||
ads--CDockContainerWidget ads--CDockSplitter::handle {
|
||||
background: palette(dark);
|
||||
}
|
||||
|
||||
ads--CDockAreaWidget {
|
||||
background: palette(window);
|
||||
border: 1px solid white;
|
||||
background: palette(window);
|
||||
border: 1px solid white;
|
||||
}
|
||||
|
||||
ads--CDockAreaWidget #tabsMenuButton::menu-indicator {
|
||||
image: none;
|
||||
image: none;
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab {
|
||||
background: palette(window);
|
||||
border-color: palette(light);
|
||||
border-style: solid;
|
||||
border-width: 0 1px 0 0;
|
||||
padding: 0 0px;
|
||||
background: palette(window);
|
||||
border-color: palette(light);
|
||||
border-style: solid;
|
||||
border-width: 0 1px 0 0;
|
||||
padding: 0 0px;
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab[activeTab="true"] {
|
||||
background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0
|
||||
palette(window), stop:1 palette(light));
|
||||
/*background: palette(highlight);*/
|
||||
background: qlineargradient(spread : pad, x1 : 0, y1 : 0, x2 : 0, y2 : 0.5, stop : 0
|
||||
palette(window), stop:1 palette(light));
|
||||
/*background: palette(highlight);*/
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab QLabel {
|
||||
color: palette(dark);
|
||||
color: palette(dark);
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab[activeTab="true"] QLabel {
|
||||
color: palette(foreground);
|
||||
color: palette(foreground);
|
||||
}
|
||||
|
||||
ads--CDockWidget {
|
||||
background: palette(light);
|
||||
border-color: palette(light);
|
||||
border-style: solid;
|
||||
border-width: 1px 0 0 0;
|
||||
background: palette(light);
|
||||
border-color: palette(light);
|
||||
border-style: solid;
|
||||
border-width: 1px 0 0 0;
|
||||
}
|
||||
|
||||
ads--CTitleBarButton {
|
||||
padding: 0px 0px;
|
||||
padding: 0px 0px;
|
||||
}
|
||||
|
||||
QScrollArea#dockWidgetScrollArea {
|
||||
padding: 0px;
|
||||
border: none;
|
||||
padding: 0px;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#dockAreaCloseButton {
|
||||
qproperty-icon: url(:/ads/images/close-button.svg),
|
||||
url(:/ads/images/close-button-disabled.svg) disabled;
|
||||
qproperty-iconSize: 16px;
|
||||
qproperty-icon: url(:/ads/images/close-button.svg),
|
||||
url(:/ads/images/close-button-disabled.svg) disabled;
|
||||
qproperty-iconSize: 16px;
|
||||
}
|
||||
|
||||
#detachGroupButton {
|
||||
qproperty-icon: url(:/ads/images/detach-button.svg),
|
||||
url(:/ads/images/detach-button-disabled.svg) disabled;
|
||||
qproperty-iconSize: 16px;
|
||||
qproperty-icon: url(:/ads/images/detach-button.svg),
|
||||
url(:/ads/images/detach-button-disabled.svg) disabled;
|
||||
qproperty-iconSize: 16px;
|
||||
}
|
||||
|
||||
#tabCloseButton {
|
||||
margin-top: 2px;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0px -2px;
|
||||
qproperty-icon: url(:/ads/images/close-button.svg),
|
||||
url(:/ads/images/close-button-disabled.svg) disabled;
|
||||
qproperty-iconSize: 16px;
|
||||
margin-top: 2px;
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0px -2px;
|
||||
qproperty-icon: url(:/ads/images/close-button.svg),
|
||||
url(:/ads/images/close-button-disabled.svg) disabled;
|
||||
qproperty-iconSize: 16px;
|
||||
}
|
||||
|
||||
#tabCloseButton:hover {
|
||||
/*border: 1px solid rgba(0, 0, 0, 32);*/
|
||||
background: rgba(0, 0, 0, 24);
|
||||
/*border: 1px solid rgba(0, 0, 0, 32);*/
|
||||
background: rgba(0, 0, 0, 24);
|
||||
}
|
||||
|
||||
#tabCloseButton:pressed {
|
||||
background: rgba(0, 0, 0, 48);
|
||||
background: rgba(0, 0, 0, 48);
|
||||
}
|
||||
|
||||
|
||||
@@ -96,75 +96,100 @@ QScrollArea#dockWidgetScrollArea {
|
||||
|
||||
/* Focus related styling */
|
||||
ads--CDockWidgetTab[focused="true"] {
|
||||
background: palette(highlight);
|
||||
border-color: palette(highlight);
|
||||
background: palette(highlight);
|
||||
border-color: palette(highlight);
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab[focused="true"]>#tabCloseButton {
|
||||
qproperty-icon: url(:/ads/images/close-button-focused.svg)
|
||||
qproperty-icon: url(:/ads/images/close-button-focused.svg)
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab[focused="true"]>#tabCloseButton:hover {
|
||||
background: rgba(255, 255, 255, 48);
|
||||
background: rgba(255, 255, 255, 48);
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab[focused="true"]>#tabCloseButton:pressed {
|
||||
background: rgba(255, 255, 255, 92);
|
||||
background: rgba(255, 255, 255, 92);
|
||||
}
|
||||
|
||||
ads--CDockWidgetTab[focused="true"] QLabel {
|
||||
color: palette(light);
|
||||
color: palette(light);
|
||||
}
|
||||
|
||||
ads--CDockAreaTitleBar {
|
||||
background: transparent;
|
||||
border-bottom: 2px solid palette(light);
|
||||
padding-bottom: 0px;
|
||||
background: transparent;
|
||||
border-bottom: 2px solid palette(light);
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
ads--CDockAreaWidget[focused="true"] ads--CDockAreaTitleBar {
|
||||
background: transparent;
|
||||
border-bottom: 2px solid palette(highlight);
|
||||
padding-bottom: 0px;
|
||||
background: transparent;
|
||||
border-bottom: 2px solid palette(highlight);
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
|
||||
|
||||
ads--CFloatingWidgetTitleBar {
|
||||
qproperty-maximizeIcon: url(:/ads/images/maximize-button.svg);
|
||||
qproperty-normalIcon: url(:/ads/images/restore-button.svg);
|
||||
}
|
||||
|
||||
|
||||
/* does not properly work on KDE
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] ads--CFloatingWidgetTitleBar {
|
||||
background: palette(highlight);
|
||||
background: palette(highlight);
|
||||
qproperty-maximizeIcon: url(:/ads/images/maximize-button-focused.svg);
|
||||
qproperty-normalIcon: url(:/ads/images/restore-button-focused.svg);
|
||||
}
|
||||
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleLabel {
|
||||
color: palette(light);
|
||||
color: palette(light);
|
||||
}
|
||||
*/
|
||||
|
||||
#floatingTitleCloseButton, #floatingTitleMaximizeButton {
|
||||
qproperty-iconSize: 16px;
|
||||
border: none;
|
||||
margin: 6px 3px 6px 3px;
|
||||
}
|
||||
|
||||
|
||||
#floatingTitleCloseButton {
|
||||
qproperty-icon: url(:/ads/images/close-button.svg);
|
||||
qproperty-iconSize: 16px;
|
||||
border: none;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
#floatingTitleCloseButton:hover {
|
||||
|
||||
#floatingTitleCloseButton:hover, #floatingTitleMaximizeButton:hover {
|
||||
background: rgba(0, 0, 0, 24);
|
||||
border: none;
|
||||
}
|
||||
|
||||
#floatingTitleCloseButton:pressed {
|
||||
|
||||
#floatingTitleCloseButton:pressed, #floatingTitleMaximizeButton:pressed {
|
||||
background: rgba(0, 0, 0, 48);
|
||||
}
|
||||
|
||||
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton {
|
||||
qproperty-iconSize: 16px;
|
||||
}
|
||||
|
||||
|
||||
/* does not properly work on KDE
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton {
|
||||
qproperty-icon: url(:/ads/images/close-button-focused.svg);
|
||||
qproperty-iconSize: 16px;
|
||||
}
|
||||
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:hover {
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:hover,
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton:hover {
|
||||
background: rgba(255, 255, 255, 48);
|
||||
}
|
||||
|
||||
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:pressed {
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleCloseButton:pressed,
|
||||
ads--CFloatingDockContainer[isActiveWindow="true"] #floatingTitleMaximizeButton:pressed {
|
||||
background: rgba(255, 255, 255, 92);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||