Compare commits
336 Commits
fix-python
...
v1.2.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2fb70009cc | ||
|
|
289ddffbe2 | ||
|
|
54738bbea2 | ||
|
|
5c6eb352d6 | ||
|
|
f657399ef8 | ||
|
|
c4ffe10e12 | ||
|
|
efcad6d2be | ||
|
|
b6925c928a | ||
|
|
75368d334a | ||
|
|
d39ce8f66e | ||
|
|
805ea41d8a | ||
|
|
d7ed2494be | ||
|
|
0990337cdc | ||
|
|
e41cdb6f78 | ||
|
|
666673a251 | ||
|
|
34cb2ae5f0 | ||
|
|
51d8c2ff3e | ||
|
|
aa9f50d0f4 | ||
|
|
b7c36a2ec9 | ||
|
|
e18fb7ffd8 | ||
|
|
96439339c7 | ||
|
|
04d418b2e9 | ||
|
|
c04d856322 | ||
|
|
1c41c33f33 | ||
|
|
1dae128511 | ||
|
|
eab80c0545 | ||
|
|
288c3df30b | ||
|
|
e8728e8a35 | ||
|
|
94bfc4f2d1 | ||
|
|
d2da07508a | ||
|
|
7082e40cd5 | ||
|
|
2c8bbd10f7 | ||
|
|
ed8a401fe8 | ||
|
|
72428075f0 | ||
|
|
562db7c812 | ||
|
|
3ee15d1307 | ||
|
|
cf232dda34 | ||
|
|
bfeac02a45 | ||
|
|
22f4c36eb0 | ||
|
|
3dc56ea4ef | ||
|
|
cbedc06e97 | ||
|
|
8f85f28ed4 | ||
|
|
b5c2757874 | ||
|
|
46f57ffbbc | ||
|
|
fb6e2afd7b | ||
|
|
f74eb73326 | ||
|
|
ceb796d807 | ||
|
|
9a9488117c | ||
|
|
e55d75ba98 | ||
|
|
742763e6e5 | ||
|
|
d7242f17b7 | ||
|
|
eba395dc4c | ||
|
|
89635d8b98 | ||
|
|
f475312f11 | ||
|
|
9f604829dd | ||
|
|
85f829f97a | ||
|
|
e3bb0b3d48 | ||
|
|
22c0b6f9b6 | ||
|
|
200cb7aded | ||
|
|
4999fdd819 | ||
|
|
76aca4139a | ||
|
|
64276cb872 | ||
|
|
aad63d117b | ||
|
|
bd66af0a9f | ||
|
|
a21d80279e | ||
|
|
4347aefc8f | ||
|
|
b6341154fb | ||
|
|
16f6692b79 | ||
|
|
6c1026956a | ||
|
|
97679abb02 | ||
|
|
e173a4cfff | ||
|
|
26971ef1e2 | ||
|
|
d7bde47105 | ||
|
|
143c82291d | ||
|
|
979b2fdd40 | ||
|
|
46337d900b | ||
|
|
ec1f1bea9a | ||
|
|
d207028d60 | ||
|
|
a237eae508 | ||
|
|
243396f22b | ||
|
|
f240bf5d40 | ||
|
|
785db1b50c | ||
|
|
b6a7048a4f | ||
|
|
52bff59024 | ||
|
|
bba0195196 | ||
|
|
41fdb9c7df | ||
|
|
c1c1da25a8 | ||
|
|
b4e7b97646 | ||
|
|
2c687fe469 | ||
|
|
10e0402afa | ||
|
|
ebb1179167 | ||
|
|
15c196d865 | ||
|
|
e897ce6e8e | ||
|
|
83d9db1b64 | ||
|
|
60331fc654 | ||
|
|
e8f16dd172 | ||
|
|
44bd451362 | ||
|
|
1d2a791dfc | ||
|
|
a4ba45b423 | ||
|
|
12576970c6 | ||
|
|
e0ee7d14b0 | ||
|
|
66f447ad3f | ||
|
|
75db599142 | ||
|
|
a5c65ae039 | ||
|
|
5c055e0b8d | ||
|
|
090483f04e | ||
|
|
953219f6f3 | ||
|
|
8356bb0c3c | ||
|
|
758548f7a2 | ||
|
|
2aa16eb6d9 | ||
|
|
9d6cef24c1 | ||
|
|
52999d4cc9 | ||
|
|
bc2fff2c04 | ||
|
|
40fa4e98f8 | ||
|
|
a07f63a2c7 | ||
|
|
39c9a4da9b | ||
|
|
e0aa547393 | ||
|
|
08eab8882f | ||
|
|
04723ac3a9 | ||
|
|
c25043fa00 | ||
|
|
5372920cd0 | ||
|
|
28ae4c3b8c | ||
|
|
6158ebd520 | ||
|
|
b77430e574 | ||
|
|
fad81d595a | ||
|
|
0980a7f601 | ||
|
|
46830713e0 | ||
|
|
cd796db0ff | ||
|
|
29da5f4a8a | ||
|
|
315bdc71e5 | ||
|
|
a8965bea91 | ||
|
|
bf259c7ffc | ||
|
|
8a990451d7 | ||
|
|
974bdbd637 | ||
|
|
cb9d77cd18 | ||
|
|
af10efa587 | ||
|
|
a0fb47af58 | ||
|
|
598fbdc51b | ||
|
|
81c3f3f0c6 | ||
|
|
b9962b3df0 | ||
|
|
a71386e62a | ||
|
|
812ce1c08b | ||
|
|
189e82450b | ||
|
|
a3dbc3739c | ||
|
|
c8d34375af | ||
|
|
6c3775ea45 | ||
|
|
5a72e1adab | ||
|
|
0f7f310734 | ||
|
|
e8bf2a5222 | ||
|
|
468f545c9a | ||
|
|
a59ff6dfee | ||
|
|
4fa415ba05 | ||
|
|
d851c60b2f | ||
|
|
bf097098e5 | ||
|
|
8c93b85a24 | ||
|
|
f87d67dd59 | ||
|
|
bc3278b218 | ||
|
|
d2c55a67df | ||
|
|
a3414fd92b | ||
|
|
12f3ba9074 | ||
|
|
034d2c8aee | ||
|
|
ad3f4141c8 | ||
|
|
cde2e4e571 | ||
|
|
e0775467b2 | ||
|
|
b20ffcde61 | ||
|
|
43bdb6a4c2 | ||
|
|
929aabdc0d | ||
|
|
6a90a5125f | ||
|
|
77016a619f | ||
|
|
dc328ff7c4 | ||
|
|
dc13665566 | ||
|
|
d1279ab119 | ||
|
|
80bf6032f3 | ||
|
|
22437e75c6 | ||
|
|
801e49de9d | ||
|
|
a847a574ed | ||
|
|
ef8807bc09 | ||
|
|
d441477fa9 | ||
|
|
ece7b22bec | ||
|
|
97d8e4f18b | ||
|
|
9937f5d789 | ||
|
|
675edfe6db | ||
|
|
c23d179385 | ||
|
|
36af020505 | ||
|
|
7b2d195139 | ||
|
|
984ab3bb13 | ||
|
|
0331f90791 | ||
|
|
b19c53d650 | ||
|
|
3670cf2377 | ||
|
|
864670b0a1 | ||
|
|
0cf148b389 | ||
|
|
921d0892a0 | ||
|
|
beb2d9e659 | ||
|
|
59168da231 | ||
|
|
3dbf699c49 | ||
|
|
baa7561b13 | ||
|
|
ac5f4b871c | ||
|
|
52bf449366 | ||
|
|
08a1c4e6df | ||
|
|
156dad6e03 | ||
|
|
b642d2df2f | ||
|
|
5cedfab82c | ||
|
|
af9d62a58c | ||
|
|
0758496b0d | ||
|
|
a452723919 | ||
|
|
774e66ba6f | ||
|
|
f13de89db5 | ||
|
|
1393ae224f | ||
|
|
d92d7c258c | ||
|
|
619ca74051 | ||
|
|
aa39a71ae5 | ||
|
|
f4e33c1409 | ||
|
|
ad96336a36 | ||
|
|
50d1e75709 | ||
|
|
793c4e509b | ||
|
|
e4a33ad8b7 | ||
|
|
52cf53ce5c | ||
|
|
8791870efb | ||
|
|
4f8c47bfa4 | ||
|
|
ad141df6b1 | ||
|
|
72605292b7 | ||
|
|
1443eff1d9 | ||
|
|
22d5db32ce | ||
|
|
e9a321039f | ||
|
|
b93f115b53 | ||
|
|
7faaf2cc69 | ||
|
|
978f9d3a5e | ||
|
|
09793b3481 | ||
|
|
f4d9a96ddb | ||
|
|
4ac892038f | ||
|
|
387ba291be | ||
|
|
5d3d189774 | ||
|
|
a6a1047f75 | ||
|
|
3e70b846e8 | ||
|
|
0a2aebd78d | ||
|
|
ddad0feaf3 | ||
|
|
aba1cce1f6 | ||
|
|
7318675e84 | ||
|
|
cf700f8eb6 | ||
|
|
2c1d099c83 | ||
|
|
91ff29ae64 | ||
|
|
523dfb0d12 | ||
|
|
b84e0f3605 | ||
|
|
f72e8e6a1c | ||
|
|
c6c1fe79c3 | ||
|
|
ea382dcc17 | ||
|
|
c142eb8ecd | ||
|
|
46c039153e | ||
|
|
473f03360c | ||
|
|
3fb3984a72 | ||
|
|
9c5e3cf5af | ||
|
|
7419ca806d | ||
|
|
8a51c31663 | ||
|
|
a586a7894b | ||
|
|
31fcbebaff | ||
|
|
c4cc6b3e6e | ||
|
|
420ac9044e | ||
|
|
392dac5691 | ||
|
|
29744c01c6 | ||
|
|
a16adb9578 | ||
|
|
49e488df24 | ||
|
|
1a3f00eac8 | ||
|
|
c6ea8d5525 | ||
|
|
7738585d01 | ||
|
|
61bc24c6ea | ||
|
|
ae90001d7a | ||
|
|
c0ea3a097c | ||
|
|
abca57be11 | ||
|
|
645201480c | ||
|
|
8cffba3e22 | ||
|
|
8f62004f5b | ||
|
|
4fff6edb7b | ||
|
|
64cff4ba49 | ||
|
|
ce3c4d5661 | ||
|
|
5f333f0934 | ||
|
|
f70722934c | ||
|
|
b9eb9f10d4 | ||
|
|
6f89d94eef | ||
|
|
3a494d706a | ||
|
|
2ffbe07bcf | ||
|
|
371fd361a8 | ||
|
|
97416607e5 | ||
|
|
51ccbe7c7c | ||
|
|
65599399c7 | ||
|
|
c0816d4924 | ||
|
|
2988e97e14 | ||
|
|
046ceae500 | ||
|
|
33c0cda582 | ||
|
|
df7acc1075 | ||
|
|
3859e4b277 | ||
|
|
26253b65c7 | ||
|
|
424453ab57 | ||
|
|
d7de0ebd20 | ||
|
|
bf1c5140cd | ||
|
|
fb7a35db5b | ||
|
|
5872c2fbe3 | ||
|
|
ba04c70d5a | ||
|
|
de1e2d301f | ||
|
|
b67bdf779e | ||
|
|
78a3221395 | ||
|
|
f698b56dad | ||
|
|
4ed18fdf1d | ||
|
|
6e05f13c77 | ||
|
|
cb51d0af11 | ||
|
|
a146cd81b2 | ||
|
|
8dbd6df456 | ||
|
|
ac6d845c8d | ||
|
|
cfc9d1abcd | ||
|
|
a66748f6ca | ||
|
|
e5f46ead3b | ||
|
|
171023558e | ||
|
|
059a424b88 | ||
|
|
307b22deaf | ||
|
|
e405688f67 | ||
|
|
68554119f4 | ||
|
|
86a4a740ef | ||
|
|
0a004b83ca | ||
|
|
4fa47403c5 | ||
|
|
9e418ced53 | ||
|
|
bc04863439 | ||
|
|
77f259a435 | ||
|
|
16bcace663 | ||
|
|
52fddaa1cd | ||
|
|
f3d7400c15 | ||
|
|
7ebc3f3533 | ||
|
|
0ee94b425e | ||
|
|
d44a173945 | ||
|
|
ac001d6f32 | ||
|
|
e3de2df69c | ||
|
|
39d3c90b2f | ||
|
|
bca21defa5 | ||
|
|
dd3116ae7f | ||
|
|
49b3765eae | ||
|
|
1f5dd35bec | ||
|
|
e57b46979d | ||
|
|
683b67abb0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -34,7 +34,6 @@ latex
|
|||||||
html
|
html
|
||||||
custom_titlebar
|
custom_titlebar
|
||||||
libkddockwidgets.so*
|
libkddockwidgets.so*
|
||||||
libkddockwidgets_multisplitter.so*
|
|
||||||
*.depends
|
*.depends
|
||||||
kddockwidgets_basic_quick
|
kddockwidgets_basic_quick
|
||||||
/src/KDDockWidgetsConfig.cmake
|
/src/KDDockWidgetsConfig.cmake
|
||||||
|
|||||||
@@ -11,12 +11,17 @@
|
|||||||
|
|
||||||
# Pass the following variables to cmake to control the build:
|
# Pass the following variables to cmake to control the build:
|
||||||
#
|
#
|
||||||
|
# -DKDDockWidgets_QT6=[true|false]
|
||||||
|
# Build against Qt6 rather than Qt5
|
||||||
|
# Default=false (Qt5 will be used even if Qt6 is available)
|
||||||
|
#
|
||||||
# -DKDDockWidgets_STATIC=[true|false]
|
# -DKDDockWidgets_STATIC=[true|false]
|
||||||
# Build static versions of the libraries
|
# Build static versions of the libraries
|
||||||
# Default=false
|
# Default=false
|
||||||
#
|
#
|
||||||
# -DKDDockWidgets_TESTS=[true|false]
|
# -DKDDockWidgets_TESTS=[true|false]
|
||||||
# Build the test harness.
|
# Build the test harness.
|
||||||
|
# Currently does nothing unless you also set KDDockWidgets_DEVELOPER_MODE=True
|
||||||
# Default=false
|
# Default=false
|
||||||
#
|
#
|
||||||
# -DKDDockWidgets_EXAMPLES=[true|false]
|
# -DKDDockWidgets_EXAMPLES=[true|false]
|
||||||
@@ -42,9 +47,13 @@
|
|||||||
# Default=false
|
# Default=false
|
||||||
#
|
#
|
||||||
# -DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=[path]
|
# -DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=[path]
|
||||||
# alternative install path for python bindings
|
# Set an alternative install path for Python bindings
|
||||||
# Default=CMAKE_INSTALL_PREFIX
|
# Default=CMAKE_INSTALL_PREFIX
|
||||||
#
|
#
|
||||||
|
# -DKDDockWidgets_UNITY_BUILD=[true|false]
|
||||||
|
# Build with CMake's UNITY_BUILD (requires CMake version 3.16 or higher)
|
||||||
|
# Default=true
|
||||||
|
#
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.7)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
if(POLICY CMP0020)
|
if(POLICY CMP0020)
|
||||||
@@ -72,19 +81,26 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${PROJECT_NAME}_VERSION_MAJOR 1)
|
set(${PROJECT_NAME}_VERSION_MAJOR 1)
|
||||||
set(${PROJECT_NAME}_VERSION_MINOR 1)
|
set(${PROJECT_NAME}_VERSION_MINOR 2)
|
||||||
set(${PROJECT_NAME}_VERSION_PATCH 95)
|
set(${PROJECT_NAME}_VERSION_PATCH 0)
|
||||||
|
|
||||||
set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH})
|
set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH})
|
||||||
set(${PROJECT_NAME}_SOVERSION "1.2")
|
set(${PROJECT_NAME}_SOVERSION "1.2")
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
|
option(${PROJECT_NAME}_QT6 "Build against Qt 6" OFF)
|
||||||
option(${PROJECT_NAME}_DEVELOPER_MODE "Developer Mode" OFF)
|
option(${PROJECT_NAME}_DEVELOPER_MODE "Developer Mode" OFF)
|
||||||
option(${PROJECT_NAME}_PYTHON_BINDINGS "Build python bindings" OFF)
|
option(${PROJECT_NAME}_PYTHON_BINDINGS "Build python bindings" OFF)
|
||||||
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0")
|
||||||
|
option(${PROJECT_NAME}_UNITY_BUILD "Build with CMake's UNITY_BUILD" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
if(${PROJECT_NAME}_PYTHON_BINDINGS AND (CMAKE_BUILD_TYPE MATCHES "^[Dd]eb" OR ${PROJECT_NAME}_STATIC))
|
if(${PROJECT_NAME}_PYTHON_BINDINGS AND (CMAKE_BUILD_TYPE MATCHES "^[Dd]eb" OR ${PROJECT_NAME}_STATIC))
|
||||||
message(FATAL_ERROR "** Python Bindings are disabled in debug or static builds.")
|
message(FATAL_ERROR "** Python Bindings are disabled in debug or static builds.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
option(${PROJECT_NAME}_TESTS "Build the tests" OFF)
|
option(${PROJECT_NAME}_TESTS "Build the tests" OFF)
|
||||||
option(${PROJECT_NAME}_EXAMPLES "Build the examples" ON)
|
option(${PROJECT_NAME}_EXAMPLES "Build the examples" ON)
|
||||||
option(${PROJECT_NAME}_DOCS "Build the API documentation" OFF)
|
option(${PROJECT_NAME}_DOCS "Build the API documentation" OFF)
|
||||||
@@ -96,9 +112,18 @@ endif()
|
|||||||
|
|
||||||
#option(${PROJECT_NAME}_QTQUICK "Build for QtQuick instead of QtWidgets" OFF)
|
#option(${PROJECT_NAME}_QTQUICK "Build for QtQuick instead of QtWidgets" OFF)
|
||||||
|
|
||||||
find_package(Qt5Widgets 5.9 REQUIRED)
|
if (${PROJECT_NAME}_QT6)
|
||||||
|
find_package(Qt6Widgets REQUIRED)
|
||||||
|
find_package(Qt6Test REQUIRED)
|
||||||
|
set(QT_MAJOR_VERSION 6)
|
||||||
|
else()
|
||||||
|
find_package(Qt5Widgets 5.9 REQUIRED)
|
||||||
|
find_package(Qt5Test 5.9 REQUIRED)
|
||||||
|
set(QT_MAJOR_VERSION 5)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
|
||||||
set(ECM_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ECM/modules/")
|
set(ECM_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ECM/modules/")
|
||||||
set(PYTHON_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake/Python")
|
set(PYTHON_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake/Python")
|
||||||
@@ -111,8 +136,8 @@ include(QtInstallPaths) #to set QT_INSTALL_FOO variables
|
|||||||
|
|
||||||
macro(set_compiler_flags targetName)
|
macro(set_compiler_flags targetName)
|
||||||
if(${PROJECT_NAME}_DEVELOPER_MODE)
|
if(${PROJECT_NAME}_DEVELOPER_MODE)
|
||||||
target_compile_definitions(${targetName} PRIVATE DOCKS_DEVELOPER_MODE QT_FORCE_ASSERTS)
|
target_compile_definitions(${targetName} PUBLIC DOCKS_DEVELOPER_MODE PRIVATE QT_FORCE_ASSERTS)
|
||||||
if(NOT MSVC)
|
if(NOT MSVC AND NOT ${PROJECT_NAME}_QT6) # We're not warnings clean with Qt6 yet
|
||||||
target_compile_options(${targetName} PRIVATE -Wall -Wextra -Werror -Wno-error=deprecated-declarations)
|
target_compile_options(${targetName} PRIVATE -Wall -Wextra -Werror -Wno-error=deprecated-declarations)
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
target_compile_options(${targetName} PRIVATE -Wweak-vtables)
|
target_compile_options(${targetName} PRIVATE -Wweak-vtables)
|
||||||
@@ -163,7 +188,6 @@ endif()
|
|||||||
if(${PROJECT_NAME}_EXAMPLES)
|
if(${PROJECT_NAME}_EXAMPLES)
|
||||||
if (${PROJECT_NAME}_QTQUICK)
|
if (${PROJECT_NAME}_QTQUICK)
|
||||||
add_subdirectory(examples/qtquick)
|
add_subdirectory(examples/qtquick)
|
||||||
set_compiler_flags(kddockwidgets_example_quick)
|
|
||||||
else()
|
else()
|
||||||
add_subdirectory(examples/dockwidgets)
|
add_subdirectory(examples/dockwidgets)
|
||||||
add_subdirectory(examples/minimal)
|
add_subdirectory(examples/minimal)
|
||||||
@@ -178,10 +202,9 @@ if(${PROJECT_NAME}_DEVELOPER_MODE)
|
|||||||
enable_testing()
|
enable_testing()
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
if (NOT ${PROJECT_NAME}_QTQUICK)
|
# Require Qt5.15.1 or higher to run the tests_launcher tests on Mac
|
||||||
#Require Qt5.15.1 or higher to run the tests_launcher tests on Mac
|
if (NOT APPLE OR Qt5Widgets_VERSION VERSION_GREATER 5.15.0)
|
||||||
if(NOT APPLE OR Qt5Widgets_VERSION VERSION_GREATER 5.15.0)
|
# tst_docks.exe is pretty big (160 tests), so split it in more runs so we can use threads.
|
||||||
# tst_docks.exe is pretty big (140 tests), so split it in 6 runs so we can use threads.
|
|
||||||
add_test(NAME tst_docks0 COMMAND tests_launcher 0 5)
|
add_test(NAME tst_docks0 COMMAND tests_launcher 0 5)
|
||||||
add_test(NAME tst_docks1 COMMAND tests_launcher 1 5)
|
add_test(NAME tst_docks1 COMMAND tests_launcher 1 5)
|
||||||
add_test(NAME tst_docks2 COMMAND tests_launcher 2 5)
|
add_test(NAME tst_docks2 COMMAND tests_launcher 2 5)
|
||||||
@@ -204,15 +227,20 @@ if(${PROJECT_NAME}_DEVELOPER_MODE)
|
|||||||
add_test(NAME tst_docks19 COMMAND tests_launcher 18 5)
|
add_test(NAME tst_docks19 COMMAND tests_launcher 18 5)
|
||||||
add_test(NAME tst_docks20 COMMAND tests_launcher 19 5)
|
add_test(NAME tst_docks20 COMMAND tests_launcher 19 5)
|
||||||
add_test(NAME tst_docks21 COMMAND tests_launcher 20 5) # one more for rounding leftovers
|
add_test(NAME tst_docks21 COMMAND tests_launcher 20 5) # one more for rounding leftovers
|
||||||
endif()
|
endif()
|
||||||
|
if (NOT ${PROJECT_NAME}_QTQUICK)
|
||||||
|
# tst_multisplitter depends on QWidget
|
||||||
|
add_test(NAME tst_multisplitter COMMAND tst_multisplitter)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_test(NAME tst_multisplitter COMMAND tst_multisplitter)
|
add_test(NAME tst_docks COMMAND tst_docks)
|
||||||
add_test(NAME tst_common COMMAND tst_common)
|
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${PROJECT_NAME}_DOCS)
|
if(${PROJECT_NAME}_DOCS)
|
||||||
add_subdirectory(docs) # needs to go last, in case there are build source files
|
add_subdirectory(docs) # needs to go last, in case there are build source files
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (${PROJECT_NAME}_UNITY_BUILD)
|
||||||
|
set_target_properties(kddockwidgets PROPERTIES UNITY_BUILD ON)
|
||||||
|
endif()
|
||||||
|
|||||||
24
Changelog
24
Changelog
@@ -1,7 +1,19 @@
|
|||||||
* v1.2.0 (unreleased)
|
* v1.3.0 (unreleased)
|
||||||
- QtQuick support
|
- [TODO] QtQuick support
|
||||||
|
|
||||||
* v1.1.0 (unreleased)
|
* v1.2.0 (17 December 2020)
|
||||||
|
- Wayland support
|
||||||
|
- Added Flag_KeepAboveIfNotUtilityWindow, so you can have keep above even if
|
||||||
|
floating window is shown in the task-bar.
|
||||||
|
- Added DockWidget::windowActiveAboutToChange() signal
|
||||||
|
- Added support for Qt6 (PySide6 support is lacking)
|
||||||
|
- Added WASM support
|
||||||
|
|
||||||
|
* v1.1.1 (11 December 2020)
|
||||||
|
- Windows: Fixed a crash when clicking on the close button for floating windows in some situations (#110)
|
||||||
|
- Don't show dock/undock icon when dockwidget is not dockable (#99)
|
||||||
|
|
||||||
|
* v1.1.0 (26 October 2020)
|
||||||
- New drop indicator style type: Segmented Indicators
|
- New drop indicator style type: Segmented Indicators
|
||||||
- Windows: Drop Shadow for floating windows
|
- Windows: Drop Shadow for floating windows
|
||||||
- Added AutoHide / SideBar support
|
- Added AutoHide / SideBar support
|
||||||
@@ -12,6 +24,8 @@
|
|||||||
- Added Config::Flag_TitleBarHasMinimizeButton
|
- Added Config::Flag_TitleBarHasMinimizeButton
|
||||||
- Added Config::Flag_TitleBarNoFloatButton
|
- Added Config::Flag_TitleBarNoFloatButton
|
||||||
- Added Config::Flag_AutoHideSupport
|
- Added Config::Flag_AutoHideSupport
|
||||||
|
- Added Config::setTabbingAllowedFunc(TabbingAllowedFunc func)
|
||||||
|
- HDPI improvements, new high-res icons
|
||||||
- Bugfixes:
|
- Bugfixes:
|
||||||
- Windows: Fixed windows not having proper minimum size.
|
- Windows: Fixed windows not having proper minimum size.
|
||||||
- Windows: Fixed moving windows across screens with different DPI (#72)
|
- Windows: Fixed moving windows across screens with different DPI (#72)
|
||||||
@@ -19,9 +33,7 @@
|
|||||||
- Fixed floating window's title not being correct (#74)
|
- Fixed floating window's title not being correct (#74)
|
||||||
- Fixed focus scope not reacting when clicking on current tab (#71)
|
- Fixed focus scope not reacting when clicking on current tab (#71)
|
||||||
- Fixed floating window borders not being rendered correctly on HDPI due to rounding errors.
|
- Fixed floating window borders not being rendered correctly on HDPI due to rounding errors.
|
||||||
|
- cmake/Python - don't require pkg-config, only use if available (#68)
|
||||||
* v1.0.1 (unreleased)
|
|
||||||
- cmake/Python - don't require pkg-config, only use if available (#68)
|
|
||||||
|
|
||||||
* v1.0.0 (2 September 2020)
|
* v1.0.0 (2 September 2020)
|
||||||
- PySide2 bindings
|
- PySide2 bindings
|
||||||
|
|||||||
29
README-WASM.md
Normal file
29
README-WASM.md
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
WebAssembly
|
||||||
|
===========
|
||||||
|
|
||||||
|
KDDockWidgets works with WebAssembly with the following known limitations:
|
||||||
|
|
||||||
|
- Classic drop indicators are not supported, only the segmented ones. This is because
|
||||||
|
WASM doesn't support windows with translucency.
|
||||||
|
|
||||||
|
- It's slow while dragging Windows and resizing.
|
||||||
|
Please file a bug with Qt, as it's out of scope for KDDW to fix.
|
||||||
|
|
||||||
|
|
||||||
|
Build tips for KDDW:
|
||||||
|
====================
|
||||||
|
|
||||||
|
- Visit https://doc.qt.io/qt-5/wasm.html if you haven't yet
|
||||||
|
- Open a terminal suitable for WASM development (with the correct Qt and toolchain in PATH, etc)
|
||||||
|
- KDDockWidgets can be built with `cmake -DCMAKE_TOOLCHAIN_FILE=/usr/local/emsdk-1.39.8/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake -DCMAKE_FIND_ROOT_PATH=~/Qt/5.15.1/wasm_32/ -DKDDockWidgets_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Release`
|
||||||
|
(Adapt the paths to your own situation)
|
||||||
|
|
||||||
|
Builds tips for your own app:
|
||||||
|
=============================
|
||||||
|
- Link to KDDW (libkddockwidgets.so, or similar)
|
||||||
|
- As the build is static, don't forget to initialize KDDW's resources:
|
||||||
|
```
|
||||||
|
#ifdef QT_STATIC
|
||||||
|
Q_INIT_RESOURCE(kddockwidgets_resources);
|
||||||
|
#endif
|
||||||
|
```
|
||||||
34
README-Wayland.md
Normal file
34
README-Wayland.md
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
Wayland support is done and has been tested on KDE (Kwin) and weston.
|
||||||
|
|
||||||
|
Limitations
|
||||||
|
============
|
||||||
|
|
||||||
|
Wayland works very differently than traditional desktops and imposes us some,
|
||||||
|
limitations. Here's a list of different behaviours which KDDockWidgets will have
|
||||||
|
when running on Wayland:
|
||||||
|
|
||||||
|
|
||||||
|
- A title bar can either be used for drag&dock or for moving the window around.
|
||||||
|
|
||||||
|
- For this reason, floating windows now have two title bars.
|
||||||
|
The native one, drawn by the server and the client one, drawn by KDDockWidgets.
|
||||||
|
The native one allows you to drag the window around but not drop/dock.
|
||||||
|
The client title bar allows you to perform a drag and drop/dock but not move the window around.
|
||||||
|
|
||||||
|
- You can detach a window by:
|
||||||
|
- Clicking the title-bar's float button
|
||||||
|
- Double-clicking the title bar of a docked widget
|
||||||
|
- Double-clicking a tab
|
||||||
|
- If no title bar is shown, double-clicking the empty space of the tab bar will detach
|
||||||
|
the entire group of tabbed dock widgets
|
||||||
|
|
||||||
|
- Layout save/restore won't restore the position of floating windows, as wayland
|
||||||
|
doesn't allow us to set geometry.
|
||||||
|
|
||||||
|
- Kwin specific:
|
||||||
|
- The pixmap that's shown during a drag can't be bigger than 250x250. Might be a bug.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
All in all it's pretty decent and usable. Any further improvements should be done at the server or
|
||||||
|
protocol level now.
|
||||||
@@ -43,6 +43,8 @@ Features
|
|||||||
- Customize title bars
|
- Customize title bars
|
||||||
- Customize window frames
|
- Customize window frames
|
||||||
- Custom widget separators
|
- Custom widget separators
|
||||||
|
- Crossplatform (macOS, Linux, Windows, WebAssembly, Wayland, X11/XCB, EGLFS are working)
|
||||||
|
See README-Wayland.md and README-WASM.md for platform specific information.
|
||||||
- Layouting engine honouring min/max size constraints and some size policies
|
- Layouting engine honouring min/max size constraints and some size policies
|
||||||
- PySide2 bindings
|
- PySide2 bindings
|
||||||
- Clean codebase
|
- Clean codebase
|
||||||
@@ -136,6 +138,7 @@ Supported Qt versions
|
|||||||
======================
|
======================
|
||||||
KDDockWidgets requires Qt >= 5.9 (or >=5.12 if Python bindings are enabled).
|
KDDockWidgets requires Qt >= 5.9 (or >=5.12 if Python bindings are enabled).
|
||||||
The QtQuick support will require Qt >= 5.15.
|
The QtQuick support will require Qt >= 5.15.
|
||||||
|
Qt 6 will be support as long as QTBUG-88611 is finished, most likely for 6.1.
|
||||||
|
|
||||||
Licensing
|
Licensing
|
||||||
=========
|
=========
|
||||||
@@ -170,3 +173,8 @@ to the Qt Project. We can give advanced or standard trainings anywhere
|
|||||||
around the globe on Qt as well as C++, OpenGL, 3D and more.
|
around the globe on Qt as well as C++, OpenGL, 3D and more.
|
||||||
|
|
||||||
Please visit https://www.kdab.com to meet the people who write code like this.
|
Please visit https://www.kdab.com to meet the people who write code like this.
|
||||||
|
|
||||||
|
Stay up-to-date with KDAB product announcements:
|
||||||
|
|
||||||
|
* [KDAB Newsletter](https://news.kdab.com)
|
||||||
|
* [KDAB Blogs](https://www.kdab.com/category/blogs)
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ if (NOT ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX)
|
|||||||
SET(${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE FILEPATH "Custom path to install python bindings.")
|
SET(${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE FILEPATH "Custom path to install python bindings.")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
message(STATUS "PYTHON INSTALL PREFIX ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}")
|
message(STATUS "PYTHON INSTALL PREFIX ${${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}")
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
set(PATH_SEP "\;")
|
set(PATH_SEP "\;")
|
||||||
@@ -153,5 +153,5 @@ macro(CREATE_PYTHON_BINDINGS
|
|||||||
LINK_FLAGS "-undefined dynamic_lookup")
|
LINK_FLAGS "-undefined dynamic_lookup")
|
||||||
endif()
|
endif()
|
||||||
install(TARGETS ${TARGET_NAME}
|
install(TARGETS ${TARGET_NAME}
|
||||||
LIBRARY DESTINATION ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/${TARGET_NAME})
|
LIBRARY DESTINATION ${${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/${TARGET_NAME})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|||||||
@@ -30,12 +30,12 @@
|
|||||||
|
|
||||||
#
|
#
|
||||||
# Create variables for all the various install paths for the Qt version in use
|
# Create variables for all the various install paths for the Qt version in use
|
||||||
# Make sure to have found Qt5 before using this.
|
# Make sure to have found Qt before using this.
|
||||||
# sets variables like QT_INSTALL_PREFIX, QT_INSTALL_DATA, QT_INSTALL_DOCS, etc.
|
# sets variables like QT_INSTALL_PREFIX, QT_INSTALL_DATA, QT_INSTALL_DOCS, etc.
|
||||||
# run qmake -query to see a full list
|
# run qmake -query to see a full list
|
||||||
|
|
||||||
if(TARGET Qt5::qmake)
|
if(TARGET Qt${QT_MAJOR_VERSION}::qmake)
|
||||||
get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake LOCATION)
|
get_target_property(QT_QMAKE_EXECUTABLE Qt${QT_MAJOR_VERSION}::qmake LOCATION)
|
||||||
else()
|
else()
|
||||||
message(FATAL_ERROR "No supported Qt version found. Make sure you find Qt before calling this")
|
message(FATAL_ERROR "No supported Qt version found. Make sure you find Qt before calling this")
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from conans import ConanFile, CMake, tools
|
|||||||
|
|
||||||
class KDDockWidgetsConan(ConanFile):
|
class KDDockWidgetsConan(ConanFile):
|
||||||
name = "kddockwidgets"
|
name = "kddockwidgets"
|
||||||
version = "1.1.95"
|
version = "1.2.0"
|
||||||
default_user = "kdab"
|
default_user = "kdab"
|
||||||
default_channel = "stable"
|
default_channel = "stable"
|
||||||
license = ("https://raw.githubusercontent.com/KDAB/KDDockWidgets/master/LICENSES/GPL-2.0-only.txt",
|
license = ("https://raw.githubusercontent.com/KDAB/KDDockWidgets/master/LICENSES/GPL-2.0-only.txt",
|
||||||
|
|||||||
@@ -1,3 +1,21 @@
|
|||||||
|
kddockwidgets (1.2.0) release candidate; urgency=high
|
||||||
|
|
||||||
|
* 1.2.0 final
|
||||||
|
|
||||||
|
-- Allen Winter <allen.winter@kdab.com> Thu, 17 Dec 2020 12:00:00 -0500
|
||||||
|
|
||||||
|
kddockwidgets (1.1.1) release candidate; urgency=high
|
||||||
|
|
||||||
|
* 1.1.1 final
|
||||||
|
|
||||||
|
-- Allen Winter <allen.winter@kdab.com> Fri, 11 Dec 2020 12:00:00 -0500
|
||||||
|
|
||||||
|
kddockwidgets (1.1.0) release candidate; urgency=high
|
||||||
|
|
||||||
|
* 1.1.0 final
|
||||||
|
|
||||||
|
-- Allen Winter <allen.winter@kdab.com> Mon, 26 Oct 2020 12:00:00 -0500
|
||||||
|
|
||||||
kddockwidgets (1.0.0) release candidate; urgency=high
|
kddockwidgets (1.0.0) release candidate; urgency=high
|
||||||
|
|
||||||
* 1.0.0 final
|
* 1.0.0 final
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ add_custom_command(
|
|||||||
OUTPUT ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch
|
OUTPUT ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch
|
||||||
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||||
#handle a bug in doxygen where image files referred to in markdown are not copied the output
|
#handle a bug in doxygen where image files referred to in markdown are not copied the output
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/screencap.gif ${DOXYGEN_OUTPUT_DIR}/html
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../../screencap.gif ${DOXYGEN_OUTPUT_DIR}/html
|
||||||
DEPENDS ${_dox_deps} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
DEPENDS ${_dox_deps} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||||
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ cmake_minimum_required(VERSION 3.7)
|
|||||||
project(kddockwidgets_example)
|
project(kddockwidgets_example)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
||||||
|
|
||||||
if(NOT TARGET kddockwidgets)
|
if(NOT TARGET kddockwidgets)
|
||||||
@@ -21,7 +22,7 @@ if(NOT TARGET kddockwidgets)
|
|||||||
find_package(KDDockWidgets REQUIRED)
|
find_package(KDDockWidgets REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt5_add_resources(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/resources_example.qrc)
|
set(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/resources_example.qrc)
|
||||||
|
|
||||||
add_executable(kddockwidgets_example
|
add_executable(kddockwidgets_example
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|||||||
@@ -24,6 +24,8 @@
|
|||||||
#include <QRandomGenerator>
|
#include <QRandomGenerator>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,10 @@ using namespace KDDockWidgets;
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
#endif
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
app.setOrganizationName(QStringLiteral("KDAB"));
|
app.setOrganizationName(QStringLiteral("KDAB"));
|
||||||
@@ -91,6 +93,9 @@ int main(int argc, char **argv)
|
|||||||
QCommandLineOption noUtilityWindows("u", QCoreApplication::translate("main", "FloatingWindows will be normal windows instead of utility windows"));
|
QCommandLineOption noUtilityWindows("u", QCoreApplication::translate("main", "FloatingWindows will be normal windows instead of utility windows"));
|
||||||
parser.addOption(noUtilityWindows);
|
parser.addOption(noUtilityWindows);
|
||||||
|
|
||||||
|
QCommandLineOption keepAbove("o", QCoreApplication::translate("main", "FloatingWindows will have Qt::WindowStaysOnTopHint. Implies not being an utility window (try it with -u too)"));
|
||||||
|
parser.addOption(keepAbove);
|
||||||
|
|
||||||
parser.addPositionalArgument("savedlayout", QCoreApplication::translate("main", "loads the specified json file at startup"));
|
parser.addPositionalArgument("savedlayout", QCoreApplication::translate("main", "loads the specified json file at startup"));
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
||||||
@@ -111,8 +116,13 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
QCommandLineOption noQtTool("no-qttool", QCoreApplication::translate("main", "(internal) Don't use Qt::Tool"));
|
QCommandLineOption noQtTool("no-qttool", QCoreApplication::translate("main", "(internal) Don't use Qt::Tool"));
|
||||||
QCommandLineOption noParentForFloating("no-parent-for-floating", QCoreApplication::translate("main", "(internal) FloatingWindows won't have a parent"));
|
QCommandLineOption noParentForFloating("no-parent-for-floating", QCoreApplication::translate("main", "(internal) FloatingWindows won't have a parent"));
|
||||||
|
QCommandLineOption nativeTitleBar("native-title-bar", QCoreApplication::translate("main", "(internal) FloatingWindows a native title bar"));
|
||||||
|
QCommandLineOption noDropIndicators("no-drop-indicators", QCoreApplication::translate("main", "(internal) Don't use any drop indicators"));
|
||||||
|
|
||||||
parser.addOption(noQtTool);
|
parser.addOption(noQtTool);
|
||||||
parser.addOption(noParentForFloating);
|
parser.addOption(noParentForFloating);
|
||||||
|
parser.addOption(nativeTitleBar);
|
||||||
|
parser.addOption(noDropIndicators);
|
||||||
|
|
||||||
# if defined(Q_OS_WIN)
|
# if defined(Q_OS_WIN)
|
||||||
QCommandLineOption noAeroSnap("no-aero-snap", QCoreApplication::translate("main", "(internal) Disable AeroSnap"));
|
QCommandLineOption noAeroSnap("no-aero-snap", QCoreApplication::translate("main", "(internal) Disable AeroSnap"));
|
||||||
@@ -143,12 +153,21 @@ int main(int argc, char **argv)
|
|||||||
if (parser.isSet(noQtTool))
|
if (parser.isSet(noQtTool))
|
||||||
flags |= KDDockWidgets::Config::Flag_internal_DontUseQtToolWindowsForFloatingWindows;
|
flags |= KDDockWidgets::Config::Flag_internal_DontUseQtToolWindowsForFloatingWindows;
|
||||||
|
|
||||||
|
if (parser.isSet(keepAbove))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_KeepAboveIfNotUtilityWindow;
|
||||||
|
|
||||||
if (parser.isSet(noParentForFloating))
|
if (parser.isSet(noParentForFloating))
|
||||||
flags |= KDDockWidgets::Config::Flag_internal_DontUseParentForFloatingWindows;
|
flags |= KDDockWidgets::Config::Flag_internal_DontUseParentForFloatingWindows;
|
||||||
|
|
||||||
|
if (parser.isSet(nativeTitleBar))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_NativeTitleBar;
|
||||||
|
|
||||||
|
if (parser.isSet(noDropIndicators))
|
||||||
|
KDDockWidgets::DefaultWidgetFactory::s_dropIndicatorType = KDDockWidgets::DropIndicatorType::None;
|
||||||
|
|
||||||
# if defined(Q_OS_WIN)
|
# if defined(Q_OS_WIN)
|
||||||
if (parser.isSet(noAeroSnap))
|
if (parser.isSet(noAeroSnap))
|
||||||
flags &= ~KDDockWidgets::Config::Flag_AeroSnapWithClientDecos;
|
flags |= KDDockWidgets::Config::Flag_internal_NoAeroSnap;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ cmake_minimum_required(VERSION 3.7)
|
|||||||
project(kddockwidgets_minimal_example)
|
project(kddockwidgets_minimal_example)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
||||||
|
|
||||||
if(NOT TARGET kddockwidgets)
|
if(NOT TARGET kddockwidgets)
|
||||||
@@ -21,7 +22,7 @@ if(NOT TARGET kddockwidgets)
|
|||||||
find_package(KDDockWidgets REQUIRED)
|
find_package(KDDockWidgets REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
qt5_add_resources(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../dockwidgets/resources_example.qrc)
|
set(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../dockwidgets/resources_example.qrc)
|
||||||
|
|
||||||
add_executable(kddockwidgets_minimal_example
|
add_executable(kddockwidgets_minimal_example
|
||||||
main.cpp
|
main.cpp
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#include <kddockwidgets/MainWindow.h>
|
#include <kddockwidgets/MainWindow.h>
|
||||||
|
|
||||||
#include <QStyleFactory>
|
#include <QStyleFactory>
|
||||||
|
#include <QApplication>
|
||||||
|
|
||||||
// clazy:excludeall=qstring-allocations
|
// clazy:excludeall=qstring-allocations
|
||||||
|
|
||||||
@@ -22,8 +23,10 @@ using namespace KDDockWidgets;
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||||
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
#endif
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
app.setOrganizationName(QStringLiteral("KDAB"));
|
app.setOrganizationName(QStringLiteral("KDAB"));
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#
|
|
||||||
# This file is part of KDDockWidgets.
|
# This file is part of KDDockWidgets.
|
||||||
#
|
#
|
||||||
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
# Author: Sergio Martins <sergio.martins@kdab.com>
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
#
|
#
|
||||||
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
@@ -9,26 +8,8 @@
|
|||||||
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
#
|
#
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.7)
|
add_subdirectory(customtitlebar)
|
||||||
project(kddockwidgets_example_quick)
|
add_subdirectory(dockwidgets)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set_compiler_flags(kddockwidgets_example_quick)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
set_compiler_flags(kddockwidgets_customtitlebar_quick)
|
||||||
|
|
||||||
if(NOT TARGET kddockwidgets)
|
|
||||||
# This will look for Qt, do find_package yourself manually before
|
|
||||||
# if you want to look for a specific Qt version for instance.
|
|
||||||
find_package(KDDockWidgets REQUIRED)
|
|
||||||
endif()
|
|
||||||
|
|
||||||
qt5_add_resources(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/resources_example.qrc)
|
|
||||||
|
|
||||||
add_executable(kddockwidgets_example_quick
|
|
||||||
main.cpp
|
|
||||||
${RESOURCES_EXAMPLE_SRC}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_link_libraries(kddockwidgets_example_quick
|
|
||||||
PRIVATE
|
|
||||||
KDAB::kddockwidgets
|
|
||||||
)
|
|
||||||
|
|||||||
37
examples/qtquick/customtitlebar/CMakeLists.txt
Normal file
37
examples/qtquick/customtitlebar/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
|
project(kddockwidgets_customtitlebar_quick)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
||||||
|
|
||||||
|
if(NOT TARGET kddockwidgets)
|
||||||
|
# This will look for Qt, do find_package yourself manually before
|
||||||
|
# if you want to look for a specific Qt version for instance.
|
||||||
|
find_package(KDDockWidgets REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(RESOURCES_EXAMPLE_SRC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/resources_qtquick_example.qrc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../dockwidgets/resources_example.qrc)
|
||||||
|
|
||||||
|
add_executable(kddockwidgets_customtitlebar_quick
|
||||||
|
main.cpp
|
||||||
|
${RESOURCES_EXAMPLE_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(kddockwidgets_customtitlebar_quick
|
||||||
|
PRIVATE
|
||||||
|
KDAB::kddockwidgets
|
||||||
|
)
|
||||||
36
examples/qtquick/customtitlebar/Guest.qml
Normal file
36
examples/qtquick/customtitlebar/Guest.qml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
property alias background: background.source
|
||||||
|
property alias logo: logo.source
|
||||||
|
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: background
|
||||||
|
anchors.fill: parent
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: logo
|
||||||
|
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
margins: 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
examples/qtquick/customtitlebar/Guest1.qml
Normal file
18
examples/qtquick/customtitlebar/Guest1.qml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Guest {
|
||||||
|
anchors.fill: parent
|
||||||
|
background: "qrc:/assets/triangles.png"
|
||||||
|
logo: "qrc:/assets/KDAB_bubble_white.png"
|
||||||
|
}
|
||||||
@@ -11,10 +11,7 @@
|
|||||||
|
|
||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
|
|
||||||
Rectangle {
|
Guest {
|
||||||
color: "pink"
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Text {
|
logo: "qrc:/assets/KDAB_bubble_blue.png"
|
||||||
text: "Guest Widget #2!"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -11,10 +11,8 @@
|
|||||||
|
|
||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
|
|
||||||
Rectangle {
|
Guest {
|
||||||
color: "lightblue"
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Text {
|
background: "qrc:/assets/base.png"
|
||||||
text: "Guest Widget #1 !"
|
logo: "qrc:/assets/KDAB_bubble_fulcolor.png"
|
||||||
}
|
|
||||||
}
|
}
|
||||||
54
examples/qtquick/customtitlebar/MyTitleBar.qml
Normal file
54
examples/qtquick/customtitlebar/MyTitleBar.qml
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.6
|
||||||
|
|
||||||
|
// Will be moved to a plugin in the future
|
||||||
|
import "qrc:/kddockwidgets/private/quick/qml/" as KDDW
|
||||||
|
|
||||||
|
KDDW.TitleBarBase {
|
||||||
|
id: root
|
||||||
|
color: "black"
|
||||||
|
border.color: "orange"
|
||||||
|
border.width: 2
|
||||||
|
heightWhenVisible: 50
|
||||||
|
|
||||||
|
Text {
|
||||||
|
color: "orange"
|
||||||
|
font.bold: true
|
||||||
|
text: root.title
|
||||||
|
anchors {
|
||||||
|
left: parent.left
|
||||||
|
leftMargin: 10
|
||||||
|
verticalCenter: root.verticalCenter
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: closeButton
|
||||||
|
enabled: root.closeButtonEnabled
|
||||||
|
radius: 5
|
||||||
|
color: "green"
|
||||||
|
height: root.height - 20
|
||||||
|
width: height
|
||||||
|
anchors {
|
||||||
|
right: root.right
|
||||||
|
rightMargin: 10
|
||||||
|
verticalCenter: root.verticalCenter
|
||||||
|
}
|
||||||
|
MouseArea {
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
root.closeButtonClicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,17 +10,41 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "private/DockRegistry_p.h"
|
#include <kddockwidgets/Config.h>
|
||||||
#include "private/quick/DockWidgetQuick.h"
|
#include <kddockwidgets/DockWidgetQuick.h>
|
||||||
#include "Config.h"
|
#include <kddockwidgets/private/DockRegistry_p.h>
|
||||||
|
#include <kddockwidgets/FrameworkWidgetFactory.h>
|
||||||
|
|
||||||
#include <QQuickView>
|
#include <QQuickView>
|
||||||
#include <QGuiApplication>
|
#include <QGuiApplication>
|
||||||
|
|
||||||
|
class CustomFrameworkWidgetFactory : public KDDockWidgets::DefaultWidgetFactory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
~CustomFrameworkWidgetFactory() override;
|
||||||
|
|
||||||
|
QUrl titleBarFilename() const override
|
||||||
|
{
|
||||||
|
return QUrl("qrc:/MyTitleBar.qml");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
CustomFrameworkWidgetFactory::~CustomFrameworkWidgetFactory() = default;
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||||
|
#endif
|
||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
|
auto &config = KDDockWidgets::Config::self();
|
||||||
|
auto flags = config.flags();
|
||||||
|
|
||||||
|
config.setFlags(flags);
|
||||||
|
config.setFrameworkWidgetFactory(new CustomFrameworkWidgetFactory());
|
||||||
|
|
||||||
QQuickView view;
|
QQuickView view;
|
||||||
view.setObjectName("MainWindow QQuickView");
|
view.setObjectName("MainWindow QQuickView");
|
||||||
KDDockWidgets::Config::self().setQmlEngine(view.engine());
|
KDDockWidgets::Config::self().setQmlEngine(view.engine());
|
||||||
@@ -42,13 +66,10 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
auto dw3 = new KDDockWidgets::DockWidgetQuick("Dock #3");
|
auto dw3 = new KDDockWidgets::DockWidgetQuick("Dock #3");
|
||||||
dw3->setWidget(QStringLiteral("qrc:/Guest3.qml"));
|
dw3->setWidget(QStringLiteral("qrc:/Guest3.qml"));
|
||||||
dw3->resize(QSize(800, 800));
|
|
||||||
dw3->show();
|
|
||||||
|
|
||||||
dw1->addDockWidgetToContainingWindow(dw3, KDDockWidgets::Location_OnRight);
|
dw1->addDockWidgetToContainingWindow(dw3, KDDockWidgets::Location_OnRight);
|
||||||
|
|
||||||
KDDockWidgets::MainWindowBase *mainWindow = KDDockWidgets::DockRegistry::self()->mainwindows().constFirst();
|
KDDockWidgets::MainWindowBase *mainWindow = KDDockWidgets::DockRegistry::self()->mainwindows().constFirst();
|
||||||
mainWindow->addDockWidget(dw2, KDDockWidgets::Location_OnTop);
|
mainWindow->addDockWidget(dw2, KDDockWidgets::Location_OnTop);
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<RCC>
|
||||||
|
<qresource prefix="/">
|
||||||
|
<file>main.qml</file>
|
||||||
|
<file>Guest1.qml</file>
|
||||||
|
<file>Guest2.qml</file>
|
||||||
|
<file>Guest3.qml</file>
|
||||||
|
<file>Guest.qml</file>
|
||||||
|
<file>MyTitleBar.qml</file>
|
||||||
|
</qresource>
|
||||||
|
</RCC>
|
||||||
@@ -12,9 +12,7 @@
|
|||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
|
|
||||||
Rectangle {
|
Rectangle {
|
||||||
color: "blue"
|
id: root
|
||||||
|
color: "green"
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Text {
|
|
||||||
text: "Guest Widget!"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
37
examples/qtquick/dockwidgets/CMakeLists.txt
Normal file
37
examples/qtquick/dockwidgets/CMakeLists.txt
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
|
project(kddockwidgets_example_quick)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
set(CMAKE_AUTORCC ON)
|
||||||
|
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
||||||
|
|
||||||
|
if(NOT TARGET kddockwidgets)
|
||||||
|
# This will look for Qt, do find_package yourself manually before
|
||||||
|
# if you want to look for a specific Qt version for instance.
|
||||||
|
find_package(KDDockWidgets REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(RESOURCES_EXAMPLE_SRC
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/resources_qtquick_example.qrc
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/../../dockwidgets/resources_example.qrc)
|
||||||
|
|
||||||
|
add_executable(kddockwidgets_example_quick
|
||||||
|
main.cpp
|
||||||
|
${RESOURCES_EXAMPLE_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(kddockwidgets_example_quick
|
||||||
|
PRIVATE
|
||||||
|
KDAB::kddockwidgets
|
||||||
|
)
|
||||||
36
examples/qtquick/dockwidgets/Guest.qml
Normal file
36
examples/qtquick/dockwidgets/Guest.qml
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Item {
|
||||||
|
anchors.fill: parent
|
||||||
|
|
||||||
|
property alias background: background.source
|
||||||
|
property alias logo: logo.source
|
||||||
|
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: background
|
||||||
|
anchors.fill: parent
|
||||||
|
fillMode: Image.PreserveAspectCrop
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: logo
|
||||||
|
|
||||||
|
fillMode: Image.PreserveAspectFit
|
||||||
|
anchors {
|
||||||
|
fill: parent
|
||||||
|
margins: 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
examples/qtquick/dockwidgets/Guest1.qml
Normal file
47
examples/qtquick/dockwidgets/Guest1.qml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
import QtQuick.Controls 2.12
|
||||||
|
import com.kdab.dockwidgets 1.0 as KDDW
|
||||||
|
|
||||||
|
Guest {
|
||||||
|
anchors.fill: parent
|
||||||
|
background: "qrc:/assets/triangles.png"
|
||||||
|
logo: "qrc:/assets/KDAB_bubble_white.png"
|
||||||
|
|
||||||
|
KDDW.DockWidget {
|
||||||
|
id: another
|
||||||
|
uniqueName: "another1"
|
||||||
|
source: ":/Another.qml"
|
||||||
|
}
|
||||||
|
|
||||||
|
Button {
|
||||||
|
text: "Toggle Another"
|
||||||
|
anchors {
|
||||||
|
bottom: parent.bottom
|
||||||
|
left: parent.left
|
||||||
|
margins: 5
|
||||||
|
}
|
||||||
|
|
||||||
|
onClicked: {
|
||||||
|
|
||||||
|
if (another.dockWidget.visible) {
|
||||||
|
another.dockWidget.close();
|
||||||
|
} else {
|
||||||
|
another.dockWidget.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,10 +11,7 @@
|
|||||||
|
|
||||||
import QtQuick 2.9
|
import QtQuick 2.9
|
||||||
|
|
||||||
Rectangle {
|
Guest {
|
||||||
color: "gray"
|
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
Text {
|
logo: "qrc:/assets/KDAB_bubble_blue.png"
|
||||||
text: "Guest Widget #3!"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
18
examples/qtquick/dockwidgets/Guest3.qml
Normal file
18
examples/qtquick/dockwidgets/Guest3.qml
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.9
|
||||||
|
|
||||||
|
Guest {
|
||||||
|
anchors.fill: parent
|
||||||
|
background: "qrc:/assets/base.png"
|
||||||
|
logo: "qrc:/assets/KDAB_bubble_fulcolor.png"
|
||||||
|
}
|
||||||
103
examples/qtquick/dockwidgets/main.cpp
Normal file
103
examples/qtquick/dockwidgets/main.cpp
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#include <kddockwidgets/Config.h>
|
||||||
|
#include <kddockwidgets/DockWidgetQuick.h>
|
||||||
|
#include <kddockwidgets/private/DockRegistry_p.h>
|
||||||
|
#include <kddockwidgets/FrameworkWidgetFactory.h>
|
||||||
|
|
||||||
|
#include <QQuickView>
|
||||||
|
#include <QGuiApplication>
|
||||||
|
#include <QCommandLineParser>
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES);
|
||||||
|
#endif
|
||||||
|
QGuiApplication app(argc, argv);
|
||||||
|
QCommandLineParser parser;
|
||||||
|
parser.setApplicationDescription("KDDockWidgets example application");
|
||||||
|
parser.addHelpOption();
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
|
QCommandLineOption noQtTool("no-qttool", QCoreApplication::translate("main", "(internal) Don't use Qt::Tool"));
|
||||||
|
QCommandLineOption noParentForFloating("no-parent-for-floating", QCoreApplication::translate("main", "(internal) FloatingWindows won't have a parent"));
|
||||||
|
QCommandLineOption nativeTitleBar("native-title-bar", QCoreApplication::translate("main", "(internal) FloatingWindows a native title bar"));
|
||||||
|
QCommandLineOption noDropIndicators("no-drop-indicators", QCoreApplication::translate("main", "(internal) Don't use any drop indicators"));
|
||||||
|
|
||||||
|
parser.addOption(noQtTool);
|
||||||
|
parser.addOption(noParentForFloating);
|
||||||
|
parser.addOption(nativeTitleBar);
|
||||||
|
parser.addOption(noDropIndicators);
|
||||||
|
|
||||||
|
# if defined(Q_OS_WIN)
|
||||||
|
QCommandLineOption noAeroSnap("no-aero-snap", QCoreApplication::translate("main", "(internal) Disable AeroSnap"));
|
||||||
|
parser.addOption(noAeroSnap);
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
auto flags = KDDockWidgets::Config::self().flags();
|
||||||
|
|
||||||
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
|
parser.process(app);
|
||||||
|
|
||||||
|
if (parser.isSet(noQtTool))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_internal_DontUseQtToolWindowsForFloatingWindows;
|
||||||
|
|
||||||
|
if (parser.isSet(noParentForFloating))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_internal_DontUseParentForFloatingWindows;
|
||||||
|
|
||||||
|
if (parser.isSet(nativeTitleBar))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_NativeTitleBar;
|
||||||
|
else if (parser.isSet(noDropIndicators))
|
||||||
|
KDDockWidgets::DefaultWidgetFactory::s_dropIndicatorType = KDDockWidgets::DropIndicatorType::None;
|
||||||
|
|
||||||
|
# if defined(Q_OS_WIN)
|
||||||
|
if (parser.isSet(noAeroSnap))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_internal_NoAeroSnap;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
KDDockWidgets::Config::self().setFlags(flags);
|
||||||
|
|
||||||
|
QQuickView view;
|
||||||
|
view.setObjectName("MainWindow QQuickView");
|
||||||
|
KDDockWidgets::Config::self().setQmlEngine(view.engine());
|
||||||
|
view.resize(1000, 800);
|
||||||
|
view.show();
|
||||||
|
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||||
|
|
||||||
|
auto dw1 = new KDDockWidgets::DockWidgetQuick("Dock #1");
|
||||||
|
view.setSource(QUrl("qrc:/main.qml"));
|
||||||
|
|
||||||
|
dw1->setWidget(QStringLiteral("qrc:/Guest1.qml"));
|
||||||
|
dw1->resize(QSize(800, 800));
|
||||||
|
dw1->show();
|
||||||
|
|
||||||
|
auto dw2 = new KDDockWidgets::DockWidgetQuick("Dock #2");
|
||||||
|
dw2->setWidget(QStringLiteral("qrc:/Guest2.qml"));
|
||||||
|
dw2->resize(QSize(800, 800));
|
||||||
|
dw2->show();
|
||||||
|
|
||||||
|
auto dw3 = new KDDockWidgets::DockWidgetQuick("Dock #3");
|
||||||
|
dw3->setWidget(QStringLiteral("qrc:/Guest3.qml"));
|
||||||
|
|
||||||
|
dw1->addDockWidgetToContainingWindow(dw3, KDDockWidgets::Location_OnRight);
|
||||||
|
|
||||||
|
KDDockWidgets::MainWindowBase *mainWindow = KDDockWidgets::DockRegistry::self()->mainwindows().constFirst();
|
||||||
|
mainWindow->addDockWidget(dw2, KDDockWidgets::Location_OnTop);
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
23
examples/qtquick/dockwidgets/main.qml
Normal file
23
examples/qtquick/dockwidgets/main.qml
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import QtQuick 2.6
|
||||||
|
import com.kdab.dockwidgets 1.0 as KDDW
|
||||||
|
|
||||||
|
KDDW.MainWindow {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
|
||||||
|
Component.onCompleted: {
|
||||||
|
root.init("MyWindowName-1");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@@ -4,5 +4,7 @@
|
|||||||
<file>Guest1.qml</file>
|
<file>Guest1.qml</file>
|
||||||
<file>Guest2.qml</file>
|
<file>Guest2.qml</file>
|
||||||
<file>Guest3.qml</file>
|
<file>Guest3.qml</file>
|
||||||
|
<file>Guest.qml</file>
|
||||||
|
<file>Another.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
1
kddockwidgets-rpmlintrc
Normal file
1
kddockwidgets-rpmlintrc
Normal file
@@ -0,0 +1 @@
|
|||||||
|
addFilter("E: shlib-policy-name-error")
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
Format: 1.0
|
Format: 1.0
|
||||||
Source: kddockwidgets
|
Source: kddockwidgets
|
||||||
Version: 1.0.0
|
Version: 1.2.0-1
|
||||||
Binary: kddockwidgets
|
Binary: kddockwidgets
|
||||||
Maintainer: Allen Winter <allen.winter@kdab.com>
|
Maintainer: Allen Winter <allen.winter@kdab.com>
|
||||||
Architecture: any
|
Architecture: any
|
||||||
Build-Depends: debhelper (>=9), cdbs, cmake, qt5-default, qtbase5-dev, libqt5x11extras5-dev
|
Build-Depends: debhelper (>=9), cdbs, cmake, qt5-default, qtbase5-dev, libqt5x11extras5-dev
|
||||||
|
|
||||||
Files:
|
Files:
|
||||||
00000000000000000000000000000000 00000 kddockwidgets-1.0.0.tar.gz
|
00000000000000000000000000000000 00000 kddockwidgets-1.2.0.tar.gz
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
Name: kddockwidgets
|
Name: kddockwidgets
|
||||||
Version: 1.0.0
|
Version: 1.2.0
|
||||||
Release: 1
|
Release: 1
|
||||||
Summary: KDAB's Dock Widget Framework for Qt
|
Summary: KDAB's Dock Widget Framework for Qt
|
||||||
Source0: %{name}-%{version}.tar.gz
|
Source0: %{name}-%{version}.tar.gz
|
||||||
Source1: %{name}-%{version}.tar.gz.asc
|
Source1: %{name}-%{version}.tar.gz.asc
|
||||||
|
Source2: %{name}-rpmlintrc
|
||||||
URL: https://github.com/KDAB/KDDockWidgets
|
URL: https://github.com/KDAB/KDDockWidgets
|
||||||
Group: System/Libraries
|
Group: System/Libraries
|
||||||
License: GPL-2.0-only OR GPL-3.0-only
|
License: GPL-2.0-only OR GPL-3.0-only
|
||||||
@@ -75,7 +76,6 @@ cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
|
|||||||
%defattr(-,root,root)
|
%defattr(-,root,root)
|
||||||
%{_prefix}/share/doc/KDDockWidgets
|
%{_prefix}/share/doc/KDDockWidgets
|
||||||
%{_libdir}/libkddockwidgets.so.*
|
%{_libdir}/libkddockwidgets.so.*
|
||||||
%{_libdir}/libkddockwidgets_multisplitter.so.*
|
|
||||||
|
|
||||||
%files devel
|
%files devel
|
||||||
%defattr(-,root,root,-)
|
%defattr(-,root,root,-)
|
||||||
@@ -85,10 +85,15 @@ cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
|
|||||||
%dir %{_libdir}/cmake/KDDockWidgets
|
%dir %{_libdir}/cmake/KDDockWidgets
|
||||||
%{_libdir}/cmake/KDDockWidgets/*
|
%{_libdir}/cmake/KDDockWidgets/*
|
||||||
%{_libdir}/libkddockwidgets.so
|
%{_libdir}/libkddockwidgets.so
|
||||||
%{_libdir}/libkddockwidgets_multisplitter.so
|
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
* Wed Sep 02 2020 Allen Winter <allen.winter@kdb.com> 1.0.0
|
* Thu Dec 17 2020 Allen Winter <allen.winter@kdab.com> 1.2.0
|
||||||
|
1.2.0 final
|
||||||
|
* Fri Dec 11 2020 Allen Winter <allen.winter@kdab.com> 1.1.1
|
||||||
|
1.1.1 final
|
||||||
|
* Mon Oct 26 2020 Allen Winter <allen.winter@kdab.com> 1.1.0
|
||||||
|
1.1.0 final
|
||||||
|
* Wed Sep 02 2020 Allen Winter <allen.winter@kdab.com> 1.0.0
|
||||||
1.0.0 final
|
1.0.0 final
|
||||||
* Thu Aug 06 2020 Allen Winter <allen.winter@kdb.com> 0.99.9
|
* Thu Aug 06 2020 Allen Winter <allen.winter@kdab.com> 0.99.9
|
||||||
1.0.0 release candidate
|
1.0.0 release candidate
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ set(PyKDDockWidgets_typesystem_paths
|
|||||||
|
|
||||||
# Include flags/path that will be set in 'target_include_directories'
|
# Include flags/path that will be set in 'target_include_directories'
|
||||||
set(PyKDDockWidgets_target_include_directories
|
set(PyKDDockWidgets_target_include_directories
|
||||||
${CMAKE_SOURCE_DIR}
|
${CMAKE_SOURCE_DIR}/src
|
||||||
)
|
)
|
||||||
|
|
||||||
# Libraries that will be necessary to link the target, this will used in the command 'target_link_libraries'
|
# Libraries that will be necessary to link the target, this will used in the command 'target_link_libraries'
|
||||||
@@ -74,8 +74,8 @@ create_python_bindings(
|
|||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
)
|
)
|
||||||
|
|
||||||
# Make moduled import from build dir works
|
# Make module import from build dir work
|
||||||
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py)
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py)
|
||||||
|
|
||||||
# install
|
# install
|
||||||
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py DESTINATION ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/PyKDDockWidgets)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py DESTINATION ${${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/PyKDDockWidgets)
|
||||||
|
|||||||
@@ -17,8 +17,11 @@
|
|||||||
// Define PYTHON_BINDINGS this will be used in some part of c++ to skip problematic parts
|
// Define PYTHON_BINDINGS this will be used in some part of c++ to skip problematic parts
|
||||||
#define PYTHON_BINDINGS
|
#define PYTHON_BINDINGS
|
||||||
|
|
||||||
#include <MainWindowBase.h>
|
#ifndef QT_WIDGETS_LIB
|
||||||
#include <MainWindow.h>
|
# define QT_WIDGETS_LIB
|
||||||
#include <DockWidgetBase.h>
|
#endif
|
||||||
#include <DockWidget.h>
|
|
||||||
|
|
||||||
|
#include <kddockwidgets/MainWindowBase.h>
|
||||||
|
#include <kddockwidgets/MainWindow.h>
|
||||||
|
#include <kddockwidgets/DockWidgetBase.h>
|
||||||
|
#include <kddockwidgets/DockWidget.h>
|
||||||
|
|||||||
@@ -23,30 +23,66 @@ add_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS
|
|||||||
|
|
||||||
set(DOCKSLIBS_SRCS
|
set(DOCKSLIBS_SRCS
|
||||||
Config.cpp
|
Config.cpp
|
||||||
|
Config.h
|
||||||
Qt5Qt6Compat_p.h
|
Qt5Qt6Compat_p.h
|
||||||
FocusScope.cpp
|
FocusScope.cpp
|
||||||
|
FocusScope.h
|
||||||
FrameworkWidgetFactory.cpp
|
FrameworkWidgetFactory.cpp
|
||||||
|
FrameworkWidgetFactory.h
|
||||||
DockWidgetBase.cpp
|
DockWidgetBase.cpp
|
||||||
|
DockWidgetBase.h
|
||||||
MainWindowBase.cpp
|
MainWindowBase.cpp
|
||||||
|
MainWindowBase.h
|
||||||
LayoutSaver.cpp
|
LayoutSaver.cpp
|
||||||
|
LayoutSaver.h
|
||||||
|
LayoutSaver_p.h
|
||||||
private/MultiSplitter.cpp
|
private/MultiSplitter.cpp
|
||||||
|
private/MultiSplitter_p.h
|
||||||
private/Position.cpp
|
private/Position.cpp
|
||||||
private/ObjectViewer.cpp
|
private/Position_p.h
|
||||||
private/DropIndicatorOverlayInterface.cpp
|
private/DropIndicatorOverlayInterface.cpp
|
||||||
|
private/DropIndicatorOverlayInterface_p.h
|
||||||
private/DropArea.cpp
|
private/DropArea.cpp
|
||||||
|
private/DropArea_p.h
|
||||||
private/FloatingWindow.cpp
|
private/FloatingWindow.cpp
|
||||||
|
private/FloatingWindow_p.h
|
||||||
private/Logging.cpp
|
private/Logging.cpp
|
||||||
|
private/Logging_p.h
|
||||||
private/TitleBar.cpp
|
private/TitleBar.cpp
|
||||||
|
private/TitleBar_p.h
|
||||||
private/SideBar.cpp
|
private/SideBar.cpp
|
||||||
|
private/SideBar_p.h
|
||||||
private/DockRegistry.cpp
|
private/DockRegistry.cpp
|
||||||
|
private/DockRegistry_p.h
|
||||||
private/Draggable.cpp
|
private/Draggable.cpp
|
||||||
|
private/Draggable_p.h
|
||||||
private/WindowBeingDragged.cpp
|
private/WindowBeingDragged.cpp
|
||||||
|
private/WindowBeingDragged_p.h
|
||||||
private/DragController.cpp
|
private/DragController.cpp
|
||||||
|
private/DragController_p.h
|
||||||
private/Frame.cpp
|
private/Frame.cpp
|
||||||
|
private/Frame_p.h
|
||||||
private/DropAreaWithCentralFrame.cpp
|
private/DropAreaWithCentralFrame.cpp
|
||||||
|
private/DropAreaWithCentralFrame_p.h
|
||||||
private/WidgetResizeHandler.cpp
|
private/WidgetResizeHandler.cpp
|
||||||
|
private/WidgetResizeHandler_p.h
|
||||||
|
private/indicators/NullIndicators.cpp
|
||||||
|
private/indicators/NullIndicators_p.h
|
||||||
private/indicators/ClassicIndicators.cpp
|
private/indicators/ClassicIndicators.cpp
|
||||||
|
private/indicators/ClassicIndicators_p.h
|
||||||
private/indicators/ClassicIndicatorsWindow.cpp
|
private/indicators/ClassicIndicatorsWindow.cpp
|
||||||
|
private/indicators/ClassicIndicatorsWindow_p.h
|
||||||
|
|
||||||
|
private/multisplitter/Item.cpp
|
||||||
|
private/multisplitter/Item_p.h
|
||||||
|
private/multisplitter/Logging.cpp
|
||||||
|
private/multisplitter/Logging_p.h
|
||||||
|
private/multisplitter/MultiSplitterConfig.cpp
|
||||||
|
private/multisplitter/MultiSplitterConfig.h
|
||||||
|
private/multisplitter/Separator.cpp
|
||||||
|
private/multisplitter/Separator_p.h
|
||||||
|
private/multisplitter/Widget.cpp
|
||||||
|
private/multisplitter/Widget.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_INCLUDES
|
set(DOCKS_INSTALLABLE_INCLUDES
|
||||||
@@ -55,6 +91,7 @@ set(DOCKS_INSTALLABLE_INCLUDES
|
|||||||
FrameworkWidgetFactory.h
|
FrameworkWidgetFactory.h
|
||||||
DockWidgetBase.h
|
DockWidgetBase.h
|
||||||
KDDockWidgets.h
|
KDDockWidgets.h
|
||||||
|
Qt5Qt6Compat_p.h
|
||||||
FocusScope.h
|
FocusScope.h
|
||||||
QWidgetAdapter.h
|
QWidgetAdapter.h
|
||||||
LayoutSaver.h
|
LayoutSaver.h
|
||||||
@@ -70,6 +107,7 @@ set(DOCKS_INSTALLABLE_PRIVATE_INCLUDES
|
|||||||
private/SideBar_p.h
|
private/SideBar_p.h
|
||||||
private/TitleBar_p.h
|
private/TitleBar_p.h
|
||||||
private/WindowBeingDragged_p.h
|
private/WindowBeingDragged_p.h
|
||||||
|
private/DockRegistry_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
||||||
@@ -85,33 +123,67 @@ set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
|||||||
|
|
||||||
if(${PROJECT_NAME}_QTQUICK)
|
if(${PROJECT_NAME}_QTQUICK)
|
||||||
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
||||||
private/quick/DockWidgetQuick.cpp
|
DockWidgetQuick.cpp
|
||||||
|
DockWidgetQuick.h
|
||||||
|
private/quick/DockWidgetInstantiator.cpp
|
||||||
|
private/quick/DockWidgetInstantiator_p.h
|
||||||
private/quick/QWidgetAdapter_quick.cpp
|
private/quick/QWidgetAdapter_quick.cpp
|
||||||
|
private/quick/QWidgetAdapter_quick_p.h
|
||||||
private/quick/FloatingWindowQuick.cpp
|
private/quick/FloatingWindowQuick.cpp
|
||||||
|
private/quick/FloatingWindowQuick_p.h
|
||||||
private/quick/TitleBarQuick.cpp
|
private/quick/TitleBarQuick.cpp
|
||||||
|
private/quick/TitleBarQuick_p.h
|
||||||
private/quick/QmlTypes.cpp
|
private/quick/QmlTypes.cpp
|
||||||
|
private/quick/QmlTypes.h
|
||||||
private/quick/FrameQuick.cpp
|
private/quick/FrameQuick.cpp
|
||||||
|
private/quick/FrameQuick_p.h
|
||||||
|
private/quick/RubberBandQuick.cpp
|
||||||
|
private/quick/RubberBandQuick.h
|
||||||
private/quick/MainWindowQuick.cpp
|
private/quick/MainWindowQuick.cpp
|
||||||
|
private/quick/MainWindowQuick_p.h
|
||||||
private/quick/MainWindowWrapper.cpp
|
private/quick/MainWindowWrapper.cpp
|
||||||
)
|
private/quick/MainWindowWrapper_p.h
|
||||||
|
private/multisplitter/Widget_quick.cpp
|
||||||
qt5_add_resources(RESOURCES_QUICK ${CMAKE_CURRENT_SOURCE_DIR}/qtquick.qrc)
|
private/multisplitter/Widget_quick.h
|
||||||
|
private/multisplitter/Separator_quick.cpp
|
||||||
|
private/multisplitter/Separator_quick.h
|
||||||
|
private/multisplitter/Rubberband_quick.cpp
|
||||||
|
private/multisplitter/Rubberband_quick.h
|
||||||
|
kddockwidgets_qtquick.qrc)
|
||||||
else()
|
else()
|
||||||
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
||||||
private/DebugWindow.cpp
|
private/DebugWindow.cpp
|
||||||
|
private/DebugWindow_p.h
|
||||||
|
private/ObjectViewer.cpp
|
||||||
|
private/ObjectViewer_p.h
|
||||||
MainWindow.cpp
|
MainWindow.cpp
|
||||||
|
MainWindow.h
|
||||||
|
DockWidget.h
|
||||||
|
private/multisplitter/Widget_qwidget.cpp
|
||||||
|
private/multisplitter/Widget_qwidget.h
|
||||||
|
private/multisplitter/Separator_qwidget.cpp
|
||||||
|
private/multisplitter/Separator_qwidget.h
|
||||||
private/widgets/TabWidget.cpp
|
private/widgets/TabWidget.cpp
|
||||||
|
private/widgets/TabWidget_p.h
|
||||||
private/widgets/TabBarWidget.cpp
|
private/widgets/TabBarWidget.cpp
|
||||||
|
private/widgets/TabBarWidget_p.h
|
||||||
private/widgets/FloatingWindowWidget.cpp
|
private/widgets/FloatingWindowWidget.cpp
|
||||||
|
private/widgets/FloatingWindowWidget_p.h
|
||||||
private/widgets/FrameWidget.cpp
|
private/widgets/FrameWidget.cpp
|
||||||
|
private/widgets/FrameWidget_p.h
|
||||||
private/widgets/SideBarWidget.cpp
|
private/widgets/SideBarWidget.cpp
|
||||||
|
private/widgets/SideBarWidget_p.h
|
||||||
private/widgets/TabWidgetWidget.cpp
|
private/widgets/TabWidgetWidget.cpp
|
||||||
|
private/widgets/TabWidgetWidget_p.h
|
||||||
private/widgets/TitleBarWidget.cpp
|
private/widgets/TitleBarWidget.cpp
|
||||||
|
private/widgets/TitleBarWidget_p.h
|
||||||
private/widgets/DockWidget.cpp
|
private/widgets/DockWidget.cpp
|
||||||
private/widgets/QWidgetAdapter_widgets.cpp
|
private/widgets/QWidgetAdapter_widgets.cpp
|
||||||
|
private/widgets/QWidgetAdapter_widgets_p.h
|
||||||
private/indicators/SegmentedIndicators.cpp
|
private/indicators/SegmentedIndicators.cpp
|
||||||
|
private/indicators/SegmentedIndicators_p.h
|
||||||
# private/indicators/AnimatedIndicators.cpp
|
# private/indicators/AnimatedIndicators.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_INCLUDES
|
set(DOCKS_INSTALLABLE_INCLUDES
|
||||||
${DOCKS_INSTALLABLE_INCLUDES}
|
${DOCKS_INSTALLABLE_INCLUDES}
|
||||||
@@ -127,9 +199,7 @@ else()
|
|||||||
set(IS_CLANG_BUILD FALSE)
|
set(IS_CLANG_BUILD FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(private/multisplitter)
|
set(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/kddockwidgets_resources.qrc)
|
||||||
|
|
||||||
qt5_add_resources(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc)
|
|
||||||
|
|
||||||
add_library(kddockwidgets ${KDDockWidgets_LIBRARY_MODE} ${DOCKSLIBS_SRCS} ${DOCKS_INSTALLABLE_INCLUDES} ${RESOURCES} ${RESOURCES_QUICK})
|
add_library(kddockwidgets ${KDDockWidgets_LIBRARY_MODE} ${DOCKSLIBS_SRCS} ${DOCKS_INSTALLABLE_INCLUDES} ${RESOURCES} ${RESOURCES_QUICK})
|
||||||
add_library(KDAB::kddockwidgets ALIAS kddockwidgets)
|
add_library(KDAB::kddockwidgets ALIAS kddockwidgets)
|
||||||
@@ -138,12 +208,11 @@ set_compiler_flags(kddockwidgets)
|
|||||||
target_include_directories(kddockwidgets
|
target_include_directories(kddockwidgets
|
||||||
PUBLIC
|
PUBLIC
|
||||||
$<INSTALL_INTERFACE:include>
|
$<INSTALL_INTERFACE:include>
|
||||||
$<INSTALL_INTERFACE:include/kddockwidgets>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fwd_headers>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fwd_headers>
|
||||||
PRIVATE
|
PRIVATE
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/private
|
${CMAKE_CURRENT_SOURCE_DIR}/private
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/private/multisplitter/
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(kddockwidgets
|
target_compile_definitions(kddockwidgets
|
||||||
@@ -168,19 +237,23 @@ if(CMAKE_COMPILER_IS_GNUCXX OR IS_CLANG_BUILD)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${PROJECT_NAME}_QTQUICK)
|
if(${PROJECT_NAME}_QTQUICK)
|
||||||
target_link_libraries(kddockwidgets PUBLIC Qt5::Widgets Qt5::Quick Qt5::QuickControls2 kddockwidgets_multisplitter PRIVATE Qt5::GuiPrivate)
|
target_link_libraries(kddockwidgets PUBLIC Qt${QT_MAJOR_VERSION}::Widgets Qt${QT_MAJOR_VERSION}::Quick Qt${QT_MAJOR_VERSION}::QuickControls2)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(kddockwidgets PUBLIC Qt5::Widgets kddockwidgets_multisplitter PRIVATE Qt5::GuiPrivate)
|
target_link_libraries(kddockwidgets PUBLIC Qt${QT_MAJOR_VERSION}::Widgets)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
target_link_libraries(kddockwidgets PRIVATE Dwmapi)
|
target_link_libraries(kddockwidgets PRIVATE Qt${QT_MAJOR_VERSION}::GuiPrivate Dwmapi)
|
||||||
elseif(NOT APPLE)
|
elseif(NOT APPLE AND NOT EMSCRIPTEN AND NOT ${PROJECT_NAME}_QT6)
|
||||||
find_package(Qt5X11Extras)
|
find_package(Qt${QT_MAJOR_VERSION}X11Extras)
|
||||||
target_link_libraries(kddockwidgets PUBLIC Qt5::X11Extras)
|
target_link_libraries(kddockwidgets PUBLIC Qt${QT_MAJOR_VERSION}::X11Extras)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(kddockwidgets PROPERTIES VERSION ${${PROJECT_NAME}_SOVERSION})
|
set_target_properties(kddockwidgets PROPERTIES
|
||||||
|
SOVERSION ${${PROJECT_NAME}_SOVERSION}
|
||||||
|
VERSION ${${PROJECT_NAME}_VERSION}
|
||||||
|
)
|
||||||
|
|
||||||
#version libraries on Windows
|
#version libraries on Windows
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(postfix ${${PROJECT_NAME}_VERSION_MAJOR})
|
set(postfix ${${PROJECT_NAME}_VERSION_MAJOR})
|
||||||
@@ -208,7 +281,6 @@ install(FILES private/multisplitter/Widget.h DESTINATION include/kddockwidgets/p
|
|||||||
install(FILES private/multisplitter/Widget_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
|
install(FILES private/multisplitter/Widget_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
|
||||||
install(FILES private/multisplitter/Separator_p.h DESTINATION include/kddockwidgets/private/multisplitter)
|
install(FILES private/multisplitter/Separator_p.h DESTINATION include/kddockwidgets/private/multisplitter)
|
||||||
install(FILES private/multisplitter/Separator_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
|
install(FILES private/multisplitter/Separator_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
|
||||||
install(FILES private/multisplitter/multisplitter_export.h DESTINATION include/kddockwidgets/private/multisplitter)
|
|
||||||
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
|
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
|
||||||
|
|
||||||
install(FILES private/indicators/ClassicIndicators_p.h DESTINATION include/kddockwidgets/private/indicators)
|
install(FILES private/indicators/ClassicIndicators_p.h DESTINATION include/kddockwidgets/private/indicators)
|
||||||
@@ -238,6 +310,7 @@ if(${PROJECT_NAME}_DEVELOPER_MODE)
|
|||||||
|
|
||||||
if (NOT ${PROJECT_NAME}_QTQUICK) # TODO: We can support it
|
if (NOT ${PROJECT_NAME}_QTQUICK) # TODO: We can support it
|
||||||
add_executable(kddockwidgets_linter layoutlinter_main.cpp)
|
add_executable(kddockwidgets_linter layoutlinter_main.cpp)
|
||||||
target_link_libraries(kddockwidgets_linter kddockwidgets kddockwidgets_multisplitter Qt5::Widgets)
|
target_link_libraries(kddockwidgets_linter kddockwidgets Qt${QT_MAJOR_VERSION}::Widgets)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -18,15 +18,19 @@
|
|||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "multisplitter/MultiSplitterConfig.h"
|
#include "multisplitter/MultiSplitterConfig.h"
|
||||||
#include "multisplitter/Widget_qwidget.h"
|
#include "multisplitter/Widget.h"
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QOperatingSystemVersion>
|
#include <QOperatingSystemVersion>
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
|
# include <QQmlEngine>
|
||||||
|
# include <QQmlContext>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace KDDockWidgets
|
namespace KDDockWidgets
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -48,7 +52,8 @@ public:
|
|||||||
QQmlEngine *m_qmlEngine = nullptr;
|
QQmlEngine *m_qmlEngine = nullptr;
|
||||||
DockWidgetFactoryFunc m_dockWidgetFactoryFunc = nullptr;
|
DockWidgetFactoryFunc m_dockWidgetFactoryFunc = nullptr;
|
||||||
MainWindowFactoryFunc m_mainWindowFactoryFunc = nullptr;
|
MainWindowFactoryFunc m_mainWindowFactoryFunc = nullptr;
|
||||||
FrameworkWidgetFactory *m_frameworkWidgetFactory;
|
TabbingAllowedFunc m_tabbingAllowedFunc = nullptr;
|
||||||
|
FrameworkWidgetFactory *m_frameworkWidgetFactory = nullptr;
|
||||||
Flags m_flags = Flag_Default;
|
Flags m_flags = Flag_Default;
|
||||||
qreal m_draggedWindowOpacity = Q_QNAN;
|
qreal m_draggedWindowOpacity = Q_QNAN;
|
||||||
};
|
};
|
||||||
@@ -157,6 +162,17 @@ qreal Config::draggedWindowOpacity() const
|
|||||||
return d->m_draggedWindowOpacity;
|
return d->m_draggedWindowOpacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::setTabbingAllowedFunc(TabbingAllowedFunc func)
|
||||||
|
{
|
||||||
|
d->m_tabbingAllowedFunc = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabbingAllowedFunc Config::tabbingAllowedFunc() const
|
||||||
|
{
|
||||||
|
return d->m_tabbingAllowedFunc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
void Config::setQmlEngine(QQmlEngine *qmlEngine)
|
void Config::setQmlEngine(QQmlEngine *qmlEngine)
|
||||||
{
|
{
|
||||||
if (d->m_qmlEngine) {
|
if (d->m_qmlEngine) {
|
||||||
@@ -164,13 +180,22 @@ void Config::setQmlEngine(QQmlEngine *qmlEngine)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!qmlEngine) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Null QML engine";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
d->m_qmlEngine = qmlEngine;
|
d->m_qmlEngine = qmlEngine;
|
||||||
|
|
||||||
|
QQmlContext *context = qmlEngine->rootContext();
|
||||||
|
context->setContextProperty(QStringLiteral("_kddw_widgetFactory"), d->m_frameworkWidgetFactory);
|
||||||
}
|
}
|
||||||
|
|
||||||
QQmlEngine *Config::qmlEngine() const
|
QQmlEngine *Config::qmlEngine() const
|
||||||
{
|
{
|
||||||
return d->m_qmlEngine;
|
return d->m_qmlEngine;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void Config::Private::fixFlags()
|
void Config::Private::fixFlags()
|
||||||
{
|
{
|
||||||
@@ -206,9 +231,19 @@ void Config::Private::fixFlags()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
#if (!defined(Q_OS_WIN) && !defined(Q_OS_MACOS))
|
||||||
|
// QtQuick doesn't support AeroSnap yet. Some problem with the native events not being received...
|
||||||
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
|
// We allow to disable aero-snap during development
|
||||||
|
if (m_flags & Flag_internal_NoAeroSnap) {
|
||||||
|
// The only way to disable AeroSnap
|
||||||
|
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
77
src/Config.h
77
src/Config.h
@@ -35,6 +35,14 @@ class FrameworkWidgetFactory;
|
|||||||
typedef KDDockWidgets::DockWidgetBase* (*DockWidgetFactoryFunc)(const QString &name);
|
typedef KDDockWidgets::DockWidgetBase* (*DockWidgetFactoryFunc)(const QString &name);
|
||||||
typedef KDDockWidgets::MainWindowBase* (*MainWindowFactoryFunc)(const QString &name);
|
typedef KDDockWidgets::MainWindowBase* (*MainWindowFactoryFunc)(const QString &name);
|
||||||
|
|
||||||
|
/// @brief Function to allow the user more granularity to disallow dock widgets to tab together
|
||||||
|
/// @param source The dock widgets being dragged
|
||||||
|
/// @param target The dock widgets within an existing docked tab group
|
||||||
|
/// @return true if the docking is allowed.
|
||||||
|
/// @sa setTabbingAllowedFunc
|
||||||
|
typedef bool (*TabbingAllowedFunc)(const QVector<DockWidgetBase*> &source,
|
||||||
|
const QVector<DockWidgetBase*> &target);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Singleton to allow to choose certain behaviours of the framework.
|
* @brief Singleton to allow to choose certain behaviours of the framework.
|
||||||
*
|
*
|
||||||
@@ -53,29 +61,31 @@ public:
|
|||||||
|
|
||||||
///@brief Flag enum to tune certain behaviours, the defaults are Flag_Default
|
///@brief Flag enum to tune certain behaviours, the defaults are Flag_Default
|
||||||
enum Flag {
|
enum Flag {
|
||||||
Flag_None = 0, ///> No option set
|
Flag_None = 0, ///< No option set
|
||||||
Flag_NativeTitleBar = 1, ///> Enables the Native OS title bar on OSes that support it (Windows 10, macOS), ignored otherwise. This is mutually exclusive with Flag_AeroSnap
|
Flag_NativeTitleBar = 1, ///< Enables the Native OS title bar on OSes that support it (Windows 10, macOS), ignored otherwise. This is mutually exclusive with Flag_AeroSnap
|
||||||
Flag_AeroSnapWithClientDecos = 2, ///> Deprecated. This is now default and cannot be turned off. Moving a window on Windows 10 uses native moving, as that works well across screens with different HDPI settings. There's no reason to use manual client/Qt window moving.
|
Flag_AeroSnapWithClientDecos = 2, ///< Deprecated. This is now default and cannot be turned off. Moving a window on Windows 10 uses native moving, as that works well across screens with different HDPI settings. There's no reason to use manual client/Qt window moving.
|
||||||
Flag_AlwaysTitleBarWhenFloating = 4, ///> Floating windows will have a title bar even if Flag_HideTitleBarWhenTabsVisible is specified. Unneeded if Flag_HideTitleBarWhenTabsVisible isn't specified, as that's the default already.
|
Flag_AlwaysTitleBarWhenFloating = 4, ///< Floating windows will have a title bar even if Flag_HideTitleBarWhenTabsVisible is specified. Unneeded if Flag_HideTitleBarWhenTabsVisible isn't specified, as that's the default already.
|
||||||
Flag_HideTitleBarWhenTabsVisible = 8, ///> Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
|
Flag_HideTitleBarWhenTabsVisible = 8, ///< Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
|
||||||
Flag_AlwaysShowTabs = 16, ///> Always show tabs, even if there's only one,
|
Flag_AlwaysShowTabs = 16, ///< Always show tabs, even if there's only one,
|
||||||
Flag_AllowReorderTabs = 32, /// Allows user to re-order tabs by dragging them
|
Flag_AllowReorderTabs = 32, ///< Allows user to re-order tabs by dragging them
|
||||||
Flag_TabsHaveCloseButton = 64, /// Tabs will have a close button. Equivalent to QTabWidget::setTabsClosable(true).
|
Flag_TabsHaveCloseButton = 64, ///< Tabs will have a close button. Equivalent to QTabWidget::setTabsClosable(true).
|
||||||
Flag_DoubleClickMaximizes = 128, /// Double clicking the titlebar will maximize a floating window instead of re-docking it
|
Flag_DoubleClickMaximizes = 128, ///< Double clicking the titlebar will maximize a floating window instead of re-docking it
|
||||||
Flag_TitleBarHasMaximizeButton = 256, /// The title bar will have a maximize/restore button when floating. This is mutually-exclusive with the floating button (since many apps behave that way).
|
Flag_TitleBarHasMaximizeButton = 256, ///< The title bar will have a maximize/restore button when floating. This is mutually-exclusive with the floating button (since many apps behave that way).
|
||||||
Flag_TitleBarIsFocusable = 512, /// You can click the title bar and it will focus the last focused widget in the focus scope. If no previously focused widget then it focuses the user's dock widget guest, which should accept focus or use a focus proxy.
|
Flag_TitleBarIsFocusable = 512, ///< You can click the title bar and it will focus the last focused widget in the focus scope. If no previously focused widget then it focuses the user's dock widget guest, which should accept focus or use a focus proxy.
|
||||||
Flag_LazyResize = 1024, /// The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button.
|
Flag_LazyResize = 1024, ///< The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button.
|
||||||
|
|
||||||
// These two are internal, for testing purposes across platforms. Use Flag_DontUseUtilityFloatingWindows instead.
|
// These two are internal, for testing purposes across platforms. Use Flag_DontUseUtilityFloatingWindows instead.
|
||||||
Flag_internal_DontUseQtToolWindowsForFloatingWindows = 0x800, ///> FloatingWindows will use Qt::Window instead of Qt::Tool. Internal, use Flag_DontUseUtilityFloatingWindows instead.
|
Flag_internal_DontUseQtToolWindowsForFloatingWindows = 0x800, ///< FloatingWindows will use Qt::Window instead of Qt::Tool. Internal, use Flag_DontUseUtilityFloatingWindows instead.
|
||||||
Flag_internal_DontUseParentForFloatingWindows = 0x1000, ///> FloatingWindows won't have a parent top-level. Internal, use Flag_DontUseUtilityFloatingWindows instead.
|
Flag_internal_DontUseParentForFloatingWindows = 0x1000, ///< FloatingWindows won't have a parent top-level. Internal, use Flag_DontUseUtilityFloatingWindows instead.
|
||||||
|
|
||||||
Flag_DontUseUtilityFloatingWindows = Flag_internal_DontUseQtToolWindowsForFloatingWindows | Flag_internal_DontUseParentForFloatingWindows,
|
Flag_DontUseUtilityFloatingWindows = Flag_internal_DontUseQtToolWindowsForFloatingWindows | Flag_internal_DontUseParentForFloatingWindows,
|
||||||
Flag_TitleBarHasMinimizeButton = 0x2000 | Flag_DontUseUtilityFloatingWindows, ///> The title bar will have a minimize button when floating. This implies Flag_DontUseUtilityFloatingWindows too, otherwise they wouldn't appear in the task bar.
|
Flag_TitleBarHasMinimizeButton = 0x2000 | Flag_DontUseUtilityFloatingWindows, ///< The title bar will have a minimize button when floating. This implies Flag_DontUseUtilityFloatingWindows too, otherwise they wouldn't appear in the task bar.
|
||||||
Flag_TitleBarNoFloatButton = 0x4000, ///> The TitleBar won't show the float button
|
Flag_TitleBarNoFloatButton = 0x4000, ///< The TitleBar won't show the float button
|
||||||
Flag_AutoHideSupport = 0x8000 | Flag_TitleBarNoFloatButton, ///> Supports minimizing dock widgets to the side-bar.
|
Flag_AutoHideSupport = 0x8000 | Flag_TitleBarNoFloatButton, ///< Supports minimizing dock widgets to the side-bar.
|
||||||
///> By default it also turns off the float button, but you can remove Flag_TitleBarNoFloatButton to have both.
|
///< By default it also turns off the float button, but you can remove Flag_TitleBarNoFloatButton to have both.
|
||||||
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
|
Flag_KeepAboveIfNotUtilityWindow = 0x10000, ///< Only meaningful if Flag_DontUseUtilityFloatingWindows is set. If floating windows are normal windows, you might still want them to keep above and not minimize when you focus the main window.
|
||||||
|
Flag_internal_NoAeroSnap = 0x20000, ///< Internal flag, only for development. Disables Aero-snap.
|
||||||
|
Flag_Default = Flag_AeroSnapWithClientDecos ///< The defaults
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
|
|
||||||
@@ -150,9 +160,38 @@ public:
|
|||||||
///By default it's 1.0, fully opaque
|
///By default it's 1.0, fully opaque
|
||||||
qreal draggedWindowOpacity() const;
|
qreal draggedWindowOpacity() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Allows the user to intercept a docking attempt to center (tabbed) and disallow it.
|
||||||
|
*
|
||||||
|
* Whenever the user tries to tab two widgets together, the framework will call @p func. If
|
||||||
|
* it returns true, then tabbing is allowed, otherwise not.
|
||||||
|
*
|
||||||
|
* Example:
|
||||||
|
* @code
|
||||||
|
* #include <kddockwidgets/Config.h>
|
||||||
|
* (...)
|
||||||
|
*
|
||||||
|
* auto func = [] (const KDDockWidgets::DockWidgetBase::List &source,
|
||||||
|
* const KDDockWidgets::DockWidgetBase::List &target)
|
||||||
|
* {
|
||||||
|
* // disallows dockFoo to be tabbed with dockBar.
|
||||||
|
* return !(source.contains(dockFoo) && target.contains(dockBar));
|
||||||
|
* }
|
||||||
|
* @endcode
|
||||||
|
* KDDockWidgets::Config::self()->setTabbingAllowedFunc(func);
|
||||||
|
*/
|
||||||
|
void setTabbingAllowedFunc(TabbingAllowedFunc func);
|
||||||
|
|
||||||
|
///@brief Used internally by the framework. Returns the function which was passed to setTabbingAllowedFunc()
|
||||||
|
///By default it's nullptr.
|
||||||
|
///@sa setTabbingAllowedFunc().
|
||||||
|
TabbingAllowedFunc tabbingAllowedFunc() const;
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
|
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
|
||||||
void setQmlEngine(QQmlEngine *);
|
void setQmlEngine(QQmlEngine *);
|
||||||
QQmlEngine* qmlEngine() const;
|
QQmlEngine* qmlEngine() const;
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(Config)
|
Q_DISABLE_COPY(Config)
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
#include "SideBar_p.h"
|
#include "SideBar_p.h"
|
||||||
|
|
||||||
#include <QAction>
|
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
@@ -146,6 +145,9 @@ DockWidgetBase::DockWidgetBase(const QString &name, Options options)
|
|||||||
|
|
||||||
if (name.isEmpty())
|
if (name.isEmpty())
|
||||||
qWarning() << Q_FUNC_INFO << "Name can't be null";
|
qWarning() << Q_FUNC_INFO << "Name can't be null";
|
||||||
|
|
||||||
|
setAttribute(Qt::WA_PendingMoveEvent, false);
|
||||||
|
qApp->installEventFilter(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
DockWidgetBase::~DockWidgetBase()
|
DockWidgetBase::~DockWidgetBase()
|
||||||
@@ -183,7 +185,7 @@ void DockWidgetBase::addDockWidgetAsTab(DockWidgetBase *other, AddingOption addi
|
|||||||
Frame *frame = this->frame();
|
Frame *frame = this->frame();
|
||||||
|
|
||||||
if (frame) {
|
if (frame) {
|
||||||
if (frame->contains(other)) {
|
if (frame->containsDockWidget(other)) {
|
||||||
qWarning() << Q_FUNC_INFO << "Already contains" << other;
|
qWarning() << Q_FUNC_INFO << "Already contains" << other;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -528,7 +530,7 @@ FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
|
|||||||
if (geo.isNull()) {
|
if (geo.isNull()) {
|
||||||
geo = geometry();
|
geo = geometry();
|
||||||
|
|
||||||
if (!testAttribute(Qt::WA_Moved)) { // If user already moved it, we don't interfere
|
if (!testAttribute(Qt::WA_PendingMoveEvent)) { // If user already moved it, we don't interfere
|
||||||
const QPoint center = d->defaultCenterPosForFloating();
|
const QPoint center = d->defaultCenterPosForFloating();
|
||||||
if (!center.isNull())
|
if (!center.isNull())
|
||||||
geo.moveCenter(center);
|
geo.moveCenter(center);
|
||||||
@@ -594,6 +596,16 @@ void DockWidgetBase::updateFloatAction()
|
|||||||
d->updateFloatAction();
|
d->updateFloatAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockWidgetBase::eventFilter(QObject *watched, QEvent *event)
|
||||||
|
{
|
||||||
|
const bool isWindowActivate = event->type() == QEvent::WindowActivate;
|
||||||
|
const bool isWindowDeactivate = event->type() == QEvent::WindowDeactivate;
|
||||||
|
if ((isWindowActivate || isWindowDeactivate) && watched == window())
|
||||||
|
Q_EMIT windowActiveAboutToChange(isWindowActivate);
|
||||||
|
|
||||||
|
return QWidgetAdapter::eventFilter(watched, event);
|
||||||
|
}
|
||||||
|
|
||||||
QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
|
QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
|
||||||
{
|
{
|
||||||
MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
||||||
@@ -653,14 +665,12 @@ void DockWidgetBase::Private::onDockWidgetShown()
|
|||||||
{
|
{
|
||||||
updateToggleAction();
|
updateToggleAction();
|
||||||
updateFloatAction();
|
updateFloatAction();
|
||||||
qCDebug(hiding) << Q_FUNC_INFO << "parent=" << q->parentWidget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::onDockWidgetHidden()
|
void DockWidgetBase::Private::onDockWidgetHidden()
|
||||||
{
|
{
|
||||||
updateToggleAction();
|
updateToggleAction();
|
||||||
updateFloatAction();
|
updateFloatAction();
|
||||||
qCDebug(hiding) << Q_FUNC_INFO << "parent=" << q->parentWidget();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::close()
|
void DockWidgetBase::Private::close()
|
||||||
|
|||||||
@@ -30,10 +30,81 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QAction;
|
class QAction;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class TestDocks;
|
||||||
|
|
||||||
namespace Layouting {
|
namespace Layouting {
|
||||||
class Item;
|
class Item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if defined(QT_WIDGETS_LIB)
|
||||||
|
# include <QAction>
|
||||||
|
#else
|
||||||
|
// A QAction for QtQuick. Just so it compiles, for now
|
||||||
|
class QAction : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
using QObject::QObject;
|
||||||
|
|
||||||
|
bool isChecked() const {
|
||||||
|
return m_isChecked ;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCheckable(bool is) {
|
||||||
|
m_isCheckable = is;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setText(const QString &text) {
|
||||||
|
m_text = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setToolTip(const QString &text) {
|
||||||
|
m_toolTip = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString toolTip() const {
|
||||||
|
returm m_toolTip;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool enabled() const {
|
||||||
|
return m_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEnabled(bool enabled) {
|
||||||
|
m_enabled = enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checked() const {
|
||||||
|
return m_checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setChecked(bool checked) {
|
||||||
|
m_checked = checked;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isEnabled() const {
|
||||||
|
return m_enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggle() {
|
||||||
|
m_enabled = !m_enabled;
|
||||||
|
Q_EMIT toggled(m_enabled);
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_SIGNALS:
|
||||||
|
bool toggled(bool);
|
||||||
|
private:
|
||||||
|
QString m_text;
|
||||||
|
QString m_toolTip;
|
||||||
|
|
||||||
|
bool m_isChecked = false;
|
||||||
|
bool m_isCheckable = false;
|
||||||
|
bool m_enabled = false;
|
||||||
|
bool m_checked = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
struct LastPositions;
|
struct LastPositions;
|
||||||
@@ -46,6 +117,7 @@ class TabWidget;
|
|||||||
class TitleBar;
|
class TitleBar;
|
||||||
class MainWindowBase;
|
class MainWindowBase;
|
||||||
class StateDragging;
|
class StateDragging;
|
||||||
|
class FrameQuick;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The DockWidget base-class. DockWidget and DockWidgetBase are only
|
* @brief The DockWidget base-class. DockWidget and DockWidgetBase are only
|
||||||
@@ -256,7 +328,7 @@ public:
|
|||||||
* @brief Like QWidget::close() but the hosted widget won't be asked if we
|
* @brief Like QWidget::close() but the hosted widget won't be asked if we
|
||||||
* should close.
|
* should close.
|
||||||
*/
|
*/
|
||||||
void forceClose();
|
Q_INVOKABLE void forceClose();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns this dock widget's title bar.
|
* @brief Returns this dock widget's title bar.
|
||||||
@@ -301,7 +373,7 @@ public:
|
|||||||
QStringList affinities() const;
|
QStringList affinities() const;
|
||||||
|
|
||||||
/// @brief Equivalent to QWidget::show(), but it's optimized to reduce flickering on some platforms
|
/// @brief Equivalent to QWidget::show(), but it's optimized to reduce flickering on some platforms
|
||||||
void show();
|
Q_INVOKABLE void show();
|
||||||
|
|
||||||
/// @brief Brings the dock widget to the front.
|
/// @brief Brings the dock widget to the front.
|
||||||
///
|
///
|
||||||
@@ -310,7 +382,7 @@ public:
|
|||||||
/// - If the dock widget is floating, QWindow::raise() is called.
|
/// - If the dock widget is floating, QWindow::raise() is called.
|
||||||
///
|
///
|
||||||
/// This only applies if the dock widget is already open. If closed, does nothing.
|
/// This only applies if the dock widget is already open. If closed, does nothing.
|
||||||
void raise();
|
Q_INVOKABLE void raise();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns whether widget() is a KDDockWidget::MainWindow
|
* @brief Returns whether widget() is a KDDockWidget::MainWindow
|
||||||
@@ -407,6 +479,14 @@ Q_SIGNALS:
|
|||||||
///Only relevant for the auto-hide/sidebar feature
|
///Only relevant for the auto-hide/sidebar feature
|
||||||
void removedFromSideBar();
|
void removedFromSideBar();
|
||||||
|
|
||||||
|
///@brief Emitted when the top-level window this dock widget is in is activated or deactivated
|
||||||
|
///This is convenience to replace tracking dockWidget->window(), since the window changes when
|
||||||
|
///docking and undocking
|
||||||
|
///
|
||||||
|
/// It's called 'aboutTo' because it's done in an event filter and the target window doesn't
|
||||||
|
/// have it's 'activeWindow' property updated yet at this point.
|
||||||
|
void windowActiveAboutToChange(bool activated);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onParentChanged();
|
void onParentChanged();
|
||||||
void onShown(bool spontaneous);
|
void onShown(bool spontaneous);
|
||||||
@@ -439,7 +519,7 @@ private:
|
|||||||
friend class MultiSplitter;
|
friend class MultiSplitter;
|
||||||
friend class Frame;
|
friend class Frame;
|
||||||
friend class DropArea;
|
friend class DropArea;
|
||||||
friend class TestDocks;
|
friend class ::TestDocks;
|
||||||
friend class StateDragging;
|
friend class StateDragging;
|
||||||
friend class KDDockWidgets::TabWidget;
|
friend class KDDockWidgets::TabWidget;
|
||||||
friend class KDDockWidgets::TitleBar;
|
friend class KDDockWidgets::TitleBar;
|
||||||
@@ -447,6 +527,7 @@ private:
|
|||||||
friend class KDDockWidgets::DockRegistry;
|
friend class KDDockWidgets::DockRegistry;
|
||||||
friend class KDDockWidgets::LayoutSaver;
|
friend class KDDockWidgets::LayoutSaver;
|
||||||
friend class KDDockWidgets::MainWindowBase;
|
friend class KDDockWidgets::MainWindowBase;
|
||||||
|
friend class KDDockWidgets::FrameQuick;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief the Frame which contains this dock widgets.
|
* @brief the Frame which contains this dock widgets.
|
||||||
@@ -478,6 +559,9 @@ private:
|
|||||||
///@brief Updates the floatAction state
|
///@brief Updates the floatAction state
|
||||||
void updateFloatAction();
|
void updateFloatAction();
|
||||||
|
|
||||||
|
///@reimp
|
||||||
|
bool eventFilter(QObject *, QEvent *) override;
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
Private *const d;
|
Private *const d;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ void DockWidgetQuick::setWidget(const QString &qmlFilename)
|
|||||||
setWidget(adapter);
|
setWidget(adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetQuick::setWidget(QWidgetOrQuick *widget)
|
void DockWidgetQuick::setWidget(QWidgetAdapter *widget)
|
||||||
{
|
{
|
||||||
widget->QWidgetAdapter::setParent(this);
|
widget->QWidgetAdapter::setParent(this);
|
||||||
QWidgetAdapter::makeItemFillParent(widget);
|
QWidgetAdapter::makeItemFillParent(widget);
|
||||||
@@ -87,3 +87,23 @@ bool DockWidgetQuick::event(QEvent *e)
|
|||||||
|
|
||||||
return DockWidgetBase::event(e);
|
return DockWidgetBase::event(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QSize DockWidgetQuick::minimumSize() const
|
||||||
|
{
|
||||||
|
if (QWidgetAdapter *guestWidget = widget()) {
|
||||||
|
// The guests min-size is the same as the widget's, there's no spacing or margins.
|
||||||
|
return guestWidget->minimumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DockWidgetBase::minimumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize DockWidgetQuick::maximumSize() const
|
||||||
|
{
|
||||||
|
if (QWidgetAdapter *guestWidget = widget()) {
|
||||||
|
// The guests max-size is the same as the widget's, there's no spacing or margins.
|
||||||
|
return guestWidget->maximumSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return DockWidgetBase::maximumSize();
|
||||||
|
}
|
||||||
@@ -55,7 +55,13 @@ public:
|
|||||||
void setWidget(const QString &qmlFilename);
|
void setWidget(const QString &qmlFilename);
|
||||||
|
|
||||||
/// @reimp
|
/// @reimp
|
||||||
void setWidget(QWidgetOrQuick *widget) override;
|
void setWidget(QWidgetAdapter *widget) override;
|
||||||
|
|
||||||
|
/// @reimp
|
||||||
|
QSize minimumSize() const override;
|
||||||
|
|
||||||
|
/// @reimp
|
||||||
|
QSize maximumSize() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool event(QEvent *e) override;
|
bool event(QEvent *e) override;
|
||||||
@@ -18,9 +18,12 @@
|
|||||||
|
|
||||||
#include "FocusScope.h"
|
#include "FocusScope.h"
|
||||||
#include "TitleBar_p.h"
|
#include "TitleBar_p.h"
|
||||||
|
#include "Frame_p.h"
|
||||||
|
#include "DockWidgetBase.h"
|
||||||
|
#include "DockRegistry_p.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QApplication>
|
#include <QGuiApplication>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
@@ -45,6 +48,7 @@ public:
|
|||||||
void setIsFocused(bool);
|
void setIsFocused(bool);
|
||||||
void onFocusObjectChanged(QObject *);
|
void onFocusObjectChanged(QObject *);
|
||||||
bool isInFocusScope(WidgetType *) const;
|
bool isInFocusScope(WidgetType *) const;
|
||||||
|
void emitDockWidgetFocusChanged();
|
||||||
|
|
||||||
FocusScope *const q;
|
FocusScope *const q;
|
||||||
QWidgetAdapter *const m_thisWidget;
|
QWidgetAdapter *const m_thisWidget;
|
||||||
@@ -101,6 +105,9 @@ void FocusScope::Private::setIsFocused(bool is)
|
|||||||
if (is != m_isFocused) {
|
if (is != m_isFocused) {
|
||||||
m_isFocused = is;
|
m_isFocused = is;
|
||||||
|
|
||||||
|
if (is)
|
||||||
|
emitDockWidgetFocusChanged();
|
||||||
|
|
||||||
if (!m_inCtor) // Hack so we don't call pure-virtual
|
if (!m_inCtor) // Hack so we don't call pure-virtual
|
||||||
Q_EMIT q->isFocusedChanged();
|
Q_EMIT q->isFocusedChanged();
|
||||||
}
|
}
|
||||||
@@ -109,16 +116,19 @@ void FocusScope::Private::setIsFocused(bool is)
|
|||||||
void FocusScope::Private::onFocusObjectChanged(QObject *obj)
|
void FocusScope::Private::onFocusObjectChanged(QObject *obj)
|
||||||
{
|
{
|
||||||
auto widget = qobject_cast<WidgetType*>(obj);
|
auto widget = qobject_cast<WidgetType*>(obj);
|
||||||
if (!widget)
|
if (!widget) {
|
||||||
|
setIsFocused(false);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
const bool is = isInFocusScope(widget);
|
const bool is = isInFocusScope(widget);
|
||||||
if (is && m_lastFocusedInScope != widget && !qobject_cast<TitleBar*>(obj)) {
|
if (is && m_lastFocusedInScope != widget && !qobject_cast<TitleBar*>(obj)) {
|
||||||
m_lastFocusedInScope = widget;
|
m_lastFocusedInScope = widget;
|
||||||
|
setIsFocused(is);
|
||||||
Q_EMIT q->focusedWidgetChanged();
|
Q_EMIT q->focusedWidgetChanged();
|
||||||
|
} else {
|
||||||
|
setIsFocused(is);
|
||||||
}
|
}
|
||||||
|
|
||||||
setIsFocused(is);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FocusScope::Private::isInFocusScope(WidgetType *widget) const
|
bool FocusScope::Private::isInFocusScope(WidgetType *widget) const
|
||||||
@@ -133,3 +143,33 @@ bool FocusScope::Private::isInFocusScope(WidgetType *widget) const
|
|||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FocusScope::Private::emitDockWidgetFocusChanged()
|
||||||
|
{
|
||||||
|
auto p = qobject_cast<WidgetType*>(qApp->focusObject());
|
||||||
|
if (!p) return;
|
||||||
|
|
||||||
|
// Find the nearest DockWidget and send the focusChangedSignal
|
||||||
|
while (p) {
|
||||||
|
if (auto frame = qobject_cast<Frame*>(p)) {
|
||||||
|
// Special case: The focused widget is inside the frame but not inside the dockwidget.
|
||||||
|
// For example, it's a line edit in the QTabBar. We still need to send the signal for
|
||||||
|
// the current dw in the tab group
|
||||||
|
if (auto dw = frame->currentDockWidget()) {
|
||||||
|
DockRegistry::self()->setFocusedDockWidget(dw);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (p == m_thisWidget)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (auto dw = qobject_cast<DockWidgetBase*>(p)) {
|
||||||
|
DockRegistry::self()->setFocusedDockWidget(dw);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = KDDockWidgets::Private::parentWidget(p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
namespace KDDockWidgets
|
namespace KDDockWidgets
|
||||||
{
|
{
|
||||||
///@brief Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets
|
///@brief Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets
|
||||||
class FocusScope
|
class DOCKS_EXPORT FocusScope
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
///@brief constructor
|
///@brief constructor
|
||||||
|
|||||||
@@ -16,9 +16,10 @@
|
|||||||
#include "FloatingWindow_p.h"
|
#include "FloatingWindow_p.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "indicators/ClassicIndicators_p.h"
|
#include "indicators/ClassicIndicators_p.h"
|
||||||
|
#include "indicators/NullIndicators_p.h"
|
||||||
|
#include "Utils_p.h"
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
# include "indicators/ClassicIndicators_p.h"
|
|
||||||
# include "widgets/TabWidget_p.h"
|
# include "widgets/TabWidget_p.h"
|
||||||
# include "widgets/FrameWidget_p.h"
|
# include "widgets/FrameWidget_p.h"
|
||||||
# include "widgets/TitleBarWidget_p.h"
|
# include "widgets/TitleBarWidget_p.h"
|
||||||
@@ -32,10 +33,11 @@
|
|||||||
# include <QRubberBand>
|
# include <QRubberBand>
|
||||||
# include <QToolButton>
|
# include <QToolButton>
|
||||||
#else
|
#else
|
||||||
|
# include "DockWidgetQuick.h"
|
||||||
# include "quick/FrameQuick_p.h"
|
# include "quick/FrameQuick_p.h"
|
||||||
# include "quick/DockWidgetQuick.h"
|
|
||||||
# include "quick/TitleBarQuick_p.h"
|
# include "quick/TitleBarQuick_p.h"
|
||||||
# include "quick/FloatingWindowQuick_p.h"
|
# include "quick/FloatingWindowQuick_p.h"
|
||||||
|
# include "quick/RubberBandQuick.h"
|
||||||
# include "multisplitter/Separator_quick.h"
|
# include "multisplitter/Separator_quick.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -90,11 +92,18 @@ FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWin
|
|||||||
|
|
||||||
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
|
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WASM
|
||||||
|
// On WASM windows don't support translucency, which is required for the classic indicators.
|
||||||
|
return new SegmentedIndicators(dropArea);
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (s_dropIndicatorType) {
|
switch (s_dropIndicatorType) {
|
||||||
case DropIndicatorType::Classic:
|
case DropIndicatorType::Classic:
|
||||||
return new ClassicIndicators(dropArea);
|
return new ClassicIndicators(dropArea);
|
||||||
case DropIndicatorType::Segmented:
|
case DropIndicatorType::Segmented:
|
||||||
return new SegmentedIndicators(dropArea);
|
return new SegmentedIndicators(dropArea);
|
||||||
|
case DropIndicatorType::None:
|
||||||
|
return new NullIndicators(dropArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ClassicIndicators(dropArea);
|
return new ClassicIndicators(dropArea);
|
||||||
@@ -157,6 +166,16 @@ FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWin
|
|||||||
|
|
||||||
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
|
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
|
||||||
{
|
{
|
||||||
|
switch (s_dropIndicatorType) {
|
||||||
|
case DropIndicatorType::Classic:
|
||||||
|
return new ClassicIndicators(dropArea);
|
||||||
|
case DropIndicatorType::Segmented:
|
||||||
|
qWarning() << "Segmented indicators not supported for QtQuick yet";
|
||||||
|
return new NullIndicators(dropArea);
|
||||||
|
case DropIndicatorType::None:
|
||||||
|
return new NullIndicators(dropArea);
|
||||||
|
}
|
||||||
|
|
||||||
return new ClassicIndicators(dropArea);
|
return new ClassicIndicators(dropArea);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -181,7 +200,7 @@ Layouting::Separator *DefaultWidgetFactory::createSeparator(Layouting::Widget *p
|
|||||||
|
|
||||||
QWidgetOrQuick *DefaultWidgetFactory::createRubberBand(QWidgetOrQuick *parent) const
|
QWidgetOrQuick *DefaultWidgetFactory::createRubberBand(QWidgetOrQuick *parent) const
|
||||||
{
|
{
|
||||||
return new QWidgetOrQuick(parent);
|
return new RubberBandQuick(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
SideBar *DefaultWidgetFactory::createSideBar(SideBarLocation loc, MainWindowBase *parent) const
|
SideBar *DefaultWidgetFactory::createSideBar(SideBarLocation loc, MainWindowBase *parent) const
|
||||||
@@ -193,6 +212,11 @@ SideBar *DefaultWidgetFactory::createSideBar(SideBarLocation loc, MainWindowBase
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QUrl DefaultWidgetFactory::titleBarFilename() const
|
||||||
|
{
|
||||||
|
return QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/TitleBar.qml"));
|
||||||
|
}
|
||||||
|
|
||||||
#endif // QtQuick
|
#endif // QtQuick
|
||||||
|
|
||||||
// iconForButtonType impl is the same for QtQuick and QtWidgets
|
// iconForButtonType impl is the same for QtQuick and QtWidgets
|
||||||
@@ -233,10 +257,11 @@ QIcon DefaultWidgetFactory::iconForButtonType(TitleBarButtonType type, qreal dpr
|
|||||||
const bool isFractional = int(dpr) != dpr;
|
const bool isFractional = int(dpr) != dpr;
|
||||||
if (isFractional) {
|
if (isFractional) {
|
||||||
// We don't support 1.5x yet.
|
// We don't support 1.5x yet.
|
||||||
// Linux is the only one affected as Windows and macOS use integral factors.
|
|
||||||
// Problem with Linux is that rendering is off due to a rounding bug only fixed in 5.15.2
|
// Problem with Linux is that rendering is off due to a rounding bug only fixed in 5.15.2
|
||||||
// Will enable for fractional later.
|
// Will enable for fractional later.
|
||||||
// QTBUG-86170
|
// QTBUG-86170
|
||||||
|
// Mostly affects Linux. Unless you're using Qt::HighDpiScaleFactorRoundingPolicy::PassThrough, in which case it will
|
||||||
|
// affect other OSes too.
|
||||||
return icon;
|
return icon;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|||||||
@@ -61,7 +61,12 @@ class TabBar;
|
|||||||
*
|
*
|
||||||
* @sa Config::setFrameworkWidgetFactory()
|
* @sa Config::setFrameworkWidgetFactory()
|
||||||
*/
|
*/
|
||||||
class DOCKS_EXPORT FrameworkWidgetFactory {
|
class DOCKS_EXPORT FrameworkWidgetFactory : public QObject
|
||||||
|
{
|
||||||
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
|
Q_PROPERTY(QUrl titleBarFilename READ titleBarFilename CONSTANT)
|
||||||
|
#endif
|
||||||
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
FrameworkWidgetFactory() = default;
|
FrameworkWidgetFactory() = default;
|
||||||
|
|
||||||
@@ -134,10 +139,10 @@ public:
|
|||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
///@brief Called internally by the framework to create a title bar button
|
///@brief Called internally by the framework to create a title bar button
|
||||||
///@parent the button's parent
|
///@p parent the button's parent
|
||||||
virtual QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const = 0;
|
virtual QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const = 0;
|
||||||
#else
|
#else
|
||||||
// QtQuick will have some other base class for buttons
|
virtual QUrl titleBarFilename() const = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// @brief Returns the icon to be used with the specified @p type
|
/// @brief Returns the icon to be used with the specified @p type
|
||||||
@@ -168,6 +173,8 @@ public:
|
|||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const override;
|
QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const override;
|
||||||
|
#else
|
||||||
|
QUrl titleBarFilename() const override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const override;
|
QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const override;
|
||||||
|
|||||||
@@ -19,15 +19,15 @@
|
|||||||
#ifndef KD_KDDOCKWIDGETS_H
|
#ifndef KD_KDDOCKWIDGETS_H
|
||||||
#define KD_KDDOCKWIDGETS_H
|
#define KD_KDDOCKWIDGETS_H
|
||||||
|
|
||||||
|
#include "Qt5Qt6Compat_p.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
// Only on Windows, where this is popular. On linux it the Qt::Tool windows need reparenting. Untested on macOS.
|
// Only on Windows, where this is popular. On linux the Qt::Tool windows need reparenting. Untested on macOS.
|
||||||
# define KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
# define KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace KDDockWidgets
|
namespace KDDockWidgets
|
||||||
{
|
{
|
||||||
enum Location {
|
enum Location {
|
||||||
@@ -76,7 +76,8 @@ namespace KDDockWidgets
|
|||||||
|
|
||||||
enum class DropIndicatorType {
|
enum class DropIndicatorType {
|
||||||
Classic, ///< The default
|
Classic, ///< The default
|
||||||
Segmented
|
Segmented, ///< Segmented indicators
|
||||||
|
None ///< Don't show any drop indicators while dragging
|
||||||
};
|
};
|
||||||
|
|
||||||
///@internal
|
///@internal
|
||||||
@@ -119,7 +120,7 @@ namespace KDDockWidgets
|
|||||||
};
|
};
|
||||||
|
|
||||||
///@internal
|
///@internal
|
||||||
inline uint qHash(SideBarLocation loc, uint seed)
|
inline Qt5Qt6Compat::qhashtype qHash(SideBarLocation loc, Qt5Qt6Compat::qhashtype seed)
|
||||||
{
|
{
|
||||||
return ::qHash(static_cast<uint>(loc), seed);
|
return ::qHash(static_cast<uint>(loc), seed);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,11 +28,11 @@
|
|||||||
#include "multisplitter/Item_p.h"
|
#include "multisplitter/Item_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "MainWindowBase.h"
|
#include "MainWindowBase.h"
|
||||||
|
#include "FloatingWindow_p.h"
|
||||||
|
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
#include <QApplication>
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -700,6 +700,12 @@ QVariantMap LayoutSaver::MainWindow::toVariantMap() const
|
|||||||
map.insert(QStringLiteral("isVisible"), isVisible);
|
map.insert(QStringLiteral("isVisible"), isVisible);
|
||||||
map.insert(QStringLiteral("affinities"), stringListToVariant(affinities));
|
map.insert(QStringLiteral("affinities"), stringListToVariant(affinities));
|
||||||
|
|
||||||
|
for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) {
|
||||||
|
const QStringList dockWidgets = dockWidgetsPerSideBar.value(loc);
|
||||||
|
if (!dockWidgets.isEmpty())
|
||||||
|
map.insert(QStringLiteral("sidebar-%1").arg(int(loc)), stringListToVariant(dockWidgets));
|
||||||
|
}
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -720,6 +726,13 @@ void LayoutSaver::MainWindow::fromVariantMap(const QVariantMap &map)
|
|||||||
affinities.push_back(affinityName);
|
affinities.push_back(affinityName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Load the SideBars:
|
||||||
|
dockWidgetsPerSideBar.clear();
|
||||||
|
for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) {
|
||||||
|
const QVariantList dockWidgets = map.value(QStringLiteral("sidebar-%1").arg(int(loc))).toList();
|
||||||
|
if (!dockWidgets.isEmpty())
|
||||||
|
dockWidgetsPerSideBar.insert(loc, variantToStringList(dockWidgets));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutSaver::MultiSplitter::isValid() const
|
bool LayoutSaver::MultiSplitter::isValid() const
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ QT_BEGIN_NAMESPACE
|
|||||||
class QByteArray;
|
class QByteArray;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class TestDocks;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class DockWidgetBase;
|
class DockWidgetBase;
|
||||||
@@ -105,7 +107,7 @@ public:
|
|||||||
struct ScreenInfo;
|
struct ScreenInfo;
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(LayoutSaver)
|
Q_DISABLE_COPY(LayoutSaver)
|
||||||
friend class TestDocks;
|
friend class ::TestDocks;
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
Private *const d;
|
Private *const d;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
#include <QRect>
|
#include <QRect>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QApplication>
|
#include <QGuiApplication>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
@@ -236,6 +236,7 @@ public:
|
|||||||
QVariantMap toVariantMap() const;
|
QVariantMap toVariantMap() const;
|
||||||
void fromVariantMap(const QVariantMap &map);
|
void fromVariantMap(const QVariantMap &map);
|
||||||
|
|
||||||
|
QHash<SideBarLocation, QStringList> dockWidgetsPerSideBar;
|
||||||
KDDockWidgets::MainWindowOptions options;
|
KDDockWidgets::MainWindowOptions options;
|
||||||
LayoutSaver::MultiSplitter multiSplitterLayout;
|
LayoutSaver::MultiSplitter multiSplitterLayout;
|
||||||
QString uniqueName;
|
QString uniqueName;
|
||||||
|
|||||||
@@ -25,7 +25,6 @@
|
|||||||
#include "DropAreaWithCentralFrame_p.h"
|
#include "DropAreaWithCentralFrame_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
@@ -99,8 +98,6 @@ MainWindow::MainWindow(const QString &name, MainWindowOptions options,
|
|||||||
}
|
}
|
||||||
|
|
||||||
setCentralWidget(centralWidget);
|
setCentralWidget(centralWidget);
|
||||||
|
|
||||||
// qApp->installEventFilter(this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindow::~MainWindow()
|
MainWindow::~MainWindow()
|
||||||
|
|||||||
@@ -48,6 +48,7 @@ public:
|
|||||||
QRect rectForOverlay(Frame *, SideBarLocation) const;
|
QRect rectForOverlay(Frame *, SideBarLocation) const;
|
||||||
SideBarLocation preferredSideBar(DockWidgetBase *) const;
|
SideBarLocation preferredSideBar(DockWidgetBase *) const;
|
||||||
void updateOverlayGeometry();
|
void updateOverlayGeometry();
|
||||||
|
void clearSideBars();
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
QStringList affinities;
|
QStringList affinities;
|
||||||
@@ -337,6 +338,15 @@ void MainWindowBase::Private::updateOverlayGeometry()
|
|||||||
m_overlayedDockWidget->frame()->QWidgetAdapter::setGeometry(rectForOverlay(m_overlayedDockWidget->frame(), sb->location()));
|
m_overlayedDockWidget->frame()->QWidgetAdapter::setGeometry(rectForOverlay(m_overlayedDockWidget->frame(), sb->location()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::Private::clearSideBars()
|
||||||
|
{
|
||||||
|
for (auto loc : { SideBarLocation::North, SideBarLocation::South,
|
||||||
|
SideBarLocation::East, SideBarLocation::West }) {
|
||||||
|
if (SideBar *sb = q->sideBar(loc))
|
||||||
|
sb->clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindowBase::moveToSideBar(DockWidgetBase *dw)
|
void MainWindowBase::moveToSideBar(DockWidgetBase *dw)
|
||||||
{
|
{
|
||||||
moveToSideBar(dw, d->preferredSideBar(dw));
|
moveToSideBar(dw, d->preferredSideBar(dw));
|
||||||
@@ -401,7 +411,7 @@ void MainWindowBase::overlayOnSideBar(DockWidgetBase *dw)
|
|||||||
void MainWindowBase::toggleOverlayOnSideBar(DockWidgetBase *dw)
|
void MainWindowBase::toggleOverlayOnSideBar(DockWidgetBase *dw)
|
||||||
{
|
{
|
||||||
const bool wasOverlayed = d->m_overlayedDockWidget == dw;
|
const bool wasOverlayed = d->m_overlayedDockWidget == dw;
|
||||||
clearSideBarOverlay();
|
clearSideBarOverlay(); // Because only 1 dock widget can be overlayed each time
|
||||||
if (!wasOverlayed) {
|
if (!wasOverlayed) {
|
||||||
overlayOnSideBar(dw);
|
overlayOnSideBar(dw);
|
||||||
}
|
}
|
||||||
@@ -425,7 +435,7 @@ SideBar *MainWindowBase::sideBarForDockWidget(const DockWidgetBase *dw) const
|
|||||||
SideBarLocation::East, SideBarLocation::West }) {
|
SideBarLocation::East, SideBarLocation::West }) {
|
||||||
|
|
||||||
if (SideBar *sb = sideBar(loc)) {
|
if (SideBar *sb = sideBar(loc)) {
|
||||||
if (sb->contains(const_cast<DockWidgetBase *>(dw)))
|
if (sb->containsDockWidget(const_cast<DockWidgetBase *>(dw)))
|
||||||
return sb;
|
return sb;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -440,8 +450,20 @@ DockWidgetBase *MainWindowBase::overlayedDockWidget() const
|
|||||||
|
|
||||||
bool MainWindowBase::sideBarIsVisible(SideBarLocation loc) const
|
bool MainWindowBase::sideBarIsVisible(SideBarLocation loc) const
|
||||||
{
|
{
|
||||||
if (SideBar *sb = sideBar(loc))
|
if (SideBar *sb = sideBar(loc)) {
|
||||||
return sb->isVisible();
|
return !sb->isEmpty(); // isVisible() is always true, but its height is 0 when empty.
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindowBase::anySideBarIsVisible() const
|
||||||
|
{
|
||||||
|
for (auto loc : { SideBarLocation::North, SideBarLocation::South,
|
||||||
|
SideBarLocation::East, SideBarLocation::West }) {
|
||||||
|
if (sideBarIsVisible(loc))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -481,7 +503,34 @@ bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
|
|||||||
d->affinities = mw.affinities;
|
d->affinities = mw.affinities;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dropArea()->deserialize(mw.multiSplitterLayout);
|
const bool success = dropArea()->deserialize(mw.multiSplitterLayout);
|
||||||
|
|
||||||
|
// Restore the SideBars
|
||||||
|
d->clearSideBars();
|
||||||
|
for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) {
|
||||||
|
SideBar *sb = sideBar(loc);
|
||||||
|
if (!sb)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
const QStringList dockWidgets = mw.dockWidgetsPerSideBar.value(loc);
|
||||||
|
for (const QString &uniqueName : dockWidgets) {
|
||||||
|
|
||||||
|
DockWidgetBase *dw = DockRegistry::self()->dockByName(uniqueName);
|
||||||
|
if (!dw) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Could not find dock widget" << uniqueName
|
||||||
|
<< ". Won't restore it to sidebar";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb->addDockWidget(dw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commented-out for now, we dont' want to restore the popup/overlay. popups are perishable
|
||||||
|
//if (!mw.overlayedDockWidget.isEmpty())
|
||||||
|
// overlayOnSideBar(DockRegistry::self()->dockByName(mw.overlayedDockWidget));
|
||||||
|
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutSaver::MainWindow MainWindowBase::serialize() const
|
LayoutSaver::MainWindow MainWindowBase::serialize() const
|
||||||
@@ -497,5 +546,13 @@ LayoutSaver::MainWindow MainWindowBase::serialize() const
|
|||||||
m.multiSplitterLayout = dropArea()->serialize();
|
m.multiSplitterLayout = dropArea()->serialize();
|
||||||
m.affinities = d->affinities;
|
m.affinities = d->affinities;
|
||||||
|
|
||||||
|
for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) {
|
||||||
|
if (SideBar *sb = sideBar(loc)) {
|
||||||
|
const QStringList dockwidgets = sb->serialize();
|
||||||
|
if (!dockwidgets.isEmpty())
|
||||||
|
m.dockWidgetsPerSideBar.insert(loc, dockwidgets);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QMargins>
|
#include <QMargins>
|
||||||
|
|
||||||
|
class TestDocks;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class DockWidgetBase;
|
class DockWidgetBase;
|
||||||
@@ -166,6 +168,9 @@ public:
|
|||||||
/// @brief Returns whether the specified sidebar is visible
|
/// @brief Returns whether the specified sidebar is visible
|
||||||
bool sideBarIsVisible(SideBarLocation) const;
|
bool sideBarIsVisible(SideBarLocation) const;
|
||||||
|
|
||||||
|
/// @brief Returns whether any side bar is visible
|
||||||
|
bool anySideBarIsVisible() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setUniqueName(const QString &uniqueName);
|
void setUniqueName(const QString &uniqueName);
|
||||||
void onResized(QResizeEvent *); // Because QtQuick doesn't have resizeEvent()
|
void onResized(QResizeEvent *); // Because QtQuick doesn't have resizeEvent()
|
||||||
@@ -180,6 +185,7 @@ private:
|
|||||||
class Private;
|
class Private;
|
||||||
Private *const d;
|
Private *const d;
|
||||||
|
|
||||||
|
friend class ::TestDocks;
|
||||||
friend class LayoutSaver;
|
friend class LayoutSaver;
|
||||||
bool deserialize(const LayoutSaver::MainWindow &);
|
bool deserialize(const LayoutSaver::MainWindow &);
|
||||||
LayoutSaver::MainWindow serialize() const;
|
LayoutSaver::MainWindow serialize() const;
|
||||||
|
|||||||
@@ -13,20 +13,39 @@
|
|||||||
#define KDDOCKWIDGETS_QT5QT6_COMPAT_P_H
|
#define KDDOCKWIDGETS_QT5QT6_COMPAT_P_H
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
|
#include <QDropEvent>
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
namespace Qt5Qt6Compat {
|
namespace Qt5Qt6Compat {
|
||||||
|
|
||||||
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
|
||||||
|
using QEnterEvent = QEnterEvent;
|
||||||
|
using qintptr = ::qintptr;
|
||||||
|
using qhashtype = size_t;
|
||||||
|
|
||||||
|
inline QPoint eventPos(QDropEvent *ev)
|
||||||
|
{
|
||||||
|
return ev->position().toPoint();
|
||||||
|
}
|
||||||
|
|
||||||
inline QPoint eventGlobalPos(QMouseEvent *ev)
|
inline QPoint eventGlobalPos(QMouseEvent *ev)
|
||||||
{
|
{
|
||||||
return ev->globalPosition().toPoint();
|
return ev->globalPosition().toPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
// Qt 5:
|
// Qt 5:
|
||||||
|
|
||||||
|
using QEnterEvent = QEvent;
|
||||||
|
using qintptr = long;
|
||||||
|
using qhashtype = uint;
|
||||||
|
|
||||||
|
inline QPoint eventPos(QDropEvent *ev)
|
||||||
|
{
|
||||||
|
return ev->pos();
|
||||||
|
}
|
||||||
|
|
||||||
inline QPoint eventGlobalPos(QMouseEvent *ev)
|
inline QPoint eventGlobalPos(QMouseEvent *ev)
|
||||||
{
|
{
|
||||||
return ev->globalPos();
|
return ev->globalPos();
|
||||||
|
|||||||
12
src/fwd_headers/kddockwidgets/DockWidgetBase.h
Normal file
12
src/fwd_headers/kddockwidgets/DockWidgetBase.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../DockWidgetBase.h"
|
||||||
12
src/fwd_headers/kddockwidgets/DockWidgetQuick.h
Normal file
12
src/fwd_headers/kddockwidgets/DockWidgetQuick.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../DockWidgetQuick.h"
|
||||||
12
src/fwd_headers/kddockwidgets/FocusScope.h
Normal file
12
src/fwd_headers/kddockwidgets/FocusScope.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../FocusScope.h"
|
||||||
12
src/fwd_headers/kddockwidgets/MainWindowBase.h
Normal file
12
src/fwd_headers/kddockwidgets/MainWindowBase.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../MainWindowBase.h"
|
||||||
12
src/fwd_headers/kddockwidgets/QWidgetAdapter.h
Normal file
12
src/fwd_headers/kddockwidgets/QWidgetAdapter.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../QWidgetAdapter.h"
|
||||||
12
src/fwd_headers/kddockwidgets/Qt5Qt6Compat_p.h
Normal file
12
src/fwd_headers/kddockwidgets/Qt5Qt6Compat_p.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../Qt5Qt6Compat_p.h"
|
||||||
12
src/fwd_headers/kddockwidgets/docks_export.h
Normal file
12
src/fwd_headers/kddockwidgets/docks_export.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../docks_export.h"
|
||||||
12
src/fwd_headers/kddockwidgets/private/DockRegistry_p.h
Normal file
12
src/fwd_headers/kddockwidgets/private/DockRegistry_p.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../private/DockRegistry_p.h"
|
||||||
@@ -4,10 +4,14 @@
|
|||||||
<file>private/quick/qml/DropArea.qml</file>
|
<file>private/quick/qml/DropArea.qml</file>
|
||||||
<file>private/quick/qml/FloatingWindow.qml</file>
|
<file>private/quick/qml/FloatingWindow.qml</file>
|
||||||
<file>private/quick/qml/Frame.qml</file>
|
<file>private/quick/qml/Frame.qml</file>
|
||||||
|
<file>private/quick/qml/RubberBand.qml</file>
|
||||||
<file>private/quick/qml/TitleBarBase.qml</file>
|
<file>private/quick/qml/TitleBarBase.qml</file>
|
||||||
<file>private/quick/qml/TitleBar.qml</file>
|
<file>private/quick/qml/TitleBar.qml</file>
|
||||||
<file>private/quick/qml/TitleBarButton.qml</file>
|
<file>private/quick/qml/TitleBarButton.qml</file>
|
||||||
<file>private/quick/qml/ClassicIndicatorsOverlay.qml</file>
|
<file>private/quick/qml/ClassicIndicatorsOverlay.qml</file>
|
||||||
<file>private/quick/qml/ClassicIndicator.qml</file>
|
<file>private/quick/qml/ClassicIndicator.qml</file>
|
||||||
</qresource>
|
</qresource>
|
||||||
|
<qresource prefix="/kddockwidgets/multisplitter/">
|
||||||
|
<file>private/multisplitter/qml/Separator.qml</file>
|
||||||
|
</qresource>
|
||||||
</RCC>
|
</RCC>
|
||||||
@@ -18,10 +18,11 @@
|
|||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "SideBar_p.h"
|
#include "SideBar_p.h"
|
||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
|
#include "FloatingWindow_p.h"
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QApplication>
|
#include <QGuiApplication>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
@@ -34,8 +35,11 @@ using namespace KDDockWidgets;
|
|||||||
|
|
||||||
static void initKDDockWidgetResources()
|
static void initKDDockWidgetResources()
|
||||||
{
|
{
|
||||||
#ifdef KDDOCKWIDGETS_STATICLIB
|
#if defined(KDDOCKWIDGETS_STATICLIB) || defined(QT_STATIC)
|
||||||
Q_INIT_RESOURCE(resources);
|
Q_INIT_RESOURCE(kddockwidgets_resources);
|
||||||
|
# if defined(KDDOCKWIDGETS_QTQUICK)
|
||||||
|
Q_INIT_RESOURCE(kddockwidgets_qtquick);
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,6 +58,7 @@ DockRegistry::DockRegistry(QObject *parent)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
KDDockWidgets::registerQmlTypes();
|
KDDockWidgets::registerQmlTypes();
|
||||||
|
QQuickWindow::setDefaultAlphaBuffer(true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
connect(qApp, &QGuiApplication::focusObjectChanged,
|
connect(qApp, &QGuiApplication::focusObjectChanged,
|
||||||
@@ -74,28 +79,27 @@ void DockRegistry::maybeDelete()
|
|||||||
|
|
||||||
void DockRegistry::onFocusObjectChanged(QObject *obj)
|
void DockRegistry::onFocusObjectChanged(QObject *obj)
|
||||||
{
|
{
|
||||||
DockWidgetBase *const unfocusedDW = m_focusedDockWidget.data();
|
// In this function we reset the focused dock widget.
|
||||||
DockWidgetBase *newFocusedDockWidget = nullptr;
|
|
||||||
|
|
||||||
// Check if it's inside a dock widget:
|
|
||||||
auto p = qobject_cast<WidgetType*>(obj);
|
auto p = qobject_cast<WidgetType*>(obj);
|
||||||
while (p) {
|
while (p) {
|
||||||
if (auto dw = qobject_cast<DockWidgetBase*>(p)) {
|
if (qobject_cast<DockWidgetBase*>(p) || qobject_cast<Frame*>(p))
|
||||||
newFocusedDockWidget = dw;
|
return;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = KDDockWidgets::Private::parentWidget(p);
|
p = KDDockWidgets::Private::parentWidget(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Nothing changed
|
setFocusedDockWidget(nullptr);
|
||||||
if (m_focusedDockWidget.data() == newFocusedDockWidget)
|
}
|
||||||
|
|
||||||
|
void DockRegistry::setFocusedDockWidget(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
if (m_focusedDockWidget.data() == dw)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_focusedDockWidget = newFocusedDockWidget;
|
if (m_focusedDockWidget)
|
||||||
|
Q_EMIT m_focusedDockWidget->isFocusedChanged(false);
|
||||||
|
|
||||||
if (unfocusedDW)
|
m_focusedDockWidget = dw;
|
||||||
Q_EMIT unfocusedDW->isFocusedChanged(false);
|
|
||||||
|
|
||||||
if (m_focusedDockWidget)
|
if (m_focusedDockWidget)
|
||||||
Q_EMIT m_focusedDockWidget->isFocusedChanged(true);
|
Q_EMIT m_focusedDockWidget->isFocusedChanged(true);
|
||||||
@@ -328,6 +332,11 @@ void DockRegistry::unregisterFrame(Frame *frame)
|
|||||||
m_frames.removeOne(frame);
|
m_frames.removeOne(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockRegistry::containsDockWidget(const QString &uniqueName) const
|
||||||
|
{
|
||||||
|
return dockByName(uniqueName) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
DockWidgetBase *DockRegistry::dockByName(const QString &name) const
|
DockWidgetBase *DockRegistry::dockByName(const QString &name) const
|
||||||
{
|
{
|
||||||
for (auto dock : qAsConst(m_dockWidgets)) {
|
for (auto dock : qAsConst(m_dockWidgets)) {
|
||||||
@@ -504,6 +513,37 @@ FloatingWindow *DockRegistry::floatingWindowForHandle(QWindow *windowHandle) con
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FloatingWindow *DockRegistry::floatingWindowForHandle(WId hwnd) const
|
||||||
|
{
|
||||||
|
for (FloatingWindow *fw : m_floatingWindows) {
|
||||||
|
if (fw->windowHandle() && fw->windowHandle()->winId() == hwnd)
|
||||||
|
return fw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowBase *DockRegistry::mainWindowForHandle(QWindow *windowHandle) const
|
||||||
|
{
|
||||||
|
for (MainWindowBase *mw : m_mainWindows) {
|
||||||
|
if (mw->windowHandle() == windowHandle)
|
||||||
|
return mw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QWidgetOrQuick *DockRegistry::topLevelForHandle(QWindow *windowHandle) const
|
||||||
|
{
|
||||||
|
if (auto fw = floatingWindowForHandle(windowHandle))
|
||||||
|
return fw;
|
||||||
|
|
||||||
|
if (auto mw = mainWindowForHandle(windowHandle))
|
||||||
|
return mw;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
QVector<QWindow *> DockRegistry::topLevels(bool excludeFloatingDocks) const
|
QVector<QWindow *> DockRegistry::topLevels(bool excludeFloatingDocks) const
|
||||||
{
|
{
|
||||||
QVector<QWindow *> windows;
|
QVector<QWindow *> windows;
|
||||||
|
|||||||
@@ -12,9 +12,8 @@
|
|||||||
#ifndef KD_DOCKREGISTRY_P_H
|
#ifndef KD_DOCKREGISTRY_P_H
|
||||||
#define KD_DOCKREGISTRY_P_H
|
#define KD_DOCKREGISTRY_P_H
|
||||||
|
|
||||||
#include "DockWidgetBase.h"
|
#include "../DockWidgetBase.h"
|
||||||
#include "MainWindowBase.h"
|
#include "../MainWindowBase.h"
|
||||||
#include "FloatingWindow_p.h"
|
|
||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@@ -28,7 +27,10 @@
|
|||||||
namespace KDDockWidgets
|
namespace KDDockWidgets
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class FloatingWindow;
|
||||||
|
class Frame;
|
||||||
class SideBar;
|
class SideBar;
|
||||||
|
struct WindowBeingDragged;
|
||||||
|
|
||||||
class DOCKS_EXPORT DockRegistry : public QObject
|
class DOCKS_EXPORT DockRegistry : public QObject
|
||||||
{
|
{
|
||||||
@@ -53,6 +55,7 @@ public:
|
|||||||
|
|
||||||
DockWidgetBase *focusedDockWidget() const;
|
DockWidgetBase *focusedDockWidget() const;
|
||||||
|
|
||||||
|
bool containsDockWidget(const QString &uniqueName) const;
|
||||||
DockWidgetBase *dockByName(const QString &) const;
|
DockWidgetBase *dockByName(const QString &) const;
|
||||||
MainWindowBase *mainWindowByName(const QString &) const;
|
MainWindowBase *mainWindowByName(const QString &) const;
|
||||||
|
|
||||||
@@ -80,7 +83,7 @@ public:
|
|||||||
const QVector<MultiSplitter*> layouts() const;
|
const QVector<MultiSplitter*> layouts() const;
|
||||||
|
|
||||||
///@brief returns a list of all Frame instances
|
///@brief returns a list of all Frame instances
|
||||||
const Frame::List frames() const;
|
const QList<Frame*> frames() const;
|
||||||
|
|
||||||
///@brief returns all FloatingWindow instances. Not necessarily all floating dock widgets,
|
///@brief returns all FloatingWindow instances. Not necessarily all floating dock widgets,
|
||||||
/// As there might be DockWidgets which weren't morphed yet.
|
/// As there might be DockWidgets which weren't morphed yet.
|
||||||
@@ -95,6 +98,17 @@ public:
|
|||||||
///@brief returns the FloatingWindow with handle @p windowHandle
|
///@brief returns the FloatingWindow with handle @p windowHandle
|
||||||
FloatingWindow *floatingWindowForHandle(QWindow *windowHandle) const;
|
FloatingWindow *floatingWindowForHandle(QWindow *windowHandle) const;
|
||||||
|
|
||||||
|
///@brief returns the FloatingWindow with handle @p hwnd
|
||||||
|
FloatingWindow *floatingWindowForHandle(WId hwnd) const;
|
||||||
|
|
||||||
|
///@brief returns the MainWindow with handle @p windowHandle
|
||||||
|
MainWindowBase *mainWindowForHandle(QWindow *windowHandle) const;
|
||||||
|
|
||||||
|
///@brief returns the top level widget associated with the specified QWindow.
|
||||||
|
///For QtWidgets, it returns a QWidget which is either a KDDockWidgets::MainWindow or a FloatingWindow.
|
||||||
|
///For QtQuick ir returns the same, but the type is a QWidgetAdapter (a QQuickItem), not QWidget obviously.
|
||||||
|
QWidgetOrQuick *topLevelForHandle(QWindow *windowHandle) const;
|
||||||
|
|
||||||
///@brief Returns the list with all visiblye top-level parents of our FloatingWindow and MainWindow instances.
|
///@brief Returns the list with all visiblye top-level parents of our FloatingWindow and MainWindow instances.
|
||||||
///
|
///
|
||||||
/// Typically these are the FloatingWindows and MainWindows themselves. However, since a
|
/// Typically these are the FloatingWindows and MainWindows themselves. However, since a
|
||||||
@@ -193,14 +207,17 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||||
private:
|
private:
|
||||||
|
friend class FocusScope;
|
||||||
explicit DockRegistry(QObject *parent = nullptr);
|
explicit DockRegistry(QObject *parent = nullptr);
|
||||||
void onDockWidgetPressed(DockWidgetBase *dw);
|
void onDockWidgetPressed(DockWidgetBase *dw);
|
||||||
|
void onFocusObjectChanged(QObject *obj);
|
||||||
void maybeDelete();
|
void maybeDelete();
|
||||||
void onFocusObjectChanged(QObject *);
|
void setFocusedDockWidget(DockWidgetBase *);
|
||||||
|
|
||||||
bool m_isProcessingAppQuitEvent = false;
|
bool m_isProcessingAppQuitEvent = false;
|
||||||
DockWidgetBase::List m_dockWidgets;
|
DockWidgetBase::List m_dockWidgets;
|
||||||
MainWindowBase::List m_mainWindows;
|
MainWindowBase::List m_mainWindows;
|
||||||
Frame::List m_frames;
|
QList<Frame*> m_frames;
|
||||||
QVector<FloatingWindow*> m_floatingWindows;
|
QVector<FloatingWindow*> m_floatingWindows;
|
||||||
QVector<MultiSplitter*> m_layouts;
|
QVector<MultiSplitter*> m_layouts;
|
||||||
QPointer<DockWidgetBase> m_focusedDockWidget;
|
QPointer<DockWidgetBase> m_focusedDockWidget;
|
||||||
|
|||||||
@@ -20,9 +20,11 @@
|
|||||||
#include "Qt5Qt6Compat_p.h"
|
#include "Qt5Qt6Compat_p.h"
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QApplication>
|
#include <QGuiApplication>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
#include <QDrag>
|
||||||
|
#include <QScopedValueRollback>
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
# include <QWindow>
|
# include <QWindow>
|
||||||
@@ -32,7 +34,7 @@
|
|||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
///@brief Custom mouse grabber, as platforms like wayland don't support grabbing the mouse
|
///@brief Custom mouse grabber, for platforms that don't support grabbing the mouse
|
||||||
class FallbackMouseGrabber : public QObject /// clazy:exclude=missing-qobject-macro
|
class FallbackMouseGrabber : public QObject /// clazy:exclude=missing-qobject-macro
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -51,6 +53,20 @@ public:
|
|||||||
|
|
||||||
void releaseMouse()
|
void releaseMouse()
|
||||||
{
|
{
|
||||||
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
|
// Ungrab harder if QtQuick.
|
||||||
|
// QtQuick has the habit og grabbing the MouseArea internally, then doesn't ungrab it since
|
||||||
|
// we're consuming the events. So explicitly ungrab if any QQuickWindow::mouseGrabberItem()
|
||||||
|
// is still set.
|
||||||
|
|
||||||
|
QQuickView *view = m_target ? m_target->quickView()
|
||||||
|
: nullptr;
|
||||||
|
QQuickItem *grabber = view ? view->mouseGrabberItem()
|
||||||
|
: nullptr;
|
||||||
|
if (grabber)
|
||||||
|
grabber->ungrabMouse();
|
||||||
|
#endif
|
||||||
|
|
||||||
m_target = nullptr;
|
m_target = nullptr;
|
||||||
qApp->removeEventFilter(this);
|
qApp->removeEventFilter(this);
|
||||||
}
|
}
|
||||||
@@ -60,14 +76,9 @@ public:
|
|||||||
if (m_reentrancyGuard || !m_target)
|
if (m_reentrancyGuard || !m_target)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (ev->type() == QEvent::MouseButtonPress ||
|
if (QMouseEvent *me = mouseEvent(ev)) {
|
||||||
ev->type() == QEvent::MouseButtonRelease ||
|
|
||||||
ev->type() == QEvent::MouseMove ||
|
|
||||||
ev->type() == QEvent::NonClientAreaMouseButtonPress ||
|
|
||||||
ev->type() == QEvent::NonClientAreaMouseButtonRelease ||
|
|
||||||
ev->type() == QEvent::NonClientAreaMouseMove) {
|
|
||||||
m_reentrancyGuard = true;
|
m_reentrancyGuard = true;
|
||||||
qApp->sendEvent(m_target, ev);
|
qApp->sendEvent(m_target, me);
|
||||||
m_reentrancyGuard = false;
|
m_reentrancyGuard = false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -83,8 +94,51 @@ FallbackMouseGrabber::~FallbackMouseGrabber() {}
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
State::State(MinimalStateMachine *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
, m_machine(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
State::~State() = default;
|
||||||
|
|
||||||
|
bool State::isCurrentState() const
|
||||||
|
{
|
||||||
|
return m_machine->currentState() == this;
|
||||||
|
}
|
||||||
|
|
||||||
|
MinimalStateMachine::MinimalStateMachine(QObject *parent)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Obj, typename Signal>
|
||||||
|
void State::addTransition(Obj *obj, Signal signal, State *dest)
|
||||||
|
{
|
||||||
|
connect(obj, signal, this, [this, dest] {
|
||||||
|
if (isCurrentState()) {
|
||||||
|
m_machine->setCurrentState(dest);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
State *MinimalStateMachine::currentState() const
|
||||||
|
{
|
||||||
|
return m_currentState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MinimalStateMachine::setCurrentState(State *state)
|
||||||
|
{
|
||||||
|
if (state != m_currentState) {
|
||||||
|
m_currentState = state;
|
||||||
|
if (state)
|
||||||
|
state->onEntry();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
StateBase::StateBase(DragController *parent)
|
StateBase::StateBase(DragController *parent)
|
||||||
: QState(parent)
|
: State(parent)
|
||||||
, q(parent)
|
, q(parent)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -101,7 +155,7 @@ StateNone::StateNone(DragController *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void StateNone::onEntry(QEvent *)
|
void StateNone::onEntry()
|
||||||
{
|
{
|
||||||
qCDebug(state) << "StateNone entered";
|
qCDebug(state) << "StateNone entered";
|
||||||
q->m_pressPos = QPoint();
|
q->m_pressPos = QPoint();
|
||||||
@@ -142,7 +196,7 @@ StatePreDrag::StatePreDrag(DragController *parent)
|
|||||||
|
|
||||||
StatePreDrag::~StatePreDrag() = default;
|
StatePreDrag::~StatePreDrag() = default;
|
||||||
|
|
||||||
void StatePreDrag::onEntry(QEvent *)
|
void StatePreDrag::onEntry()
|
||||||
{
|
{
|
||||||
qCDebug(state) << "StatePreDrag entered";
|
qCDebug(state) << "StatePreDrag entered";
|
||||||
WidgetResizeHandler::s_disableAllHandlers = true; // Disable the resize handler during dragging
|
WidgetResizeHandler::s_disableAllHandlers = true; // Disable the resize handler during dragging
|
||||||
@@ -163,6 +217,15 @@ bool StatePreDrag::handleMouseButtonRelease(QPoint)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StatePreDrag::handleMouseDoubleClick()
|
||||||
|
{
|
||||||
|
// This is only needed for QtQuick.
|
||||||
|
// With QtQuick, when double clicking, we get: Press, Release, Press, Double-click. and never
|
||||||
|
// receive the last Release event.
|
||||||
|
Q_EMIT q->dragCanceled();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
StateDragging::StateDragging(DragController *parent)
|
StateDragging::StateDragging(DragController *parent)
|
||||||
: StateBase(parent)
|
: StateBase(parent)
|
||||||
{
|
{
|
||||||
@@ -170,7 +233,7 @@ StateDragging::StateDragging(DragController *parent)
|
|||||||
|
|
||||||
StateDragging::~StateDragging() = default;
|
StateDragging::~StateDragging() = default;
|
||||||
|
|
||||||
void StateDragging::onEntry(QEvent *)
|
void StateDragging::onEntry()
|
||||||
{
|
{
|
||||||
if (DockWidgetBase *dw = q->m_draggable->singleDockWidget()) {
|
if (DockWidgetBase *dw = q->m_draggable->singleDockWidget()) {
|
||||||
// When we start to drag a floating window which has a single dock widget, we save the position
|
// When we start to drag a floating window which has a single dock widget, we save the position
|
||||||
@@ -294,6 +357,14 @@ bool StateDragging::handleMouseMove(QPoint globalPos)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StateDragging::handleMouseDoubleClick()
|
||||||
|
{
|
||||||
|
// See comment in StatePreDrag::handleMouseDoubleClick().
|
||||||
|
// Very unlikely that we're in this state though, due to manhattan length
|
||||||
|
Q_EMIT q->dragCanceled();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
StateDraggingWayland::StateDraggingWayland(DragController *parent)
|
StateDraggingWayland::StateDraggingWayland(DragController *parent)
|
||||||
: StateDragging(parent)
|
: StateDragging(parent)
|
||||||
{
|
{
|
||||||
@@ -303,23 +374,92 @@ StateDraggingWayland::~StateDraggingWayland()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void StateDraggingWayland::onEntry(QEvent *)
|
void StateDraggingWayland::onEntry()
|
||||||
{
|
{
|
||||||
// Create a QDrag here
|
qCDebug(state) << "StateDragging entered";
|
||||||
|
|
||||||
|
if (m_inQDrag) {
|
||||||
|
// Maybe we can exit the state due to the nested event loop of QDrag::Exec();
|
||||||
|
qWarning() << Q_FUNC_INFO << "Impossible!";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
QScopedValueRollback<bool> guard(m_inQDrag, true);
|
||||||
|
q->m_windowBeingDragged = std::unique_ptr<WindowBeingDragged>(new WindowBeingDraggedWayland(q->m_draggable));
|
||||||
|
|
||||||
|
auto mimeData = new WaylandMimeData();
|
||||||
|
QDrag drag(this);
|
||||||
|
drag.setMimeData(mimeData);
|
||||||
|
drag.setPixmap(q->m_windowBeingDragged->pixmap());
|
||||||
|
|
||||||
|
qApp->installEventFilter(q);
|
||||||
|
const Qt::DropAction result = drag.exec();
|
||||||
|
qApp->removeEventFilter(q);
|
||||||
|
if (result == Qt::IgnoreAction)
|
||||||
|
Q_EMIT q->dragCanceled();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StateDraggingWayland::handleMouseButtonRelease(QPoint /*globalPos*/)
|
bool StateDraggingWayland::handleMouseButtonRelease(QPoint /*globalPos*/)
|
||||||
{
|
{
|
||||||
|
qCDebug(state) << Q_FUNC_INFO;
|
||||||
Q_EMIT q->dragCanceled();
|
Q_EMIT q->dragCanceled();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool StateDraggingWayland::handleMouseMove(QPoint /*globalPos*/)
|
bool StateDraggingWayland::handleDragEnter(QDragEnterEvent *ev, DropArea *dropArea)
|
||||||
{
|
{
|
||||||
|
auto mimeData = qobject_cast<const WaylandMimeData*>(ev->mimeData());
|
||||||
|
if (!mimeData || !q->m_windowBeingDragged)
|
||||||
|
return false; // Not for us, some other user drag.
|
||||||
|
|
||||||
|
if (q->m_windowBeingDragged->contains(dropArea)) {
|
||||||
|
ev->ignore();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dropArea->hover(q->m_windowBeingDragged.get(), dropArea->mapToGlobal(Qt5Qt6Compat::eventPos(ev)));
|
||||||
|
|
||||||
|
ev->accept();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
DragController::DragController(QObject *)
|
bool StateDraggingWayland::handleDragLeave(DropArea *dropArea)
|
||||||
|
{
|
||||||
|
dropArea->removeHover();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StateDraggingWayland::handleDrop(QDropEvent *ev, DropArea *dropArea)
|
||||||
|
{
|
||||||
|
auto mimeData = qobject_cast<const WaylandMimeData*>(ev->mimeData());
|
||||||
|
if (!mimeData || !q->m_windowBeingDragged)
|
||||||
|
return false; // Not for us, some other user drag.
|
||||||
|
|
||||||
|
if (dropArea->drop(q->m_windowBeingDragged.get(), dropArea->mapToGlobal(Qt5Qt6Compat::eventPos(ev)))) {
|
||||||
|
ev->setDropAction(Qt::MoveAction);
|
||||||
|
ev->accept();
|
||||||
|
Q_EMIT q->dropped();
|
||||||
|
} else {
|
||||||
|
Q_EMIT q->dragCanceled();
|
||||||
|
}
|
||||||
|
|
||||||
|
dropArea->removeHover();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StateDraggingWayland::handleDragMove(QDragMoveEvent *ev, DropArea *dropArea)
|
||||||
|
{
|
||||||
|
auto mimeData = qobject_cast<const WaylandMimeData*>(ev->mimeData());
|
||||||
|
if (!mimeData || !q->m_windowBeingDragged)
|
||||||
|
return false; // Not for us, some other user drag.
|
||||||
|
|
||||||
|
dropArea->hover(q->m_windowBeingDragged.get(), dropArea->mapToGlobal(Qt5Qt6Compat::eventPos(ev)));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
DragController::DragController(QObject *parent)
|
||||||
|
: MinimalStateMachine(parent)
|
||||||
{
|
{
|
||||||
qCDebug(creation) << "DragController()";
|
qCDebug(creation) << "DragController()";
|
||||||
|
|
||||||
@@ -334,8 +474,10 @@ DragController::DragController(QObject *)
|
|||||||
stateDragging->addTransition(this, &DragController::dragCanceled, stateNone);
|
stateDragging->addTransition(this, &DragController::dragCanceled, stateNone);
|
||||||
stateDragging->addTransition(this, &DragController::dropped, stateNone);
|
stateDragging->addTransition(this, &DragController::dropped, stateNone);
|
||||||
|
|
||||||
setInitialState(stateNone);
|
if (usesFallbackMouseGrabber())
|
||||||
start();
|
enableFallbackMouseGrabber();
|
||||||
|
|
||||||
|
setCurrentState(stateNone);
|
||||||
}
|
}
|
||||||
|
|
||||||
DragController *DragController::instance()
|
DragController *DragController::instance()
|
||||||
@@ -373,6 +515,9 @@ bool DragController::isInClientDrag() const
|
|||||||
|
|
||||||
void DragController::grabMouseFor(QWidgetOrQuick *target)
|
void DragController::grabMouseFor(QWidgetOrQuick *target)
|
||||||
{
|
{
|
||||||
|
if (isWayland())
|
||||||
|
return; // No grabbing supported on wayland
|
||||||
|
|
||||||
if (m_fallbackMouseGrabber) {
|
if (m_fallbackMouseGrabber) {
|
||||||
m_fallbackMouseGrabber->grabMouse(target);
|
m_fallbackMouseGrabber->grabMouse(target);
|
||||||
} else {
|
} else {
|
||||||
@@ -382,6 +527,9 @@ void DragController::grabMouseFor(QWidgetOrQuick *target)
|
|||||||
|
|
||||||
void DragController::releaseMouse(QWidgetOrQuick *target)
|
void DragController::releaseMouse(QWidgetOrQuick *target)
|
||||||
{
|
{
|
||||||
|
if (isWayland())
|
||||||
|
return; // No grabbing supported on wayland
|
||||||
|
|
||||||
if (m_fallbackMouseGrabber) {
|
if (m_fallbackMouseGrabber) {
|
||||||
m_fallbackMouseGrabber->releaseMouse();
|
m_fallbackMouseGrabber->releaseMouse();
|
||||||
} else {
|
} else {
|
||||||
@@ -406,39 +554,46 @@ WindowBeingDragged *DragController::windowBeingDragged() const
|
|||||||
return m_windowBeingDragged.get();
|
return m_windowBeingDragged.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
static QMouseEvent *mouseEvent(QEvent *e)
|
|
||||||
{
|
|
||||||
switch (e->type()) {
|
|
||||||
case QEvent::MouseButtonPress:
|
|
||||||
case QEvent::MouseButtonRelease:
|
|
||||||
case QEvent::MouseMove:
|
|
||||||
case QEvent::NonClientAreaMouseButtonPress:
|
|
||||||
case QEvent::NonClientAreaMouseButtonRelease:
|
|
||||||
case QEvent::NonClientAreaMouseMove:
|
|
||||||
return static_cast<QMouseEvent *>(e);
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool DragController::eventFilter(QObject *o, QEvent *e)
|
bool DragController::eventFilter(QObject *o, QEvent *e)
|
||||||
{
|
{
|
||||||
if (m_nonClientDrag && e->type() == QEvent::Move) {
|
if (m_nonClientDrag && e->type() == QEvent::Move) {
|
||||||
// On Windows, non-client mouse moves are only sent at the end, so we must fake it:
|
// On Windows, non-client mouse moves are only sent at the end, so we must fake it:
|
||||||
qCDebug(mouseevents) << "DragController::eventFilter e=" << e->type() << "; o=" << o;
|
qCDebug(mouseevents) << "DragController::eventFilter e=" << e->type() << "; o=" << o;
|
||||||
activeState()->handleMouseMove(QCursor::pos());
|
activeState()->handleMouseMove(QCursor::pos());
|
||||||
return QStateMachine::eventFilter(o, e);
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isWayland()) {
|
||||||
|
// Wayland is very different. It uses QDrag for the dragging of a window.
|
||||||
|
if (auto dropArea = qobject_cast<DropArea*>(o)) {
|
||||||
|
switch (int(e->type())) {
|
||||||
|
case QEvent::DragEnter:
|
||||||
|
if (activeState()->handleDragEnter(static_cast<QDragEnterEvent*>(e), dropArea))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case QEvent::DragLeave:
|
||||||
|
if (activeState()->handleDragLeave(dropArea))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case QEvent::DragMove:
|
||||||
|
if (activeState()->handleDragMove(static_cast<QDragMoveEvent*>(e), dropArea))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case QEvent::Drop:
|
||||||
|
if (activeState()->handleDrop(static_cast<QDropEvent*>(e), dropArea))
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QMouseEvent *me = mouseEvent(e);
|
QMouseEvent *me = mouseEvent(e);
|
||||||
if (!me)
|
if (!me)
|
||||||
return QStateMachine::eventFilter(o, e);
|
return false;
|
||||||
|
|
||||||
auto w = qobject_cast<QWidgetOrQuick*>(o);
|
auto w = qobject_cast<QWidgetOrQuick*>(o);
|
||||||
if (!w)
|
if (!w)
|
||||||
return QStateMachine::eventFilter(o, e);
|
return false;
|
||||||
|
|
||||||
qCDebug(mouseevents) << "DragController::eventFilter e=" << e->type() << "; o=" << o
|
qCDebug(mouseevents) << "DragController::eventFilter e=" << e->type() << "; o=" << o
|
||||||
<< "; m_nonClientDrag=" << m_nonClientDrag;
|
<< "; m_nonClientDrag=" << m_nonClientDrag;
|
||||||
@@ -451,13 +606,15 @@ bool DragController::eventFilter(QObject *o, QEvent *e)
|
|||||||
return activeState()->handleMouseButtonPress(draggableForQObject(o), Qt5Qt6Compat::eventGlobalPos(me), me->pos());
|
return activeState()->handleMouseButtonPress(draggableForQObject(o), Qt5Qt6Compat::eventGlobalPos(me), me->pos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QStateMachine::eventFilter(o, e);
|
return false;
|
||||||
}
|
}
|
||||||
case QEvent::MouseButtonPress:
|
case QEvent::MouseButtonPress:
|
||||||
// For top-level windows that support native dragging all goes through the NonClient* events.
|
// For top-level windows that support native dragging all goes through the NonClient* events.
|
||||||
// This also forbids dragging a FloatingWindow simply by pressing outside of the title area, in the background
|
// This also forbids dragging a FloatingWindow simply by pressing outside of the title area, in the background
|
||||||
if (!KDDockWidgets::usesNativeDraggingAndResizing() || !w->isWindow())
|
if (!KDDockWidgets::usesNativeDraggingAndResizing() || !w->isWindow()) {
|
||||||
|
Q_ASSERT(activeState());
|
||||||
return activeState()->handleMouseButtonPress(draggableForQObject(o), Qt5Qt6Compat::eventGlobalPos(me), me->pos());
|
return activeState()->handleMouseButtonPress(draggableForQObject(o), Qt5Qt6Compat::eventGlobalPos(me), me->pos());
|
||||||
|
}
|
||||||
else break;
|
else break;
|
||||||
case QEvent::MouseButtonRelease:
|
case QEvent::MouseButtonRelease:
|
||||||
case QEvent::NonClientAreaMouseButtonRelease:
|
case QEvent::NonClientAreaMouseButtonRelease:
|
||||||
@@ -465,28 +622,28 @@ bool DragController::eventFilter(QObject *o, QEvent *e)
|
|||||||
case QEvent::NonClientAreaMouseMove:
|
case QEvent::NonClientAreaMouseMove:
|
||||||
case QEvent::MouseMove:
|
case QEvent::MouseMove:
|
||||||
return activeState()->handleMouseMove(Qt5Qt6Compat::eventGlobalPos(me));
|
return activeState()->handleMouseMove(Qt5Qt6Compat::eventGlobalPos(me));
|
||||||
|
case QEvent::MouseButtonDblClick:
|
||||||
|
return activeState()->handleMouseDoubleClick();
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return QStateMachine::eventFilter(o, e);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
StateBase *DragController::activeState() const
|
StateBase *DragController::activeState() const
|
||||||
{
|
{
|
||||||
auto set = configuration();
|
return static_cast<StateBase *>(currentState());
|
||||||
if (set.isEmpty())
|
|
||||||
return nullptr;
|
|
||||||
return static_cast<StateBase *>(*(set.begin()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
static QWidget *qtTopLevelForHWND(HWND hwnd)
|
static QWidgetOrQuick *qtTopLevelForHWND(HWND hwnd)
|
||||||
{
|
{
|
||||||
auto topLevels = qApp->topLevelWidgets();
|
const QList<QWindow*> windows = qApp->topLevelWindows();
|
||||||
for (auto topLevel : topLevels) {
|
for (QWindow *window : windows) {
|
||||||
if (hwnd == (HWND)topLevel->winId())
|
if (hwnd == (HWND)window->winId()) {
|
||||||
return topLevel;
|
return DockRegistry::self()->topLevelForHandle(window);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(toplevels) << Q_FUNC_INFO << "Couldn't find hwnd for top-level" << hwnd;
|
qCDebug(toplevels) << Q_FUNC_INFO << "Couldn't find hwnd for top-level" << hwnd;
|
||||||
@@ -520,8 +677,7 @@ WidgetType *DragController::qtTopLevelUnderCursor() const
|
|||||||
QPoint globalPos = QCursor::pos();
|
QPoint globalPos = QCursor::pos();
|
||||||
|
|
||||||
if (qApp->platformName() == QLatin1String("windows")) { // So -platform offscreen on Windows doesn't use this
|
if (qApp->platformName() == QLatin1String("windows")) { // So -platform offscreen on Windows doesn't use this
|
||||||
# if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
auto topLevels = qApp->topLevelWidgets();
|
|
||||||
POINT globalNativePos;
|
POINT globalNativePos;
|
||||||
if (!GetCursorPos(&globalNativePos))
|
if (!GetCursorPos(&globalNativePos))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -544,7 +700,8 @@ WidgetType *DragController::qtTopLevelUnderCursor() const
|
|||||||
return tl;
|
return tl;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Maybe it's embedded in a QWinWidget:
|
# ifdef KDDOCKWIDGETS_QTWIDGETS // Maybe it's embedded in a QWinWidget:
|
||||||
|
auto topLevels = qApp->topLevelWidgets();
|
||||||
for (auto topLevel : topLevels) {
|
for (auto topLevel : topLevels) {
|
||||||
if (QLatin1String(topLevel->metaObject()->className()) == QLatin1String("QWinWidget")) {
|
if (QLatin1String(topLevel->metaObject()->className()) == QLatin1String("QWinWidget")) {
|
||||||
if (hwnd == GetParent(HWND(topLevel->windowHandle()->winId()))) {
|
if (hwnd == GetParent(HWND(topLevel->windowHandle()->winId()))) {
|
||||||
@@ -555,13 +712,13 @@ WidgetType *DragController::qtTopLevelUnderCursor() const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
# endif // QtWidgets
|
||||||
// A window belonging to another app is below the cursor
|
// A window belonging to another app is below the cursor
|
||||||
qCDebug(toplevels) << Q_FUNC_INFO << "Window from another app is under cursor" << hwnd;
|
qCDebug(toplevels) << Q_FUNC_INFO << "Window from another app is under cursor" << hwnd;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
# endif
|
#endif // Q_OS_WIN
|
||||||
} else {
|
} else {
|
||||||
// !Windows: Linux, macOS, offscreen (offscreen on Windows too), etc.
|
// !Windows: Linux, macOS, offscreen (offscreen on Windows too), etc.
|
||||||
|
|
||||||
|
|||||||
@@ -17,8 +17,9 @@
|
|||||||
#include "TitleBar_p.h"
|
#include "TitleBar_p.h"
|
||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
|
|
||||||
#include <QStateMachine>
|
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
|
#include <QMimeData>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
@@ -27,8 +28,37 @@ class StateBase;
|
|||||||
class DropArea;
|
class DropArea;
|
||||||
class Draggable;
|
class Draggable;
|
||||||
class FallbackMouseGrabber;
|
class FallbackMouseGrabber;
|
||||||
|
class MinimalStateMachine;
|
||||||
|
|
||||||
class DOCKS_EXPORT DragController : public QStateMachine
|
class State : public QObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit State(MinimalStateMachine *parent);
|
||||||
|
~State() override;
|
||||||
|
|
||||||
|
template <typename Obj, typename Signal>
|
||||||
|
void addTransition(Obj *, Signal, State *dest);
|
||||||
|
bool isCurrentState() const;
|
||||||
|
|
||||||
|
virtual void onEntry() = 0;
|
||||||
|
private:
|
||||||
|
MinimalStateMachine *const m_machine;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MinimalStateMachine : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit MinimalStateMachine(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
State *currentState() const;
|
||||||
|
void setCurrentState(State *);
|
||||||
|
|
||||||
|
private:
|
||||||
|
State *m_currentState = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
class DOCKS_EXPORT DragController : public MinimalStateMachine
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -75,6 +105,7 @@ private:
|
|||||||
friend class StatePreDrag;
|
friend class StatePreDrag;
|
||||||
friend class StateDragging;
|
friend class StateDragging;
|
||||||
friend class StateDropped;
|
friend class StateDropped;
|
||||||
|
friend class StateDraggingWayland;
|
||||||
|
|
||||||
DragController(QObject * = nullptr);
|
DragController(QObject * = nullptr);
|
||||||
StateBase *activeState() const;
|
StateBase *activeState() const;
|
||||||
@@ -92,7 +123,7 @@ private:
|
|||||||
FallbackMouseGrabber *m_fallbackMouseGrabber = nullptr;
|
FallbackMouseGrabber *m_fallbackMouseGrabber = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
class StateBase : public QState
|
class StateBase : public State
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -103,6 +134,13 @@ public:
|
|||||||
virtual bool handleMouseButtonPress(Draggable * /*receiver*/, QPoint /*globalPos*/, QPoint /*pos*/) { return false; }
|
virtual bool handleMouseButtonPress(Draggable * /*receiver*/, QPoint /*globalPos*/, QPoint /*pos*/) { return false; }
|
||||||
virtual bool handleMouseMove(QPoint /*globalPos*/) { return false; }
|
virtual bool handleMouseMove(QPoint /*globalPos*/) { return false; }
|
||||||
virtual bool handleMouseButtonRelease(QPoint /*globalPos*/) { return false; }
|
virtual bool handleMouseButtonRelease(QPoint /*globalPos*/) { return false; }
|
||||||
|
virtual bool handleMouseDoubleClick() { return false; }
|
||||||
|
|
||||||
|
// Only interesting for Wayland
|
||||||
|
virtual bool handleDragEnter(QDragEnterEvent *, DropArea *) { return false; }
|
||||||
|
virtual bool handleDragLeave(DropArea *) { return false; }
|
||||||
|
virtual bool handleDragMove(QDragMoveEvent *, DropArea *) { return false; }
|
||||||
|
virtual bool handleDrop(QDropEvent *, DropArea *) { return false; }
|
||||||
|
|
||||||
// Returns whether this is the current state
|
// Returns whether this is the current state
|
||||||
bool isActiveState() const;
|
bool isActiveState() const;
|
||||||
@@ -116,7 +154,7 @@ class StateNone : public StateBase
|
|||||||
public:
|
public:
|
||||||
explicit StateNone(DragController *parent);
|
explicit StateNone(DragController *parent);
|
||||||
~StateNone() override;
|
~StateNone() override;
|
||||||
void onEntry(QEvent *) override;
|
void onEntry() override;
|
||||||
bool handleMouseButtonPress(Draggable *draggable, QPoint globalPos, QPoint pos) override;
|
bool handleMouseButtonPress(Draggable *draggable, QPoint globalPos, QPoint pos) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -126,9 +164,10 @@ class StatePreDrag : public StateBase
|
|||||||
public:
|
public:
|
||||||
explicit StatePreDrag(DragController *parent);
|
explicit StatePreDrag(DragController *parent);
|
||||||
~StatePreDrag() override;
|
~StatePreDrag() override;
|
||||||
void onEntry(QEvent *) override;
|
void onEntry() override;
|
||||||
bool handleMouseMove(QPoint globalPos) override;
|
bool handleMouseMove(QPoint globalPos) override;
|
||||||
bool handleMouseButtonRelease(QPoint) override;
|
bool handleMouseButtonRelease(QPoint) override;
|
||||||
|
bool handleMouseDoubleClick() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used on all platforms except Wayland. @see StateDraggingWayland
|
// Used on all platforms except Wayland. @see StateDraggingWayland
|
||||||
@@ -138,9 +177,10 @@ class StateDragging : public StateBase
|
|||||||
public:
|
public:
|
||||||
explicit StateDragging(DragController *parent);
|
explicit StateDragging(DragController *parent);
|
||||||
~StateDragging() override;
|
~StateDragging() override;
|
||||||
void onEntry(QEvent *) override;
|
void onEntry() override;
|
||||||
bool handleMouseButtonRelease(QPoint globalPos) override;
|
bool handleMouseButtonRelease(QPoint globalPos) override;
|
||||||
bool handleMouseMove(QPoint globalPos) override;
|
bool handleMouseMove(QPoint globalPos) override;
|
||||||
|
bool handleMouseDoubleClick() override;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Used on wayland only to use QDrag instead of setting geometry on mouse-move.
|
// Used on wayland only to use QDrag instead of setting geometry on mouse-move.
|
||||||
@@ -150,9 +190,21 @@ class StateDraggingWayland : public StateDragging
|
|||||||
public:
|
public:
|
||||||
explicit StateDraggingWayland(DragController *parent);
|
explicit StateDraggingWayland(DragController *parent);
|
||||||
~StateDraggingWayland() override;
|
~StateDraggingWayland() override;
|
||||||
void onEntry(QEvent *) override;
|
void onEntry() override;
|
||||||
bool handleMouseButtonRelease(QPoint globalPos) override;
|
bool handleMouseButtonRelease(QPoint globalPos) override;
|
||||||
bool handleMouseMove(QPoint globalPos) override;
|
bool handleDragEnter(QDragEnterEvent *, DropArea *) override;
|
||||||
|
bool handleDragMove(QDragMoveEvent *, DropArea *) override;
|
||||||
|
bool handleDragLeave(DropArea *) override;
|
||||||
|
bool handleDrop(QDropEvent *, DropArea *) override;
|
||||||
|
bool m_inQDrag = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
// A sub-class just so we don't use QMimeData directly. We'll only accept drops if its mime data
|
||||||
|
// Can be qobject_casted to this class. For safety.
|
||||||
|
class WaylandMimeData : public QMimeData
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,8 +13,8 @@
|
|||||||
#include "DragController_p.h"
|
#include "DragController_p.h"
|
||||||
#include "FloatingWindow_p.h"
|
#include "FloatingWindow_p.h"
|
||||||
#include "WidgetResizeHandler_p.h"
|
#include "WidgetResizeHandler_p.h"
|
||||||
|
#include "Utils_p.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
@@ -54,7 +54,7 @@ QWidgetOrQuick *Draggable::asWidget() const
|
|||||||
|
|
||||||
bool Draggable::dragCanStart(QPoint pressPos, QPoint globalPos) const
|
bool Draggable::dragCanStart(QPoint pressPos, QPoint globalPos) const
|
||||||
{
|
{
|
||||||
return (globalPos - pressPos).manhattanLength() > QApplication::startDragDistance();
|
return (globalPos - pressPos).manhattanLength() > KDDockWidgets::startDragDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
WidgetResizeHandler *Draggable::widgetResizeHandler() const
|
WidgetResizeHandler *Draggable::widgetResizeHandler() const
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
#ifndef KD_DRAGGABLE_P_H
|
#ifndef KD_DRAGGABLE_P_H
|
||||||
#define KD_DRAGGABLE_P_H
|
#define KD_DRAGGABLE_P_H
|
||||||
|
|
||||||
#include "QWidgetAdapter.h"
|
#include "kddockwidgets/QWidgetAdapter.h"
|
||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "multisplitter/Item_p.h"
|
#include "multisplitter/Item_p.h"
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
|
#include "Utils_p.h"
|
||||||
|
|
||||||
// #include "indicators/AnimatedIndicators_p.h"
|
// #include "indicators/AnimatedIndicators_p.h"
|
||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
@@ -38,6 +39,13 @@ DropArea::DropArea(QWidgetOrQuick *parent)
|
|||||||
, m_dropIndicatorOverlay(Config::self().frameworkWidgetFactory()->createDropIndicatorOverlay(this))
|
, m_dropIndicatorOverlay(Config::self().frameworkWidgetFactory()->createDropIndicatorOverlay(this))
|
||||||
{
|
{
|
||||||
qCDebug(creation) << "DropArea";
|
qCDebug(creation) << "DropArea";
|
||||||
|
if (isWayland()) {
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
setAcceptDrops(true);
|
||||||
|
#else
|
||||||
|
qWarning() << "Dropping not implement for QtQuick on Wayland yet!";
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DropArea::~DropArea()
|
DropArea::~DropArea()
|
||||||
@@ -113,10 +121,10 @@ void DropArea::addDockWidget(DockWidgetBase *dw, Location location, DockWidgetBa
|
|||||||
const bool hadSingleFloatingFrame = hasSingleFloatingFrame();
|
const bool hadSingleFloatingFrame = hasSingleFloatingFrame();
|
||||||
|
|
||||||
// Check if the dock widget already exists in the layout
|
// Check if the dock widget already exists in the layout
|
||||||
if (contains(dw)) {
|
if (containsDockWidget(dw)) {
|
||||||
Frame *oldFrame = dw->frame();
|
Frame *oldFrame = dw->frame();
|
||||||
if (oldFrame->hasSingleDockWidget()) {
|
if (oldFrame->hasSingleDockWidget()) {
|
||||||
Q_ASSERT(oldFrame->contains(dw));
|
Q_ASSERT(oldFrame->containsDockWidget(dw));
|
||||||
// The frame only has this dock widget, and the frame is already in the layout. So move the frame instead
|
// The frame only has this dock widget, and the frame is already in the layout. So move the frame instead
|
||||||
frame = oldFrame;
|
frame = oldFrame;
|
||||||
} else {
|
} else {
|
||||||
@@ -141,9 +149,9 @@ void DropArea::addDockWidget(DockWidgetBase *dw, Location location, DockWidgetBa
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DropArea::contains(DockWidgetBase *dw) const
|
bool DropArea::containsDockWidget(DockWidgetBase *dw) const
|
||||||
{
|
{
|
||||||
return dw->frame() && MultiSplitter::contains(dw->frame());
|
return dw->frame() && MultiSplitter::containsFrame(dw->frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DropArea::hasSingleFloatingFrame() const
|
bool DropArea::hasSingleFloatingFrame() const
|
||||||
@@ -174,20 +182,20 @@ void DropArea::layoutParentContainerEqually(DockWidgetBase *dw)
|
|||||||
layoutEqually(item->parentContainer());
|
layoutEqually(item->parentContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropArea::hover(WindowBeingDragged *floatingWindow, QPoint globalPos)
|
DropIndicatorOverlayInterface::DropLocation DropArea::hover(WindowBeingDragged *draggedWindow, QPoint globalPos)
|
||||||
{
|
{
|
||||||
if (!validateAffinity(floatingWindow))
|
if (!validateAffinity(draggedWindow))
|
||||||
return;
|
return DropIndicatorOverlayInterface::DropLocation_None;
|
||||||
|
|
||||||
if (!m_dropIndicatorOverlay) {
|
if (!m_dropIndicatorOverlay) {
|
||||||
qWarning() << Q_FUNC_INFO << "The frontend is missing a drop indicator overlay";
|
qWarning() << Q_FUNC_INFO << "The frontend is missing a drop indicator overlay";
|
||||||
return;
|
return DropIndicatorOverlayInterface::DropLocation_None;
|
||||||
}
|
}
|
||||||
|
|
||||||
Frame *frame = frameContainingPos(globalPos); // Frame is nullptr if MainWindowOption_HasCentralFrame isn't set
|
Frame *frame = frameContainingPos(globalPos); // Frame is nullptr if MainWindowOption_HasCentralFrame isn't set
|
||||||
m_dropIndicatorOverlay->setWindowBeingDragged(floatingWindow != nullptr);
|
m_dropIndicatorOverlay->setWindowBeingDragged(true);
|
||||||
m_dropIndicatorOverlay->setHoveredFrame(frame);
|
m_dropIndicatorOverlay->setHoveredFrame(frame);
|
||||||
m_dropIndicatorOverlay->hover(globalPos);
|
return m_dropIndicatorOverlay->hover(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isOutterLocation(DropIndicatorOverlayInterface::DropLocation location)
|
static bool isOutterLocation(DropIndicatorOverlayInterface::DropLocation location)
|
||||||
@@ -205,8 +213,7 @@ static bool isOutterLocation(DropIndicatorOverlayInterface::DropLocation locatio
|
|||||||
|
|
||||||
bool DropArea::drop(WindowBeingDragged *droppedWindow, QPoint globalPos)
|
bool DropArea::drop(WindowBeingDragged *droppedWindow, QPoint globalPos)
|
||||||
{
|
{
|
||||||
FloatingWindow *floatingWindow = droppedWindow ? droppedWindow->floatingWindow()
|
FloatingWindow *floatingWindow = droppedWindow->floatingWindow();
|
||||||
: nullptr;
|
|
||||||
|
|
||||||
if (floatingWindow == window()) {
|
if (floatingWindow == window()) {
|
||||||
qWarning() << "Refusing to drop onto itself"; // Doesn't happen
|
qWarning() << "Refusing to drop onto itself"; // Doesn't happen
|
||||||
@@ -223,17 +230,35 @@ bool DropArea::drop(WindowBeingDragged *droppedWindow, QPoint globalPos)
|
|||||||
hover(droppedWindow, globalPos);
|
hover(droppedWindow, globalPos);
|
||||||
auto droploc = m_dropIndicatorOverlay->currentDropLocation();
|
auto droploc = m_dropIndicatorOverlay->currentDropLocation();
|
||||||
Frame *acceptingFrame = m_dropIndicatorOverlay->hoveredFrame();
|
Frame *acceptingFrame = m_dropIndicatorOverlay->hoveredFrame();
|
||||||
if (!(acceptingFrame || isOutterLocation(m_dropIndicatorOverlay->currentDropLocation()))) {
|
if (!(acceptingFrame || isOutterLocation(droploc))) {
|
||||||
qWarning() << "DropArea::drop: asserted with frame=" << acceptingFrame << "; Location=" << m_dropIndicatorOverlay->currentDropLocation();
|
qWarning() << "DropArea::drop: asserted with frame=" << acceptingFrame
|
||||||
|
<< "; Location=" << droploc;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return drop(floatingWindow, acceptingFrame, droploc);
|
return drop(droppedWindow, acceptingFrame, droploc);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DropArea::drop(FloatingWindow *droppedWindow, Frame *acceptingFrame,
|
bool DropArea::drop(WindowBeingDragged *draggedWindow, Frame *acceptingFrame,
|
||||||
DropIndicatorOverlayInterface::DropLocation droploc)
|
DropIndicatorOverlayInterface::DropLocation droploc)
|
||||||
{
|
{
|
||||||
|
FloatingWindow *droppedWindow = draggedWindow ? draggedWindow->floatingWindow()
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (isWayland() && !droppedWindow) {
|
||||||
|
// This is the Wayland special case.
|
||||||
|
// With other platforms, when detaching a tab or dock widget we create the FloatingWindow immediately.
|
||||||
|
// With Wayland we delay the floating window until we drop it.
|
||||||
|
// Ofc, we could just dock the dockwidget without the temporary FloatingWindow, but this way we reuse
|
||||||
|
// 99% of the rest of the code, without adding more wayland special cases
|
||||||
|
droppedWindow = draggedWindow->draggable()->makeWindow()->floatingWindow();
|
||||||
|
if (!droppedWindow) {
|
||||||
|
// Doesn't happen
|
||||||
|
qWarning() << Q_FUNC_INFO << "Wayland: Expected window" << draggedWindow;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool result = true;
|
bool result = true;
|
||||||
const bool needToFocusNewlyDroppedWidgets = Config::self().flags() & Config::Flag_TitleBarIsFocusable;
|
const bool needToFocusNewlyDroppedWidgets = Config::self().flags() & Config::Flag_TitleBarIsFocusable;
|
||||||
const DockWidgetBase::List droppedDockWidgets = needToFocusNewlyDroppedWidgets ? droppedWindow->multiSplitter()->dockWidgets()
|
const DockWidgetBase::List droppedDockWidgets = needToFocusNewlyDroppedWidgets ? droppedWindow->multiSplitter()->dockWidgets()
|
||||||
@@ -271,7 +296,7 @@ bool DropArea::drop(FloatingWindow *droppedWindow, Frame *acceptingFrame,
|
|||||||
|
|
||||||
if (needToFocusNewlyDroppedWidgets) {
|
if (needToFocusNewlyDroppedWidgets) {
|
||||||
// Let's also focus the newly dropped dock widget
|
// Let's also focus the newly dropped dock widget
|
||||||
if (droppedDockWidgets.size() > 0) {
|
if (!droppedDockWidgets.isEmpty()) {
|
||||||
// If more than 1 was dropped, we only focus the first one
|
// If more than 1 was dropped, we only focus the first one
|
||||||
Frame *frame = droppedDockWidgets.first()->frame();
|
Frame *frame = droppedDockWidgets.first()->frame();
|
||||||
frame->FocusScope::focus(Qt::MouseFocusReason);
|
frame->FocusScope::focus(Qt::MouseFocusReason);
|
||||||
|
|||||||
@@ -19,13 +19,13 @@
|
|||||||
#ifndef KD_DROP_AREA_P_H
|
#ifndef KD_DROP_AREA_P_H
|
||||||
#define KD_DROP_AREA_P_H
|
#define KD_DROP_AREA_P_H
|
||||||
|
|
||||||
#include "docks_export.h"
|
#include "kddockwidgets/docks_export.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "KDDockWidgets.h"
|
#include "KDDockWidgets.h"
|
||||||
#include "MultiSplitter_p.h"
|
#include "MultiSplitter_p.h"
|
||||||
#include "DropIndicatorOverlayInterface_p.h"
|
#include "DropIndicatorOverlayInterface_p.h"
|
||||||
|
|
||||||
class TestCommon;
|
class TestDocks;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ public:
|
|||||||
~DropArea();
|
~DropArea();
|
||||||
|
|
||||||
void removeHover();
|
void removeHover();
|
||||||
void hover(WindowBeingDragged *floatingWindow, QPoint globalPos);
|
DropIndicatorOverlayInterface::DropLocation hover(WindowBeingDragged *draggedWindow, QPoint globalPos);
|
||||||
///@brief Called when a user drops a widget via DND
|
///@brief Called when a user drops a widget via DND
|
||||||
bool drop(WindowBeingDragged *droppedWindow, QPoint globalPos);
|
bool drop(WindowBeingDragged *droppedWindow, QPoint globalPos);
|
||||||
int numFrames() const;
|
int numFrames() const;
|
||||||
@@ -54,7 +54,7 @@ public:
|
|||||||
DropIndicatorOverlayInterface *dropIndicatorOverlay() const { return m_dropIndicatorOverlay; }
|
DropIndicatorOverlayInterface *dropIndicatorOverlay() const { return m_dropIndicatorOverlay; }
|
||||||
void addDockWidget(DockWidgetBase *, KDDockWidgets::Location location, DockWidgetBase *relativeTo, AddingOption option = {});
|
void addDockWidget(DockWidgetBase *, KDDockWidgets::Location location, DockWidgetBase *relativeTo, AddingOption option = {});
|
||||||
|
|
||||||
bool contains(DockWidgetBase *) const;
|
bool containsDockWidget(DockWidgetBase *) const;
|
||||||
|
|
||||||
/// Returns whether this layout has a single dock widget which is floating
|
/// Returns whether this layout has a single dock widget which is floating
|
||||||
/// Implies it's in a FloatingWindow and that it has only one dock widget
|
/// Implies it's in a FloatingWindow and that it has only one dock widget
|
||||||
@@ -65,15 +65,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(DropArea)
|
Q_DISABLE_COPY(DropArea)
|
||||||
friend class Frame;
|
friend class Frame;
|
||||||
friend class TestDocks;
|
friend class ::TestDocks;
|
||||||
friend class ::TestCommon;
|
|
||||||
friend class DropIndicatorOverlayInterface;
|
friend class DropIndicatorOverlayInterface;
|
||||||
friend class AnimatedIndicators;
|
friend class AnimatedIndicators;
|
||||||
friend class FloatingWindow;
|
friend class FloatingWindow;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool validateAffinity(T *, Frame *acceptingFrame = nullptr) const;
|
bool validateAffinity(T *, Frame *acceptingFrame = nullptr) const;
|
||||||
bool drop(FloatingWindow *droppedWindow, Frame *acceptingFrame, DropIndicatorOverlayInterface::DropLocation);
|
bool drop(WindowBeingDragged *draggedWindow, Frame *acceptingFrame, DropIndicatorOverlayInterface::DropLocation);
|
||||||
bool drop(QWidgetOrQuick *droppedwindow, KDDockWidgets::Location location, Frame *relativeTo);
|
bool drop(QWidgetOrQuick *droppedwindow, KDDockWidgets::Location location, Frame *relativeTo);
|
||||||
Frame *frameContainingPos(QPoint globalPos) const;
|
Frame *frameContainingPos(QPoint globalPos) const;
|
||||||
void updateFloatingActions();
|
void updateFloatingActions();
|
||||||
|
|||||||
@@ -118,9 +118,9 @@ void DropIndicatorOverlayInterface::setCurrentDropLocation(DropIndicatorOverlayI
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropIndicatorOverlayInterface::hover(QPoint globalPos)
|
DropIndicatorOverlayInterface::DropLocation DropIndicatorOverlayInterface::hover(QPoint globalPos)
|
||||||
{
|
{
|
||||||
hover_impl(globalPos);
|
return hover_impl(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropIndicatorOverlayInterface::setHoveredFrameRect(QRect rect)
|
void DropIndicatorOverlayInterface::setHoveredFrameRect(QRect rect)
|
||||||
|
|||||||
@@ -53,9 +53,11 @@ public:
|
|||||||
Frame *hoveredFrame() const { return m_hoveredFrame; }
|
Frame *hoveredFrame() const { return m_hoveredFrame; }
|
||||||
void setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation location);
|
void setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation location);
|
||||||
|
|
||||||
void hover(QPoint globalPos);
|
KDDockWidgets::DropIndicatorOverlayInterface::DropLocation hover(QPoint globalPos);
|
||||||
|
|
||||||
virtual QPoint posForIndicator(DropLocation) const { return {}; }; // Used by unit-tests only
|
/// @brief returns the position of the specified drop location
|
||||||
|
/// The return is in global coordinates
|
||||||
|
virtual QPoint posForIndicator(DropLocation) const = 0;
|
||||||
|
|
||||||
static KDDockWidgets::Location multisplitterLocationFor(DropLocation);
|
static KDDockWidgets::Location multisplitterLocationFor(DropLocation);
|
||||||
|
|
||||||
@@ -71,7 +73,7 @@ private:
|
|||||||
DropLocation m_currentDropLocation = DropLocation_None;
|
DropLocation m_currentDropLocation = DropLocation_None;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void hover_impl(QPoint globalPos) = 0;
|
virtual DropIndicatorOverlayInterface::DropLocation hover_impl(QPoint globalPos) = 0;
|
||||||
virtual void onHoveredFrameChanged(Frame *);
|
virtual void onHoveredFrameChanged(Frame *);
|
||||||
virtual void updateVisibility() {};
|
virtual void updateVisibility() {};
|
||||||
|
|
||||||
@@ -79,6 +81,7 @@ protected:
|
|||||||
DropArea *const m_dropArea;
|
DropArea *const m_dropArea;
|
||||||
bool m_draggedWindowIsHovering = false;
|
bool m_draggedWindowIsHovering = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
#include "MainWindowBase.h"
|
#include "MainWindowBase.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "DropArea_p.h"
|
|
||||||
#include "TitleBar_p.h"
|
#include "TitleBar_p.h"
|
||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
@@ -34,10 +33,10 @@
|
|||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
#if defined(Q_OS_WIN)
|
||||||
|
# ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Helper to rediriect WM_NCHITTEST from child widgets to the top-level widget
|
* @brief Helper to rediriect WM_NCHITTEST from child widgets to the top-level widget
|
||||||
*
|
*
|
||||||
@@ -45,12 +44,14 @@ namespace KDDockWidgets {
|
|||||||
* in FloatingWindow::nativeEvent(). But if the child widgets have a native handle, then
|
* in FloatingWindow::nativeEvent(). But if the child widgets have a native handle, then
|
||||||
* the WM_NCHITTEST will go to them. They have to respond HTTRANSPARENT so the event
|
* the WM_NCHITTEST will go to them. They have to respond HTTRANSPARENT so the event
|
||||||
* is redirected.
|
* is redirected.
|
||||||
|
*
|
||||||
|
* This only affects QtWidgets, since QQuickItems never have native WId.
|
||||||
*/
|
*/
|
||||||
class NCHITTESTEventFilter : public QAbstractNativeEventFilter
|
class NCHITTESTEventFilter : public QAbstractNativeEventFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit NCHITTESTEventFilter(FloatingWindow *fw) : m_floatingWindow(fw) {}
|
explicit NCHITTESTEventFilter(FloatingWindow *fw) : m_floatingWindow(fw) {}
|
||||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override
|
bool nativeEventFilter(const QByteArray &eventType, void *message, Qt5Qt6Compat::qintptr *result) override
|
||||||
{
|
{
|
||||||
if (eventType != "windows_generic_MSG" || !m_floatingWindow)
|
if (eventType != "windows_generic_MSG" || !m_floatingWindow)
|
||||||
return false;
|
return false;
|
||||||
@@ -58,11 +59,14 @@ public:
|
|||||||
auto msg = static_cast<MSG *>(message);
|
auto msg = static_cast<MSG *>(message);
|
||||||
if (msg->message != WM_NCHITTEST)
|
if (msg->message != WM_NCHITTEST)
|
||||||
return false;
|
return false;
|
||||||
QWidget *child = QWidget::find(WId(msg->hwnd));
|
const WId wid = WId(msg->hwnd);
|
||||||
|
|
||||||
|
QWidget *child = QWidget::find(wid);
|
||||||
if (!child || child->window() != m_floatingWindow)
|
if (!child || child->window() != m_floatingWindow)
|
||||||
return false;
|
return false;
|
||||||
|
const bool isThisWindow = child == m_floatingWindow;
|
||||||
|
|
||||||
if (child != m_floatingWindow) {
|
if (!isThisWindow) {
|
||||||
*result = HTTRANSPARENT;
|
*result = HTTRANSPARENT;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -73,7 +77,9 @@ public:
|
|||||||
QPointer<FloatingWindow> m_floatingWindow;
|
QPointer<FloatingWindow> m_floatingWindow;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
# endif
|
||||||
|
#endif // Q_OS_WIN
|
||||||
|
|
||||||
static Qt::WindowFlags windowFlagsToUse()
|
static Qt::WindowFlags windowFlagsToUse()
|
||||||
{
|
{
|
||||||
@@ -133,32 +139,21 @@ FloatingWindow::FloatingWindow(MainWindowBase *parent)
|
|||||||
, m_dropArea(new DropArea(this))
|
, m_dropArea(new DropArea(this))
|
||||||
, m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
|
, m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
if (kddwUsesQtWidgets()) {
|
||||||
// On Windows with Qt 5.9 (and maybe earlier), the WM_NCALCSIZE isn't being processed unless we explicitly create the window.
|
// For QtQuick we do it a bit later, once we have the QQuickWindow
|
||||||
// So create it now, otherwise floating dock widgets will show a native title bar until resized.
|
setupWindow();
|
||||||
create();
|
|
||||||
|
|
||||||
if (KDDockWidgets::usesAeroSnapWithCustomDecos()) {
|
|
||||||
m_nchittestFilter = new NCHITTESTEventFilter(this);
|
|
||||||
qApp->installNativeEventFilter(m_nchittestFilter);
|
|
||||||
|
|
||||||
connect(windowHandle(), &QWindow::screenChanged, this, [this] {
|
|
||||||
// Qt honors our frame hijacking usually... but when screen changes we must give it a nudge.
|
|
||||||
// Otherwise what Qt thinks is the client area is not what Windows knows it is.
|
|
||||||
// SetWindowPos() will trigger an NCCALCSIZE message, which Qt will intercept and take note of the margins we're using.
|
|
||||||
SetWindowPos(HWND(winId()), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Show drop-shadow:
|
|
||||||
MARGINS margins = {0, 0, 0, 1}; // arbitrary, just needs to be > 0 it seems
|
|
||||||
DwmExtendFrameIntoClientArea(HWND(winId()), &margins);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
DockRegistry::self()->registerFloatingWindow(this);
|
DockRegistry::self()->registerFloatingWindow(this);
|
||||||
qCDebug(creation) << "FloatingWindow()" << this;
|
qCDebug(creation) << "FloatingWindow()" << this;
|
||||||
|
|
||||||
maybeCreateResizeHandler();
|
if (Config::self().flags() & Config::Flag_KeepAboveIfNotUtilityWindow)
|
||||||
|
setWindowFlag(Qt::WindowStaysOnTopHint, true);
|
||||||
|
|
||||||
|
if (kddwUsesQtWidgets()) {
|
||||||
|
// QtQuick will do it a bit later, once it has a QWindow
|
||||||
|
maybeCreateResizeHandler();
|
||||||
|
}
|
||||||
|
|
||||||
updateTitleBarVisibility();
|
updateTitleBarVisibility();
|
||||||
connect(m_dropArea, &MultiSplitter::visibleWidgetCountChanged, this, &FloatingWindow::onFrameCountChanged);
|
connect(m_dropArea, &MultiSplitter::visibleWidgetCountChanged, this, &FloatingWindow::onFrameCountChanged);
|
||||||
@@ -188,8 +183,37 @@ FloatingWindow::~FloatingWindow()
|
|||||||
qCDebug(creation) << "~FloatingWindow";
|
qCDebug(creation) << "~FloatingWindow";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FloatingWindow::setupWindow()
|
||||||
|
{
|
||||||
|
// Does some minor setup on our QWindow.
|
||||||
|
// Like adding the drop shadow on Windows and two other workarounds.
|
||||||
|
|
||||||
|
#if defined(Q_OS_WIN)
|
||||||
|
// On Windows with Qt 5.9 (and maybe earlier), the WM_NCALCSIZE isn't being processed unless we explicitly create the window.
|
||||||
|
// So create it now, otherwise floating dock widgets will show a native title bar until resized.
|
||||||
|
create();
|
||||||
|
|
||||||
|
if (KDDockWidgets::usesAeroSnapWithCustomDecos()) {
|
||||||
|
# ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
m_nchittestFilter = new NCHITTESTEventFilter(this);
|
||||||
|
qApp->installNativeEventFilter(m_nchittestFilter);
|
||||||
|
#endif
|
||||||
|
connect(windowHandle(), &QWindow::screenChanged, this, [this] {
|
||||||
|
// Qt honors our frame hijacking usually... but when screen changes we must give it a nudge.
|
||||||
|
// Otherwise what Qt thinks is the client area is not what Windows knows it is.
|
||||||
|
// SetWindowPos() will trigger an NCCALCSIZE message, which Qt will intercept and take note of the margins we're using.
|
||||||
|
SetWindowPos(HWND(winId()), 0, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show drop-shadow:
|
||||||
|
MARGINS margins = {0, 0, 0, 1}; // arbitrary, just needs to be > 0 it seems
|
||||||
|
DwmExtendFrameIntoClientArea(HWND(winId()), &margins);
|
||||||
|
}
|
||||||
|
#endif // Q_OS_WIN
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
||||||
bool FloatingWindow::nativeEvent(const QByteArray &eventType, void *message, long *result)
|
bool FloatingWindow::nativeEvent(const QByteArray &eventType, void *message, Qt5Qt6Compat::qintptr *result)
|
||||||
{
|
{
|
||||||
if (!m_inDtor && !m_deleteScheduled && KDDockWidgets::usesAeroSnapWithCustomDecos()) {
|
if (!m_inDtor && !m_deleteScheduled && KDDockWidgets::usesAeroSnapWithCustomDecos()) {
|
||||||
// To enable aero snap we need to tell Windows where's our custom title bar
|
// To enable aero snap we need to tell Windows where's our custom title bar
|
||||||
@@ -205,9 +229,7 @@ void FloatingWindow::maybeCreateResizeHandler()
|
|||||||
{
|
{
|
||||||
if (!KDDockWidgets::usesNativeDraggingAndResizing()) {
|
if (!KDDockWidgets::usesNativeDraggingAndResizing()) {
|
||||||
setFlag(Qt::FramelessWindowHint, true);
|
setFlag(Qt::FramelessWindowHint, true);
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
|
||||||
setWidgetResizeHandler(new WidgetResizeHandler(this));
|
setWidgetResizeHandler(new WidgetResizeHandler(this));
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -228,6 +250,11 @@ DockWidgetBase *FloatingWindow::singleDockWidget() const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DockWidgetBase::List FloatingWindow::dockWidgets() const
|
||||||
|
{
|
||||||
|
return m_dropArea->dockWidgets();
|
||||||
|
}
|
||||||
|
|
||||||
const Frame::List FloatingWindow::frames() const
|
const Frame::List FloatingWindow::frames() const
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_dropArea);
|
Q_ASSERT(m_dropArea);
|
||||||
@@ -270,6 +297,14 @@ MultiSplitter *FloatingWindow::multiSplitter() const
|
|||||||
|
|
||||||
bool FloatingWindow::isInDragArea(QPoint globalPoint) const
|
bool FloatingWindow::isInDragArea(QPoint globalPoint) const
|
||||||
{
|
{
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// A click near the border will still send a Qt::NonClientMousePressEvent. We shouldn't
|
||||||
|
// interpret that as a drag, as it's for a native resize.
|
||||||
|
// Keep track of how we handled the WM_NCHITTEST
|
||||||
|
if (m_lastHitTest != 0 && m_lastHitTest != HTCAPTION)
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
|
||||||
return dragRect().contains(globalPoint);
|
return dragRect().contains(globalPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +343,7 @@ bool FloatingWindow::hasSingleDockWidget() const
|
|||||||
|
|
||||||
bool FloatingWindow::beingDeleted() const
|
bool FloatingWindow::beingDeleted() const
|
||||||
{
|
{
|
||||||
if (m_deleteScheduled)
|
if (m_deleteScheduled || m_inDtor)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// TODO: Confusing logic
|
// TODO: Confusing logic
|
||||||
@@ -387,10 +422,10 @@ void FloatingWindow::updateTitleAndIcon()
|
|||||||
m_titleBar->setTitle(title);
|
m_titleBar->setTitle(title);
|
||||||
m_titleBar->setIcon(icon);
|
m_titleBar->setIcon(icon);
|
||||||
|
|
||||||
if (KDDockWidgets::usesNativeTitleBar()) {
|
// Even without a native title bar it's nice to set the window title/icon, so it shows
|
||||||
setWindowTitle(title);
|
// in the taskbar (when minimization is supported), or Alt-Tab (in supporting Window Managers)
|
||||||
setWindowIcon(icon);
|
setWindowTitle(title);
|
||||||
}
|
setWindowIcon(icon);
|
||||||
}
|
}
|
||||||
|
|
||||||
void FloatingWindow::onCloseEvent(QCloseEvent *e)
|
void FloatingWindow::onCloseEvent(QCloseEvent *e)
|
||||||
@@ -438,6 +473,7 @@ LayoutSaver::FloatingWindow FloatingWindow::serialize() const
|
|||||||
auto mainWindow = qobject_cast<MainWindowBase*>(parentWidget());
|
auto mainWindow = qobject_cast<MainWindowBase*>(parentWidget());
|
||||||
fw.parentIndex = mainWindow ? DockRegistry::self()->mainwindows().indexOf(mainWindow)
|
fw.parentIndex = mainWindow ? DockRegistry::self()->mainwindows().indexOf(mainWindow)
|
||||||
: -1;
|
: -1;
|
||||||
|
|
||||||
return fw;
|
return fw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -465,4 +501,3 @@ bool FloatingWindow::event(QEvent *ev)
|
|||||||
|
|
||||||
return QWidgetAdapter::event(ev);
|
return QWidgetAdapter::event(ev);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,11 +12,13 @@
|
|||||||
#ifndef KD_FLOATING_WINDOW_P_H
|
#ifndef KD_FLOATING_WINDOW_P_H
|
||||||
#define KD_FLOATING_WINDOW_P_H
|
#define KD_FLOATING_WINDOW_P_H
|
||||||
|
|
||||||
#include "docks_export.h"
|
#include "../docks_export.h"
|
||||||
|
#include "../QWidgetAdapter.h"
|
||||||
|
#include "../LayoutSaver_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "Draggable_p.h"
|
#include "Draggable_p.h"
|
||||||
#include "QWidgetAdapter.h"
|
#include "DropArea_p.h"
|
||||||
#include "LayoutSaver_p.h"
|
#include "Qt5Qt6Compat_p.h"
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAbstractNativeEventFilter;
|
class QAbstractNativeEventFilter;
|
||||||
@@ -49,9 +51,15 @@ public:
|
|||||||
std::unique_ptr<WindowBeingDragged> makeWindow() override;
|
std::unique_ptr<WindowBeingDragged> makeWindow() override;
|
||||||
DockWidgetBase *singleDockWidget() const override;
|
DockWidgetBase *singleDockWidget() const override;
|
||||||
|
|
||||||
|
const QVector<DockWidgetBase*> dockWidgets() const;
|
||||||
const Frame::List frames() const;
|
const Frame::List frames() const;
|
||||||
DropArea *dropArea() const { return m_dropArea; }
|
DropArea *dropArea() const { return m_dropArea; }
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
void setLastHitTest(int hitTest) {
|
||||||
|
m_lastHitTest = hitTest;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/**
|
/**
|
||||||
* @brief Returns the title bar.
|
* @brief Returns the title bar.
|
||||||
*
|
*
|
||||||
@@ -128,18 +136,20 @@ Q_SIGNALS:
|
|||||||
void numFramesChanged();
|
void numFramesChanged();
|
||||||
void windowStateChanged(QWindowStateChangeEvent *);
|
void windowStateChanged(QWindowStateChangeEvent *);
|
||||||
protected:
|
protected:
|
||||||
|
void setupWindow();
|
||||||
|
void maybeCreateResizeHandler();
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
||||||
bool nativeEvent(const QByteArray &eventType, void *message, long *result) override;
|
bool nativeEvent(const QByteArray &eventType, void *message, Qt5Qt6Compat::qintptr *result) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool event(QEvent *ev) override;
|
bool event(QEvent *ev) override;
|
||||||
void onCloseEvent(QCloseEvent *) override;
|
void onCloseEvent(QCloseEvent *) override;
|
||||||
|
|
||||||
DropArea *const m_dropArea;
|
QPointer<DropArea> m_dropArea;
|
||||||
TitleBar *const m_titleBar;
|
TitleBar *const m_titleBar;
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(FloatingWindow)
|
Q_DISABLE_COPY(FloatingWindow)
|
||||||
void maybeCreateResizeHandler();
|
|
||||||
void onFrameCountChanged(int count);
|
void onFrameCountChanged(int count);
|
||||||
void onVisibleFrameCountChanged(int count);
|
void onVisibleFrameCountChanged(int count);
|
||||||
bool m_disableSetVisible = false;
|
bool m_disableSetVisible = false;
|
||||||
@@ -148,6 +158,9 @@ private:
|
|||||||
bool m_updatingTitleBarVisibility = false;
|
bool m_updatingTitleBarVisibility = false;
|
||||||
QMetaObject::Connection m_layoutDestroyedConnection;
|
QMetaObject::Connection m_layoutDestroyedConnection;
|
||||||
QAbstractNativeEventFilter *m_nchittestFilter = nullptr;
|
QAbstractNativeEventFilter *m_nchittestFilter = nullptr;
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
int m_lastHitTest = 0;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -135,7 +135,7 @@ void Frame::insertWidget(DockWidgetBase *dockWidget, int index, AddingOption add
|
|||||||
<< "; addingOption=" << addingOption;
|
<< "; addingOption=" << addingOption;
|
||||||
|
|
||||||
Q_ASSERT(dockWidget);
|
Q_ASSERT(dockWidget);
|
||||||
if (contains(dockWidget)) {
|
if (containsDockWidget(dockWidget)) {
|
||||||
qWarning() << "Frame::addWidget dockWidget already exists. this=" << this << "; dockWidget=" << dockWidget;
|
qWarning() << "Frame::addWidget dockWidget already exists. this=" << this << "; dockWidget=" << dockWidget;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -171,11 +171,25 @@ void Frame::removeWidget(DockWidgetBase *dw)
|
|||||||
removeWidget_impl(dw);
|
removeWidget_impl(dw);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::detachTab(DockWidgetBase *dw)
|
FloatingWindow* Frame::detachTab(DockWidgetBase *dockWidget)
|
||||||
{
|
{
|
||||||
if (m_inCtor || m_inDtor) return;
|
if (m_inCtor || m_inDtor) return nullptr;
|
||||||
|
|
||||||
detachTab_impl(dw);
|
QRect r = dockWidget->geometry();
|
||||||
|
removeWidget(dockWidget);
|
||||||
|
|
||||||
|
auto newFrame = Config::self().frameworkWidgetFactory()->createFrame();
|
||||||
|
const QPoint globalPoint = mapToGlobal(QPoint(0, 0));
|
||||||
|
newFrame->addWidget(dockWidget);
|
||||||
|
|
||||||
|
// We're potentially already dead at this point, as frames with 0 tabs auto-destruct. Don't access members from this point.
|
||||||
|
|
||||||
|
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(newFrame);
|
||||||
|
r.moveTopLeft(globalPoint);
|
||||||
|
floatingWindow->setSuggestedGeometry(r);
|
||||||
|
floatingWindow->show();
|
||||||
|
|
||||||
|
return floatingWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Frame::indexOfDockWidget(DockWidgetBase *dw)
|
int Frame::indexOfDockWidget(DockWidgetBase *dw)
|
||||||
@@ -347,7 +361,7 @@ const DockWidgetBase::List Frame::dockWidgets() const
|
|||||||
return dockWidgets;
|
return dockWidgets;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Frame::contains(DockWidgetBase *dockWidget) const
|
bool Frame::containsDockWidget(DockWidgetBase *dockWidget) const
|
||||||
{
|
{
|
||||||
const int count = dockWidgetCount();
|
const int count = dockWidgetCount();
|
||||||
for (int i = 0, e = count; i != e; ++i) {
|
for (int i = 0, e = count; i != e; ++i) {
|
||||||
@@ -442,7 +456,7 @@ bool Frame::anyNonDockable() const
|
|||||||
|
|
||||||
void Frame::onDockWidgetShown(DockWidgetBase *w)
|
void Frame::onDockWidgetShown(DockWidgetBase *w)
|
||||||
{
|
{
|
||||||
if (hasSingleDockWidget() && contains(w)) { // We have to call contains because it might be being in process of being reparented
|
if (hasSingleDockWidget() && containsDockWidget(w)) { // We have to call contains because it might be being in process of being reparented
|
||||||
if (!QWidgetAdapter::isVisible()) {
|
if (!QWidgetAdapter::isVisible()) {
|
||||||
qCDebug(hiding) << "Widget" << w << " was shown, we're=" << "; visible="
|
qCDebug(hiding) << "Widget" << w << " was shown, we're=" << "; visible="
|
||||||
<< QWidgetAdapter::isVisible();
|
<< QWidgetAdapter::isVisible();
|
||||||
@@ -453,7 +467,7 @@ void Frame::onDockWidgetShown(DockWidgetBase *w)
|
|||||||
|
|
||||||
void Frame::onDockWidgetHidden(DockWidgetBase *w)
|
void Frame::onDockWidgetHidden(DockWidgetBase *w)
|
||||||
{
|
{
|
||||||
if (hasSingleDockWidget() && contains(w)) { // We have to call contains because it might be being in process of being reparented
|
if (hasSingleDockWidget() && containsDockWidget(w)) { // We have to call contains because it might be being in process of being reparented
|
||||||
if (QWidgetAdapter::isVisible()) {
|
if (QWidgetAdapter::isVisible()) {
|
||||||
qCDebug(hiding) << "Widget" << w << " was hidden, we're="
|
qCDebug(hiding) << "Widget" << w << " was hidden, we're="
|
||||||
<< "; visible=" << QWidgetAdapter::isVisible()
|
<< "; visible=" << QWidgetAdapter::isVisible()
|
||||||
@@ -573,7 +587,6 @@ bool Frame::isInMainWindow() const
|
|||||||
bool Frame::event(QEvent *e)
|
bool Frame::event(QEvent *e)
|
||||||
{
|
{
|
||||||
if (e->type() == QEvent::ParentChange) {
|
if (e->type() == QEvent::ParentChange) {
|
||||||
qCDebug(docking) << "Frame: parent changed to =" << QWidgetAdapter::parentWidget();
|
|
||||||
if (auto dropArea = qobject_cast<DropArea *>(QWidgetAdapter::parentWidget())) {
|
if (auto dropArea = qobject_cast<DropArea *>(QWidgetAdapter::parentWidget())) {
|
||||||
setDropArea(dropArea);
|
setDropArea(dropArea);
|
||||||
} else {
|
} else {
|
||||||
@@ -637,7 +650,7 @@ QSize Frame::dockWidgetsMinSize() const
|
|||||||
{
|
{
|
||||||
QSize size = Layouting::Item::hardcodedMinimumSize;
|
QSize size = Layouting::Item::hardcodedMinimumSize;
|
||||||
for (DockWidgetBase *dw : dockWidgets())
|
for (DockWidgetBase *dw : dockWidgets())
|
||||||
size = size.expandedTo(Layouting::Widget_qwidget::widgetMinSize(dw));
|
size = size.expandedTo(Layouting::Widget::widgetMinSize(dw));
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,18 +19,19 @@
|
|||||||
#ifndef KD_FRAME_P_H
|
#ifndef KD_FRAME_P_H
|
||||||
#define KD_FRAME_P_H
|
#define KD_FRAME_P_H
|
||||||
|
|
||||||
#include "docks_export.h"
|
#include "kddockwidgets/docks_export.h"
|
||||||
#include "QWidgetAdapter.h"
|
#include "kddockwidgets/QWidgetAdapter.h"
|
||||||
#include "LayoutSaver_p.h"
|
#include "kddockwidgets/FocusScope.h"
|
||||||
#include "multisplitter/Widget_qwidget.h"
|
#include "../LayoutSaver_p.h"
|
||||||
|
#include "multisplitter/Widget.h"
|
||||||
#include "multisplitter/Item_p.h"
|
#include "multisplitter/Item_p.h"
|
||||||
#include "FocusScope.h"
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
|
class TestDocks;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class TitleBar;
|
class TitleBar;
|
||||||
@@ -55,6 +56,7 @@ class DOCKS_EXPORT Frame
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(KDDockWidgets::TitleBar* titleBar READ titleBar CONSTANT)
|
Q_PROPERTY(KDDockWidgets::TitleBar* titleBar READ titleBar CONSTANT)
|
||||||
|
Q_PROPERTY(int currentIndex READ currentIndex NOTIFY currentDockWidgetChanged)
|
||||||
public:
|
public:
|
||||||
typedef QList<Frame *> List;
|
typedef QList<Frame *> List;
|
||||||
|
|
||||||
@@ -78,7 +80,7 @@ public:
|
|||||||
void removeWidget(DockWidgetBase *);
|
void removeWidget(DockWidgetBase *);
|
||||||
|
|
||||||
///@brief detaches this dock widget
|
///@brief detaches this dock widget
|
||||||
void detachTab(DockWidgetBase *);
|
FloatingWindow *detachTab(DockWidgetBase *);
|
||||||
|
|
||||||
///@brief returns the index of the specified dock widget
|
///@brief returns the index of the specified dock widget
|
||||||
int indexOfDockWidget(DockWidgetBase *);
|
int indexOfDockWidget(DockWidgetBase *);
|
||||||
@@ -165,7 +167,7 @@ public:
|
|||||||
bool alwaysShowsTabs() const { return m_options & FrameOption_AlwaysShowsTabs; }
|
bool alwaysShowsTabs() const { return m_options & FrameOption_AlwaysShowsTabs; }
|
||||||
|
|
||||||
/// @brief returns whether the dockwidget @p w is inside this frame
|
/// @brief returns whether the dockwidget @p w is inside this frame
|
||||||
bool contains(DockWidgetBase *w) const;
|
bool containsDockWidget(DockWidgetBase *w) const;
|
||||||
|
|
||||||
///@brief returns the FloatingWindow this frame is in, if any
|
///@brief returns the FloatingWindow this frame is in, if any
|
||||||
FloatingWindow *floatingWindow() const;
|
FloatingWindow *floatingWindow() const;
|
||||||
@@ -268,7 +270,6 @@ protected:
|
|||||||
void onDockWidgetCountChanged();
|
void onDockWidgetCountChanged();
|
||||||
|
|
||||||
virtual void removeWidget_impl(DockWidgetBase *) = 0;
|
virtual void removeWidget_impl(DockWidgetBase *) = 0;
|
||||||
virtual void detachTab_impl(DockWidgetBase *) = 0;
|
|
||||||
virtual int indexOfDockWidget_impl(DockWidgetBase *) = 0;
|
virtual int indexOfDockWidget_impl(DockWidgetBase *) = 0;
|
||||||
virtual int currentIndex_impl() const = 0;
|
virtual int currentIndex_impl() const = 0;
|
||||||
virtual void setCurrentTabIndex_impl(int index) = 0;
|
virtual void setCurrentTabIndex_impl(int index) = 0;
|
||||||
@@ -277,10 +278,12 @@ protected:
|
|||||||
virtual DockWidgetBase *dockWidgetAt_impl(int index) const = 0;
|
virtual DockWidgetBase *dockWidgetAt_impl(int index) const = 0;
|
||||||
virtual DockWidgetBase *currentDockWidget_impl() const = 0;
|
virtual DockWidgetBase *currentDockWidget_impl() const = 0;
|
||||||
virtual int dockWidgetCount_impl() const = 0;
|
virtual int dockWidgetCount_impl() const = 0;
|
||||||
|
virtual int nonContentsHeight() const = 0;
|
||||||
|
|
||||||
bool m_inDtor = false;
|
bool m_inDtor = false;
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(Frame)
|
Q_DISABLE_COPY(Frame)
|
||||||
friend class TestDocks;
|
friend class ::TestDocks;
|
||||||
friend class TabWidget;
|
friend class TabWidget;
|
||||||
void onCurrentTabChanged(int index);
|
void onCurrentTabChanged(int index);
|
||||||
void scheduleDeleteLater();
|
void scheduleDeleteLater();
|
||||||
|
|||||||
@@ -17,17 +17,9 @@ Q_LOGGING_CATEGORY(hovering, "kdab.docks.hovering", QtWarningMsg)
|
|||||||
Q_LOGGING_CATEGORY(mouseevents, "kdab.docks.mouseevents", QtWarningMsg)
|
Q_LOGGING_CATEGORY(mouseevents, "kdab.docks.mouseevents", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(state, "kdab.docks.state", QtWarningMsg)
|
Q_LOGGING_CATEGORY(state, "kdab.docks.state", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(docking, "kdab.docks.docking", QtWarningMsg)
|
Q_LOGGING_CATEGORY(docking, "kdab.docks.docking", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(globalevents, "kdab.docks.globalevents", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(hiding, "kdab.docks.hiding", QtWarningMsg)
|
Q_LOGGING_CATEGORY(hiding, "kdab.docks.hiding", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(closing, "kdab.docks.closing", QtWarningMsg)
|
Q_LOGGING_CATEGORY(closing, "kdab.docks.closing", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(overlay, "kdab.docks.overlay", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(dropping, "kdab.docks.dropping", QtWarningMsg)
|
Q_LOGGING_CATEGORY(dropping, "kdab.docks.dropping", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(restoring, "kdab.docks.restoring", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(title, "kdab.docks.title", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(closebutton, "kdab.docks.closebutton", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(sizing, "kdab.multisplitter.sizing", QtWarningMsg)
|
Q_LOGGING_CATEGORY(sizing, "kdab.multisplitter.sizing", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(multisplittercreation, "kdab.multisplitter.multisplittercreation", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(addwidget, "kdab.multisplitter.addwidget", QtWarningMsg)
|
Q_LOGGING_CATEGORY(addwidget, "kdab.multisplitter.addwidget", QtWarningMsg)
|
||||||
Q_LOGGING_CATEGORY(anchors, "kdab.multisplitter.anchors", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(item, "kdab.multisplitter.item", QtWarningMsg)
|
|
||||||
Q_LOGGING_CATEGORY(placeholder, "kdab.multisplitter.placeholder", QtWarningMsg)
|
Q_LOGGING_CATEGORY(placeholder, "kdab.multisplitter.placeholder", QtWarningMsg)
|
||||||
|
|||||||
@@ -29,7 +29,7 @@
|
|||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "multisplitter/Widget_qwidget.h"
|
#include "multisplitter/Widget.h"
|
||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ MultiSplitter::MultiSplitter(QWidgetOrQuick *parent)
|
|||||||
|
|
||||||
setLayoutSize(parent->size());
|
setLayoutSize(parent->size());
|
||||||
|
|
||||||
qCDebug(multisplittercreation()) << "MultiSplitter";
|
qCDebug(creation) << "MultiSplitter";
|
||||||
|
|
||||||
// Initialize min size
|
// Initialize min size
|
||||||
updateSizeConstraints();
|
updateSizeConstraints();
|
||||||
@@ -56,7 +56,7 @@ MultiSplitter::MultiSplitter(QWidgetOrQuick *parent)
|
|||||||
|
|
||||||
MultiSplitter::~MultiSplitter()
|
MultiSplitter::~MultiSplitter()
|
||||||
{
|
{
|
||||||
qCDebug(multisplittercreation) << "~MultiSplitter" << this;
|
qCDebug(creation) << "~MultiSplitter" << this;
|
||||||
if (m_rootItem->hostWidget()->asQObject() == this)
|
if (m_rootItem->hostWidget()->asQObject() == this)
|
||||||
delete m_rootItem;
|
delete m_rootItem;
|
||||||
DockRegistry::self()->unregisterLayout(this);
|
DockRegistry::self()->unregisterLayout(this);
|
||||||
@@ -72,7 +72,7 @@ bool MultiSplitter::onResize(QSize newSize)
|
|||||||
qCDebug(sizing) << Q_FUNC_INFO << "; new=" << newSize
|
qCDebug(sizing) << Q_FUNC_INFO << "; new=" << newSize
|
||||||
<< "; window=" << window();
|
<< "; window=" << window();
|
||||||
|
|
||||||
QScopedValueRollback<bool>(m_inResizeEvent, true); // to avoid re-entrancy
|
QScopedValueRollback<bool> resizeGuard(m_inResizeEvent, true); // to avoid re-entrancy
|
||||||
|
|
||||||
if (!LayoutSaver::restoreInProgress()) {
|
if (!LayoutSaver::restoreInProgress()) {
|
||||||
// don't resize anything while we're restoring the layout
|
// don't resize anything while we're restoring the layout
|
||||||
@@ -135,7 +135,7 @@ bool MultiSplitter::validateInputs(QWidgetOrQuick *widget,
|
|||||||
|
|
||||||
Layouting::Item *item = itemForFrame(qobject_cast<Frame*>(widget));
|
Layouting::Item *item = itemForFrame(qobject_cast<Frame*>(widget));
|
||||||
|
|
||||||
if (contains(item)) {
|
if (containsItem(item)) {
|
||||||
qWarning() << "MultiSplitter::addWidget: Already contains" << widget;
|
qWarning() << "MultiSplitter::addWidget: Already contains" << widget;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -148,7 +148,7 @@ bool MultiSplitter::validateInputs(QWidgetOrQuick *widget,
|
|||||||
const bool relativeToThis = relativeToFrame == nullptr;
|
const bool relativeToThis = relativeToFrame == nullptr;
|
||||||
|
|
||||||
Layouting::Item *relativeToItem = itemForFrame(relativeToFrame);
|
Layouting::Item *relativeToItem = itemForFrame(relativeToFrame);
|
||||||
if (!relativeToThis && !contains(relativeToItem)) {
|
if (!relativeToThis && !containsItem(relativeToItem)) {
|
||||||
qWarning() << "MultiSplitter::addWidget: Doesn't contain relativeTo:"
|
qWarning() << "MultiSplitter::addWidget: Doesn't contain relativeTo:"
|
||||||
<< "; relativeToFrame=" << relativeToFrame
|
<< "; relativeToFrame=" << relativeToFrame
|
||||||
<< "; relativeToItem=" << relativeToItem
|
<< "; relativeToItem=" << relativeToItem
|
||||||
@@ -242,12 +242,12 @@ void MultiSplitter::removeItem(Layouting::Item *item)
|
|||||||
item->parentContainer()->removeItem(item);
|
item->parentContainer()->removeItem(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MultiSplitter::contains(const Layouting::Item *item) const
|
bool MultiSplitter::containsItem(const Layouting::Item *item) const
|
||||||
{
|
{
|
||||||
return m_rootItem->contains_recursive(item);
|
return m_rootItem->contains_recursive(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MultiSplitter::contains(const Frame *frame) const
|
bool MultiSplitter::containsFrame(const Frame *frame) const
|
||||||
{
|
{
|
||||||
return itemForFrame(frame) != nullptr;
|
return itemForFrame(frame) != nullptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,12 +35,14 @@ class Separator;
|
|||||||
class Widget_qwidget;
|
class Widget_qwidget;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class TestDocks;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class MainWindowBase;
|
class MainWindowBase;
|
||||||
class FloatingWindow;
|
class FloatingWindow;
|
||||||
class Frame;
|
class Frame;
|
||||||
class WindowBeingDragged;
|
struct WindowBeingDragged;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MultiSplitter is simply a wrapper around Layouting::Item in which the hosted widgets are
|
* MultiSplitter is simply a wrapper around Layouting::Item in which the hosted widgets are
|
||||||
@@ -87,12 +89,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Returns true if this layout contains the specified item.
|
* @brief Returns true if this layout contains the specified item.
|
||||||
*/
|
*/
|
||||||
bool contains(const Layouting::Item *) const;
|
bool containsItem(const Layouting::Item *) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns true if this layout contains the specified frame.
|
* @brief Returns true if this layout contains the specified frame.
|
||||||
*/
|
*/
|
||||||
bool contains(const Frame *) const;
|
bool containsFrame(const Frame *) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the number of Item objects in this layout.
|
* @brief Returns the number of Item objects in this layout.
|
||||||
@@ -213,7 +215,7 @@ protected:
|
|||||||
private:
|
private:
|
||||||
bool m_inResizeEvent = false;
|
bool m_inResizeEvent = false;
|
||||||
|
|
||||||
friend class TestDocks;
|
friend class ::TestDocks;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns the frames contained in @p frameOrMultiSplitter
|
* @brief returns the frames contained in @p frameOrMultiSplitter
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "Position_p.h"
|
#include "Position_p.h"
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "MultiSplitter_p.h"
|
#include "MultiSplitter_p.h"
|
||||||
|
#include "FloatingWindow_p.h"
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -82,7 +83,7 @@ bool Position::containsPlaceholder(Layouting::Item *item) const
|
|||||||
|
|
||||||
void Position::removePlaceholders()
|
void Position::removePlaceholders()
|
||||||
{
|
{
|
||||||
QScopedValueRollback<bool>(m_clearing, true);
|
QScopedValueRollback<bool> clearGuard(m_clearing, true);
|
||||||
m_placeholders.clear();
|
m_placeholders.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ void SideBar::removeDockWidget(DockWidgetBase *dw)
|
|||||||
updateSize();
|
updateSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SideBar::contains(DockWidgetBase *dw) const
|
bool SideBar::containsDockWidget(DockWidgetBase *dw) const
|
||||||
{
|
{
|
||||||
return m_dockWidgets.contains(dw);
|
return m_dockWidgets.contains(dw);
|
||||||
}
|
}
|
||||||
@@ -107,3 +107,19 @@ void SideBar::toggleOverlay(DockWidgetBase *dw)
|
|||||||
{
|
{
|
||||||
m_mainWindow->toggleOverlayOnSideBar(dw);
|
m_mainWindow->toggleOverlayOnSideBar(dw);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList SideBar::serialize() const
|
||||||
|
{
|
||||||
|
QStringList ids;
|
||||||
|
ids.reserve(m_dockWidgets.size());
|
||||||
|
for (DockWidgetBase *dw : m_dockWidgets)
|
||||||
|
ids << dw->uniqueName();
|
||||||
|
|
||||||
|
return ids;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideBar::clear()
|
||||||
|
{
|
||||||
|
for (DockWidgetBase *dw : qAsConst(m_dockWidgets))
|
||||||
|
removeDockWidget(dw);
|
||||||
|
}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ public:
|
|||||||
|
|
||||||
void addDockWidget(DockWidgetBase *dw);
|
void addDockWidget(DockWidgetBase *dw);
|
||||||
void removeDockWidget(DockWidgetBase *dw);
|
void removeDockWidget(DockWidgetBase *dw);
|
||||||
bool contains(DockWidgetBase *) const;
|
bool containsDockWidget(DockWidgetBase *) const;
|
||||||
|
|
||||||
/// @brief Returns this side bar's orientation
|
/// @brief Returns this side bar's orientation
|
||||||
Qt::Orientation orientation() const;
|
Qt::Orientation orientation() const;
|
||||||
@@ -49,6 +49,13 @@ public:
|
|||||||
/// @brief Toggles the dock widget overlay. Equivalent to the user clicking on the button.
|
/// @brief Toggles the dock widget overlay. Equivalent to the user clicking on the button.
|
||||||
void toggleOverlay(DockWidgetBase *);
|
void toggleOverlay(DockWidgetBase *);
|
||||||
|
|
||||||
|
/// @brief returns a serialization of this sidebar's state
|
||||||
|
/// Currently it's just a list of dock widget ids
|
||||||
|
QStringList serialize() const;
|
||||||
|
|
||||||
|
/// @brief clears the sidebar (removes all dock widgets from it)
|
||||||
|
void clear();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual void addDockWidget_Impl(DockWidgetBase *dock) = 0;
|
virtual void addDockWidget_Impl(DockWidgetBase *dock) = 0;
|
||||||
virtual void removeDockWidget_Impl(DockWidgetBase *dock) = 0;
|
virtual void removeDockWidget_Impl(DockWidgetBase *dock) = 0;
|
||||||
|
|||||||
@@ -69,6 +69,8 @@ void TitleBar::init()
|
|||||||
// repaint
|
// repaint
|
||||||
update();
|
update();
|
||||||
});
|
});
|
||||||
|
updateCloseButton();
|
||||||
|
updateFloatButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBar::~TitleBar()
|
TitleBar::~TitleBar()
|
||||||
@@ -89,6 +91,16 @@ bool TitleBar::onDoubleClicked()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TitleBar::updateCloseButton()
|
||||||
|
{
|
||||||
|
|
||||||
|
const bool anyNonClosable = frame() ? frame()->anyNonClosable()
|
||||||
|
: (floatingWindow() ? floatingWindow()->anyNonClosable()
|
||||||
|
: false);
|
||||||
|
|
||||||
|
setCloseButtonEnabled(!anyNonClosable);
|
||||||
|
}
|
||||||
|
|
||||||
void TitleBar::toggleMaximized()
|
void TitleBar::toggleMaximized()
|
||||||
{
|
{
|
||||||
if (!m_floatingWindow)
|
if (!m_floatingWindow)
|
||||||
@@ -116,15 +128,34 @@ bool TitleBar::isOverlayed() const
|
|||||||
return m_frame && m_frame->isOverlayed();
|
return m_frame && m_frame->isOverlayed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TitleBar::setCloseButtonEnabled(bool enabled)
|
||||||
|
{
|
||||||
|
if (enabled != m_closeButtonEnabled) {
|
||||||
|
m_closeButtonEnabled = enabled;
|
||||||
|
Q_EMIT closeButtonEnabledChanged(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TitleBar::setFloatButtonVisible(bool visible)
|
||||||
|
{
|
||||||
|
if (visible != m_floatButtonVisible) {
|
||||||
|
m_floatButtonVisible = visible;
|
||||||
|
Q_EMIT floatButtonVisibleChanged(visible);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TitleBar::setFloatButtonToolTip(const QString &tip)
|
||||||
|
{
|
||||||
|
if (tip != m_floatButtonToolTip) {
|
||||||
|
m_floatButtonToolTip = tip;
|
||||||
|
Q_EMIT floatButtonToolTipChanged(tip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TitleBar::setTitle(const QString &title)
|
void TitleBar::setTitle(const QString &title)
|
||||||
{
|
{
|
||||||
if (title != m_title) {
|
if (title != m_title) {
|
||||||
m_title = title;
|
m_title = title;
|
||||||
qCDebug(::title) << Q_FUNC_INFO << "\n title=" << title
|
|
||||||
<< "\n this=" << this
|
|
||||||
<< "\n parentWidget=" << parentWidget()
|
|
||||||
<< "\n isVisible=" << isVisible()
|
|
||||||
<< "\nwindow=" << window();
|
|
||||||
update();
|
update();
|
||||||
Q_EMIT titleChanged();
|
Q_EMIT titleChanged();
|
||||||
}
|
}
|
||||||
@@ -140,7 +171,7 @@ std::unique_ptr<WindowBeingDragged> TitleBar::makeWindow()
|
|||||||
{
|
{
|
||||||
if (!isVisible() && window()->isVisible()) {
|
if (!isVisible() && window()->isVisible()) {
|
||||||
qWarning() << "TitleBar::makeWindow shouldn't be called on invisible title bar"
|
qWarning() << "TitleBar::makeWindow shouldn't be called on invisible title bar"
|
||||||
<< this << window()->isVisible() << parentWidget();
|
<< this << window()->isVisible();
|
||||||
|
|
||||||
if (m_floatingWindow) {
|
if (m_floatingWindow) {
|
||||||
qWarning() << "Has floating window with titlebar=" << m_floatingWindow->titleBar()
|
qWarning() << "Has floating window with titlebar=" << m_floatingWindow->titleBar()
|
||||||
@@ -198,6 +229,12 @@ bool TitleBar::supportsFloatingButton() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (DockWidgetBase *dw = singleDockWidget()) {
|
||||||
|
// Don't show the dock/undock button if the window is not dockable
|
||||||
|
if (dw->options() & DockWidgetBase::Option_NotDockable)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// If we have a floating window with nested dock widgets we can't re-attach, because we don't
|
// If we have a floating window with nested dock widgets we can't re-attach, because we don't
|
||||||
// know where to
|
// know where to
|
||||||
return !m_floatingWindow || m_floatingWindow->hasSingleFrame();
|
return !m_floatingWindow || m_floatingWindow->hasSingleFrame();
|
||||||
@@ -361,3 +398,24 @@ void TitleBar::onAutoHideClicked()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TitleBar::closeButtonEnabled() const
|
||||||
|
{
|
||||||
|
return m_closeButtonEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool TitleBar::floatButtonVisible() const
|
||||||
|
{
|
||||||
|
return m_floatButtonVisible;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString TitleBar::floatButtonToolTip() const
|
||||||
|
{
|
||||||
|
return m_floatButtonToolTip;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TitleBar::updateFloatButton()
|
||||||
|
{
|
||||||
|
setFloatButtonToolTip(floatingWindow() ? tr("Dock window") : tr("Undock window"));
|
||||||
|
setFloatButtonVisible(supportsFloatingButton());
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,12 +12,12 @@
|
|||||||
#ifndef KD_TITLEBAR_P_H
|
#ifndef KD_TITLEBAR_P_H
|
||||||
#define KD_TITLEBAR_P_H
|
#define KD_TITLEBAR_P_H
|
||||||
|
|
||||||
#include "docks_export.h"
|
#include "kddockwidgets/docks_export.h"
|
||||||
|
|
||||||
#include "QWidgetAdapter.h"
|
#include "kddockwidgets/QWidgetAdapter.h"
|
||||||
|
#include "kddockwidgets/DockWidgetBase.h"
|
||||||
#include "Draggable_p.h"
|
#include "Draggable_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "DockWidgetBase.h"
|
|
||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QIcon>
|
#include <QIcon>
|
||||||
@@ -27,7 +27,7 @@ class QHBoxLayout;
|
|||||||
class QLabel;
|
class QLabel;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class TestCommon;
|
class TestDocks;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
@@ -41,6 +41,9 @@ class DOCKS_EXPORT TitleBar : public QWidgetAdapter
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
|
Q_PROPERTY(QString title READ title NOTIFY titleChanged)
|
||||||
Q_PROPERTY(bool hasIcon READ hasIcon NOTIFY iconChanged)
|
Q_PROPERTY(bool hasIcon READ hasIcon NOTIFY iconChanged)
|
||||||
|
Q_PROPERTY(bool closeButtonEnabled READ closeButtonEnabled WRITE setCloseButtonEnabled NOTIFY closeButtonEnabledChanged)
|
||||||
|
Q_PROPERTY(bool floatButtonVisible READ floatButtonVisible WRITE setFloatButtonVisible NOTIFY floatButtonVisibleChanged)
|
||||||
|
Q_PROPERTY(QString floatButtonToolTip READ floatButtonToolTip NOTIFY floatButtonToolTipChanged)
|
||||||
public:
|
public:
|
||||||
typedef QVector<TitleBar *> List;
|
typedef QVector<TitleBar *> List;
|
||||||
|
|
||||||
@@ -87,20 +90,24 @@ public:
|
|||||||
QIcon icon() const;
|
QIcon icon() const;
|
||||||
|
|
||||||
///@brief toggle floating
|
///@brief toggle floating
|
||||||
bool onDoubleClicked();
|
Q_INVOKABLE bool onDoubleClicked();
|
||||||
|
|
||||||
///@brief getter for m_frame
|
///@brief getter for m_frame
|
||||||
const Frame *frame() const { return m_frame; }
|
Frame *frame() const { return m_frame; }
|
||||||
|
|
||||||
///@brief getter for m_floatingWindow
|
///@brief getter for m_floatingWindow
|
||||||
const FloatingWindow *floatingWindow() const { return m_floatingWindow; }
|
FloatingWindow *floatingWindow() const { return m_floatingWindow; }
|
||||||
|
|
||||||
virtual void updateCloseButton() {}
|
/// @brief updates the close button enabled state
|
||||||
|
void updateCloseButton();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void titleChanged();
|
void titleChanged();
|
||||||
void iconChanged();
|
void iconChanged();
|
||||||
void isFocusedChanged();
|
void isFocusedChanged();
|
||||||
|
void closeButtonEnabledChanged(bool);
|
||||||
|
void floatButtonVisibleChanged(bool);
|
||||||
|
void floatButtonToolTipChanged(const QString &);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
@@ -111,25 +118,31 @@ protected:
|
|||||||
Q_INVOKABLE void toggleMaximized();
|
Q_INVOKABLE void toggleMaximized();
|
||||||
Q_INVOKABLE void onAutoHideClicked();
|
Q_INVOKABLE void onAutoHideClicked();
|
||||||
|
|
||||||
virtual void updateFloatButton() {}
|
bool closeButtonEnabled() const;
|
||||||
|
bool floatButtonVisible() const;
|
||||||
|
QString floatButtonToolTip() const;
|
||||||
|
|
||||||
virtual void updateMaximizeButton() {}
|
virtual void updateMaximizeButton() {}
|
||||||
|
|
||||||
virtual void updateMinimizeButton() {}
|
virtual void updateMinimizeButton() {}
|
||||||
virtual void updateAutoHideButton() {}
|
virtual void updateAutoHideButton() {}
|
||||||
|
|
||||||
|
#ifdef DOCKS_DEVELOPER_MODE
|
||||||
// The following are needed for the unit-tests
|
// The following are needed for the unit-tests
|
||||||
virtual bool isCloseButtonVisible() const { return true; }
|
virtual bool isCloseButtonVisible() const = 0;
|
||||||
virtual bool isCloseButtonEnabled() const { return true; }
|
virtual bool isCloseButtonEnabled() const = 0;
|
||||||
virtual bool isFloatButtonVisible() const { return true; }
|
virtual bool isFloatButtonVisible() const = 0;
|
||||||
virtual bool isFloatButtonEnabled() const { return true; }
|
virtual bool isFloatButtonEnabled() const = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
void focusInEvent(QFocusEvent *event) override;
|
void focusInEvent(QFocusEvent *event) override;
|
||||||
|
|
||||||
bool isOverlayed() const;
|
bool isOverlayed() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class TestDocks;
|
friend class ::TestDocks;
|
||||||
friend class ::TestCommon;
|
void updateFloatButton();
|
||||||
|
void setCloseButtonEnabled(bool);
|
||||||
|
void setFloatButtonVisible(bool);
|
||||||
|
void setFloatButtonToolTip(const QString &);
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
@@ -140,6 +153,9 @@ private:
|
|||||||
Frame *const m_frame;
|
Frame *const m_frame;
|
||||||
FloatingWindow *const m_floatingWindow;
|
FloatingWindow *const m_floatingWindow;
|
||||||
const bool m_supportsAutoHide;
|
const bool m_supportsAutoHide;
|
||||||
|
bool m_closeButtonEnabled = true;
|
||||||
|
bool m_floatButtonVisible = true;
|
||||||
|
QString m_floatButtonToolTip;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,28 +13,58 @@
|
|||||||
#define KD_UTILS_P_H
|
#define KD_UTILS_P_H
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "QWidgetAdapter.h"
|
||||||
|
|
||||||
#include <QApplication>
|
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QWidget>
|
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTQUICK
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
|
# include "private/quick/TitleBarQuick_p.h"
|
||||||
|
|
||||||
# include <QQuickItem>
|
# include <QQuickItem>
|
||||||
# include <QQuickWindow>
|
# include <QQuickView>
|
||||||
|
#else
|
||||||
|
# include <QApplication>
|
||||||
|
# include <QAbstractButton>
|
||||||
|
# include <QLineEdit>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef QT_X11EXTRAS_LIB
|
#ifdef QT_X11EXTRAS_LIB
|
||||||
# include <QtX11Extras/QX11Info>
|
# include <QtX11Extras/QX11Info>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QWidget;
|
||||||
|
class QWindow;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
|
inline QQuickItem* mouseAreaForPos(QQuickItem *item, QPointF globalPos);
|
||||||
|
#endif
|
||||||
|
|
||||||
inline bool isWayland()
|
inline bool isWayland()
|
||||||
{
|
{
|
||||||
return qApp->platformName() == QLatin1String("wayland");
|
return qApp->platformName() == QLatin1String("wayland");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool isOffscreen()
|
||||||
|
{
|
||||||
|
return qApp->platformName() == QLatin1String("offscreen");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool kddwUsesQtWidgets()
|
||||||
|
{
|
||||||
|
// Returns whether KDDW is built for QtWidgets or QtQuick
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isLeftButtonPressed()
|
inline bool isLeftButtonPressed()
|
||||||
{
|
{
|
||||||
return qApp->mouseButtons() & Qt::LeftButton;
|
return qApp->mouseButtons() & Qt::LeftButton;
|
||||||
@@ -69,6 +99,24 @@ inline bool usesNativeDraggingAndResizing()
|
|||||||
return usesNativeTitleBar() || usesAeroSnapWithCustomDecos();
|
return usesNativeTitleBar() || usesAeroSnapWithCustomDecos();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool usesFallbackMouseGrabber()
|
||||||
|
{
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
// Will use QWidget::grabMouse()
|
||||||
|
return false;
|
||||||
|
#else
|
||||||
|
// For QtQuick we use the global event filter as mouse delivery is flaky
|
||||||
|
// For example, the same QQuickItem that receives the press isn't receiving the mouse moves
|
||||||
|
// when the top-level window moves.
|
||||||
|
return true;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void activateWindow(QWindow *window)
|
||||||
|
{
|
||||||
|
window->requestActivate();
|
||||||
|
}
|
||||||
|
|
||||||
inline bool windowManagerHasTranslucency()
|
inline bool windowManagerHasTranslucency()
|
||||||
{
|
{
|
||||||
#ifdef QT_X11EXTRAS_LIB
|
#ifdef QT_X11EXTRAS_LIB
|
||||||
@@ -102,6 +150,84 @@ inline int screenNumberForWindow(const QWindow *window)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QMouseEvent *mouseEvent(QEvent *e)
|
||||||
|
{
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::MouseButtonPress:
|
||||||
|
case QEvent::MouseButtonDblClick:
|
||||||
|
case QEvent::MouseButtonRelease:
|
||||||
|
case QEvent::MouseMove:
|
||||||
|
case QEvent::NonClientAreaMouseButtonPress:
|
||||||
|
case QEvent::NonClientAreaMouseButtonRelease:
|
||||||
|
case QEvent::NonClientAreaMouseMove:
|
||||||
|
return static_cast<QMouseEvent *>(e);
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isNonClientMouseEvent(const QEvent *e)
|
||||||
|
{
|
||||||
|
switch (e->type()) {
|
||||||
|
case QEvent::NonClientAreaMouseButtonPress:
|
||||||
|
case QEvent::NonClientAreaMouseButtonRelease:
|
||||||
|
case QEvent::NonClientAreaMouseMove:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isWindow(const QWindow *w)
|
||||||
|
{
|
||||||
|
return w != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int startDragDistance()
|
||||||
|
{
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
return QApplication::startDragDistance();
|
||||||
|
#else
|
||||||
|
return 4;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @brief Returns the QWidget or QtQuickItem at the specified position
|
||||||
|
/// Basically QApplication::widgetAt() but with support for QtQuick
|
||||||
|
inline WidgetType* mouseReceiverAt(QPoint globalPos)
|
||||||
|
{
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
return qApp->widgetAt(globalPos);
|
||||||
|
#else
|
||||||
|
auto window = qobject_cast<QQuickWindow*>(qApp->topLevelAt(globalPos));
|
||||||
|
if (!window)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
return mouseAreaForPos(window->contentItem(), globalPos);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Not the entire TitleBar is draggable. For example, the close button won't allow to start a drag from there.
|
||||||
|
/// Returns true if we're over such controls where we shouldn't drag.
|
||||||
|
inline bool inDisallowDragWidget(QPoint globalPos)
|
||||||
|
{
|
||||||
|
WidgetType *widget = mouseReceiverAt(globalPos);
|
||||||
|
if (!widget)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
// User might have a line edit on the toolbar. TODO: Not so elegant fix, we should make the user's tabbar implement some virtual method...
|
||||||
|
return qobject_cast<QAbstractButton*>(widget) ||
|
||||||
|
qobject_cast<QLineEdit*>(widget);
|
||||||
|
#else
|
||||||
|
return widget->objectName() != QLatin1String("draggableMouseArea");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
inline int screenNumberForWidget(const QWidget *widget)
|
inline int screenNumberForWidget(const QWidget *widget)
|
||||||
{
|
{
|
||||||
@@ -113,6 +239,21 @@ inline QSize screenSizeForWidget(const QWidget *widget)
|
|||||||
return screenSizeForWindow(widget->window()->windowHandle());
|
return screenSizeForWindow(widget->window()->windowHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QPoint mapToGlobal(QWidget *w, QPoint p)
|
||||||
|
{
|
||||||
|
return w->mapToGlobal(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void activateWindow(QWidget *widget)
|
||||||
|
{
|
||||||
|
widget->activateWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool isWindow(const QWidget *w)
|
||||||
|
{
|
||||||
|
return w && w->isWindow();
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
inline int screenNumberForWidget(const QQuickItem *w)
|
inline int screenNumberForWidget(const QQuickItem *w)
|
||||||
@@ -125,6 +266,34 @@ inline QSize screenSizeForWidget(const QQuickItem *w)
|
|||||||
return screenSizeForWindow(w->window());
|
return screenSizeForWindow(w->window());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline QPoint mapToGlobal(QQuickItem *item, QPoint p)
|
||||||
|
{
|
||||||
|
return item->mapToGlobal(p).toPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QQuickItem* mouseAreaForPos(QQuickItem *item, QPointF globalPos)
|
||||||
|
{
|
||||||
|
QRectF rect = item->boundingRect();
|
||||||
|
rect.moveTopLeft(item->mapToGlobal(QPointF(0, 0)));
|
||||||
|
|
||||||
|
// Assumes children are inside its parent. That's fine for KDDW's purposes.
|
||||||
|
if (!rect.contains(globalPos)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
const QList<QQuickItem*> children = item->childItems();
|
||||||
|
|
||||||
|
for (auto it = children.rbegin(), end = children.rend(); it != end; ++it) {
|
||||||
|
if (QQuickItem *receiver = mouseAreaForPos(*it, globalPos))
|
||||||
|
return receiver;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (QLatin1String(item->metaObject()->className()) == QLatin1String("QQuickMouseArea"))
|
||||||
|
return item;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -15,16 +15,14 @@
|
|||||||
#include "DragController_p.h"
|
#include "DragController_p.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
#include "Qt5Qt6Compat_p.h"
|
#include "Qt5Qt6Compat_p.h"
|
||||||
|
#include "Utils_p.h"
|
||||||
|
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QWidget>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QApplication>
|
#include <QGuiApplication>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include <QAbstractButton>
|
|
||||||
#include <QLineEdit>
|
|
||||||
|
|
||||||
#if defined(Q_OS_WIN)
|
#if defined(Q_OS_WIN)
|
||||||
# include <QtGui/private/qhighdpiscaling_p.h>
|
# include <QtGui/private/qhighdpiscaling_p.h>
|
||||||
@@ -42,7 +40,7 @@ int widgetResizeHandlerMargin = 4; //4 pixel
|
|||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
bool WidgetResizeHandler::s_disableAllHandlers = false;
|
bool WidgetResizeHandler::s_disableAllHandlers = false;
|
||||||
WidgetResizeHandler::WidgetResizeHandler(QWidget *target)
|
WidgetResizeHandler::WidgetResizeHandler(QWidgetOrQuick *target)
|
||||||
: QObject(target)
|
: QObject(target)
|
||||||
{
|
{
|
||||||
setTarget(target);
|
setTarget(target);
|
||||||
@@ -54,10 +52,11 @@ WidgetResizeHandler::~WidgetResizeHandler()
|
|||||||
|
|
||||||
bool WidgetResizeHandler::eventFilter(QObject *o, QEvent *e)
|
bool WidgetResizeHandler::eventFilter(QObject *o, QEvent *e)
|
||||||
{
|
{
|
||||||
if (s_disableAllHandlers || o != mTarget)
|
if (s_disableAllHandlers || o != mTarget) {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
auto widget = qobject_cast<QWidget*>(o);
|
auto widget = qobject_cast<QWidgetOrQuick*>(o);
|
||||||
if (!widget || !widget->isTopLevel()) {
|
if (!widget || !widget->isTopLevel()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -68,7 +67,7 @@ bool WidgetResizeHandler::eventFilter(QObject *o, QEvent *e)
|
|||||||
break;
|
break;
|
||||||
auto mouseEvent = static_cast<QMouseEvent *>(e);
|
auto mouseEvent = static_cast<QMouseEvent *>(e);
|
||||||
auto cursorPos = cursorPosition(Qt5Qt6Compat::eventGlobalPos(mouseEvent));
|
auto cursorPos = cursorPosition(Qt5Qt6Compat::eventGlobalPos(mouseEvent));
|
||||||
if (cursorPos == CursorPosition::Undefined)
|
if (cursorPos == CursorPosition_Undefined)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QRect widgetRect = mTarget->rect().marginsAdded(QMargins(widgetResizeHandlerMargin, widgetResizeHandlerMargin, widgetResizeHandlerMargin, widgetResizeHandlerMargin));
|
const QRect widgetRect = mTarget->rect().marginsAdded(QMargins(widgetResizeHandlerMargin, widgetResizeHandlerMargin, widgetResizeHandlerMargin, widgetResizeHandlerMargin));
|
||||||
@@ -129,9 +128,9 @@ void WidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
|
|||||||
const int minWidth = mTarget->minimumWidth();
|
const int minWidth = mTarget->minimumWidth();
|
||||||
const int maxWidth = mTarget->maximumWidth();
|
const int maxWidth = mTarget->maximumWidth();
|
||||||
switch (mCursorPos) {
|
switch (mCursorPos) {
|
||||||
case CursorPosition::TopLeft:
|
case CursorPosition_TopLeft:
|
||||||
case CursorPosition::Left:
|
case CursorPosition_Left:
|
||||||
case CursorPosition::BottomLeft: {
|
case CursorPosition_BottomLeft: {
|
||||||
deltaWidth = oldGeometry.left() - globalPos.x();
|
deltaWidth = oldGeometry.left() - globalPos.x();
|
||||||
newWidth = qBound(minWidth, mTarget->width() + deltaWidth, maxWidth);
|
newWidth = qBound(minWidth, mTarget->width() + deltaWidth, maxWidth);
|
||||||
deltaWidth = newWidth - mTarget->width();
|
deltaWidth = newWidth - mTarget->width();
|
||||||
@@ -142,9 +141,9 @@ void WidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CursorPosition::TopRight:
|
case CursorPosition_TopRight:
|
||||||
case CursorPosition::Right:
|
case CursorPosition_Right:
|
||||||
case CursorPosition::BottomRight: {
|
case CursorPosition_BottomRight: {
|
||||||
deltaWidth = globalPos.x() - newGeometry.right();
|
deltaWidth = globalPos.x() - newGeometry.right();
|
||||||
newWidth = qBound(minWidth, mTarget->width() + deltaWidth, maxWidth);
|
newWidth = qBound(minWidth, mTarget->width() + deltaWidth, maxWidth);
|
||||||
deltaWidth = newWidth - mTarget->width();
|
deltaWidth = newWidth - mTarget->width();
|
||||||
@@ -164,9 +163,9 @@ void WidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
|
|||||||
int deltaHeight = 0;
|
int deltaHeight = 0;
|
||||||
int newHeight = 0;
|
int newHeight = 0;
|
||||||
switch (mCursorPos) {
|
switch (mCursorPos) {
|
||||||
case CursorPosition::TopLeft:
|
case CursorPosition_TopLeft:
|
||||||
case CursorPosition::Top:
|
case CursorPosition_Top:
|
||||||
case CursorPosition::TopRight: {
|
case CursorPosition_TopRight: {
|
||||||
deltaHeight = oldGeometry.top() - globalPos.y();
|
deltaHeight = oldGeometry.top() - globalPos.y();
|
||||||
newHeight = qBound(minHeight, mTarget->height() + deltaHeight, maxHeight);
|
newHeight = qBound(minHeight, mTarget->height() + deltaHeight, maxHeight);
|
||||||
deltaHeight = newHeight - mTarget->height();
|
deltaHeight = newHeight - mTarget->height();
|
||||||
@@ -177,9 +176,9 @@ void WidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case CursorPosition::BottomLeft:
|
case CursorPosition_BottomLeft:
|
||||||
case CursorPosition::Bottom:
|
case CursorPosition_Bottom:
|
||||||
case CursorPosition::BottomRight: {
|
case CursorPosition_BottomRight: {
|
||||||
deltaHeight = globalPos.y() - newGeometry.bottom();
|
deltaHeight = globalPos.y() - newGeometry.bottom();
|
||||||
newHeight = qBound(minHeight, mTarget->height() + deltaHeight, maxHeight);
|
newHeight = qBound(minHeight, mTarget->height() + deltaHeight, maxHeight);
|
||||||
deltaHeight = newHeight - mTarget->height();
|
deltaHeight = newHeight - mTarget->height();
|
||||||
@@ -201,7 +200,7 @@ void WidgetResizeHandler::mouseMoveEvent(QMouseEvent *e)
|
|||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
|
||||||
/// Handler to enable Aero-snap
|
/// Handler to enable Aero-snap
|
||||||
bool WidgetResizeHandler::handleWindowsNativeEvent(FloatingWindow *w, const QByteArray &eventType, void *message, long *result)
|
bool WidgetResizeHandler::handleWindowsNativeEvent(FloatingWindow *w, const QByteArray &eventType, void *message, Qt5Qt6Compat::qintptr *result)
|
||||||
{
|
{
|
||||||
if (eventType != "windows_generic_MSG")
|
if (eventType != "windows_generic_MSG")
|
||||||
return false;
|
return false;
|
||||||
@@ -250,18 +249,15 @@ bool WidgetResizeHandler::handleWindowsNativeEvent(FloatingWindow *w, const QByt
|
|||||||
*result = HTRIGHT;
|
*result = HTRIGHT;
|
||||||
} else {
|
} else {
|
||||||
const QPoint globalPosQt = QHighDpi::fromNativePixels(QPoint(xPos, yPos), w->windowHandle());
|
const QPoint globalPosQt = QHighDpi::fromNativePixels(QPoint(xPos, yPos), w->windowHandle());
|
||||||
|
const QRect htCaptionRect = w->dragRect(); // The rect on which we allow for Windows to do a native drag
|
||||||
const QRect htCaptionRect = w->dragRect(); // The rect on which we allow for Windows to do Ba native drag
|
|
||||||
if (globalPosQt.y() >= htCaptionRect.top() && globalPosQt.y() <= htCaptionRect.bottom() && globalPosQt.x() >= htCaptionRect.left() && globalPosQt.x() <= htCaptionRect.right()) {
|
if (globalPosQt.y() >= htCaptionRect.top() && globalPosQt.y() <= htCaptionRect.bottom() && globalPosQt.x() >= htCaptionRect.left() && globalPosQt.x() <= htCaptionRect.right()) {
|
||||||
QWidget *hoveredWidget = qApp->widgetAt(globalPosQt);
|
if (!KDDockWidgets::inDisallowDragWidget(globalPosQt)) { // Just makes sure the mouse isn't over the close button, we don't allow drag in that case.
|
||||||
if (!qobject_cast<QAbstractButton*>(hoveredWidget) &&
|
*result = HTCAPTION;
|
||||||
!qobject_cast<QLineEdit*>(hoveredWidget)) { // User might have a line edit on the toolbar. TODO: Not so elegant fix, we should make the user's tabbar implement some virtual method...
|
|
||||||
// User clicked on the title bar, let's allow it, so we get Aero-Snap.
|
|
||||||
*result = HTCAPTION;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
w->setLastHitTest(*result);
|
||||||
return *result != 0;
|
return *result != 0;
|
||||||
} else if (msg->message == WM_NCLBUTTONDBLCLK) {
|
} else if (msg->message == WM_NCLBUTTONDBLCLK) {
|
||||||
if ((Config::self().flags() & Config::Flag_DoubleClickMaximizes)) {
|
if ((Config::self().flags() & Config::Flag_DoubleClickMaximizes)) {
|
||||||
@@ -287,7 +283,7 @@ bool WidgetResizeHandler::handleWindowsNativeEvent(FloatingWindow *w, const QByt
|
|||||||
// and patch the size
|
// and patch the size
|
||||||
|
|
||||||
// According to microsoft docs it only works for the primary screen, but extrapolates for the others
|
// According to microsoft docs it only works for the primary screen, but extrapolates for the others
|
||||||
QScreen *screen = QApplication::primaryScreen();
|
QScreen *screen = QGuiApplication::primaryScreen();
|
||||||
if (!screen || w->windowHandle()->screen() != screen) {
|
if (!screen || w->windowHandle()->screen() != screen) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -317,7 +313,7 @@ bool WidgetResizeHandler::handleWindowsNativeEvent(FloatingWindow *w, const QByt
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void WidgetResizeHandler::setTarget(QWidget *w)
|
void WidgetResizeHandler::setTarget(QWidgetOrQuick *w)
|
||||||
{
|
{
|
||||||
if (w) {
|
if (w) {
|
||||||
mTarget = w;
|
mTarget = w;
|
||||||
@@ -330,33 +326,37 @@ void WidgetResizeHandler::setTarget(QWidget *w)
|
|||||||
|
|
||||||
void WidgetResizeHandler::updateCursor(CursorPosition m)
|
void WidgetResizeHandler::updateCursor(CursorPosition m)
|
||||||
{
|
{
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
//Need for updating cursor when we change child widget
|
//Need for updating cursor when we change child widget
|
||||||
const QObjectList children = mTarget->children();
|
const QObjectList children = mTarget->children();
|
||||||
for (int i = 0, total = children.size(); i < total; ++i) {
|
for (int i = 0, total = children.size(); i < total; ++i) {
|
||||||
if (auto child = qobject_cast<QWidget*>(children.at(i))) {
|
if (auto child = qobject_cast<WidgetType*>(children.at(i))) {
|
||||||
|
|
||||||
if (!child->testAttribute(Qt::WA_SetCursor)) {
|
if (!child->testAttribute(Qt::WA_SetCursor)) {
|
||||||
child->setCursor(Qt::ArrowCursor);
|
child->setCursor(Qt::ArrowCursor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
switch (m) {
|
switch (m) {
|
||||||
case CursorPosition::TopLeft:
|
case CursorPosition_TopLeft:
|
||||||
case CursorPosition::BottomRight:
|
case CursorPosition_BottomRight:
|
||||||
mTarget->setCursor(Qt::SizeFDiagCursor);
|
mTarget->setCursor(Qt::SizeFDiagCursor);
|
||||||
break;
|
break;
|
||||||
case CursorPosition::BottomLeft:
|
case CursorPosition_BottomLeft:
|
||||||
case CursorPosition::TopRight:
|
case CursorPosition_TopRight:
|
||||||
mTarget->setCursor(Qt::SizeBDiagCursor);
|
mTarget->setCursor(Qt::SizeBDiagCursor);
|
||||||
break;
|
break;
|
||||||
case CursorPosition::Top:
|
case CursorPosition_Top:
|
||||||
case CursorPosition::Bottom:
|
case CursorPosition_Bottom:
|
||||||
mTarget->setCursor(Qt::SizeVerCursor);
|
mTarget->setCursor(Qt::SizeVerCursor);
|
||||||
break;
|
break;
|
||||||
case CursorPosition::Left:
|
case CursorPosition_Left:
|
||||||
case CursorPosition::Right:
|
case CursorPosition_Right:
|
||||||
mTarget->setCursor(Qt::SizeHorCursor);
|
mTarget->setCursor(Qt::SizeHorCursor);
|
||||||
break;
|
break;
|
||||||
case CursorPosition::Undefined:
|
case CursorPosition_Undefined:
|
||||||
mTarget->setCursor(Qt::ArrowCursor);
|
mTarget->setCursor(Qt::ArrowCursor);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -365,27 +365,25 @@ void WidgetResizeHandler::updateCursor(CursorPosition m)
|
|||||||
WidgetResizeHandler::CursorPosition WidgetResizeHandler::cursorPosition(QPoint globalPos) const
|
WidgetResizeHandler::CursorPosition WidgetResizeHandler::cursorPosition(QPoint globalPos) const
|
||||||
{
|
{
|
||||||
if (!mTarget)
|
if (!mTarget)
|
||||||
return CursorPosition::Undefined;
|
return CursorPosition_Undefined;
|
||||||
|
|
||||||
QPoint pos = mTarget->mapFromGlobal(globalPos);
|
QPoint pos = mTarget->mapFromGlobal(globalPos);
|
||||||
|
|
||||||
if (pos.y() <= widgetResizeHandlerMargin && pos.x() <= widgetResizeHandlerMargin) {
|
int result = CursorPosition_Undefined;
|
||||||
return CursorPosition::TopLeft;
|
|
||||||
} else if (pos.y() >= mTarget->height() - widgetResizeHandlerMargin && pos.x() >= mTarget->width() - widgetResizeHandlerMargin) {
|
const int x = pos.x();
|
||||||
return CursorPosition::BottomRight;
|
const int y = pos.y();
|
||||||
} else if (pos.y() >= mTarget->height() - widgetResizeHandlerMargin && pos.x() <= widgetResizeHandlerMargin) {
|
const int margin = widgetResizeHandlerMargin;
|
||||||
return CursorPosition::BottomLeft;
|
|
||||||
} else if (pos.y() <= widgetResizeHandlerMargin && pos.x() >= mTarget->width() - widgetResizeHandlerMargin) {
|
if (x <= margin)
|
||||||
return CursorPosition::TopRight;
|
result |= CursorPosition_Left;
|
||||||
} else if (pos.y() <= widgetResizeHandlerMargin) {
|
else if (x >= mTarget->width() - margin)
|
||||||
return CursorPosition::Top;
|
result |= CursorPosition_Right;
|
||||||
} else if (pos.y() >= mTarget->height() - widgetResizeHandlerMargin) {
|
|
||||||
return CursorPosition::Bottom;
|
if (y <= margin)
|
||||||
} else if (pos.x() <= widgetResizeHandlerMargin) {
|
result |= CursorPosition_Top;
|
||||||
return CursorPosition::Left;
|
else if (y >= mTarget->height() - margin)
|
||||||
} else if ( pos.x() >= mTarget->width() - widgetResizeHandlerMargin) {
|
result |= CursorPosition_Bottom;
|
||||||
return CursorPosition::Right;
|
|
||||||
} else {
|
return static_cast<CursorPosition>(result);
|
||||||
return CursorPosition::Undefined;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,9 @@
|
|||||||
#ifndef KD_WIDGET_RESIZE_HANDLER_P_H
|
#ifndef KD_WIDGET_RESIZE_HANDLER_P_H
|
||||||
#define KD_WIDGET_RESIZE_HANDLER_P_H
|
#define KD_WIDGET_RESIZE_HANDLER_P_H
|
||||||
|
|
||||||
#include <QWidget>
|
#include "QWidgetAdapter.h"
|
||||||
|
#include "Qt5Qt6Compat_p.h"
|
||||||
|
|
||||||
#include <QPoint>
|
#include <QPoint>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
@@ -28,35 +30,37 @@ class WidgetResizeHandler : public QObject
|
|||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit WidgetResizeHandler(QWidget *target = nullptr);
|
|
||||||
|
enum CursorPosition {
|
||||||
|
CursorPosition_Undefined = 0,
|
||||||
|
CursorPosition_Left = 1,
|
||||||
|
CursorPosition_Right = 2,
|
||||||
|
CursorPosition_Top = 4,
|
||||||
|
CursorPosition_Bottom = 8,
|
||||||
|
CursorPosition_TopLeft = CursorPosition_Top | CursorPosition_Left,
|
||||||
|
CursorPosition_TopRight = CursorPosition_Top | CursorPosition_Right,
|
||||||
|
CursorPosition_BottomRight = CursorPosition_Bottom | CursorPosition_Right,
|
||||||
|
CursorPosition_BottomLeft = CursorPosition_Bottom | CursorPosition_Left
|
||||||
|
};
|
||||||
|
|
||||||
|
explicit WidgetResizeHandler(QWidgetOrQuick *target = nullptr);
|
||||||
~WidgetResizeHandler() override;
|
~WidgetResizeHandler() override;
|
||||||
|
|
||||||
void setTarget(QWidget *w);
|
void setTarget(QWidgetOrQuick *w);
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
static bool handleWindowsNativeEvent(FloatingWindow *w, const QByteArray &eventType, void *message, long *result);
|
static bool handleWindowsNativeEvent(FloatingWindow *w, const QByteArray &eventType, void *message, Qt5Qt6Compat::qintptr *result);
|
||||||
#endif
|
#endif
|
||||||
static bool s_disableAllHandlers;
|
static bool s_disableAllHandlers;
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *o, QEvent *e) override;
|
bool eventFilter(QObject *o, QEvent *e) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class CursorPosition {
|
|
||||||
Left,
|
|
||||||
Right,
|
|
||||||
TopLeft,
|
|
||||||
TopRight,
|
|
||||||
BottomRight,
|
|
||||||
BottomLeft,
|
|
||||||
Top,
|
|
||||||
Bottom,
|
|
||||||
Undefined
|
|
||||||
};
|
|
||||||
void mouseMoveEvent(QMouseEvent *e);
|
void mouseMoveEvent(QMouseEvent *e);
|
||||||
void updateCursor(CursorPosition m);
|
void updateCursor(CursorPosition m);
|
||||||
CursorPosition cursorPosition(QPoint) const;
|
CursorPosition cursorPosition(QPoint) const;
|
||||||
QWidget *mTarget = nullptr;
|
QWidgetOrQuick *mTarget = nullptr;
|
||||||
CursorPosition mCursorPos = CursorPosition::Undefined;
|
CursorPosition mCursorPos = CursorPosition_Undefined;
|
||||||
QPoint mNewPosition;
|
QPoint mNewPosition;
|
||||||
bool mResizeWidget = false;
|
bool mResizeWidget = false;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -14,6 +14,15 @@
|
|||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
|
#include "Frame_p.h"
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
# include "widgets/TabBarWidget_p.h"
|
||||||
|
# include "widgets/TabWidgetWidget_p.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QPixmap>
|
||||||
|
#include <QPainter>
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
@@ -48,23 +57,36 @@ static Draggable* bestDraggable(Draggable *draggable)
|
|||||||
|
|
||||||
WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw, Draggable *draggable)
|
WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw, Draggable *draggable)
|
||||||
: m_floatingWindow(fw)
|
: m_floatingWindow(fw)
|
||||||
, m_draggable(bestDraggable(draggable)->asWidget())
|
, m_draggable(bestDraggable(draggable))
|
||||||
, m_affinities(fw->affinities())
|
, m_draggableWidget(m_draggable ? m_draggable->asWidget() : nullptr)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
// Set opacity while dragging, if needed
|
if (!isWayland()) { // Wayland doesn't support setting opacity
|
||||||
const qreal opacity = Config::self().draggedWindowOpacity();
|
// Set opacity while dragging, if needed
|
||||||
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
const qreal opacity = Config::self().draggedWindowOpacity();
|
||||||
fw->setWindowOpacity(opacity);
|
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
||||||
|
fw->setWindowOpacity(opacity);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if DOCKS_DEVELOPER_MODE
|
|
||||||
|
WindowBeingDragged::WindowBeingDragged(Draggable *draggable)
|
||||||
|
: m_draggable(draggable)
|
||||||
|
, m_draggableWidget(m_draggable->asWidget())
|
||||||
|
{
|
||||||
|
if (!isWayland()) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Wrong ctor called."; // Doesn't happen
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DOCKS_DEVELOPER_MODE
|
||||||
|
|
||||||
// Just used by tests
|
// Just used by tests
|
||||||
WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw)
|
WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw)
|
||||||
: m_floatingWindow(fw)
|
: m_floatingWindow(fw)
|
||||||
, m_draggable(nullptr)
|
, m_draggable(nullptr)
|
||||||
, m_affinities(fw->affinities())
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,10 +96,12 @@ WindowBeingDragged::~WindowBeingDragged()
|
|||||||
{
|
{
|
||||||
grabMouse(false);
|
grabMouse(false);
|
||||||
|
|
||||||
// Restore opacity to fully opaque if needed
|
if (!isWayland()) { // Wayland doesn't support setting opacity
|
||||||
const qreal opacity = Config::self().draggedWindowOpacity();
|
// Restore opacity to fully opaque if needed
|
||||||
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
const qreal opacity = Config::self().draggedWindowOpacity();
|
||||||
m_floatingWindow->setWindowOpacity(1);
|
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
||||||
|
m_floatingWindow->setWindowOpacity(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void WindowBeingDragged::init()
|
void WindowBeingDragged::init()
|
||||||
@@ -89,19 +113,20 @@ void WindowBeingDragged::init()
|
|||||||
|
|
||||||
void WindowBeingDragged::grabMouse(bool grab)
|
void WindowBeingDragged::grabMouse(bool grab)
|
||||||
{
|
{
|
||||||
if (!m_draggable)
|
if (!m_draggableWidget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
qCDebug(hovering) << "WindowBeingDragged: grab " << m_floatingWindow << grab << m_draggable;
|
qCDebug(hovering) << "WindowBeingDragged: grab " << m_floatingWindow << grab << m_draggableWidget;
|
||||||
if (grab)
|
if (grab)
|
||||||
DragController::instance()->grabMouseFor(m_draggable);
|
DragController::instance()->grabMouseFor(m_draggableWidget);
|
||||||
else
|
else
|
||||||
DragController::instance()->releaseMouse(m_draggable);
|
DragController::instance()->releaseMouse(m_draggableWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList WindowBeingDragged::affinities() const
|
QStringList WindowBeingDragged::affinities() const
|
||||||
{
|
{
|
||||||
return m_affinities;
|
return m_floatingWindow ? m_floatingWindow->affinities()
|
||||||
|
: QStringList();
|
||||||
}
|
}
|
||||||
|
|
||||||
QSize WindowBeingDragged::size() const
|
QSize WindowBeingDragged::size() const
|
||||||
@@ -131,3 +156,153 @@ QSize WindowBeingDragged::maxSize() const
|
|||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WindowBeingDragged::contains(DropArea *dropArea) const
|
||||||
|
{
|
||||||
|
if (!dropArea)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (m_floatingWindow)
|
||||||
|
return m_floatingWindow->dropArea() == dropArea;
|
||||||
|
|
||||||
|
if (auto fw = qobject_cast<FloatingWindow*>(m_draggableWidget->window())) {
|
||||||
|
// We're not dragging via the floating window itself, but via the tab bar. Still might represent floating window though.
|
||||||
|
return fw->dropArea() == dropArea && fw->hasSingleFrame();
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<DockWidgetBase *> WindowBeingDragged::dockWidgets() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow)
|
||||||
|
return m_floatingWindow->dockWidgets();
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
Draggable *WindowBeingDragged::draggable() const
|
||||||
|
{
|
||||||
|
return m_draggable;
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowBeingDraggedWayland::WindowBeingDraggedWayland(Draggable *draggable)
|
||||||
|
: WindowBeingDragged(draggable)
|
||||||
|
{
|
||||||
|
if (!isWayland()) {
|
||||||
|
// Doesn't happen
|
||||||
|
qWarning() << Q_FUNC_INFO << "This CTOR is only called on Wayland";
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (auto tb = qobject_cast<TitleBar*>(draggable->asWidget())) {
|
||||||
|
if (auto fw = tb->floatingWindow()) {
|
||||||
|
// case #1: we're dragging the whole floating window by its titlebar
|
||||||
|
m_floatingWindow = fw;
|
||||||
|
} else if (Frame *frame = tb->frame()) {
|
||||||
|
m_frame = frame;
|
||||||
|
} else {
|
||||||
|
qWarning() << Q_FUNC_INFO <<"Shouldn't happen. TitleBar of what ?";
|
||||||
|
}
|
||||||
|
} else if (auto fw = qobject_cast<FloatingWindow*>(draggable->asWidget())) {
|
||||||
|
// case #2: the floating window itself is the draggable, happens on platforms that support
|
||||||
|
// native dragging. Not the case for Wayland. But adding this case for completeness.
|
||||||
|
m_floatingWindow = fw;
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
} else if (auto tbw = qobject_cast<TabBarWidget*>(draggable->asWidget())) {
|
||||||
|
m_dockWidget = tbw->currentDockWidget();
|
||||||
|
} else if (auto tw = qobject_cast<TabWidgetWidget*>(draggable->asWidget())) {
|
||||||
|
m_frame = tw->frame();
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
qWarning() << "Unknown draggable" << draggable->asWidget()
|
||||||
|
<< "please fix";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowBeingDraggedWayland::~WindowBeingDraggedWayland()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap WindowBeingDraggedWayland::pixmap() const
|
||||||
|
{
|
||||||
|
QPixmap pixmap(size());
|
||||||
|
QPainter p(&pixmap);
|
||||||
|
p.setOpacity(0.7);
|
||||||
|
|
||||||
|
if (m_floatingWindow) {
|
||||||
|
m_floatingWindow->render(&p);
|
||||||
|
} else if (m_frame) {
|
||||||
|
m_frame->render(&p);
|
||||||
|
} else if (m_dockWidget) {
|
||||||
|
m_dockWidget->render(&p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pixmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList WindowBeingDraggedWayland::affinities() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow)
|
||||||
|
return WindowBeingDragged::affinities();
|
||||||
|
else if (m_frame)
|
||||||
|
return m_frame->affinities();
|
||||||
|
else if (m_dockWidget)
|
||||||
|
return { m_dockWidget->affinities() };
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QVector<DockWidgetBase *> WindowBeingDraggedWayland::dockWidgets() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow)
|
||||||
|
return WindowBeingDragged::dockWidgets();
|
||||||
|
else if (m_frame)
|
||||||
|
return m_frame->dockWidgets();
|
||||||
|
else if (m_dockWidget)
|
||||||
|
return { m_dockWidget };
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize WindowBeingDraggedWayland::size() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow)
|
||||||
|
return WindowBeingDragged::size();
|
||||||
|
else if (m_frame)
|
||||||
|
return m_frame->QWidgetAdapter::size();
|
||||||
|
else if (m_dockWidget)
|
||||||
|
return m_dockWidget->size();
|
||||||
|
|
||||||
|
qWarning() << Q_FUNC_INFO << "Unknown size, shouldn't happen";
|
||||||
|
return QSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize WindowBeingDraggedWayland::minSize() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow) {
|
||||||
|
return WindowBeingDragged::minSize();
|
||||||
|
} else if (m_frame) {
|
||||||
|
return m_frame->minSize();
|
||||||
|
} else if (m_dockWidget) {
|
||||||
|
return Layouting::Widget::widgetMinSize(m_dockWidget.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << Q_FUNC_INFO << "Unknown minSize, shouldn't happen";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize WindowBeingDraggedWayland::maxSize() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow) {
|
||||||
|
return WindowBeingDragged::maxSize();
|
||||||
|
} else if (m_frame) {
|
||||||
|
return m_frame->maxSizeHint();
|
||||||
|
} else if (m_dockWidget) {
|
||||||
|
return Layouting::Widget::widgetMaxSize(m_dockWidget.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << Q_FUNC_INFO << "Unknown maxSize, shouldn't happen";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,21 +17,27 @@
|
|||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPixmap;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class FloatingWindow;
|
class FloatingWindow;
|
||||||
class Draggable;
|
class Draggable;
|
||||||
|
class DropArea;
|
||||||
|
|
||||||
struct DOCKS_EXPORT_FOR_UNIT_TESTS WindowBeingDragged
|
struct DOCKS_EXPORT_FOR_UNIT_TESTS WindowBeingDragged
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit WindowBeingDragged(FloatingWindow *fw, Draggable *draggable);
|
explicit WindowBeingDragged(FloatingWindow *fw, Draggable *draggable);
|
||||||
#if DOCKS_DEVELOPER_MODE
|
|
||||||
|
#ifdef DOCKS_DEVELOPER_MODE
|
||||||
// For tests.
|
// For tests.
|
||||||
explicit WindowBeingDragged(FloatingWindow *fw);
|
explicit WindowBeingDragged(FloatingWindow *fw);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
~WindowBeingDragged();
|
virtual ~WindowBeingDragged();
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
FloatingWindow *floatingWindow() const { return m_floatingWindow; }
|
FloatingWindow *floatingWindow() const { return m_floatingWindow; }
|
||||||
@@ -39,24 +45,58 @@ public:
|
|||||||
///@brief grabs or releases the mouse
|
///@brief grabs or releases the mouse
|
||||||
void grabMouse(bool grab);
|
void grabMouse(bool grab);
|
||||||
|
|
||||||
|
/// @brief returns whether this window being dragged contains the specified drop area
|
||||||
|
/// useful since we don't want to drop onto outselves.
|
||||||
|
bool contains(DropArea *) const;
|
||||||
|
|
||||||
///@brief returns the affinities of the window being dragged
|
///@brief returns the affinities of the window being dragged
|
||||||
QStringList affinities() const;
|
virtual QStringList affinities() const;
|
||||||
|
|
||||||
///@brief size of the window being dragged contents
|
///@brief size of the window being dragged contents
|
||||||
QSize size() const;
|
virtual QSize size() const;
|
||||||
|
|
||||||
/// @brief returns the min-size of the window being dragged contents
|
/// @brief returns the min-size of the window being dragged contents
|
||||||
QSize minSize() const;
|
virtual QSize minSize() const;
|
||||||
|
|
||||||
/// @brief returns the max-size of the window being dragged contents
|
/// @brief returns the max-size of the window being dragged contents
|
||||||
QSize maxSize() const;
|
virtual QSize maxSize() const;
|
||||||
|
|
||||||
private:
|
/// @brief Returns a pixmap representing this Window. For purposes of QDrag. Wayland only.
|
||||||
|
virtual QPixmap pixmap() const { return {}; }
|
||||||
|
|
||||||
|
/// @brief Returns the list of dock widgets being dragged
|
||||||
|
virtual QVector<DockWidgetBase*> dockWidgets() const;
|
||||||
|
|
||||||
|
/// @brief Returns the draggable
|
||||||
|
Draggable *draggable() const;
|
||||||
|
protected:
|
||||||
|
explicit WindowBeingDragged(Draggable *);
|
||||||
Q_DISABLE_COPY(WindowBeingDragged)
|
Q_DISABLE_COPY(WindowBeingDragged)
|
||||||
QPointer<FloatingWindow> m_floatingWindow;
|
QPointer<FloatingWindow> m_floatingWindow;
|
||||||
QPointer<QWidgetOrQuick> m_draggable;
|
Draggable *const m_draggable;
|
||||||
const QStringList m_affinities;
|
QPointer<QWidgetOrQuick> m_draggableWidget; // Just to have a QPointer on it
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WindowBeingDraggedWayland : public WindowBeingDragged
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit WindowBeingDraggedWayland(Draggable *draggable);
|
||||||
|
~WindowBeingDraggedWayland() override;
|
||||||
|
|
||||||
|
QSize size() const override;
|
||||||
|
QSize minSize() const override;
|
||||||
|
QSize maxSize() const override;
|
||||||
|
QPixmap pixmap() const override;
|
||||||
|
QStringList affinities() const override;
|
||||||
|
QVector<DockWidgetBase*> dockWidgets() const override;
|
||||||
|
|
||||||
|
// These two are set for Wayland only, where we can't make the floating window immediately (no way to position it)
|
||||||
|
// So we're dragging either a frame with multiple dock widgets or a single tab, keep them here.
|
||||||
|
// It's important to know what we're dragging, so drop rubber band respect min/max sizes.
|
||||||
|
QPointer<Frame> m_frame;
|
||||||
|
QPointer<DockWidgetBase> m_dockWidget;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,8 +14,6 @@
|
|||||||
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QPainterPath>
|
#include <QPainterPath>
|
||||||
#include <QState>
|
|
||||||
#include <QStateMachine>
|
|
||||||
|
|
||||||
#define RUBBERBAND_LENGTH 11
|
#define RUBBERBAND_LENGTH 11
|
||||||
#define RUBBERBAND_SPACING 2
|
#define RUBBERBAND_SPACING 2
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "ClassicIndicatorsWindow_p.h"
|
#include "ClassicIndicatorsWindow_p.h"
|
||||||
|
#include "Utils_p.h"
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
@@ -40,9 +41,9 @@ ClassicIndicators::~ClassicIndicators()
|
|||||||
delete m_indicatorWindow;
|
delete m_indicatorWindow;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassicIndicators::hover_impl(QPoint globalPos)
|
DropIndicatorOverlayInterface::DropLocation ClassicIndicators::hover_impl(QPoint globalPos)
|
||||||
{
|
{
|
||||||
m_indicatorWindow->hover(globalPos);
|
return m_indicatorWindow->hover(globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint ClassicIndicators::posForIndicator(DropIndicatorOverlayInterface::DropLocation loc) const
|
QPoint ClassicIndicators::posForIndicator(DropIndicatorOverlayInterface::DropLocation loc) const
|
||||||
@@ -101,8 +102,14 @@ void ClassicIndicators::updateIndicatorsVisibility(bool visible)
|
|||||||
|
|
||||||
|
|
||||||
// Only allow to dock to center if the affinities match
|
// Only allow to dock to center if the affinities match
|
||||||
|
auto tabbingAllowedFunc = Config::self().tabbingAllowedFunc();
|
||||||
m_tabIndicatorVisible = m_innerIndicatorsVisible && windowBeingDragged &&
|
m_tabIndicatorVisible = m_innerIndicatorsVisible && windowBeingDragged &&
|
||||||
DockRegistry::self()->affinitiesMatch(m_hoveredFrame->affinities(), windowBeingDragged->affinities());
|
DockRegistry::self()->affinitiesMatch(m_hoveredFrame->affinities(), windowBeingDragged->affinities());
|
||||||
|
if (m_tabIndicatorVisible && tabbingAllowedFunc) {
|
||||||
|
const DockWidgetBase::List source = windowBeingDragged->dockWidgets();
|
||||||
|
const DockWidgetBase::List target = m_hoveredFrame->dockWidgets();
|
||||||
|
m_tabIndicatorVisible = tabbingAllowedFunc(source, target);
|
||||||
|
}
|
||||||
|
|
||||||
Q_EMIT innerIndicatorsVisibleChanged();
|
Q_EMIT innerIndicatorsVisibleChanged();
|
||||||
Q_EMIT outterIndicatorsVisibleChanged();
|
Q_EMIT outterIndicatorsVisibleChanged();
|
||||||
@@ -139,7 +146,6 @@ KDDockWidgets::Location locationToMultisplitterLocation(ClassicIndicators::DropL
|
|||||||
|
|
||||||
void ClassicIndicators::setDropLocation(ClassicIndicators::DropLocation location)
|
void ClassicIndicators::setDropLocation(ClassicIndicators::DropLocation location)
|
||||||
{
|
{
|
||||||
qCDebug(overlay) << "ClassicIndicators::setCurrentDropLocation" << location;
|
|
||||||
setCurrentDropLocation(location);
|
setCurrentDropLocation(location);
|
||||||
|
|
||||||
if (location == DropLocation_None) {
|
if (location == DropLocation_None) {
|
||||||
@@ -191,7 +197,10 @@ void ClassicIndicators::setDropLocation(ClassicIndicators::DropLocation location
|
|||||||
void ClassicIndicators::updateWindowPosition()
|
void ClassicIndicators::updateWindowPosition()
|
||||||
{
|
{
|
||||||
QRect rect = this->rect();
|
QRect rect = this->rect();
|
||||||
QPoint pos = mapToGlobal(QPoint(0, 0));
|
if (KDDockWidgets::isWindow(m_indicatorWindow)) {
|
||||||
rect.moveTo(pos);
|
// On all non-wayland platforms it's a top-level.
|
||||||
|
QPoint pos = mapToGlobal(QPoint(0, 0));
|
||||||
|
rect.moveTo(pos);
|
||||||
|
}
|
||||||
m_indicatorWindow->setGeometry(rect);
|
m_indicatorWindow->setGeometry(rect);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -101,8 +101,22 @@ QString Indicator::iconFileName(bool active) const
|
|||||||
: QStringLiteral(":/img/classic_indicators/opaque/%1.png").arg(name);
|
: QStringLiteral(":/img/classic_indicators/opaque/%1.png").arg(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QWidgetAdapter* parentForIndicatorWindow(ClassicIndicators *classicIndicators_)
|
||||||
|
{
|
||||||
|
// On Wayland it can't be a top-level, as we have no way of positioning it
|
||||||
|
|
||||||
|
return isWayland() ? classicIndicators_
|
||||||
|
: nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Qt::WindowFlags flagsForIndicatorWindow()
|
||||||
|
{
|
||||||
|
return isWayland() ? Qt::Widget
|
||||||
|
: (Qt::Tool | Qt::BypassWindowManagerHint);
|
||||||
|
}
|
||||||
|
|
||||||
IndicatorWindow::IndicatorWindow(ClassicIndicators *classicIndicators_)
|
IndicatorWindow::IndicatorWindow(ClassicIndicators *classicIndicators_)
|
||||||
: QWidget(nullptr, Qt::Tool | Qt::BypassWindowManagerHint)
|
: QWidget(parentForIndicatorWindow(classicIndicators_), flagsForIndicatorWindow())
|
||||||
, classicIndicators(classicIndicators_)
|
, classicIndicators(classicIndicators_)
|
||||||
, m_center(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Center)) // Each indicator is not a top-level. Otherwise there's noticeable delay.
|
, m_center(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Center)) // Each indicator is not a top-level. Otherwise there's noticeable delay.
|
||||||
, m_left(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Left))
|
, m_left(new Indicator(classicIndicators, this, DropIndicatorOverlayInterface::DropLocation_Left))
|
||||||
@@ -193,12 +207,20 @@ QPoint IndicatorWindow::posForIndicator(DropIndicatorOverlayInterface::DropLocat
|
|||||||
return indicator->mapToGlobal(indicator->rect().center());
|
return indicator->mapToGlobal(indicator->rect().center());
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndicatorWindow::hover(QPoint globalPos)
|
DropIndicatorOverlayInterface::DropLocation IndicatorWindow::hover(QPoint globalPos)
|
||||||
{
|
{
|
||||||
|
DropIndicatorOverlayInterface::DropLocation loc = DropIndicatorOverlayInterface::DropLocation_None;
|
||||||
|
|
||||||
for (Indicator *indicator : qAsConst(m_indicators)) {
|
for (Indicator *indicator : qAsConst(m_indicators)) {
|
||||||
if (indicator->isVisible())
|
if (indicator->isVisible()) {
|
||||||
indicator->setHovered(indicator->rect().contains(indicator->mapFromGlobal(globalPos)));
|
const bool hovered = indicator->rect().contains(indicator->mapFromGlobal(globalPos));
|
||||||
|
indicator->setHovered(hovered);
|
||||||
|
if (hovered)
|
||||||
|
loc = indicator->m_dropLocation;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return loc;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndicatorWindow::updatePositions()
|
void IndicatorWindow::updatePositions()
|
||||||
@@ -246,17 +268,26 @@ IndicatorWindow::IndicatorWindow(KDDockWidgets::ClassicIndicators *classicIndica
|
|||||||
|
|
||||||
rootContext()->setContextProperty(QStringLiteral("_window"), QVariant::fromValue<QObject*>(this));
|
rootContext()->setContextProperty(QStringLiteral("_window"), QVariant::fromValue<QObject*>(this));
|
||||||
setSource(QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/ClassicIndicatorsOverlay.qml")));
|
setSource(QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/ClassicIndicatorsOverlay.qml")));
|
||||||
|
|
||||||
|
{
|
||||||
|
// Small hack to avoid flickering when we drag over a window the first time
|
||||||
|
// Not sure why a simply create() doesn't work instead
|
||||||
|
// Not if offscreen though, as that QPA is flaky with window activation/focus
|
||||||
|
if (!KDDockWidgets::isOffscreen()) {
|
||||||
|
resize(QSize(1, 1));
|
||||||
|
show();
|
||||||
|
hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IndicatorWindow::hover(QPoint pt)
|
DropIndicatorOverlayInterface::DropLocation IndicatorWindow::hover(QPoint pt)
|
||||||
{
|
{
|
||||||
QQuickItem *item = indicatorForPos(pt);
|
QQuickItem *item = indicatorForPos(pt);
|
||||||
if (item) {
|
const DropIndicatorOverlayInterface::DropLocation loc = item ? locationForIndicator(item)
|
||||||
const auto loc = DropIndicatorOverlayInterface::DropLocation(item->property("indicatorType").toInt());
|
: DropIndicatorOverlayInterface::DropLocation_None;
|
||||||
classicIndicators()->setDropLocation(loc);
|
classicIndicators()->setDropLocation(loc);
|
||||||
} else {
|
return loc;
|
||||||
classicIndicators()->setDropLocation(DropIndicatorOverlayInterface::DropLocation_None);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QQuickItem *IndicatorWindow::indicatorForPos(QPoint pt) const
|
QQuickItem *IndicatorWindow::indicatorForPos(QPoint pt) const
|
||||||
@@ -265,10 +296,13 @@ QQuickItem *IndicatorWindow::indicatorForPos(QPoint pt) const
|
|||||||
Q_ASSERT(indicators.size() == 9);
|
Q_ASSERT(indicators.size() == 9);
|
||||||
|
|
||||||
for (QQuickItem *item : indicators) {
|
for (QQuickItem *item : indicators) {
|
||||||
QRect rect(0, 0, int(item->width()), int(item->height()));
|
if (item->isVisible()) {
|
||||||
rect.moveTopLeft(item->mapToGlobal(QPointF(0, 0)).toPoint());
|
QRect rect(0, 0, int(item->width()), int(item->height()));
|
||||||
if (rect.contains(pt))
|
rect.moveTopLeft(item->mapToGlobal(QPointF(0, 0)).toPoint());
|
||||||
return item;
|
if (rect.contains(pt)) {
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -279,10 +313,10 @@ void IndicatorWindow::updatePositions()
|
|||||||
// Not needed to implement, the Indicators use QML anchors
|
// Not needed to implement, the Indicators use QML anchors
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint IndicatorWindow::posForIndicator(KDDockWidgets::DropIndicatorOverlayInterface::DropLocation) const
|
QPoint IndicatorWindow::posForIndicator(KDDockWidgets::DropIndicatorOverlayInterface::DropLocation loc) const
|
||||||
{
|
{
|
||||||
qDebug() << Q_FUNC_INFO;
|
QQuickItem *indicator = IndicatorWindow::indicatorForLocation(loc);
|
||||||
return {};
|
return indicator->mapToGlobal(indicator->boundingRect().center()).toPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString IndicatorWindow::iconName(int loc, bool active) const
|
QString IndicatorWindow::iconName(int loc, bool active) const
|
||||||
@@ -295,6 +329,25 @@ ClassicIndicators *IndicatorWindow::classicIndicators() const
|
|||||||
return m_classicIndicators;
|
return m_classicIndicators;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QQuickItem *IndicatorWindow::indicatorForLocation(DropIndicatorOverlayInterface::DropLocation loc) const
|
||||||
|
{
|
||||||
|
const QVector<QQuickItem *> indicators = indicatorItems();
|
||||||
|
Q_ASSERT(indicators.size() == 9);
|
||||||
|
|
||||||
|
for (QQuickItem *item : indicators) {
|
||||||
|
if (locationForIndicator(item) == loc)
|
||||||
|
return item;
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << Q_FUNC_INFO << "Couldn't find indicator for location" << loc;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DropIndicatorOverlayInterface::DropLocation IndicatorWindow::locationForIndicator(const QQuickItem *item) const
|
||||||
|
{
|
||||||
|
return DropIndicatorOverlayInterface::DropLocation(item->property("indicatorType").toInt());
|
||||||
|
}
|
||||||
|
|
||||||
QVector<QQuickItem *> IndicatorWindow::indicatorItems() const
|
QVector<QQuickItem *> IndicatorWindow::indicatorItems() const
|
||||||
{
|
{
|
||||||
QVector<QQuickItem *> indicators;
|
QVector<QQuickItem *> indicators;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class IndicatorWindow : public QWidget
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit IndicatorWindow(ClassicIndicators *classicIndicators);
|
explicit IndicatorWindow(ClassicIndicators *classicIndicators);
|
||||||
void hover(QPoint globalPos);
|
DropIndicatorOverlayInterface::DropLocation hover(QPoint globalPos);
|
||||||
void updatePositions();
|
void updatePositions();
|
||||||
QPoint posForIndicator(DropIndicatorOverlayInterface::DropLocation) const;
|
QPoint posForIndicator(DropIndicatorOverlayInterface::DropLocation) const;
|
||||||
private:
|
private:
|
||||||
@@ -91,12 +91,14 @@ class IndicatorWindow : public QQuickView
|
|||||||
Q_PROPERTY(KDDockWidgets::ClassicIndicators* classicIndicators READ classicIndicators CONSTANT)
|
Q_PROPERTY(KDDockWidgets::ClassicIndicators* classicIndicators READ classicIndicators CONSTANT)
|
||||||
public:
|
public:
|
||||||
explicit IndicatorWindow(ClassicIndicators *);
|
explicit IndicatorWindow(ClassicIndicators *);
|
||||||
void hover(QPoint);
|
DropIndicatorOverlayInterface::DropLocation hover(QPoint);
|
||||||
void updatePositions();
|
void updatePositions();
|
||||||
QPoint posForIndicator(DropIndicatorOverlayInterface::DropLocation) const;
|
QPoint posForIndicator(DropIndicatorOverlayInterface::DropLocation) const;
|
||||||
Q_INVOKABLE QString iconName(int loc, bool active) const;
|
Q_INVOKABLE QString iconName(int loc, bool active) const;
|
||||||
KDDockWidgets::ClassicIndicators* classicIndicators() const;
|
KDDockWidgets::ClassicIndicators* classicIndicators() const;
|
||||||
|
QQuickItem* indicatorForLocation(DropIndicatorOverlayInterface::DropLocation loc) const;
|
||||||
private:
|
private:
|
||||||
|
DropIndicatorOverlayInterface::DropLocation locationForIndicator(const QQuickItem *) const;
|
||||||
QQuickItem *indicatorForPos(QPoint) const;
|
QQuickItem *indicatorForPos(QPoint) const;
|
||||||
QVector<QQuickItem*> indicatorItems() const;
|
QVector<QQuickItem*> indicatorItems() const;
|
||||||
ClassicIndicators *const m_classicIndicators;
|
ClassicIndicators *const m_classicIndicators;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user