Compare commits

..

78 Commits
2.3.0 ... 2.5.1

Author SHA1 Message Date
Uwe Kindler
64231d037d Fixed build for Qt5.5.1 2019-07-12 14:45:35 +02:00
githubuser0xFFFF
6eb869014e Merge pull request #38 from tatatupi/bugfix/linux_cmake
adding linux src files to CMake
2019-07-12 14:41:39 +02:00
Taiguara
a564ca5ce5 adding linux src files to CMake 2019-07-12 09:35:06 -03:00
githubuser0xFFFF
365b989364 Update README.md
Updated Linux documentation because linux_experimental branch has been merged into master
2019-07-12 11:05:12 +02:00
Uwe Kindler
a3baf7dcf6 Changes in eclipse project file 2019-07-12 10:51:21 +02:00
Uwe Kindler
538e690c22 Fixed warning for unused parameter in DockOverlay.cpp 2019-07-12 10:39:59 +02:00
Uwe Kindler
b1309da89a Some changes to fix build for windows 2019-07-12 10:37:14 +02:00
Uwe Kindler
d2f751ef87 Moved linux specific code into linux sub folder 2019-07-11 16:12:15 +02:00
Uwe Kindler
35c1b04c58 Merge branch 'refs/heads/master' into linux_experimental 2019-07-11 15:50:24 +02:00
Uwe Kindler
0de1a9ccae Properly implemented support for DockWidgetFloatable feature - now detaching a DockWidget or a DockAre that is not floatable is not possible (support for DockWidgetMovable feature is not implemented yet) 2019-07-11 15:12:39 +02:00
Uwe Kindler
c45327aafd Removed enum eXmlMode and added XmlAutoFormatting flag anc XmlCompressionEnabled flag to eConfigFlags. Added support for XML compression for the XML generated by the store function. If enabled then XML the generated XML is not human readable anymore but it needs less space when storing into settings file 2019-06-26 14:57:14 +02:00
Uwe Kindler
8853c751d6 Merge branch 'master' into linux_experimental 2019-06-04 13:40:20 +02:00
githubuser0xFFFF
e978a32a09 Merge pull request #32 from simulton/master
Feature: Remove docks
2019-06-04 13:32:15 +02:00
Joel Bodenmann
ca5683f5bf Merge pull request #1 from simulton/feature/remove_docks
Feature/remove docks
2019-05-17 21:40:36 +02:00
Tibo Clausen
c630a59afe Replace CDockWidget::releaseWidget() with CDockWidget::takeWidget() 2019-05-16 13:08:48 +01:00
Tibo Clausen
b9b8ff9c76 Add CDockWidget::releaseWidget() 2019-05-16 11:53:31 +01:00
Tibo Clausen
e2c5204d00 Clear LastAddedAreaCache when restoring 2019-05-15 16:13:55 +01:00
Tibo Clausen
5ee94d7602 Improve CDockManager::addDockWidgetTab() for dynamically added widgets 2019-05-15 14:30:32 +01:00
Tibo Clausen
69894f3f88 Remove area from LastAddedAreaCache 2019-05-15 14:20:08 +01:00
Tibo Clausen
641946bff5 Add CDockManager::removeDockWidget() 2019-05-15 13:47:58 +01:00
githubuser0xFFFF
27dd7a1b75 Update README.md 2019-05-15 10:14:22 +02:00
Uwe Kindler
5425f2b9e1 Added missing FloatingWidgetTitleBar.cpp and missing stylesheet file for linux 2019-05-15 09:12:22 +02:00
githubuser0xFFFF
4320e350c8 Update README.md 2019-05-14 16:03:47 +02:00
Uwe Kindler
8351aa11e7 Added linux screenshot 2019-05-14 15:42:47 +02:00
Uwe Kindler
e98fd5bcb3 Improved icons for all button, adjusted size of dock marker 2019-05-14 15:32:50 +02:00
Uwe Kindler
a012af2aac Created experimental linux branch with initial experimental linux
support
2019-05-14 14:09:10 +02:00
githubuser0xFFFF
df285dd385 Merge pull request #26 from gameraccoon/master
Fix compilation on linux using cmake
2019-05-13 09:02:43 +02:00
Uwe Kindler
a6ed4354a9 Implemented workaround for blurry icons in latest Qt versions 2019-05-10 11:33:26 +02:00
Uwe Kindler
1fccb943fe Fixed setWidget function of DockWidget to properly setup the internal scroll area 2019-05-10 10:32:06 +02:00
Pavel Grebnev
7bd3765fa7 Fix compilation on linux 2019-05-04 19:08:47 +03:00
Uwe Kindler
9b56ca08e1 Changes to work around new QT issues in non client area code that comes with the new Qt version 5.12.2 2019-03-22 13:57:17 +01:00
Uwe Kindler
49a7682e74 Merge branch 'master' of https://github.com/githubuser0xFFFF/Qt-Advanced-Docking-System 2019-03-06 14:37:35 +01:00
Uwe Kindler
e25bf2eac2 Disabled minimize button for floating widgets because user cannot restore minimized windows because they do not have a taskbar entry 2019-03-06 14:36:20 +01:00
githubuser0xFFFF
9bd06401d9 Update README.md
Fixed Travis CI and Appveyor badges to use the right account
2019-01-28 13:37:01 +01:00
Uwe Kindler
b44a7e75ca Implemented workarund for NonClientArea mouse event bug in Qt versions > 5.9.2. 2019-01-26 14:44:14 +01:00
githubuser0xFFFF
c9645ef85b Update README.md
Added travis badge
2019-01-26 13:54:35 +01:00
githubuser0xFFFF
fd09a681c4 Merge pull request #19 from VSRonin/master
Various fixes to the project files to uniform names and correctly compile static libraries.

Added configuration files for Appveyor and Travis CI, adding the project to those services should work out of the box.
2019-01-26 13:45:21 +01:00
Luca Beldi
e113790bbe Various fixes after code review
Minimum required Qt lowered to 5.5.0
Added CI for Qt 5.5.1 build
Increased C++ standard to C++14
Fixed use of spaces instead of tabs
Removed duplicate constructors
2019-01-25 16:28:36 +00:00
githubuser0xFFFF
e352ce559b Merge pull request #20 from yozka/feature_2
set tooltip for titlebar and menu
2019-01-25 09:21:46 +01:00
Yozka
0c3ef64d3e Fixed? remove space in tabs 2019-01-25 09:05:30 +05:00
Yozka
f72e2ce058 Added demo example tooltip for calendar dockWidget #20 2019-01-25 08:56:30 +05:00
yozka
befdcce343 set tooltip for titlebar and menu #20 2019-01-23 22:04:37 +05:00
Yozka
6fc8964ffc set tooltip for titlebar and menu #20 2019-01-23 22:01:30 +05:00
Yozka
6cb1f33451 ToolTip from titlebar and menu 2019-01-23 11:43:07 +05:00
Luca Beldi
ee616c2541 fixed travis script 2019-01-18 08:33:11 +00:00
Luca Beldi
7dd2a3c83c added travis configuration 2019-01-17 09:00:41 +00:00
Luca Beldi
9db502e652 Fixed appveyor project 2019-01-17 08:31:04 +00:00
Andreev Alexander
1ad6caeb8a Merge pull request #1 from githubuser0xFFFF/master
merge base
2019-01-17 10:54:30 +05:00
githubuser0xFFFF
4dde545c8f Merge pull request #18 from yozka/feature
set title bar and title toggle view action
2019-01-16 21:54:43 +01:00
Luca Beldi
b7a5918974 Fixed project files
Fixed compilation on compilers that do not support C++14
Only 2 minor places required C++14, no need to impose it
2019-01-16 17:52:53 +00:00
Luca Beldi
ddfa6c2a43 added appveyor project 2019-01-16 16:52:45 +00:00
Luca Beldi
275520ae29 Fixes to project files
Fixed naming of projects using CMake
Added working static compile using qmake
Added conventional naming of debug libraries
Added install target to qmake
2019-01-16 16:49:59 +00:00
Andreev Alexander
1078387f5d Merge branch 'master' into feature 2019-01-16 18:28:09 +05:00
Yozka
c33dddbd47 set title bar and title toggle view action 2019-01-16 16:23:07 +05:00
githubuser0xFFFF
2570a880af Merge pull request #17 from VSRonin/master
Added CMake project file
2019-01-16 12:22:43 +01:00
Luca Beldi
40a8d9e6b4 Added CMake project file
CMake has been announced as the build system of choice for Qt in the
future so it's useful to provide a project file for it

Also added the possibility to compile as a static library
2019-01-16 09:44:34 +00:00
Uwe Kindler
9af6622466 Removed non existing resources from main.qrc 2019-01-15 19:45:14 +01:00
githubuser0xFFFF
4fa89374c4 Merge pull request #16 from sgaist/various_fixes
Various fixes
2019-01-15 19:29:32 +01:00
Samuel Gaist
1aaa56ef29 Removed non existing header in include 2019-01-15 17:24:29 +01:00
Samuel Gaist
d298a47bda Removed unused constants 2019-01-15 17:24:11 +01:00
Samuel Gaist
146b65206a Fix missing override warning 2019-01-15 17:23:47 +01:00
Samuel Gaist
616ad9f86e Add more generated files to gitignore 2019-01-15 17:20:29 +01:00
Samuel Gaist
aa9762718c Fix subdirs handling
It's considered bad practice to use the ordered CONFIG option. This
patch properly setups the subdirs dependencies.
2019-01-15 17:17:45 +01:00
githubuser0xFFFF
f26bee6677 Update README.md
Added video
2019-01-15 13:05:21 +01:00
Uwe Kindler
fb18de4868 Added new image for faking embedded youtube video 2019-01-15 13:01:47 +01:00
Uwe Kindler
e204e10113 Removed unused function 2019-01-15 11:47:57 +01:00
githubuser0xFFFF
a06a14d6cd Merge pull request #15 from skartashev/master
Qt 5.5.1 (ubuntu 16.04) compatibility buildfixes
2019-01-15 11:41:37 +01:00
Sergey Kartashev
88d4bea2c1 Qt 5.5.1 (ubuntu 16.04) compatibility buildfixes 2019-01-15 10:12:34 +03:00
Uwe Kindler
b8ad2f7577 Removed superfluous windows.h include from main.cpp and removed unused local variable FloatingContainer from dropIntoSection() function 2019-01-14 14:18:44 +01:00
Uwe Kindler
32e5d599f7 Improved handling of sizes when dropping or removing content 2019-01-14 13:58:40 +01:00
Uwe Kindler
48382ccd82 Merged the two draging state enumerations into a single one and reused it in FloatingDockContainer 2018-12-20 16:25:30 +01:00
Uwe Kindler
e37e4fdf57 Added context menu for dock area title bar to enable closing of area and other areas via context menu and to enable detaching of dock area via context menu 2018-12-20 15:29:38 +01:00
Uwe Kindler
c9a97534a8 Fixed indentationin README.md example 2018-12-20 09:20:17 +01:00
Uwe Kindler
8f54dd2a82 Added example project and updated documentation 2018-12-20 09:15:02 +01:00
githubuser0xFFFF
c0d6f959ec Merge pull request #12 from skartashev/master
fix forward declarations (class/struct)
2018-12-17 16:21:30 +01:00
Sergey Kartashev
8570139cd1 fix forward declarations (class/struct) 2018-12-17 14:41:43 +03:00
githubuser0xFFFF
b38919e909 Update README.md 2018-12-14 23:18:15 +01:00
githubuser0xFFFF
b19cc98c84 Update README.md 2018-12-14 23:16:49 +01:00
47 changed files with 2016 additions and 280 deletions

160
.appveyor.yml Normal file
View File

@@ -0,0 +1,160 @@
version: '2.3.2.{build}'
branches:
only:
- master
image: Visual Studio 2015
clone_depth: 1
environment:
global:
# Appveyor doesn't have Qt 12 yet
LatestLTSQtVersion: 5.9
LatestQtVersion: 5.11
matrix:
# Latest version of Qt, dll, 64bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestQtVersion%\msvc2015_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
targetPlatform: amd64
use_mingw: "false"
use_static: "false"
use_cmake: "false"
# 32 bit builds
# MSVC 2015 builds
# Dynamic Library builds
# LTS version of Qt, dll, 32bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestLTSQtVersion%\msvc2015
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
targetPlatform: x86
use_mingw: "false"
use_static: "false"
use_cmake: "false"
# LTS version of Qt, dll, 32bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestLTSQtVersion%\msvc2015
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
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\%LatestLTSQtVersion%\msvc2015
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
targetPlatform: x86
use_mingw: "false"
use_static: "true"
use_cmake: "false"
# LTS version of Qt, static, 32bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestLTSQtVersion%\msvc2015
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
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\%LatestLTSQtVersion%\mingw53_32
COMPILER: C:\Qt\Tools\mingw530_32
targetPlatform: x86
use_mingw: "true"
use_static: "false"
use_cmake: "false"
# LTS version of Qt, dll, 32bit, MinGW, cmake
- QT5: C:\Qt\%LatestLTSQtVersion%\mingw53_32
COMPILER: C:\Qt\Tools\mingw530_32
targetPlatform: x86
use_mingw: "true"
use_static: "false"
use_cmake: "true"
# end Dynamic Library builds
# Static Library builds
# LTS version of Qt, static, 32bit, MinGW, qmake
- QT5: C:\Qt\%LatestLTSQtVersion%\mingw53_32
COMPILER: C:\Qt\Tools\mingw530_32
targetPlatform: x86
use_mingw: "true"
use_static: "true"
use_cmake: "false"
# LTS version of Qt, static, 32bit, MinGW, cmake
- QT5: C:\Qt\%LatestLTSQtVersion%\mingw53_32
COMPILER: C:\Qt\Tools\mingw530_32
targetPlatform: x86
use_mingw: "true"
use_static: "true"
use_cmake: "true"
# end Static Library builds
# end MinGW builds
# end 32 bit builds
# 64 bit builds
# MSVC 2015 builds
# Dynamic Library builds
# LTS version of Qt, dll, 64bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestLTSQtVersion%\msvc2015_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
targetPlatform: amd64
use_mingw: "false"
use_static: "false"
use_cmake: "false"
# LTS version of Qt, dll, 64bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestLTSQtVersion%\msvc2015_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
targetPlatform: amd64
use_mingw: "false"
use_static: "false"
use_cmake: "true"
# end Dynamic Library builds
# Static Library builds
# LTS version of Qt, static, 64bit, MSVC 2015, qmake
- QT5: C:\Qt\%LatestLTSQtVersion%\msvc2015_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
targetPlatform: amd64
use_mingw: "false"
use_static: "true"
use_cmake: "false"
# LTS version of Qt, static, 64bit, MSVC 2015, cmake
- QT5: C:\Qt\%LatestLTSQtVersion%\msvc2015_64
COMPILER: C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC
targetPlatform: amd64
use_mingw: "false"
use_static: "true"
use_cmake: "true"
# end Static Library builds
# end MSVC 2015 builds
# end 64 bit builds
matrix:
fast_finish: true
before_build:
- set PATH=%COMPILER%\bin;%QT5%\bin;%PATH%
- set originalWD=%CD%
- call "%QT5%\bin\qtenv2.bat"
- cd %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;=%
build_script:
- if %use_cmake%==true mkdir .\build
- if %use_cmake%==true cd .\build
- if %use_cmake%==true cmake --version
- if %use_cmake%==true cmake -G %CMAKEGENERATOR% -DCMAKE_BUILD_TYPE=DEBUG -DBUILD_EXAMPLES=ON -DCMAKE_DEBUG_POSTFIX=d -DBUILD_STATIC=%USESTATIC% -DCMAKE_INSTALL_PREFIX="./installed" ../
- if %use_cmake%==true cmake --build .
- if %use_cmake%==true cmake --build . --target install
- if %use_cmake%==true cmake -G %CMAKEGENERATOR% -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_EXAMPLES=ON -DBUILD_STATIC=%USESTATIC% -DCMAKE_INSTALL_PREFIX="./installed" ../
- if %use_cmake%==true cmake --build .
- if %use_cmake%==true cmake --build . --target install
- if %use_cmake%==false if %use_static%==true qmake "CONFIG+=adsBuildStatic"
- if %use_cmake%==false if %use_static%==false qmake
- if %use_cmake%==false %MAKEENGINE% debug
- if %use_cmake%==false %MAKEENGINE% install
- if %use_cmake%==false %MAKEENGINE% release
- if %use_cmake%==false %MAKEENGINE% install
after_build:
- if %use_mingw%==true set PATH=C:\Program Files\Git\usr\bin;%PATH%

View File

@@ -83,6 +83,7 @@
</target>
<target name="Clean" path=" build" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -99,7 +100,6 @@
<target name="qmake" path=" build" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>qmake</buildCommand>
<buildArguments>-recursive ../ads.pro</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
@@ -122,7 +122,6 @@
</target>
<target name="Clean" path=" build/src" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -139,7 +138,6 @@
<target name="qmake" path=" build/src" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>qmake</buildCommand>
<buildArguments>-recursive ../../src/src.pro</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
@@ -152,6 +150,46 @@
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="Build all" path=" build/example" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>mingw32-make</buildCommand>
<buildArguments>-j</buildArguments>
<buildTarget>all</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="Clean" path=" build/example" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="Debug Build" path=" build/example" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>mingw32-make</buildCommand>
<buildArguments>-j6</buildArguments>
<buildTarget>debug</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="qmake" path=" build/example" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>qmake</buildCommand>
<buildArguments>-recursive ../../example/example.pro</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="Release Build" path=" build/example" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>mingw32-make</buildCommand>
<buildArguments>-j4</buildArguments>
<buildTarget>release</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
</target>
<target name="Build all" path=" build/demo" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>mingw32-make</buildCommand>
<buildArguments>-j</buildArguments>
@@ -162,7 +200,6 @@
</target>
<target name="Clean" path=" build/demo" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -179,7 +216,6 @@
<target name="qmake" path=" build/demo" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>qmake</buildCommand>
<buildArguments>-recursive ../../demo/demo.pro</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>
@@ -202,6 +238,7 @@
</target>
<target name="Clean" path=" build/AdvancedDockingSystemDemo" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -240,6 +277,7 @@
</target>
<target name="Clean" path=" build/AdvancedDockingSystemDemo_v2" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -278,6 +316,7 @@
</target>
<target name="Clean" path=" build/AdvancedDockingSystem" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>make</buildCommand>
<buildArguments/>
<buildTarget>clean</buildTarget>
<stopOnError>false</stopOnError>
<useDefaultCommand>true</useDefaultCommand>
@@ -294,7 +333,6 @@
<target name="qmake" path=" build/AdvancedDockingSystem" targetID="org.eclipse.cdt.build.MakeTargetBuilder">
<buildCommand>qmake</buildCommand>
<buildArguments>-recursive ../../AdvancedDockingSystem/src.pro</buildArguments>
<buildTarget/>
<stopOnError>true</stopOnError>
<useDefaultCommand>false</useDefaultCommand>
<runAllBuilders>false</runAllBuilders>

8
.gitignore vendored
View File

@@ -1,2 +1,10 @@
*.pro.user
/ build
*.o
*.dylib
*.app
qrc_*
moc_*
ui_*
Makefile

155
.travis.yml Normal file
View File

@@ -0,0 +1,155 @@
language: cpp
# gcc is clang on mac
compiler: gcc
git:
depth: 1
matrix:
fast_finish: true
include:
- name: Ubuntu qmake Qt5.5.1
os: linux
dist: trusty
group: stable
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt551-trusty'
update: true
packages:
- qt55base
- qt55tools
- gcc-6
- g++-6
- libc6-i386
script:
- PATH="/opt/qt55/bin:$PATH"
- CXX="g++-6"
- CC="gcc-6"
- qt55-env.sh
- qmake
- make
- make install
- name: Ubuntu qmake dll
os: linux
dist: xenial
group: stable
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt-5.12.0-xenial'
update: true
packages:
- qt512base
- qt512tools
- gcc-6
- g++-6
- libc6-i386
- libgl-dev
- libgl1-mesa-dev
- mesa-common-dev
script:
- PATH="/opt/qt512/bin:$PATH"
- CXX="g++-6"
- CC="gcc-6"
- qt512-env.sh
- qmake
- make
- make install
- name: Ubuntu qmake static
os: linux
dist: xenial
group: stable
addons:
apt:
sources:
- ubuntu-toolchain-r-test
- sourceline: 'ppa:beineri/opt-qt-5.12.0-xenial'
update: true
packages:
- qt512base
- qt512tools
- gcc-6
- g++-6
- libc6-i386
- libgl-dev
- libgl1-mesa-dev
- mesa-common-dev
script:
- PATH="/opt/qt512/bin:$PATH"
- CXX="g++-6"
- CC="gcc-6"
- qt512-env.sh
- qmake "CONFIG+=adsBuildStatic"
- make
- make install
- name: macOS CMake dll
os: osx
osx_image: xcode10.1
addons:
homebrew:
packages:
- qt
update: true
script:
- PATH="/usr/local/opt/qt5/bin:$PATH"
- mkdir -p build
- cd build
- cmake --version
- cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_DEBUG_POSTFIX=_debug -DBUILD_EXAMPLES=ON -DBUILD_STATIC=OFF -DCMAKE_INSTALL_PREFIX="./installed" ../
- cmake --build .
- cmake --build . --target install
- cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_EXAMPLES=ON -DBUILD_STATIC=OFF -DCMAKE_INSTALL_PREFIX="./installed" ../
- cmake --build .
- cmake --build . --target install
- name: macOS CMake static
os: osx
osx_image: xcode10.1
addons:
homebrew:
packages:
- qt
update: true
script:
- PATH="/usr/local/opt/qt5/bin:$PATH"
- mkdir -p build
- cd build
- cmake --version
- cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=DEBUG -DCMAKE_DEBUG_POSTFIX=_debug -DBUILD_EXAMPLES=ON -DBUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX="./installed" ../
- cmake --build .
- cmake --build . --target install
- cmake -G "Unix Makefiles" -DCMAKE_BUILD_TYPE=RELEASE -DBUILD_EXAMPLES=ON -DBUILD_STATIC=ON -DCMAKE_INSTALL_PREFIX="./installed" ../
- cmake --build .
- cmake --build . --target install
- name: macOS qmake dll
os: osx
osx_image: xcode10.1
addons:
homebrew:
packages:
- qt
update: true
script:
- PATH="/usr/local/opt/qt5/bin:$PATH"
- qmake
- make
- make install
- name: macOS qmake static
os: osx
osx_image: xcode10.1
addons:
homebrew:
packages:
- qt
update: true
script:
- PATH="/usr/local/opt/qt5/bin:$PATH"
- qmake "CONFIG+=adsBuildStatic"
- make
- make install
notifications:
email: false

105
CMakeLists.txt Normal file
View File

@@ -0,0 +1,105 @@
cmake_minimum_required(VERSION 3.3)
set(ads_VERSION "2.3.2")
set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
project(QtAdvancedDockingSystem VERSION ${ads_VERSION})
option(BUILD_STATIC "Build the static library" OFF)
option(BUILD_EXAMPLES "Build the examples" ON)
set(REQUIRED_QT_VERSION 5.5.0)
find_package(Qt5Core ${REQUIRED_QT_VERSION} REQUIRED)
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED)
find_package(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED)
message(STATUS "Found Qt ${Qt5Core_VERSION}")
set(ads_INCLUDE ${ads_INCLUDE} ${Qt5Core_INCLUDE_DIRS})
set(ads_INCLUDE ${ads_INCLUDE} "${CMAKE_CURRENT_SOURCE_DIR}/src")
set(ads_LIBS ${ads_LIBS} ${Qt5Core_LIBRARIES})
set(ads_COMPILE_DEFINE ${ads_COMPILE_DEFINE} ${Qt5Core_COMPILE_DEFINITIONS})
set(ads_LIBS ${ads_LIBS} ${Qt5Gui_LIBRARIES})
set(ads_INCLUDE ${ads_INCLUDE} ${Qt5Gui_INCLUDE_DIRS})
set(ads_COMPILE_DEFINE ${ads_COMPILE_DEFINE} ${Qt5Gui_COMPILE_DEFINITIONS})
set(ads_LIBS ${ads_LIBS} ${Qt5Widgets_LIBRARIES})
set(ads_INCLUDE ${ads_INCLUDE} ${Qt5Widgets_INCLUDE_DIRS})
set(ads_COMPILE_DEFINE ${ads_COMPILE_DEFINE} ${Qt5Widgets_COMPILE_DEFINITIONS})
if(BUILD_STATIC)
set(CMAKE_STATIC_LIBRARY_SUFFIX "_static${CMAKE_STATIC_LIBRARY_SUFFIX}")
endif()
set(ads_SRCS
src/ads_globals.cpp
src/DockAreaTabBar.cpp
src/DockAreaTitleBar.cpp
src/DockAreaWidget.cpp
src/DockContainerWidget.cpp
src/DockManager.cpp
src/DockOverlay.cpp
src/DockSplitter.cpp
src/DockWidget.cpp
src/DockWidgetTab.cpp
src/ElidingLabel.cpp
src/FloatingDockContainer.cpp
src/ads.qrc
src/linux/FloatingWidgetTitleBar.cpp
)
set(ads_INSTALL_INCLUDE
src/ads_globals.h
src/DockAreaTabBar.h
src/DockAreaTitleBar.h
src/DockAreaWidget.h
src/DockContainerWidget.h
src/DockManager.h
src/DockOverlay.h
src/DockSplitter.h
src/DockWidget.h
src/DockWidgetTab.h
src/ElidingLabel.h
src/FloatingDockContainer.h
src/linux/FloatingWidgetTitleBar.h
)
if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "4")
set(ads_PlatformDir "x86")
else()
set(ads_PlatformDir "x64")
endif()
if(BUILD_STATIC)
add_library(qtadvanceddocking STATIC ${ads_SRCS})
set(ads_COMPILE_DEFINE ${ads_COMPILE_DEFINE} ADS_STATIC)
else()
add_library(qtadvanceddocking SHARED ${ads_SRCS})
set(ads_COMPILE_DEFINE ${ads_COMPILE_DEFINE} ADS_SHARED_EXPORT)
endif()
install(FILES ${ads_INSTALL_INCLUDE}
DESTINATION include
COMPONENT headers
)
install(FILES
"${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.md"
"${CMAKE_CURRENT_SOURCE_DIR}/gnu-lgpl-v2.1.md"
DESTINATION license
COMPONENT license
)
install(TARGETS qtadvanceddocking
EXPORT adsBinary
RUNTIME DESTINATION bin COMPONENT library
LIBRARY DESTINATION lib COMPONENT library
ARCHIVE DESTINATION lib COMPONENT library
)
target_include_directories(qtadvanceddocking PUBLIC
$<BUILD_INTERFACE:${ads_INCLUDE}>
$<INSTALL_INTERFACE:include>
)
target_link_libraries(qtadvanceddocking PUBLIC ${ads_LIBS})
target_compile_definitions(qtadvanceddocking PRIVATE ${ads_COMPILE_DEFINE})
set_target_properties(qtadvanceddocking PROPERTIES
VERSION ${ads_VERSION}
EXPORT_NAME "Qt Advanced Docking System"
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"
)
if(BUILD_EXAMPLES)
add_subdirectory(example)
add_subdirectory(demo)
endif()

100
README.md
View File

@@ -1,4 +1,9 @@
# Advanced Docking System for Qt
# Advanced Docking System for Qt
[![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
[![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](gnu-lgpl-v2.1.md)
Qt Advanced Docking System lets you create customizable layouts using a full
featured window docking system similar to what is found in many popular
@@ -13,6 +18,10 @@ from Manuel Freiholz. I did an almost complete rewrite of his code to improve
code quality, readibility and to fix all issues from the issue tracker
of his docking system project.
The following video gives a first impression what is possible with the Advanced Docking System for Qt.
[![Video Advanced Docking](doc/advanced-docking_video.png)](https://www.youtube.com/watch?v=7pdNfafg3Qc)
## Features
### Docking everywhere - no central widget
There is no central widget like in the Qt docking system. You can dock on every
@@ -52,16 +61,103 @@ main window layout.
![Perspective](doc/perspectives_dark.png)
## Tested Compatible Environments
- Windows 10
### Windows
Windows 10 [![Build status](https://ci.appveyor.com/api/projects/status/qcfb3cy932jw9mpy/branch/master?svg=true)](https://ci.appveyor.com/project/githubuser0xFFFF/qt-advanced-docking-system/branch/master)
The library was developed on and for Windows. It is used in a commercial Windows application and is therefore constantly tested.
### macOS
macOS [![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
The application can be compiled for macOS. A user reported, that the library works on macOS. If have not tested it.
### Linux
Ubuntu [![Build Status](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System.svg?branch=master)](https://travis-ci.org/githubuser0xFFFF/Qt-Advanced-Docking-System)
The application can be compiled for Linux and has been developed and tested with **Kubuntu 18.04**.
![Advanced Docking on Linux](doc/linux_kubuntu_1804.png)
## Build
Open the `ads.pro` with QtCreator and start the build, that's it.
You can run the demo project and test it yourself.
## Getting started / Example
The following example shows the minimum code required to use the advanced Qt docking system.
*MainWindow.h*
```cpp
#include <QMainWindow>
#include "DockManager.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
// The main container for docking
ads::CDockManager* m_DockManager;
};
```
*MainWindow.cpp*
```cpp
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QLabel>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Create the dock manager. Because the parent parameter is a QMainWindow
// the dock manager registers itself as the central widget.
m_DockManager = new ads::CDockManager(this);
// Create example content label - this can be any application specific
// widget
QLabel* l = new QLabel();
l->setWordWrap(true);
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
// Create a dock widget with the title Label 1 and set the created label
// as the dock widget content
ads::CDockWidget* DockWidget = new ads::CDockWidget("Label 1");
DockWidget->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_DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
}
MainWindow::~MainWindow()
{
delete ui;
}
```
## Developers
- Uwe Kindler, Project Maintainer
- Manuel Freiholz
## License information
[![License: LGPL v2.1](https://img.shields.io/badge/License-LGPL%20v2.1-blue.svg)](gnu-lgpl-v2.1.md)
This project uses the [LGPLv2.1 license](gnu-lgpl-v2.1.md)

View File

@@ -1,6 +1,9 @@
TEMPLATE = subdirs
CONFIG += ordered
SUBDIRS = \
src \
demo
demo \
example
demo.depends = src
example.depends = src

48
demo/CMakeLists.txt Normal file
View File

@@ -0,0 +1,48 @@
cmake_minimum_required(VERSION 3.3)
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTORCC ON)
project(ads_demo VERSION "1.0")
set(REQUIRED_QT_VERSION 5.5.0)
find_package(Qt5Core ${REQUIRED_QT_VERSION} REQUIRED)
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED)
find_package(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED)
set(ads_demo_LIBS ${ads_demo_LIBS} ${Qt5Core_LIBRARIES})
set(ads_demo_INCLUDE ${ads_demo_INCLUDE} ${Qt5Core_INCLUDE_DIRS})
set(ads_demo_COMPILE_DEFINE ${ads_demo_COMPILE_DEFINE} ${Qt5Core_COMPILE_DEFINITIONS} )
set(ads_demo_LIBS ${ads_demo_LIBS} ${Qt5Gui_LIBRARIES})
set(ads_demo_INCLUDE ${ads_demo_INCLUDE} ${Qt5Gui_INCLUDE_DIRS})
set(ads_demo_COMPILE_DEFINE ${ads_demo_COMPILE_DEFINE} ${Qt5Gui_COMPILE_DEFINITIONS})
set(ads_demo_LIBS ${ads_demo_LIBS} ${Qt5Widgets_LIBRARIES})
set(ads_demo_INCLUDE ${ads_demo_INCLUDE} ${Qt5Widgets_INCLUDE_DIRS})
set(ads_demo_COMPILE_DEFINE ${ads_demo_COMPILE_DEFINE} ${Qt5Widgets_COMPILE_DEFINITIONS})
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(ads_demo_SRCS
main.cpp
MainWindow.cpp
mainwindow.ui
main.qrc
)
add_executable(AdvancedDockingSystemDemo WIN32 ${ads_demo_SRCS})
if(BUILD_STATIC)
set(ads_demo_DEFINE ${ads_demo_DEFINE} ADS_STATIC)
endif()
add_dependencies(AdvancedDockingSystemDemo qtadvanceddocking)
target_include_directories(AdvancedDockingSystemDemo PUBLIC
$<BUILD_INTERFACE:${ads_demo_INCLUDE}>
$<INSTALL_INTERFACE:include>
)
target_include_directories(AdvancedDockingSystemDemo PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../src" ${ads_demo_INCLUDE})
target_link_libraries(AdvancedDockingSystemDemo PRIVATE qtadvanceddocking ${ads_demo_LIBS})
target_compile_definitions(AdvancedDockingSystemDemo PRIVATE ${ads_demo_DEFINE})
set_target_properties(AdvancedDockingSystemDemo PROPERTIES
VERSION "1.0"
SOVERSION 1
EXPORT_NAME "Qt Advanced Docking System Demo"
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/lib"
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/${ads_PlatformDir}/bin"
)

View File

@@ -57,7 +57,6 @@
#include "DockManager.h"
#include "DockWidget.h"
#include "DockAreaWidget.h"
#include "AnimatedLabel.h"
//============================================================================
@@ -89,6 +88,32 @@ static ads::CDockWidget* createLongTextLabelDockWidget(QMenu* ViewMenu)
}
/**
* Function returns a features string with closable (c), movable (m) and floatable (f)
* features. i.e. The following string is for a not closable but movable and floatable
* widget: c- m+ f+
*/
static QString featuresString(ads::CDockWidget* DockWidget)
{
auto f = DockWidget->features();
return QString("c%1 m%2 f%3")
.arg(f.testFlag(ads::CDockWidget::DockWidgetClosable) ? "+" : "-")
.arg(f.testFlag(ads::CDockWidget::DockWidgetMovable) ? "+" : "-")
.arg(f.testFlag(ads::CDockWidget::DockWidgetFloatable) ? "+" : "-");
}
/**
* Appends the string returned by featuresString() to the window title of
* the given DockWidget
*/
static void appendFeaturStringToWindowTitle(ads::CDockWidget* DockWidget)
{
DockWidget->setWindowTitle(DockWidget->windowTitle()
+ QString(" (%1)").arg(featuresString(DockWidget)));
}
//============================================================================
static ads::CDockWidget* createCalendarDockWidget(QMenu* ViewMenu)
{
@@ -111,7 +136,8 @@ static ads::CDockWidget* createFileSystemTreeDockWidget(QMenu* ViewMenu)
QFileSystemModel* m = new QFileSystemModel(w);
m->setRootPath(QDir::currentPath());
w->setModel(m);
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1").arg(FileSystemCount++));
ads::CDockWidget* DockWidget = new ads::CDockWidget(QString("Filesystem %1")
.arg(FileSystemCount++));
DockWidget->setWidget(w);
ViewMenu->addAction(DockWidget->toggleViewAction());
return DockWidget;
@@ -128,7 +154,7 @@ struct MainWindowPrivate
Ui::MainWindow ui;
QAction* SavePerspectiveAction = nullptr;
QWidgetAction* PerspectiveListAction = nullptr;
QComboBox* PerspectiveComboBox = nullptr;;
QComboBox* PerspectiveComboBox = nullptr;
ads::CDockManager* DockManager = nullptr;
MainWindowPrivate(CMainWindow* _public) : _this(_public) {}
@@ -186,9 +212,12 @@ void MainWindowPrivate::createContent()
ToolBar->addAction(ui.actionSaveState);
ToolBar->addAction(ui.actionRestoreState);
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetMovable, false);
FileSystemWidget->setFeature(ads::CDockWidget::DockWidgetFloatable, false);
appendFeaturStringToWindowTitle(FileSystemWidget);
auto TopDockArea = DockManager->addDockWidget(ads::TopDockWidgetArea, FileSystemWidget);
DockWidget = createCalendarDockWidget(ViewMenu);
DockWidget->setFeature(ads::CDockWidget::DockWidgetClosable, false);
DockWidget->setTabToolTip(QString("Tab ToolTip\nHodie est dies magna"));
DockManager->addDockWidget(ads::CenterDockWidgetArea, DockWidget, TopDockArea);
// Test dock area docking
@@ -282,7 +311,7 @@ CMainWindow::CMainWindow(QWidget *parent) :
d->createContent();
// Default window geometry
resize(800, 600);
resize(1280, 720);
d->restoreState();
d->restorePerspectives();

View File

@@ -1,31 +1,45 @@
ADS_ROOT = $${PWD}/..
ADS_OUT_ROOT = $${OUT_PWD}/..
TARGET = AdvancedDockingSystemDemo
DESTDIR = $${ADS_OUT_ROOT}/lib
QT += core gui widgets
CONFIG *= c++14
CONFIG += c++14
CONFIG += debug_and_release
DEFINES += QT_DEPRECATED_WARNINGS
adsBuildStatic {
DEFINES += ADS_STATIC
}
SOURCES += \
main.cpp \
MainWindow.cpp
HEADERS += \
MainWindow.h
FORMS += \
mainwindow.ui
RESOURCES += main.qrc
LIBS += -L$${ADS_OUT_ROOT}/lib
# Dependency: AdvancedDockingSystem (shared)
win32:CONFIG(release, debug|release): LIBS += -lqtadvanceddocking
else:win32:CONFIG(debug, debug|release): LIBS += -lqtadvanceddockingd
else:unix: LIBS += -lAdvancedDockingSystem
CONFIG(debug, debug|release){
win32 {
LIBS += -lqtadvanceddockingd
}
else:mac {
LIBS += -lqtadvanceddocking_debug
}
else {
LIBS += -lqtadvanceddocking
}
}
else{
LIBS += -lqtadvanceddocking
}
INCLUDEPATH += ../src
DEPENDPATH += ../src

View File

@@ -1,5 +1,3 @@
#include <windows.h>
#include <MainWindow.h>
#include <QString>
#include <QFile>
@@ -38,7 +36,9 @@ void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QS
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#if QT_VERSION >= 0x050600
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
std::shared_ptr<int> b;
QApplication a(argc, argv);
a.setQuitOnLastWindowClosed(true);

View File

@@ -1,7 +1,3 @@
<RCC>
<qresource prefix="/main">
<file>bricks.gif</file>
<file>bricks_orange.gif</file>
<file>bricks.apng</file>
</qresource>
<qresource prefix="/main"/>
</RCC>

Binary file not shown.

After

Width:  |  Height:  |  Size: 276 KiB

BIN
doc/linux_kubuntu_1804.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

46
example/CMakeLists.txt Normal file
View File

@@ -0,0 +1,46 @@
cmake_minimum_required(VERSION 3.3)
set (CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
project(ads_example VERSION "1.0")
set(REQUIRED_QT_VERSION 5.5.0)
find_package(Qt5Core ${REQUIRED_QT_VERSION} REQUIRED)
find_package(Qt5Gui ${REQUIRED_QT_VERSION} REQUIRED)
find_package(Qt5Widgets ${REQUIRED_QT_VERSION} REQUIRED)
set(ads_example_LIBS ${ads_example_LIBS} ${Qt5Core_LIBRARIES})
set(ads_example_INCLUDE ${ads_example_INCLUDE} ${Qt5Core_INCLUDE_DIRS})
set(ads_example_COMPILE_DEFINE ${ads_example_COMPILE_DEFINE} ${Qt5Core_COMPILE_DEFINITIONS} )
set(ads_example_LIBS ${ads_example_LIBS} ${Qt5Gui_LIBRARIES})
set(ads_example_INCLUDE ${ads_example_INCLUDE} ${Qt5Gui_INCLUDE_DIRS})
set(ads_example_COMPILE_DEFINE ${ads_example_COMPILE_DEFINE} ${Qt5Gui_COMPILE_DEFINITIONS})
set(ads_example_LIBS ${ads_example_LIBS} ${Qt5Widgets_LIBRARIES})
set(ads_example_INCLUDE ${ads_example_INCLUDE} ${Qt5Widgets_INCLUDE_DIRS})
set(ads_example_COMPILE_DEFINE ${ads_example_COMPILE_DEFINE} ${Qt5Widgets_COMPILE_DEFINITIONS})
set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(ads_example_SRCS
main.cpp
MainWindow.cpp
MainWindow.ui
)
add_executable(Example1 WIN32 ${ads_example_SRCS})
if(BUILD_STATIC)
set(ads_example_DEFINE ${ads_example_DEFINE} ADS_STATIC)
endif()
add_dependencies(Example1 qtadvanceddocking)
target_include_directories(Example1 PUBLIC
$<BUILD_INTERFACE:${ads_example_INCLUDE}>
$<INSTALL_INTERFACE:include>
)
target_include_directories(Example1 PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/../src" ${ads_example_INCLUDE})
target_link_libraries(Example1 PRIVATE qtadvanceddocking ${ads_example_LIBS})
target_compile_definitions(Example1 PRIVATE ${ads_example_DEFINE})
set_target_properties(Example1 PROPERTIES
VERSION "1.0"
SOVERSION 1
EXPORT_NAME "Qt Advanced Docking System 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"
)

39
example/MainWindow.cpp Normal file
View File

@@ -0,0 +1,39 @@
#include "MainWindow.h"
#include "ui_MainWindow.h"
#include <QLabel>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// Create the dock manager. Because the parent parameter is a QMainWindow
// the dock manager registers itself as the central widget.
m_DockManager = new ads::CDockManager(this);
// Create example content label - this can be any application specific
// widget
QLabel* l = new QLabel();
l->setWordWrap(true);
l->setAlignment(Qt::AlignTop | Qt::AlignLeft);
l->setText("Lorem ipsum dolor sit amet, consectetuer adipiscing elit. ");
// Create a dock widget with the title Label 1 and set the created label
// as the dock widget content
ads::CDockWidget* DockWidget = new ads::CDockWidget("Label 1");
DockWidget->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_DockManager->addDockWidget(ads::TopDockWidgetArea, DockWidget);
}
MainWindow::~MainWindow()
{
delete ui;
}

24
example/MainWindow.h Normal file
View File

@@ -0,0 +1,24 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include "DockManager.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private:
Ui::MainWindow *ui;
ads::CDockManager* m_DockManager;
};
#endif // MAINWINDOW_H

38
example/MainWindow.ui Normal file
View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>400</width>
<height>300</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>400</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="QStatusBar" name="statusBar"/>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
<connections/>
</ui>

48
example/example.pro Normal file
View File

@@ -0,0 +1,48 @@
ADS_OUT_ROOT = $${OUT_PWD}/..
QT += core gui widgets
TARGET = Example1
DESTDIR = $${ADS_OUT_ROOT}/lib
TEMPLATE = app
CONFIG += c++14
CONFIG += debug_and_release
adsBuildStatic {
DEFINES += ADS_STATIC
}
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
MainWindow.cpp
HEADERS += \
MainWindow.h
FORMS += \
MainWindow.ui
#RESOURCES += main.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

11
example/main.cpp Normal file
View File

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

View File

@@ -205,6 +205,13 @@ void CDockAreaTabBar::mouseMoveEvent(QMouseEvent* ev)
return;
}
// If one single dock widget in this area is not floatable then the whole
// area is not floatable
if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
{
return;
}
int DragDistance = (d->DragStartMousePos - ev->pos()).manhattanLength();
if (DragDistance >= CDockManager::startDragDistance())
{
@@ -228,16 +235,22 @@ void CDockAreaTabBar::mouseDoubleClickEvent(QMouseEvent *event)
{
return;
}
startFloating(event->pos());
if (!d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
{
return;
}
makeAreaFloating(event->pos(), DraggingInactive);
}
//============================================================================
CFloatingDockContainer* CDockAreaTabBar::makeAreaFloating(const QPoint& Pos)
CFloatingDockContainer* CDockAreaTabBar::makeAreaFloating(const QPoint& Offset,
eDragState DragState)
{
QSize Size = d->DockArea->size();
CFloatingDockContainer* FloatingWidget = new CFloatingDockContainer(d->DockArea);
FloatingWidget->startFloating(Pos, Size);
FloatingWidget->startFloating(Offset, Size, DragState, nullptr);
auto TopLevelDockWidget = FloatingWidget->topLevelDockWidget();
if (TopLevelDockWidget)
{
@@ -249,9 +262,9 @@ CFloatingDockContainer* CDockAreaTabBar::makeAreaFloating(const QPoint& Pos)
//============================================================================
void CDockAreaTabBar::startFloating(const QPoint& Pos)
void CDockAreaTabBar::startFloating(const QPoint& Offset)
{
d->FloatingWidget = makeAreaFloating(Pos);
d->FloatingWidget = makeAreaFloating(Offset, DraggingFloatingWidget);
}

View File

@@ -30,6 +30,7 @@
// INCLUDES
//============================================================================
#include <QScrollArea>
#include "ads_globals.h"
namespace ads
{
@@ -49,7 +50,7 @@ class CDockAreaTabBar : public QScrollArea
Q_OBJECT
private:
DockAreaTabBarPrivate* d; ///< private data (pimpl)
friend class DockAreaTabBarPrivate;
friend struct DockAreaTabBarPrivate;
friend class CDockAreaTitleBar;
private slots:
@@ -84,12 +85,13 @@ protected:
/**
* Starts floating
*/
void startFloating(const QPoint& Pos);
void startFloating(const QPoint& Offset);
/**
* Makes the dock area loating
* Makes the dock area floating
*/
CFloatingDockContainer* makeAreaFloating(const QPoint& Pos);
CFloatingDockContainer* makeAreaFloating(const QPoint& Offset,
eDragState DragState);
public:

View File

@@ -47,6 +47,7 @@
#include "DockWidgetTab.h"
#include "DockAreaTabBar.h"
#include <iostream>
namespace ads
{
@@ -96,6 +97,23 @@ struct DockAreaTitleBarPrivate
{
return DockArea->dockManager()->configFlags().testFlag(Flag);
}
/**
* Helper class to set title bar button icons depending on operating system
* and to avoid duplicated code
*/
void setTitleBarButtonIcon(tTileBarButton* Button, QStyle::StandardPixmap StandarPixmap)
{
#ifdef Q_OS_LINUX
Button->setIcon(_this->style()->standardIcon(StandarPixmap));
#else
QIcon Icon;
QPixmap normalPixmap = _this->style()->standardPixmap(StandarPixmap, 0, Button);
Icon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
Icon.addPixmap(normalPixmap, QIcon::Normal);
Button->setIcon(Icon);
#endif
}
};// struct DockAreaTitleBarPrivate
@@ -111,42 +129,46 @@ DockAreaTitleBarPrivate::DockAreaTitleBarPrivate(CDockAreaTitleBar* _public) :
//============================================================================
void DockAreaTitleBarPrivate::createButtons()
{
// Tabs menu button
TabsMenuButton = new tTileBarButton();
TabsMenuButton->setObjectName("tabsMenuButton");
TabsMenuButton->setAutoRaise(true);
TabsMenuButton->setPopupMode(QToolButton::InstantPopup);
TabsMenuButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarUnshadeButton));
setTitleBarButtonIcon(TabsMenuButton, QStyle::SP_TitleBarUnshadeButton);
QMenu* TabsMenu = new QMenu(TabsMenuButton);
#ifndef QT_NO_TOOLTIP
TabsMenu->setToolTipsVisible(true);
#endif
_this->connect(TabsMenu, SIGNAL(aboutToShow()), SLOT(onTabsMenuAboutToShow()));
TabsMenuButton->setMenu(TabsMenu);
#ifndef QT_NO_TOOLTIP
TabsMenuButton->setToolTip(QObject::tr("List all tabs"));
#endif
TabsMenuButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
TopLayout->addWidget(TabsMenuButton, 0);
_this->connect(TabsMenuButton->menu(), SIGNAL(triggered(QAction*)),
SLOT(onTabsMenuActionTriggered(QAction*)));
// Undock button
UndockButton = new tTileBarButton();
UndockButton->setObjectName("undockButton");
UndockButton->setAutoRaise(true);
#ifndef QT_NO_TOOLTIP
UndockButton->setToolTip(QObject::tr("Detach Group"));
UndockButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarNormalButton));
UndockButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
#endif
setTitleBarButtonIcon(UndockButton, QStyle::SP_TitleBarNormalButton);
UndockButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
TopLayout->addWidget(UndockButton, 0);
_this->connect(UndockButton, SIGNAL(clicked()), SLOT(onUndockButtonClicked()));
// Close button
CloseButton = new tTileBarButton();
CloseButton->setObjectName("closeButton");
CloseButton->setAutoRaise(true);
// The standard icons do not look good on high DPI screens
QIcon CloseIcon = _this->style()->standardIcon(QStyle::SP_TitleBarCloseButton);
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
QPixmap disabledPixmap = internal::createTransparentPixmap(normalPixmap, 0.25);
CloseIcon.addPixmap(disabledPixmap, QIcon::Disabled);
CloseButton->setIcon(CloseIcon);
setTitleBarButtonIcon(CloseButton, QStyle::SP_TitleBarCloseButton);
#ifndef QT_NO_TOOLTIP
if (testConfigFlag(CDockManager::DockAreaCloseButtonClosesTab))
{
CloseButton->setToolTip(QObject::tr("Close Active Tab"));
@@ -155,7 +177,9 @@ void DockAreaTitleBarPrivate::createButtons()
{
CloseButton->setToolTip(QObject::tr("Close Group"));
}
#endif
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
CloseButton->setIconSize(QSize(16, 16));
TopLayout->addWidget(CloseButton, 0);
_this->connect(CloseButton, SIGNAL(clicked()), SLOT(onCloseButtonClicked()));
}
@@ -173,6 +197,10 @@ void DockAreaTitleBarPrivate::createTabBar()
_this->connect(TabBar, SIGNAL(tabMoved(int, int)), SLOT(markTabsMenuOutdated()));
_this->connect(TabBar, SIGNAL(currentChanged(int)), SLOT(onCurrentTabChanged(int)));
_this->connect(TabBar, SIGNAL(tabBarClicked(int)), SIGNAL(tabBarClicked(int)));
TabBar->setContextMenuPolicy(Qt::CustomContextMenu);
_this->connect(TabBar, SIGNAL(customContextMenuRequested(const QPoint&)),
SLOT(showContextMenu(const QPoint&)));
}
@@ -235,6 +263,9 @@ void CDockAreaTitleBar::onTabsMenuAboutToShow()
}
auto Tab = d->TabBar->tab(i);
QAction* Action = menu->addAction(Tab->icon(), Tab->text());
#ifndef QT_NO_TOOLTIP
Action->setToolTip(Tab->toolTip());
#endif
Action->setData(i);
}
@@ -260,7 +291,10 @@ void CDockAreaTitleBar::onCloseButtonClicked()
//============================================================================
void CDockAreaTitleBar::onUndockButtonClicked()
{
d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()));
if (d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable))
{
d->TabBar->makeAreaFloating(mapFromGlobal(QCursor::pos()), DraggingInactive);
}
}
@@ -307,6 +341,21 @@ QAbstractButton* CDockAreaTitleBar::button(TitleBarButton which) const
void CDockAreaTitleBar::setVisible(bool Visible)
{
Super::setVisible(Visible);
markTabsMenuOutdated();
}
//============================================================================
void CDockAreaTitleBar::showContextMenu(const QPoint& pos)
{
QMenu Menu(this);
auto Action = Menu.addAction(tr("Detach Area"), this, SLOT(onUndockButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetFloatable));
Menu.addSeparator();
Action = Menu.addAction(tr("Close Area"), this, SLOT(onCloseButtonClicked()));
Action->setEnabled(d->DockArea->features().testFlag(CDockWidget::DockWidgetClosable));
Menu.addAction(tr("Close Other Areas"), d->DockArea, SLOT(closeOtherAreas()));
Menu.exec(mapToGlobal(pos));
}

View File

@@ -50,15 +50,19 @@ class CDockAreaTitleBar : public QFrame
Q_OBJECT
private:
DockAreaTitleBarPrivate* d; ///< private data (pimpl)
friend class DockAreaTitleBarPrivate;
friend struct DockAreaTitleBarPrivate;
private slots:
void markTabsMenuOutdated();
void onTabsMenuAboutToShow();
void onCloseButtonClicked();
void onUndockButtonClicked();
void onTabsMenuActionTriggered(QAction* Action);
void onCurrentTabChanged(int Index);
void showContextMenu(const QPoint& pos);
public slots:
void markTabsMenuOutdated();
public:
using Super = QFrame;
@@ -87,6 +91,7 @@ public:
*/
virtual void setVisible(bool Visible) override;
signals:
/**
* This signal is emitted if a tab in the tab bar is clicked by the user

View File

@@ -1,17 +1,17 @@
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
@@ -61,9 +61,6 @@ namespace ads
{
static const char* const INDEX_PROPERTY = "index";
static const char* const ACTION_PROPERTY = "action";
static const char* const DOCKWIDGET_PROPERTY = "dockwidget";
static const int APPEND = -1;
/**
* New dock area layout mimics stack layout but only inserts the current
@@ -101,7 +98,7 @@ public:
*/
void insertWidget(int index, QWidget* Widget)
{
Widget->setParent(0);
Widget->setParent(nullptr);
if (index < 0)
{
index = m_Widgets.count();
@@ -130,7 +127,7 @@ public:
auto LayoutItem = m_ParentLayout->takeAt(1);
if (LayoutItem)
{
LayoutItem->widget()->setParent(0);
LayoutItem->widget()->setParent(nullptr);
}
m_CurrentWidget = nullptr;
m_CurrentIndex = -1;
@@ -170,7 +167,7 @@ public:
auto LayoutItem = m_ParentLayout->takeAt(1);
if (LayoutItem)
{
LayoutItem->widget()->setParent(0);
LayoutItem->widget()->setParent(nullptr);
}
m_ParentLayout->addWidget(next);
@@ -239,12 +236,12 @@ using DockAreaLayout = CDockAreaLayout;
*/
struct DockAreaWidgetPrivate
{
CDockAreaWidget* _this;
QBoxLayout* Layout;
DockAreaLayout* ContentsLayout;
CDockAreaTitleBar* TitleBar;
CDockManager* DockManager = nullptr;
bool UpdateCloseButton = false;
CDockAreaWidget* _this = nullptr;
QBoxLayout* Layout = nullptr;
DockAreaLayout* ContentsLayout = nullptr;
CDockAreaTitleBar* TitleBar = nullptr;
CDockManager* DockManager = nullptr;
bool UpdateTitleBarButtons = false;
/**
* Private data constructor
@@ -298,9 +295,9 @@ struct DockAreaWidgetPrivate
}
/**
* Udpates the enable state of the close button
* Udpates the enable state of the close and detach button
*/
void updateCloseButtonState();
void updateTitleBarButtonStates();
};
// struct DockAreaWidgetPrivate
@@ -318,27 +315,26 @@ void DockAreaWidgetPrivate::createTitleBar()
{
TitleBar = new CDockAreaTitleBar(_this);
Layout->addWidget(TitleBar);
_this->connect(tabBar(), SIGNAL(tabCloseRequested(int)),
SLOT(onTabCloseRequested(int)));
_this->connect(TitleBar, SIGNAL(tabBarClicked(int)),
SLOT(setCurrentIndex(int)));
_this->connect(tabBar(), SIGNAL(tabMoved(int, int)),
SLOT(reorderDockWidget(int, int)));
QObject::connect(tabBar(), &CDockAreaTabBar::tabCloseRequested, _this, &CDockAreaWidget::onTabCloseRequested);
QObject::connect(TitleBar, &CDockAreaTitleBar::tabBarClicked, _this, &CDockAreaWidget::setCurrentIndex);
QObject::connect(tabBar(), &CDockAreaTabBar::tabMoved, _this, &CDockAreaWidget::reorderDockWidget);
}
//============================================================================
void DockAreaWidgetPrivate::updateCloseButtonState()
void DockAreaWidgetPrivate::updateTitleBarButtonStates()
{
if (_this->isHidden())
{
UpdateCloseButton = true;
UpdateTitleBarButtons = true;
return;
}
TitleBar->button(TitleBarButtonClose)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetClosable));
UpdateCloseButton = false;
TitleBar->button(TitleBarButtonUndock)->setEnabled(
_this->features().testFlag(CDockWidget::DockWidgetFloatable));
UpdateTitleBarButtons = false;
}
@@ -406,7 +402,7 @@ void CDockAreaWidget::insertDockWidget(int index, CDockWidget* DockWidget,
setCurrentIndex(index);
}
DockWidget->setDockArea(this);
d->updateCloseButtonState();
d->updateTitleBarButtonStates();
}
@@ -420,14 +416,15 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
auto TabWidget = DockWidget->tabWidget();
TabWidget->hide();
d->tabBar()->removeTab(TabWidget);
CDockContainerWidget* DockContainer = dockContainer();
if (NextOpenDockWidget)
{
setCurrentDockWidget(NextOpenDockWidget);
}
else if (d->ContentsLayout->isEmpty())
else if (d->ContentsLayout->isEmpty() && DockContainer->dockAreaCount() > 1)
{
qDebug() << "Dock Area empty";
dockContainer()->removeDockArea(this);
DockContainer->removeDockArea(this);
this->deleteLater();
}
else
@@ -438,16 +435,15 @@ void CDockAreaWidget::removeDockWidget(CDockWidget* DockWidget)
hideAreaWithNoVisibleContent();
}
d->updateCloseButtonState();
d->updateTitleBarButtonStates();
updateTitleBarVisibility();
auto TopLevelDockWidget = dockContainer()->topLevelDockWidget();
auto TopLevelDockWidget = DockContainer->topLevelDockWidget();
if (TopLevelDockWidget)
{
TopLevelDockWidget->emitTopLevelChanged(true);
}
#if (ADS_DEBUG_LEVEL > 0)
CDockContainerWidget* DockContainer = dockContainer();
DockContainer->dumpLayout();
#endif
}
@@ -683,10 +679,24 @@ void CDockAreaWidget::updateTitleBarVisibility()
return;
}
d->TitleBar->setVisible(!Container->isFloating() || !Container->hasTopLevelDockWidget());
if (d->TitleBar)
{
d->TitleBar->setVisible(!Container->isFloating() || !Container->hasTopLevelDockWidget());
}
}
//============================================================================
void CDockAreaWidget::markTitleBarMenuOutdated()
{
if (d->TitleBar)
{
d->TitleBar->markTabsMenuOutdated();
}
}
//============================================================================
void CDockAreaWidget::saveState(QXmlStreamWriter& s) const
{
@@ -757,9 +767,9 @@ void CDockAreaWidget::toggleView(bool Open)
void CDockAreaWidget::setVisible(bool Visible)
{
Super::setVisible(Visible);
if (d->UpdateCloseButton)
if (d->UpdateTitleBarButtons)
{
d->updateCloseButtonState();
d->updateTitleBarButtonStates();
}
}
@@ -779,6 +789,13 @@ void CDockAreaWidget::closeArea()
DockWidget->toggleView(false);
}
}
//============================================================================
void CDockAreaWidget::closeOtherAreas()
{
dockContainer()->closeOtherAreas(this);
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -43,7 +43,7 @@ namespace ads
struct DockAreaWidgetPrivate;
class CDockManager;
class CDockContainerWidget;
struct DockContainerWidgetPrivate;
class DockContainerWidgetPrivate;
/**
@@ -58,7 +58,7 @@ private:
DockAreaWidgetPrivate* d; ///< private data (pimpl)
friend struct DockAreaWidgetPrivate;
friend class CDockContainerWidget;
friend struct DockContainerWidgetPrivate;
friend class DockContainerWidgetPrivate;
friend class CDockWidgetTab;
friend struct DockWidgetPrivate;
friend class CDockWidget;
@@ -130,6 +130,12 @@ protected:
*/
void internalSetCurrentDockWidget(CDockWidget* DockWidget);
/**
* Marks tabs menu to update
*/
void markTitleBarMenuOutdated();
protected slots:
void toggleView(bool Open);
@@ -259,6 +265,11 @@ public slots:
*/
void closeArea();
/**
* This function closes all other areas except of this area
*/
void closeOtherAreas();
signals:
/**
* This signal is emitted when user clicks on a tab at an index.

View File

@@ -47,8 +47,35 @@
#include "ads_globals.h"
#include "DockSplitter.h"
#include <functional>
#include <iostream>
#if QT_VERSION < 0x050900
inline char toHexLower(uint value)
{
return "0123456789abcdef"[value & 0xF];
}
QByteArray qByteArrayToHex(const QByteArray& src, char separator)
{
if(src.size() == 0)
return QByteArray();
const int length = separator ? (src.size() * 3 - 1) : (src.size() * 2);
QByteArray hex(length, Qt::Uninitialized);
char *hexData = hex.data();
const uchar *data = reinterpret_cast<const uchar *>(src.data());
for (int i = 0, o = 0; i < src.size(); ++i) {
hexData[o++] = toHexLower(data[i] >> 4);
hexData[o++] = toHexLower(data[i] & 0xf);
if ((separator) && (o < length))
hexData[o++] = separator;
}
return hex;
}
#endif
namespace ads
{
@@ -70,8 +97,6 @@ static int areaIdToIndex(DockWidgetArea area)
default:
return 4;
}
return 4;
}
/**
@@ -102,7 +127,7 @@ public:
QGridLayout* Layout = nullptr;
QSplitter* RootSplitter = nullptr;
bool isFloating = false;
CDockAreaWidget* LastAddedAreaCache[5]{0, 0, 0, 0, 0};
CDockAreaWidget* LastAddedAreaCache[5];
int VisibleDockAreaCount = -1;
CDockAreaWidget* TopLevelDockArea = nullptr;
@@ -139,6 +164,12 @@ public:
void dropIntoSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea, DockWidgetArea area);
/**
* Creates a new tab for a widget dropped into the center of a section
*/
void dropIntoCenterOfSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea);
/**
* Adds new dock areas to the internal dock area list
*/
@@ -235,7 +266,7 @@ public:
/**
* Helper function for creation of new splitter
*/
CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = 0)
CDockSplitter* newSplitter(Qt::Orientation orientation, QWidget* parent = nullptr)
{
CDockSplitter* s = new CDockSplitter(orientation, parent);
s->setOpaqueResize(DockManager->configFlags().testFlag(CDockManager::OpaqueSplitterResize));
@@ -259,7 +290,7 @@ public:
DockContainerWidgetPrivate::DockContainerWidgetPrivate(CDockContainerWidget* _public) :
_this(_public)
{
std::fill(std::begin(LastAddedAreaCache),std::end(LastAddedAreaCache), nullptr);
}
@@ -343,42 +374,51 @@ void DockContainerWidgetPrivate::dropIntoContainer(CFloatingDockContainer* Float
}
//============================================================================
void DockContainerWidgetPrivate::dropIntoCenterOfSection(
CFloatingDockContainer* FloatingWidget, CDockAreaWidget* TargetArea)
{
CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
auto NewDockWidgets = FloatingContainer->dockWidgets();
auto TopLevelDockArea = FloatingContainer->topLevelDockArea();
int NewCurrentIndex = -1;
// If the floating widget contains only one single dock are, then the
// current dock widget of the dock area will also be the future current
// dock widget in the drop area.
if (TopLevelDockArea)
{
NewCurrentIndex = TopLevelDockArea->currentIndex();
}
for (int i = 0; i < NewDockWidgets.count(); ++i)
{
CDockWidget* DockWidget = NewDockWidgets[i];
TargetArea->insertDockWidget(i, DockWidget, false);
// If the floating widget contains multiple visible dock areas, then we
// simply pick the first visible open dock widget and make it
// the current one.
if (NewCurrentIndex < 0 && !DockWidget->isClosed())
{
NewCurrentIndex = i;
}
}
TargetArea->setCurrentIndex(NewCurrentIndex);
FloatingWidget->deleteLater();
TargetArea->updateTitleBarVisibility();
return;
}
//============================================================================
void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* FloatingWidget,
CDockAreaWidget* TargetArea, DockWidgetArea area)
{
CDockContainerWidget* FloatingContainer = FloatingWidget->dockContainer();
// Dropping into center means all dock widgets in the dropped floating
// widget will become tabs of the drop area
if (CenterDockWidgetArea == area)
{
auto NewDockWidgets = FloatingContainer->dockWidgets();
auto TopLevelDockArea = FloatingContainer->topLevelDockArea();
int NewCurrentIndex = -1;
// If the floating widget contains only one single dock are, then the
// current dock widget of the dock area will also be the future current
// dock widget in the drop area.
if (TopLevelDockArea)
{
NewCurrentIndex = TopLevelDockArea->currentIndex();
}
for (int i = 0; i < NewDockWidgets.count(); ++i)
{
CDockWidget* DockWidget = NewDockWidgets[i];
TargetArea->insertDockWidget(i, DockWidget, false);
// If the floating widget contains multiple visible dock areas, then we
// simply pick the first visible open dock widget and make it
// the current one.
if (NewCurrentIndex < 0 && !DockWidget->isClosed())
{
NewCurrentIndex = i;
}
}
TargetArea->setCurrentIndex(NewCurrentIndex);
FloatingWidget->deleteLater();
TargetArea->updateTitleBarVisibility();
dropIntoCenterOfSection(FloatingWidget, TargetArea);
return;
}
@@ -396,40 +436,65 @@ void DockContainerWidgetPrivate::dropIntoSection(CFloatingDockContainer* Floatin
}
int AreaIndex = TargetAreaSplitter->indexOf(TargetArea);
auto Widget = FloatingWidget->dockContainer()->findChild<QWidget*>(QString(), Qt::FindDirectChildrenOnly);
auto FloatingSplitter = dynamic_cast<QSplitter*>(Widget);
auto FloatingSplitter = qobject_cast<QSplitter*>(Widget);
if (TargetAreaSplitter->orientation() == InsertParam.orientation())
{
auto Sizes = TargetAreaSplitter->sizes();
int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
bool AdjustSplitterSizes = true;
if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
{
TargetAreaSplitter->insertWidget(AreaIndex + InsertParam.insertOffset(), Widget);
}
else
{
AdjustSplitterSizes = (FloatingSplitter->count() == 1);
int InsertIndex = AreaIndex + InsertParam.insertOffset();
while (FloatingSplitter->count())
{
TargetAreaSplitter->insertWidget(InsertIndex++, FloatingSplitter->widget(0));
}
}
if (AdjustSplitterSizes)
{
int Size = (TargetAreaSize - TargetAreaSplitter->handleWidth()) / 2;
Sizes[AreaIndex] = Size;
Sizes.insert(AreaIndex, Size);
TargetAreaSplitter->setSizes(Sizes);
}
}
else
{
QList<int> NewSplitterSizes;
QSplitter* NewSplitter = newSplitter(InsertParam.orientation());
int TargetAreaSize = (InsertParam.orientation() == Qt::Horizontal) ? TargetArea->width() : TargetArea->height();
bool AdjustSplitterSizes = true;
if ((FloatingSplitter->orientation() != InsertParam.orientation()) && FloatingSplitter->count() > 1)
{
NewSplitter->addWidget(Widget);
}
else
{
AdjustSplitterSizes = (FloatingSplitter->count() == 1);
while (FloatingSplitter->count())
{
NewSplitter->addWidget(FloatingSplitter->widget(0));
}
}
TargetAreaSplitter->insertWidget(AreaIndex, 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)
{
int Size = TargetAreaSize / 2;
NewSplitter->setSizes({Size, Size});
}
TargetAreaSplitter->insertWidget(AreaIndex, NewSplitter);
TargetAreaSplitter->setSizes(Sizes);
}
FloatingWidget->deleteLater();
@@ -475,7 +540,10 @@ void DockContainerWidgetPrivate::appendDockAreas(const QList<CDockAreaWidget*> N
DockAreas.append(NewDockAreas);
for (auto DockArea : NewDockAreas)
{
_this->connect(DockArea, SIGNAL(viewToggled(bool)), SLOT(onDockAreaViewToggled(bool)));
QObject::connect(DockArea,
&CDockAreaWidget::viewToggled,
_this,
std::bind(&DockContainerWidgetPrivate::onDockAreaViewToggled, this, std::placeholders::_1));
}
}
@@ -545,7 +613,7 @@ bool DockContainerWidgetPrivate::restoreSplitter(QXmlStreamReader& s,
QSplitter* Splitter = nullptr;
if (!Testing)
{
Splitter = newSplitter((Qt::Orientation)Orientation);
Splitter = newSplitter(static_cast<Qt::Orientation>(Orientation));
}
bool Visible = false;
QList<int> Sizes;
@@ -930,6 +998,15 @@ CDockAreaWidget* CDockContainerWidget::addDockWidget(DockWidgetArea area, CDockW
}
}
//============================================================================
void CDockContainerWidget::removeDockWidget(CDockWidget* Dockwidget)
{
CDockAreaWidget* Area = Dockwidget->dockAreaWidget();
if (Area)
{
Area->removeDockWidget(Dockwidget);
}
}
//============================================================================
unsigned int CDockContainerWidget::zOrderIndex() const
@@ -986,9 +1063,15 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
// Remove are from parent splitter and recursively hide tree of parent
// splitters if it has no visible content
area->setParent(0);
area->setParent(nullptr);
internal::hideEmptyParentSplitters(Splitter);
// Remove this area from cached areas
const auto& cache = d->LastAddedAreaCache;
if (auto p = std::find(cache, cache+sizeof(cache)/sizeof(cache[0]), area)) {
d->LastAddedAreaCache[std::distance(cache, p)] = nullptr;
}
// If splitter has more than 1 widgets, we are finished and can leave
if (Splitter->count() > 1)
{
@@ -1017,7 +1100,7 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
}
// We replace the superfluous RootSplitter with the ChildSplitter
ChildSplitter->setParent(0);
ChildSplitter->setParent(nullptr);
QLayoutItem* li = d->Layout->replaceWidget(Splitter, ChildSplitter);
d->RootSplitter = ChildSplitter;
delete li;
@@ -1026,10 +1109,12 @@ void CDockContainerWidget::removeDockArea(CDockAreaWidget* area)
else if (Splitter->count() == 1)
{
qDebug() << "Replacing splitter with content";
QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
auto Sizes = ParentSplitter->sizes();
QWidget* widget = Splitter->widget(0);
widget->setParent(this);
QSplitter* ParentSplitter = internal::findParent<QSplitter*>(Splitter);
internal::replaceSplitterWidget(ParentSplitter, Splitter, widget);
ParentSplitter->setSizes(Sizes);
}
delete Splitter;
@@ -1056,14 +1141,14 @@ CDockAreaWidget* CDockContainerWidget::dockAreaAt(const QPoint& GlobalPos) const
}
}
return 0;
return nullptr;
}
//============================================================================
CDockAreaWidget* CDockContainerWidget::dockArea(int Index) const
{
return (Index < dockAreaCount()) ? d->DockAreas[Index] : 0;
return (Index < dockAreaCount()) ? d->DockAreas[Index] : nullptr;
}
@@ -1182,7 +1267,11 @@ void CDockContainerWidget::saveState(QXmlStreamWriter& s) const
{
CFloatingDockContainer* FloatingWidget = floatingWidget();
QByteArray Geometry = FloatingWidget->saveGeometry();
#if QT_VERSION < 0x050900
s.writeTextElement("Geometry", qByteArrayToHex(Geometry, ' '));
#else
s.writeTextElement("Geometry", Geometry.toHex(' '));
#endif
}
d->saveChildNodesState(s, d->RootSplitter);
s.writeEndElement();
@@ -1200,6 +1289,7 @@ bool CDockContainerWidget::restoreState(QXmlStreamReader& s, bool Testing)
{
d->VisibleDockAreaCount = -1;// invalidate the dock area count
d->DockAreas.clear();
std::fill(std::begin(d->LastAddedAreaCache),std::end(d->LastAddedAreaCache), nullptr);
}
if (IsFloating)
@@ -1378,8 +1468,20 @@ CFloatingDockContainer* CDockContainerWidget::floatingWidget() const
}
//============================================================================
void CDockContainerWidget::closeOtherAreas(CDockAreaWidget* KeepOpenArea)
{
for (const auto DockArea : d->DockAreas)
{
if (DockArea != KeepOpenArea && DockArea->features().testFlag(CDockWidget::DockWidgetClosable))
{
DockArea->closeArea();
}
}
}
} // namespace ads
#include "moc_DockContainerWidget.cpp"
//---------------------------------------------------------------------------
// EOF DockContainerWidget.cpp

View File

@@ -57,7 +57,7 @@ class ADS_EXPORT CDockContainerWidget : public QFrame
Q_OBJECT
private:
DockContainerWidgetPrivate* d; ///< private data (pimpl)
friend struct DockContainerWidgetPrivate;
friend class DockContainerWidgetPrivate;
friend class CDockManager;
friend struct DockManagerPrivate;
friend class CDockAreaWidget;
@@ -65,8 +65,6 @@ private:
friend class CFloatingDockContainer;
friend struct FloatingDockContainerPrivate;
friend class CDockWidget;
Q_PRIVATE_SLOT(d, void onDockAreaViewToggled(bool Visible))
protected:
/**
* Handles activation events to update zOrderIndex
@@ -168,6 +166,11 @@ public:
CDockAreaWidget* addDockWidget(DockWidgetArea area, CDockWidget* Dockwidget,
CDockAreaWidget* DockAreaWidget = nullptr);
/**
* Removes dockwidget
*/
void removeDockWidget(CDockWidget* Dockwidget);
/**
* Returns the current zOrderIndex
*/
@@ -233,6 +236,11 @@ public:
*/
CFloatingDockContainer* floatingWidget() const;
/**
* Call this function to close all dock areas except the KeepOpenArea
*/
void closeOtherAreas(CDockAreaWidget* KeepOpenArea);
signals:
/**
* This signal is emitted if one or multiple dock areas has been added to

View File

@@ -72,7 +72,7 @@ struct DockManagerPrivate
QMenu* ViewMenu;
CDockManager::eViewMenuInsertionOrder MenuInsertionOrder = CDockManager::MenuAlphabeticallySorted;
bool RestoringState = false;
CDockManager::ConfigFlags ConfigFlags{CDockManager::DefaultConfig};
CDockManager::ConfigFlags ConfigFlags = CDockManager::DefaultConfig;
/**
* Private data constructor
@@ -145,7 +145,11 @@ DockManagerPrivate::DockManagerPrivate(CDockManager* _public) :
void DockManagerPrivate::loadStylesheet()
{
QString Result;
#ifdef Q_OS_LINUX
QFile StyleSheetFile(":ads/stylesheets/default_linux.css");
#else
QFile StyleSheetFile(":ads/stylesheets/default.css");
#endif
StyleSheetFile.open(QIODevice::ReadOnly);
QTextStream StyleSheetStream(&StyleSheetFile);
Result = StyleSheetStream.readAll();
@@ -336,8 +340,9 @@ void DockManagerPrivate::emitTopLevelEvents()
//============================================================================
bool DockManagerPrivate::restoreState(const QByteArray &state, int version)
bool DockManagerPrivate::restoreState(const QByteArray& State, int version)
{
QByteArray state = State.startsWith("<?xml") ? State : qUncompress(State);
if (!checkFormat(state, version))
{
qDebug() << "checkFormat: Error checking format!!!!!!!";
@@ -489,11 +494,11 @@ unsigned int CDockManager::zOrderIndex() const
//============================================================================
QByteArray CDockManager::saveState(eXmlMode XmlMode, int version) const
QByteArray CDockManager::saveState(int version) const
{
QByteArray xmldata;
QXmlStreamWriter s(&xmldata);
s.setAutoFormatting(XmlAutoFormattingEnabled == XmlMode);
s.setAutoFormatting(d->ConfigFlags.testFlag(XmlAutoFormattingEnabled));
s.writeStartDocument();
s.writeStartElement("QtAdvancedDockingSystem");
s.writeAttribute("Version", QString::number(version));
@@ -506,7 +511,7 @@ QByteArray CDockManager::saveState(eXmlMode XmlMode, int version) const
s.writeEndElement();
s.writeEndDocument();
return xmldata;
return d->ConfigFlags.testFlag(XmlCompressionEnabled) ? qCompress(xmldata, 9) : xmldata;
}
@@ -565,9 +570,13 @@ CDockAreaWidget* CDockManager::addDockWidgetTab(DockWidgetArea area,
{
return addDockWidget(ads::CenterDockWidgetArea, Dockwidget, AreaWidget);
}
else if (!openedDockAreas().isEmpty())
{
return addDockWidget(area, Dockwidget, openedDockAreas().last());
}
else
{
return addDockWidget(area, Dockwidget, AreaWidget);
return addDockWidget(area, Dockwidget, nullptr);
}
}
@@ -586,6 +595,12 @@ CDockWidget* CDockManager::findDockWidget(const QString& ObjectName) const
return d->DockWidgetsMap.value(ObjectName, nullptr);
}
//============================================================================
void CDockManager::removeDockWidget(CDockWidget* Dockwidget)
{
d->DockWidgetsMap.remove(Dockwidget->objectName());
CDockContainerWidget::removeDockWidget(Dockwidget);
}
//============================================================================
QMap<QString, CDockWidget*> CDockManager::dockWidgetsMap() const
@@ -759,6 +774,7 @@ void CDockManager::setConfigFlags(const ConfigFlags Flags)
d->ConfigFlags = Flags;
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -51,7 +51,9 @@ struct DockWidgetTabPrivate;
struct DockAreaWidgetPrivate;
/**
* The central dock manager that maintains the complete docking system
* The central dock manager that maintains the complete docking system.
* With the configuration flags you can globally control the functionality
* of the docking system.
**/
class ADS_EXPORT CDockManager : public CDockContainerWidget
{
@@ -108,12 +110,6 @@ public:
MenuAlphabeticallySorted
};
enum eXmlMode
{
XmlAutoFormattingDisabled,
XmlAutoFormattingEnabled
};
/**
* These global configuration flags configure some global dock manager
* settings.
@@ -124,7 +120,9 @@ public:
DockAreaHasCloseButton = 0x02, //!< If the flag is set each dock area has a close button
DockAreaCloseButtonClosesTab = 0x04,//!< If the flag is set, the dock area close button closes the active tab, if not set, it closes the complete cock area
OpaqueSplitterResize = 0x08, //!< See QSplitter::setOpaqueResize() documentation
DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize, ///< the default configuration
XmlAutoFormattingEnabled = 0x10,//!< If enabled, the XML writer automatically adds line-breaks and indentation to empty sections between elements (ignorable whitespace).
XmlCompressionEnabled = 0x20,//!< If enabled, the XML output will be compressed and is not human readable anymore
DefaultConfig = ActiveTabHasCloseButton | DockAreaHasCloseButton | OpaqueSplitterResize | XmlCompressionEnabled, ///< the default configuration
};
Q_DECLARE_FLAGS(ConfigFlags, eConfigFlag)
@@ -192,6 +190,11 @@ public:
*/
CDockWidget* findDockWidget(const QString& ObjectName) const;
/**
* Remove the given Dock from the dock manager
*/
void removeDockWidget(CDockWidget* Dockwidget);
/**
* This function returns a readable reference to the internal dock
* widgets map so that it is possible to iterate over all dock widgets
@@ -223,7 +226,7 @@ public:
* The XmlMode XmlAutoFormattingDisabled is better if you would like to have
* a more compact XML output - i.e. for storage in ini files.
*/
QByteArray saveState(eXmlMode XmlMode = XmlAutoFormattingDisabled, int version = 0) const;
QByteArray saveState(int version = 0) const;
/**
* Restores the state of this dockmanagers dockwidgets.

View File

@@ -132,6 +132,21 @@ struct DockOverlayCrossPrivate
return Color;
}
//============================================================================
/**
* Helper function that returns the drop indicator width depending on the
* operating system
*/
qreal dropIndicatiorWidth(QLabel* l) const
{
#ifdef Q_OS_LINUX
Q_UNUSED(l)
return 40;
#else
return static_cast<qreal>(l->fontMetrics().height()) * 3.f;
#endif
}
//============================================================================
QWidget* createDropIndicatorWidget(DockWidgetArea DockWidgetArea,
@@ -140,7 +155,7 @@ struct DockOverlayCrossPrivate
QLabel* l = new QLabel();
l->setObjectName("DockWidgetAreaLabel");
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
const qreal metric = dropIndicatiorWidth(l);
const QSizeF size(metric, metric);
l->setPixmap(createHighDpiDropIndicatorPixmap(size, DockWidgetArea, Mode));
@@ -154,7 +169,7 @@ struct DockOverlayCrossPrivate
void updateDropIndicatorIcon(QWidget* DropIndicatorWidget)
{
QLabel* l = qobject_cast<QLabel*>(DropIndicatorWidget);
const qreal metric = static_cast<qreal>(l->fontMetrics().height()) * 3.f;
const qreal metric = dropIndicatiorWidth(l);
const QSizeF size(metric, metric);
int Area = l->property("dockWidgetArea").toInt();
@@ -168,7 +183,11 @@ struct DockOverlayCrossPrivate
QColor borderColor = iconColor(CDockOverlayCross::FrameColor);
QColor backgroundColor = iconColor(CDockOverlayCross::WindowBackgroundColor);
#if QT_VERSION >= 0x050600
double DevicePixelRatio = _this->window()->devicePixelRatioF();
#else
double DevicePixelRatio = _this->window()->devicePixelRatio();
#endif
QSizeF PixmapSize = size * DevicePixelRatio;
QPixmap pm(PixmapSize.toSize());
pm.fill(QColor(0, 0, 0, 0));
@@ -577,8 +596,11 @@ void CDockOverlayCross::setupOverlayCross(CDockOverlay::eMode Mode)
areaWidgets.insert(BottomDockWidgetArea, d->createDropIndicatorWidget(BottomDockWidgetArea, Mode));
areaWidgets.insert(LeftDockWidgetArea, d->createDropIndicatorWidget(LeftDockWidgetArea, Mode));
areaWidgets.insert(CenterDockWidgetArea, d->createDropIndicatorWidget(CenterDockWidgetArea, Mode));
#if QT_VERSION >= 0x050600
d->LastDevicePixelRatio = devicePixelRatioF();
#else
d->LastDevicePixelRatio = devicePixelRatio();
#endif
setAreaWidgets(areaWidgets);
d->UpdateRequired = false;
}
@@ -596,7 +618,11 @@ void CDockOverlayCross::updateOverlayIcons()
{
d->updateDropIndicatorIcon(Widget);
}
#if QT_VESION >= 0x050600
d->LastDevicePixelRatio = devicePixelRatioF();
#else
d->LastDevicePixelRatio = devicePixelRatio();
#endif
}

View File

@@ -58,14 +58,14 @@ namespace ads
*/
struct DockWidgetPrivate
{
CDockWidget* _this;
QBoxLayout* Layout;
CDockWidget* _this = nullptr;
QBoxLayout* Layout = nullptr;
QWidget* Widget = nullptr;
CDockWidgetTab* TabWidget;
CDockWidgetTab* TabWidget = nullptr;
CDockWidget::DockWidgetFeatures Features = CDockWidget::AllDockWidgetFeatures;
CDockManager* DockManager = nullptr;
CDockAreaWidget* DockArea = nullptr;
QAction* ToggleViewAction;
QAction* ToggleViewAction = nullptr;
bool Closed = false;
QScrollArea* ScrollArea = nullptr;
QToolBar* ToolBar = nullptr;
@@ -214,7 +214,7 @@ CDockWidget::CDockWidget(const QString &title, QWidget *parent) :
setObjectName(title);
d->TabWidget = new CDockWidgetTab(this);
d->ToggleViewAction = new QAction(title);
d->ToggleViewAction = new QAction(title, nullptr);
d->ToggleViewAction->setCheckable(true);
connect(d->ToggleViewAction, SIGNAL(triggered(bool)), this,
SLOT(toggleView(bool)));
@@ -243,21 +243,35 @@ void CDockWidget::setToggleViewActionChecked(bool Checked)
void CDockWidget::setWidget(QWidget* widget, eInsertMode InsertMode)
{
QScrollArea* ScrollAreaWidget = qobject_cast<QScrollArea*>(widget);
if (ScrollAreaWidget || ForceNoScrollArea != InsertMode)
if (ScrollAreaWidget || ForceNoScrollArea == InsertMode)
{
d->Layout->addWidget(widget);
if (ScrollAreaWidget && ScrollAreaWidget->viewport())
{
ScrollAreaWidget->viewport()->setProperty("dockWidgetContent", true);
}
}
else
{
d->setupScrollArea();
d->ScrollArea->setWidget(widget);
}
else
{
d->Layout->addWidget(widget);
}
d->Widget = widget;
d->Widget->setProperty("dockWidgetContent", true);
}
//============================================================================
QWidget* CDockWidget::takeWidget()
{
d->ScrollArea->takeWidget();
d->Layout->removeWidget(d->Widget);
d->Widget->setParent(nullptr);
return d->Widget;
}
//============================================================================
QWidget* CDockWidget::widget() const
{
@@ -282,7 +296,18 @@ void CDockWidget::setFeatures(DockWidgetFeatures features)
//============================================================================
void CDockWidget::setFeature(DockWidgetFeature flag, bool on)
{
#if QT_VERSION >= 0x050700
d->Features.setFlag(flag, on);
#else
if(on)
{
d->Features |= flag;
}
else
{
d->Features &= ~flag;
}
#endif
}
@@ -496,12 +521,45 @@ bool CDockWidget::event(QEvent *e)
{
if (e->type() == QEvent::WindowTitleChange)
{
emit titleChanged(windowTitle());
const auto title = windowTitle();
if (d->TabWidget)
{
d->TabWidget->setText(title);
}
if (d->ToggleViewAction)
{
d->ToggleViewAction->setText(title);
}
if (d->DockArea)
{
d->DockArea->markTitleBarMenuOutdated();//update tabs menu
}
emit titleChanged(title);
}
return QFrame::event(e);
return Super::event(e);
}
#ifndef QT_NO_TOOLTIP
//============================================================================
void CDockWidget::setTabToolTip(const QString &text)
{
if (d->TabWidget)
{
d->TabWidget->setToolTip(text);
}
if (d->ToggleViewAction)
{
d->ToggleViewAction->setToolTip(text);
}
if (d->DockArea)
{
d->DockArea->markTitleBarMenuOutdated();//update tabs menu
}
}
#endif
//============================================================================
void CDockWidget::setIcon(const QIcon& Icon)
{
@@ -671,6 +729,7 @@ QSize CDockWidget::minimumSizeHint() const
return QSize(60, 40);
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -44,7 +44,8 @@ class CDockWidgetTab;
class CDockManager;
class CDockContainerWidget;
class CDockAreaWidget;
struct DockContainerWidgetPrivate;
class DockContainerWidgetPrivate;
class CFloatingDockContainer;
/**
* The QDockWidget class provides a widget that can be docked inside a
@@ -69,7 +70,7 @@ protected:
friend class CFloatingDockContainer;
friend class CDockManager;
friend struct DockManagerPrivate;
friend struct DockContainerWidgetPrivate;
friend class DockContainerWidgetPrivate;
friend class CDockAreaTabBar;
friend class CDockWidgetTab;
friend struct DockWidgetTabPrivate;
@@ -135,10 +136,12 @@ protected:
void toggleViewInternal(bool Open);
public:
using Super = QFrame;
enum DockWidgetFeature
{
DockWidgetClosable = 0x01,
DockWidgetMovable = 0x02,
DockWidgetMovable = 0x02,///< this feature is not properly implemented yet and is ignored
DockWidgetFloatable = 0x04,
AllDockWidgetFeatures = DockWidgetClosable | DockWidgetMovable | DockWidgetFloatable,
NoDockWidgetFeatures = 0x00
@@ -235,6 +238,11 @@ public:
*/
void setWidget(QWidget* widget, eInsertMode InsertMode = AutoScrollArea);
/**
* Remove the widget from the dock and give ownership back to the caller
*/
QWidget* takeWidget();
/**
* Returns the widget for the dock widget. This function returns zero if
* the widget has not been set.
@@ -384,6 +392,14 @@ public:
QSize toolBarIconSize(eState State) const;
#ifndef QT_NO_TOOLTIP
/**
* This is function sets text tooltip for title bar widget
* and tooltip for toggle view action
*/
void setTabToolTip(const QString &text);
#endif
public: // reimplements QFrame -----------------------------------------------
/**
* Emits titleChanged signal if title change event occurs

View File

@@ -53,16 +53,6 @@
namespace ads
{
/**
* The different dragging states
*/
enum eDragState
{
DraggingInactive, //!< DraggingInactive
DraggingMousePressed, //!< DraggingMousePressed
DraggingTab, //!< DraggingTab
DraggingFloatingWidget//!< DraggingFloatingWidget
};
using tTabLabel = CElidingLabel;
using tCloseButton = QPushButton;
@@ -123,7 +113,7 @@ struct DockWidgetTabPrivate
* Returns true, if floating has been started and false if floating
* is not possible for any reason
*/
bool startFloating();
bool startFloating(eDragState DraggingState = DraggingFloatingWidget);
/**
* Returns true if the given config flag is set
@@ -156,14 +146,17 @@ void DockWidgetTabPrivate::createLayout()
CloseButton = new tCloseButton();
CloseButton->setObjectName("tabCloseButton");
// The standard icons do does not look good on high DPI screens
QIcon CloseIcon = _this->style()->standardIcon(QStyle::SP_TitleBarCloseButton);
QIcon CloseIcon;
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
QPixmap disabledPixmap = internal::createTransparentPixmap(normalPixmap, 0.25);
CloseIcon.addPixmap(disabledPixmap, QIcon::Disabled);
CloseIcon.addPixmap(normalPixmap, QIcon::Normal);
CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
CloseButton->setIcon(CloseIcon);
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
CloseButton->setVisible(false);
#ifndef QT_NO_TOOLTIP
CloseButton->setToolTip(QObject::tr("Close Tab"));
#endif
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
QFontMetrics fm(TitleLabel->font());
@@ -197,7 +190,7 @@ void DockWidgetTabPrivate::moveTab(QMouseEvent* ev)
//============================================================================
bool DockWidgetTabPrivate::startFloating()
bool DockWidgetTabPrivate::startFloating(eDragState DraggingState)
{
auto dockContainer = DockWidget->dockContainer();
qDebug() << "isFloating " << dockContainer->isFloating();
@@ -214,7 +207,7 @@ bool DockWidgetTabPrivate::startFloating()
}
qDebug() << "startFloating";
DragState = DraggingFloatingWidget;
DragState = DraggingState;
QSize Size = DockArea->size();
CFloatingDockContainer* FloatingWidget = nullptr;
if (DockArea->dockWidgetsCount() > 1)
@@ -229,11 +222,18 @@ bool DockWidgetTabPrivate::startFloating()
FloatingWidget = new CFloatingDockContainer(DockArea);
}
FloatingWidget->startFloating(DragStartMousePosition, Size);
auto Overlay = DockWidget->dockManager()->containerOverlay();
Overlay->setAllowedAreas(OuterDockAreas);
this->FloatingWidget = FloatingWidget;
DockWidget->emitTopLevelChanged(true);
if (DraggingFloatingWidget == DraggingState)
{
FloatingWidget->startDragging(DragStartMousePosition, Size, _this);
auto Overlay = DockWidget->dockManager()->containerOverlay();
Overlay->setAllowedAreas(OuterDockAreas);
this->FloatingWidget = FloatingWidget;
}
else
{
FloatingWidget->initFloatingGeometry(DragStartMousePosition, Size);
}
DockWidget->emitTopLevelChanged(true);
return true;
}
@@ -267,7 +267,7 @@ void CDockWidgetTab::mousePressEvent(QMouseEvent* ev)
emit clicked();
return;
}
QFrame::mousePressEvent(ev);
Super::mousePressEvent(ev);
}
@@ -283,7 +283,7 @@ void CDockWidgetTab::mouseReleaseEvent(QMouseEvent* ev)
d->DragStartMousePosition = QPoint();
d->DragState = DraggingInactive;
QFrame::mouseReleaseEvent(ev);
Super::mouseReleaseEvent(ev);
}
@@ -293,7 +293,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
if (!(ev->buttons() & Qt::LeftButton) || d->isDraggingState(DraggingInactive))
{
d->DragState = DraggingInactive;
QFrame::mouseMoveEvent(ev);
Super::mouseMoveEvent(ev);
return;
}
@@ -301,7 +301,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
if (d->isDraggingState(DraggingFloatingWidget))
{
d->FloatingWidget->moveFloating();
QFrame::mouseMoveEvent(ev);
Super::mouseMoveEvent(ev);
return;
}
@@ -328,7 +328,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
}
// Floating is only allowed for widgets that are movable
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetMovable))
if (d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
{
d->startFloating();
}
@@ -341,7 +341,7 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
return;
}
QFrame::mouseMoveEvent(ev);
Super::mouseMoveEvent(ev);
}
@@ -349,13 +349,13 @@ void CDockWidgetTab::mouseMoveEvent(QMouseEvent* ev)
void CDockWidgetTab::contextMenuEvent(QContextMenuEvent* ev)
{
ev->accept();
std::cout << "CDockAreaTabBar::onTabContextMenuRequested" << std::endl;
d->DragStartMousePosition = ev->pos();
QMenu Menu(this);
Menu.addAction(tr("Detach"), this, SLOT(onDetachActionTriggered()));
auto Action = Menu.addAction(tr("Detach"), this, SLOT(onDetachActionTriggered()));
Action->setEnabled(d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable));
Menu.addSeparator();
auto Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
Action = Menu.addAction(tr("Close"), this, SIGNAL(closeRequested()));
Action->setEnabled(isClosable());
Menu.addAction(tr("Close Others"), this, SIGNAL(closeOtherTabsRequested()));
Menu.exec(mapToGlobal(ev->pos()));
@@ -426,7 +426,9 @@ void CDockWidgetTab::setIcon(const QIcon& Icon)
d->IconLabel = new QLabel();
d->IconLabel->setAlignment(Qt::AlignVCenter);
d->IconLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Preferred);
#ifndef QT_NO_TOOLTIP
d->IconLabel->setToolTip(d->TitleLabel->toolTip());
#endif
Layout->insertWidget(0, d->IconLabel, Qt::AlignVCenter);
Layout->insertSpacing(1, qRound(1.5 * Layout->contentsMargins().left() / 2.0));
}
@@ -468,10 +470,11 @@ void CDockWidgetTab::mouseDoubleClickEvent(QMouseEvent *event)
// If this is the last dock area in a dock container it does not make
// sense to move it to a new floating widget and leave this one
// empty
if (!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
if ((!d->DockArea->dockContainer()->isFloating() || d->DockArea->dockWidgetsCount() > 1)
&& d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
{
d->DragStartMousePosition = event->pos();
d->startFloating();
d->startFloating(DraggingInactive);
}
Super::mouseDoubleClickEvent(event);
@@ -486,6 +489,14 @@ void CDockWidgetTab::setVisible(bool visible)
}
//============================================================================
void CDockWidgetTab::setText(const QString& title)
{
d->TitleLabel->setText(title);
}
//============================================================================
bool CDockWidgetTab::isClosable() const
{
@@ -496,11 +507,31 @@ bool CDockWidgetTab::isClosable() const
//===========================================================================
void CDockWidgetTab::onDetachActionTriggered()
{
if (!d->DockWidget->features().testFlag(CDockWidget::DockWidgetFloatable))
{
return;
}
d->DragStartMousePosition = mapFromGlobal(QCursor::pos());
d->startFloating();
d->startFloating(DraggingInactive);
}
} // namespace ads
//============================================================================
bool CDockWidgetTab::event(QEvent *e)
{
#ifndef QT_NO_TOOLTIP
if (e->type() == QEvent::ToolTipChange)
{
const auto text = toolTip();
d->TitleLabel->setToolTip(text);
}
#endif
return Super::event(e);
}
} // namespace ads
//---------------------------------------------------------------------------
// EOF DockWidgetTab.cpp

View File

@@ -125,13 +125,27 @@ public:
*/
QString text() const;
/**
* Sets the tab text
*/
void setText(const QString& title);
/**
* This function returns true if the assigned dock widget is closeable
*/
bool isClosable() const;
/**
* Track event ToolTipChange and set child ToolTip
*/
virtual bool event(QEvent *e) override;
public slots:
virtual void setVisible(bool visible);
virtual void setVisible(bool visible) override;
signals:
void activeTabChanged();

View File

@@ -88,7 +88,9 @@ CElidingLabel::CElidingLabel(const QString& text, QWidget* parent, Qt::WindowFla
d(new ElidingLabelPrivate(this))
{
d->Text = text;
#ifndef QT_NO_TOOLTIP
setToolTip(text);
#endif
}
@@ -183,7 +185,9 @@ void CElidingLabel::setText(const QString &text)
else
{
d->Text = text;
#ifndef QT_NO_TOOLTIP
setToolTip( text );
#endif
d->elideText(this->size().width());
}
}

View File

@@ -46,7 +46,7 @@ class CElidingLabel : public QLabel
Q_OBJECT
private:
ElidingLabelPrivate* d;
friend class ElidingLabelPrivate;
friend struct ElidingLabelPrivate;
protected:
virtual void mouseReleaseEvent(QMouseEvent* event) override;

View File

@@ -45,21 +45,15 @@
#include "DockWidget.h"
#include "DockOverlay.h"
#include <iostream>
#ifdef Q_OS_LINUX
#include "linux/FloatingWidgetTitleBar.h"
#include <xcb/xcb.h>
#endif
namespace ads
{
static unsigned int zOrderCounter = 0;
/**
* The different dragging states
*/
enum eDragState
{
StateInactive, //!< DraggingInactive
StateMousePressed, //!< DraggingMousePressed
StateDraggingActive//!< DraggingFloatingWidget
};
/**
* Private data class of CFloatingDockContainer class (pimpl)
*/
@@ -69,10 +63,14 @@ struct FloatingDockContainerPrivate
CDockContainerWidget* DockContainer;
unsigned int zOrderIndex = ++zOrderCounter;
QPointer<CDockManager> DockManager;
eDragState DraggingState = StateInactive;
eDragState DraggingState = DraggingInactive;
QPoint DragStartMousePosition;
CDockContainerWidget* DropContainer = nullptr;
CDockAreaWidget* SingleDockArea = nullptr;
#ifdef Q_OS_LINUX
QWidget* MouseEventHandler = nullptr;
CFloatingWidgetTitleBar* TitleBar = nullptr;
#endif
/**
* Private data constructor
@@ -94,6 +92,15 @@ struct FloatingDockContainerPrivate
{
DraggingState = StateId;
}
void setWindowTitle(const QString& Text)
{
#ifdef Q_OS_LINUX
TitleBar->setTitle(Text);
#else
_this->setWindowTitle(Text);
#endif
}
};
// struct FloatingDockContainerPrivate
@@ -111,7 +118,7 @@ FloatingDockContainerPrivate::FloatingDockContainerPrivate(CFloatingDockContaine
//============================================================================
void FloatingDockContainerPrivate::titleMouseReleaseEvent()
{
setState(StateInactive);
setState(DraggingInactive);
if (!DropContainer)
{
return;
@@ -226,25 +233,38 @@ void FloatingDockContainerPrivate::updateDropOverlays(const QPoint& GlobalPos)
//============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockManager* DockManager) :
QWidget(DockManager, Qt::Window),
tFloatingWidgetBase(DockManager),
d(new FloatingDockContainerPrivate(this))
{
d->DockManager = DockManager;
d->DockManager = DockManager;
d->DockContainer = new CDockContainerWidget(DockManager, this);
connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, SLOT(onDockAreasAddedOrRemoved()));
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, SLOT(onDockAreasAddedOrRemoved()));
#ifdef Q_OS_LINUX
d->TitleBar = new CFloatingWidgetTitleBar(this);
setWindowFlags(windowFlags() | Qt::Tool);
QDockWidget::setWidget(d->DockContainer);
QDockWidget::setFloating(true);
QDockWidget::setFeatures(QDockWidget::AllDockWidgetFeatures);
setTitleBarWidget(d->TitleBar);
connect(d->TitleBar, SIGNAL(closeRequested()), SLOT(close()));
#else
setWindowFlags(Qt::Window | Qt::WindowMaximizeButtonHint | Qt::WindowCloseButtonHint);
QBoxLayout* l = new QBoxLayout(QBoxLayout::TopToBottom);
l->setContentsMargins(0, 0, 0, 0);
l->setSpacing(0);
setLayout(l);
l->addWidget(d->DockContainer);
#endif
d->DockContainer = new CDockContainerWidget(DockManager, this);
connect(d->DockContainer, SIGNAL(dockAreasAdded()), this, SLOT(onDockAreasAddedOrRemoved()));
connect(d->DockContainer, SIGNAL(dockAreasRemoved()), this, SLOT(onDockAreasAddedOrRemoved()));
l->addWidget(d->DockContainer);
DockManager->registerFloatingWidget(this);
// We install an event filter to detect mouse release events because we
// do not receive mouse release event if the floating widget is behind
// the drop overlay cross
qApp->installEventFilter(this);
qApp->installEventFilter(this);
}
@@ -253,14 +273,20 @@ CFloatingDockContainer::CFloatingDockContainer(CDockAreaWidget* DockArea) :
CFloatingDockContainer(DockArea->dockManager())
{
d->DockContainer->addDockArea(DockArea);
#ifdef Q_OS_LINUX
d->TitleBar->enableCloseButton(isClosable());
#endif
}
//============================================================================
CFloatingDockContainer::CFloatingDockContainer(CDockWidget* DockWidget) :
CFloatingDockContainer(DockWidget->dockManager())
CFloatingDockContainer(DockWidget->dockManager())
{
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
d->DockContainer->addDockWidget(CenterDockWidgetArea, DockWidget);
#ifdef Q_OS_LINUX
d->TitleBar->enableCloseButton(isClosable());
#endif
}
//============================================================================
@@ -299,19 +325,19 @@ void CFloatingDockContainer::changeEvent(QEvent *event)
void CFloatingDockContainer::moveEvent(QMoveEvent *event)
{
QWidget::moveEvent(event);
switch (d->DraggingState)
switch (d->DraggingState)
{
case StateMousePressed:
d->setState(StateDraggingActive);
case DraggingMousePressed:
d->setState(DraggingFloatingWidget);
d->updateDropOverlays(QCursor::pos());
break;
case StateDraggingActive:
case DraggingFloatingWidget:
d->updateDropOverlays(QCursor::pos());
break;
default:
break;
}
}
}
@@ -319,11 +345,29 @@ void CFloatingDockContainer::moveEvent(QMoveEvent *event)
void CFloatingDockContainer::closeEvent(QCloseEvent *event)
{
qDebug() << "CFloatingDockContainer closeEvent";
d->setState(StateInactive);
d->setState(DraggingInactive);
if (isClosable())
{
QWidget::closeEvent(event);
// In Qt version after 5.9.2 there seems to be a bug that causes the
// QWidget::event() function to not receive any NonClientArea mouse
// events anymore after a close/show cycle. The bug is reported here:
// https://bugreports.qt.io/browse/QTBUG-73295
// The following code is a workaround for Qt versions > 5.9.2 that seems
// to work
// Starting from Qt version 5.12.2 this seems to work again. But
// now the QEvent::NonClientAreaMouseButtonPress function returns always
// Qt::RightButton even if the left button was pressed
#ifndef Q_OS_LINUX
#if (QT_VERSION > QT_VERSION_CHECK(5, 9, 2) && QT_VERSION < QT_VERSION_CHECK(5, 12, 2))
event->ignore();
this->hide();
#else
Super::closeEvent(event);
#endif
#else // Q_OS_LINUX
Super::closeEvent(event);
#endif
}
else
{
@@ -350,13 +394,6 @@ void CFloatingDockContainer::hideEvent(QHideEvent *event)
void CFloatingDockContainer::showEvent(QShowEvent *event)
{
Super::showEvent(event);
/*for (auto DockArea : d->DockContainer->openedDockAreas())
{
for (auto DockWidget : DockArea->openedDockWidgets())
{
DockWidget->setToggleViewActionChecked(true);
}
}*/
}
@@ -365,20 +402,37 @@ bool CFloatingDockContainer::event(QEvent *e)
{
switch (d->DraggingState)
{
case StateInactive:
if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons() == Qt::LeftButton)
case DraggingInactive:
{
// Normally we would check here, if the left mouse button is pressed.
// But from QT version 5.12.2 on the mouse events from
// QEvent::NonClientAreaMouseButtonPress return the wrong mouse button
// The event always returns Qt::RightButton even if the left button
// is clicked.
// It is really great to work around the whole NonClientMouseArea
// bugs
#if (QT_VERSION >= QT_VERSION_CHECK(5, 12, 2))
if (e->type() == QEvent::NonClientAreaMouseButtonPress /*&& QGuiApplication::mouseButtons().testFlag(Qt::LeftButton)*/)
{
qDebug() << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type();
d->setState(StateMousePressed);
d->setState(DraggingMousePressed);
}
#else
if (e->type() == QEvent::NonClientAreaMouseButtonPress && QGuiApplication::mouseButtons().testFlag(Qt::LeftButton))
{
qDebug() << "FloatingWidget::event Event::NonClientAreaMouseButtonPress" << e->type();
d->setState(DraggingMousePressed);
}
#endif
}
break;
case StateMousePressed:
case DraggingMousePressed:
switch (e->type())
{
case QEvent::NonClientAreaMouseButtonDblClick:
qDebug() << "FloatingWidget::event QEvent::NonClientAreaMouseButtonDblClick";
d->setState(StateInactive);
d->setState(DraggingInactive);
break;
case QEvent::Resize:
@@ -392,7 +446,7 @@ bool CFloatingDockContainer::event(QEvent *e)
// change, we check, if we are not in maximized state.
if (!isMaximized())
{
d->setState(StateInactive);
d->setState(DraggingInactive);
}
break;
@@ -401,7 +455,7 @@ bool CFloatingDockContainer::event(QEvent *e)
}
break;
case StateDraggingActive:
case DraggingFloatingWidget:
if (e->type() == QEvent::NonClientAreaMouseButtonRelease)
{
qDebug() << "FloatingWidget::event QEvent::NonClientAreaMouseButtonRelease";
@@ -423,26 +477,43 @@ bool CFloatingDockContainer::event(QEvent *e)
//============================================================================
bool CFloatingDockContainer::eventFilter(QObject *watched, QEvent *event)
{
Q_UNUSED(watched);
if (event->type() == QEvent::MouseButtonRelease && d->isState(StateDraggingActive))
Q_UNUSED(watched);
if (event->type() == QEvent::MouseButtonRelease && d->isState(DraggingFloatingWidget))
{
qDebug() << "FloatingWidget::eventFilter QEvent::MouseButtonRelease";
finishDragging();
d->titleMouseReleaseEvent();
}
}
return false;
}
//============================================================================
void CFloatingDockContainer::startFloating(const QPoint& Pos, const QSize& Size)
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(StateDraggingActive);
QPoint TargetPos = QCursor::pos() - Pos;
move(TargetPos);
d->setState(DragState);
d->DragStartMousePosition = DragStartMousePos;
#ifdef Q_OS_LINUX
if (DraggingFloatingWidget == DragState)
{
setAttribute(Qt::WA_X11NetWmWindowTypeDock, true);
setWindowOpacity(0.6);
d->MouseEventHandler = MouseEventHandler;
if (d->MouseEventHandler)
{
d->MouseEventHandler->grabMouse();
}
}
#endif
moveFloating();
show();
d->DragStartMousePosition = Pos;
}
@@ -451,7 +522,7 @@ void CFloatingDockContainer::moveFloating()
{
int BorderSize = (frameSize().width() - size().width()) / 2;
const QPoint moveToPos = QCursor::pos() - d->DragStartMousePosition - QPoint(BorderSize, 0);
move(moveToPos);
move(moveToPos);
}
@@ -470,7 +541,7 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved()
if (TopLevelDockArea)
{
d->SingleDockArea = TopLevelDockArea;
this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
connect(d->SingleDockArea, SIGNAL(currentChanged(int)), this,
SLOT(onDockAreaCurrentChanged(int)));
}
@@ -482,7 +553,7 @@ void CFloatingDockContainer::onDockAreasAddedOrRemoved()
SLOT(onDockAreaCurrentChanged(int)));
d->SingleDockArea = nullptr;
}
this->setWindowTitle(qApp->applicationDisplayName());
d->setWindowTitle(qApp->applicationDisplayName());
}
}
@@ -493,11 +564,11 @@ void CFloatingDockContainer::updateWindowTitle()
auto TopLevelDockArea = d->DockContainer->topLevelDockArea();
if (TopLevelDockArea)
{
this->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle());
d->setWindowTitle(TopLevelDockArea->currentDockWidget()->windowTitle());
}
else
{
this->setWindowTitle(qApp->applicationDisplayName());
d->setWindowTitle(qApp->applicationDisplayName());
}
}
@@ -506,7 +577,7 @@ void CFloatingDockContainer::updateWindowTitle()
void CFloatingDockContainer::onDockAreaCurrentChanged(int Index)
{
Q_UNUSED(Index);
this->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
d->setWindowTitle(d->SingleDockArea->currentDockWidget()->windowTitle());
}
@@ -544,6 +615,24 @@ QList<CDockWidget*> CFloatingDockContainer::dockWidgets() const
}
//============================================================================
void CFloatingDockContainer::finishDragging()
{
qDebug() << "CFloatingDockContainer::finishDragging";
#ifdef Q_OS_LINUX
setAttribute(Qt::WA_X11NetWmWindowTypeDock, false);
setWindowOpacity(1);
activateWindow();
if (d->MouseEventHandler)
{
d->MouseEventHandler->releaseMouse();
d->MouseEventHandler = nullptr;
}
#endif
}
} // namespace ads
//---------------------------------------------------------------------------

View File

@@ -29,10 +29,16 @@
//============================================================================
// INCLUDES
//============================================================================
#include <QWidget>
#include "ads_globals.h"
#ifdef Q_OS_LINUX
#include <QDockWidget>
#define tFloatingWidgetBase QDockWidget
#else
#include <QWidget>
#define tFloatingWidgetBase QWidget
#endif
class QXmlStreamReader;
namespace ads
@@ -49,13 +55,14 @@ class CDockWidgetTab;
struct DockWidgetTabPrivate;
class CDockAreaTitleBar;
struct DockAreaTitleBarPrivate;
class CFloatingWidgetTitleBar;
/**
* This implements a floating widget that is a dock container that accepts
* docking of dock widgets like the main window and that can be docked into
* another dock container
*/
class ADS_EXPORT CFloatingDockContainer : public QWidget
class ADS_EXPORT CFloatingDockContainer : public tFloatingWidgetBase
{
Q_OBJECT
private:
@@ -70,6 +77,7 @@ private:
friend struct DockAreaTitleBarPrivate;
friend class CDockWidget;
friend class CDockAreaWidget;
friend class CFloatingWidgetTitleBar;
private slots:
void onDockAreasAddedOrRemoved();
@@ -81,7 +89,32 @@ protected:
* Use moveToGlobalPos() to move the widget to a new position
* depending on the start position given in Pos parameter
*/
void startFloating(const QPoint& Pos, const QSize& Size = QSize());
void startFloating(const QPoint& DragStartMousePos, const QSize& Size,
eDragState DragState, QWidget* MouseEventHandler);
/**
* Call this function to start dragging the floating widget
*/
void startDragging(const QPoint& DragStartMousePos, const QSize& Size,
QWidget* MouseEventHandler)
{
startFloating(DragStartMousePos, Size, DraggingFloatingWidget, MouseEventHandler);
}
/**
* Call this function if you explecitely want to signal that dragging has
* finished
*/
void finishDragging();
/**
* Call this function if you just want to initialize the position
* and size of the floating widget
*/
void initFloatingGeometry(const QPoint& DragStartMousePos, const QSize& Size)
{
startFloating(DragStartMousePos, Size, DraggingInactive, nullptr);
}
/**
* Moves the widget to a new position relative to the position given when

View File

@@ -3,5 +3,6 @@
<file>stylesheets/default.css</file>
<file>images/close-button.svg</file>
<file>images/close-button-disabled.svg</file>
<file>stylesheets/default_linux.css</file>
</qresource>
</RCC>

View File

@@ -44,7 +44,7 @@ namespace internal
void replaceSplitterWidget(QSplitter* Splitter, QWidget* From, QWidget* To)
{
int index = Splitter->indexOf(From);
From->setParent(0);
From->setParent(nullptr);
Splitter->insertWidget(index, To);
}
@@ -90,7 +90,6 @@ void hideEmptyParentSplitters(CDockSplitter* Splitter)
}
}
} // namespace internal
} // namespace ads

View File

@@ -35,11 +35,15 @@
#include <QPixmap>
#include <QWidget>
#ifndef ADS_STATIC
#ifdef ADS_SHARED_EXPORT
#define ADS_EXPORT Q_DECL_EXPORT
#else
#define ADS_EXPORT Q_DECL_IMPORT
#endif
#else
#define ADS_EXPORT
#endif
#define ADS_DEBUG_LEVEL 0
@@ -72,6 +76,17 @@ enum TitleBarButton
TitleBarButtonClose
};
/**
* The different dragging states
*/
enum eDragState
{
DraggingInactive, //!< DraggingInactive
DraggingMousePressed, //!< DraggingMousePressed
DraggingTab, //!< DraggingTab
DraggingFloatingWidget//!< DraggingFloatingWidget
};
namespace internal
{
static const bool RestoreTesting = true;

View File

@@ -0,0 +1,187 @@
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file FloatingWidgetTitleBar.cpp
/// \author Uwe Kindler
/// \date 13.05.2019
/// \brief Implementation of CFloatingWidgetTitleBar class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include "FloatingWidgetTitleBar.h"
#include <iostream>
#include <QHBoxLayout>
#include <QPushButton>
#include <QToolButton>
#include <QPixmap>
#include <QStyle>
#include <QMouseEvent>
#include "ads_globals.h"
#include "ElidingLabel.h"
#include "FloatingDockContainer.h"
namespace ads
{
using tTabLabel = CElidingLabel;
using tCloseButton = QPushButton;
/**
* @brief Private data class of public interface CFloatingWidgetTitleBar
*/
struct FloatingWidgetTitleBarPrivate
{
CFloatingWidgetTitleBar* _this; ///< public interface class
QLabel* IconLabel = nullptr;
tTabLabel* TitleLabel;
tCloseButton* CloseButton = nullptr;
CFloatingDockContainer* FloatingWidget = nullptr;
eDragState DragState = DraggingInactive;
FloatingWidgetTitleBarPrivate(CFloatingWidgetTitleBar* _public) : _this(_public) {}
/**
* Creates the complete layout including all controls
*/
void createLayout();
};
//============================================================================
void FloatingWidgetTitleBarPrivate::createLayout()
{
TitleLabel = new tTabLabel();
TitleLabel->setElideMode(Qt::ElideRight);
TitleLabel->setText("DockWidget->windowTitle()");
TitleLabel->setObjectName("floatingTitleLabel");
TitleLabel->setAlignment(Qt::AlignLeft);
CloseButton = new tCloseButton();
CloseButton->setObjectName("floatingTitleCloseButton");
CloseButton->setFlat(true);
//CloseButton->setAutoRaise(true);
// The standard icons do does not look good on high DPI screens
QIcon CloseIcon;
QPixmap normalPixmap = _this->style()->standardPixmap(QStyle::SP_TitleBarCloseButton, 0, CloseButton);
CloseIcon.addPixmap(normalPixmap, QIcon::Normal);
CloseIcon.addPixmap(internal::createTransparentPixmap(normalPixmap, 0.25), QIcon::Disabled);
CloseButton->setIcon(_this->style()->standardIcon(QStyle::SP_TitleBarCloseButton));
CloseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
CloseButton->setVisible(true);
CloseButton->setFocusPolicy(Qt::NoFocus);
_this->connect(CloseButton, SIGNAL(clicked()), SIGNAL(closeRequested()));
QFontMetrics fm(TitleLabel->font());
int Spacing = qRound(fm.height() / 4.0);
// Fill the layout
QBoxLayout* Layout = new QBoxLayout(QBoxLayout::LeftToRight);
Layout->setContentsMargins(6,0,0,0);
Layout->setSpacing(0);
_this->setLayout(Layout);
Layout->addWidget(TitleLabel, 1);
Layout->addSpacing(Spacing);
Layout->addWidget(CloseButton);
Layout->setAlignment(Qt::AlignCenter);
TitleLabel->setVisible(true);
}
//============================================================================
CFloatingWidgetTitleBar::CFloatingWidgetTitleBar(CFloatingDockContainer *parent)
: QWidget(parent),
d(new FloatingWidgetTitleBarPrivate(this))
{
d->FloatingWidget = parent;
d->createLayout();
}
//============================================================================
CFloatingWidgetTitleBar::~CFloatingWidgetTitleBar()
{
delete d;
}
//============================================================================
void CFloatingWidgetTitleBar::mousePressEvent(QMouseEvent* ev)
{
if (ev->button() == Qt::LeftButton)
{
d->DragState = DraggingFloatingWidget;
d->FloatingWidget->startDragging(ev->pos(), d->FloatingWidget->size(), this);
return;
}
Super::mousePressEvent(ev);
}
//============================================================================
void CFloatingWidgetTitleBar::mouseReleaseEvent(QMouseEvent* ev)
{
d->DragState = DraggingInactive;
Super::mouseReleaseEvent(ev);
}
//============================================================================
void CFloatingWidgetTitleBar::mouseMoveEvent(QMouseEvent* ev)
{
if (!(ev->buttons() & Qt::LeftButton) || DraggingInactive == d->DragState)
{
d->DragState = DraggingInactive;
Super::mouseMoveEvent(ev);
return;
}
// move floating window
if (DraggingFloatingWidget == d->DragState)
{
d->FloatingWidget->moveFloating();
Super::mouseMoveEvent(ev);
return;
}
Super::mouseMoveEvent(ev);
}
//============================================================================
void CFloatingWidgetTitleBar::enableCloseButton(bool Enable)
{
d->CloseButton->setEnabled(Enable);
}
//============================================================================
void CFloatingWidgetTitleBar::setTitle(const QString& Text)
{
d->TitleLabel->setText(Text);
}
} // namespace ads

View File

@@ -0,0 +1,68 @@
#ifndef FLOATINGWIDGETTITLEBAR_H
#define FLOATINGWIDGETTITLEBAR_H
/*******************************************************************************
** Qt Advanced Docking System
** Copyright (C) 2017 Uwe Kindler
**
** This library is free software; you can redistribute it and/or
** modify it under the terms of the GNU Lesser General Public
** License as published by the Free Software Foundation; either
** version 2.1 of the License, or (at your option) any later version.
**
** This library is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
** Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public
** License along with this library; If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
//============================================================================
/// \file FloatingWidgetTitleBar.h
/// \author Uwe Kindler
/// \date 13.05.2019
/// \brief Declaration of CFloatingWidgetTitleBar class
//============================================================================
//============================================================================
// INCLUDES
//============================================================================
#include <QWidget>
namespace ads
{
class CFloatingDockContainer;
struct FloatingWidgetTitleBarPrivate;
class CFloatingWidgetTitleBar : public QWidget
{
Q_OBJECT
private:
FloatingWidgetTitleBarPrivate* d; ///< private data (pimpl)
protected:
virtual void mousePressEvent(QMouseEvent* ev) override;
virtual void mouseReleaseEvent(QMouseEvent* ev) override;
virtual void mouseMoveEvent(QMouseEvent* ev) override;
public:
using Super = QWidget;
explicit CFloatingWidgetTitleBar (CFloatingDockContainer *parent = nullptr);
/**
* Virtual Destructor
*/
virtual ~CFloatingWidgetTitleBar();
void enableCloseButton(bool Enable);
void setTitle(const QString& Text);
signals:
void closeRequested();
};
} // namespace ads
#endif // FLOATINGWIDGETTITLEBAR_H

View File

@@ -1,26 +1,24 @@
ADS_ROOT = $${PWD}/..
ADS_OUT_ROOT = $${OUT_PWD}/..
CONFIG += c++14
CONFIG += debug_and_release
TARGET = $$qtLibraryTarget(qtadvanceddocking)
DEFINES += QT_DEPRECATED_WARNINGS
TEMPLATE = lib
DESTDIR = $${ADS_OUT_ROOT}/lib
QT += core gui widgets
CONFIG += adsBuildShared
adsBuildShared {
!adsBuildStatic {
CONFIG += shared
DEFINES += ADS_SHARED_EXPORT
}
!adsBuildShared {
adsBuildStatic {
CONFIG += staticlib
DEFINES += ADS_STATIC
}
windows {
# MinGW
*-g++* {
QMAKE_CXXFLAGS += -std=c++11
QMAKE_CXXFLAGS += -Wall -Wextra -pedantic
}
# MSVC
@@ -43,9 +41,8 @@ HEADERS += \
DockSplitter.h \
DockAreaTitleBar.h \
ElidingLabel.h
SOURCES += \
ads_globals.cpp \
DockAreaWidget.cpp \
@@ -59,3 +56,20 @@ SOURCES += \
DockSplitter.cpp \
DockAreaTitleBar.cpp \
ElidingLabel.cpp
unix {
HEADERS += linux/FloatingWidgetTitleBar.h
SOURCES += linux/FloatingWidgetTitleBar.cpp
}
isEmpty(PREFIX){
PREFIX=..\installed
warning("Install Prefix not set")
}
headers.path=$$PREFIX/include
headers.files=$$HEADERS
target.path=$$PREFIX/lib
INSTALLS += headers target
DISTFILES +=

View File

@@ -63,7 +63,7 @@ ads--CDockWidget
#closeButton,
#undockButton
{
padding: 0 -2px;
padding: 0px -2px;
}

View File

@@ -0,0 +1,96 @@
/*
* Default style sheet on Windows Platforms
* Note: Always use CSS-classes with and without "ads--" namespace to support Qt4 & Qt5
*/
ads--CDockContainerWidget
{
background: palette(dark);
}
ads--CDockContainerWidget QSplitter::handle
{
background: palette(dark);
}
ads--CDockAreaWidget
{
background: palette(window);
border: 1px solid white;
}
ads--CDockAreaWidget #tabsMenuButton::menu-indicator
{
image: none;
}
ads--CDockWidgetTab
{
background: palette(window);
border-color: palette(light);
border-style: solid;
border-width: 0 1px 0 0;
padding: 0 0px;
}
ads--CDockWidgetTab[activeTab="true"]
{
background: qlineargradient(spread:pad, x1:0, y1:0, x2:0, y2:0.5, stop:0 palette(window), stop:1 palette(light));
/*background: palette(highlight);*/
}
ads--CDockWidgetTab QLabel
{
color: palette(dark);
}
ads--CDockWidgetTab[activeTab="true"] QLabel
{
color: palette(foreground);
}
ads--CDockWidget
{
background: palette(light);
border-color: palette(light);
border-style: solid;
border-width: 1px 0 0 0;
}
#tabsMenuButton,
#closeButton,
#undockButton
{
padding: 0px -2px;
}
QScrollArea#dockWidgetScrollArea
{
padding: 0px;
border: none;
}
#tabCloseButton
{
margin-top: 2px;
background: none;
border: none;
padding: 0px -2px;
}
#tabCloseButton:hover
{
border: 1px solid rgba(0, 0, 0, 32);
background: rgba(0, 0, 0, 16);
}
#tabCloseButton:pressed
{
background: rgba(0, 0, 0, 32);
}