Compare commits
201 Commits
minimize
...
fix-python
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fce8e6161 | ||
|
|
6479bcabfb | ||
|
|
a8c9735652 | ||
|
|
93b25b6a31 | ||
|
|
4eb5a0940e | ||
|
|
c2cc914b5c | ||
|
|
1219ba90af | ||
|
|
beef3c7fb5 | ||
|
|
52184ca72b | ||
|
|
78cd7c56f7 | ||
|
|
7805a1dc25 | ||
|
|
92f426e4c0 | ||
|
|
90f10042fd | ||
|
|
697c140883 | ||
|
|
3369816d31 | ||
|
|
819725351a | ||
|
|
860cbd29bc | ||
|
|
07db9f9a7a | ||
|
|
2fd4f9ce97 | ||
|
|
77d7cd7d58 | ||
|
|
e5cb42c4fe | ||
|
|
1fe1d619a9 | ||
|
|
697cc34c23 | ||
|
|
b00d1d80b0 | ||
|
|
67bb42c5b4 | ||
|
|
d50fcb80c5 | ||
|
|
9571ffc30e | ||
|
|
f4a88276b8 | ||
|
|
4ea254029a | ||
|
|
f5e85c2196 | ||
|
|
926103325c | ||
|
|
20b2988165 | ||
|
|
39aefd312b | ||
|
|
b5478bcb0d | ||
|
|
d403557b9e | ||
|
|
db9884ea64 | ||
|
|
74148aabc3 | ||
|
|
7bfac091ae | ||
|
|
60a68817b6 | ||
|
|
a56e6d7fe8 | ||
|
|
1f0b208922 | ||
|
|
9da147f50e | ||
|
|
c175451284 | ||
|
|
9a88cf3a72 | ||
|
|
d0255e5310 | ||
|
|
2a2fb0a4f2 | ||
|
|
b0ad939db8 | ||
|
|
5abf118b8c | ||
|
|
f5099167b6 | ||
|
|
30949bd4c3 | ||
|
|
63279c187e | ||
|
|
fad03f8e0b | ||
|
|
6edfcc4f02 | ||
|
|
17df7b5b4e | ||
|
|
62cbd823c9 | ||
|
|
bdcc211308 | ||
|
|
ddeb4611a1 | ||
|
|
ad639c8001 | ||
|
|
15dc64d550 | ||
|
|
03b575d16e | ||
|
|
4cacee45e8 | ||
|
|
873b860203 | ||
|
|
128ae2d889 | ||
|
|
b0ec0e22e4 | ||
|
|
6aa4e979dc | ||
|
|
36f225b859 | ||
|
|
48a75b2450 | ||
|
|
2af4f939dd | ||
|
|
b592d21064 | ||
|
|
3cdd5afe7a | ||
|
|
0ef56c1302 | ||
|
|
96f7f38a0e | ||
|
|
689ba7da8f | ||
|
|
951aeece6e | ||
|
|
2ea0d54e6c | ||
|
|
1c98fe04ca | ||
|
|
59a9ab6642 | ||
|
|
7ee5949ae2 | ||
|
|
721f08e29b | ||
|
|
df07133c9d | ||
|
|
b9e3024720 | ||
|
|
d848d3e39a | ||
|
|
3f26f4c8f2 | ||
|
|
dc9d709dd7 | ||
|
|
543f734650 | ||
|
|
3fb723a82f | ||
|
|
71c2f34ed4 | ||
|
|
d4b3bf9de6 | ||
|
|
2b234f313c | ||
|
|
d1b2d17f7d | ||
|
|
f062ab7a64 | ||
|
|
f009f57581 | ||
|
|
f86a818e69 | ||
|
|
bb80c2158d | ||
|
|
86fa6258f6 | ||
|
|
545536fab5 | ||
|
|
ef23553b66 | ||
|
|
fcf56664cc | ||
|
|
d932166bcd | ||
|
|
0c5783774d | ||
|
|
aa42ea15f7 | ||
|
|
9dd778d55d | ||
|
|
ac35a919f4 | ||
|
|
a32c5017e6 | ||
|
|
7995a6d13b | ||
|
|
d4ec2eec88 | ||
|
|
12ad3b3484 | ||
|
|
9a53c36c14 | ||
|
|
8fb3802343 | ||
|
|
c035df7e85 | ||
|
|
92f81e28ca | ||
|
|
7a87db608b | ||
|
|
d42fb81790 | ||
|
|
73934e2f90 | ||
|
|
1c8642298b | ||
|
|
bfc45bb0e9 | ||
|
|
58af9e2516 | ||
|
|
4228c044ea | ||
|
|
ccc0aec968 | ||
|
|
3718d3fe79 | ||
|
|
26ed9b722b | ||
|
|
6751669249 | ||
|
|
c7955dce1e | ||
|
|
2e432f402f | ||
|
|
07791cd901 | ||
|
|
1458da92d9 | ||
|
|
c56f998292 | ||
|
|
991075d69e | ||
|
|
234ca75728 | ||
|
|
e34d62d3e5 | ||
|
|
423be28afd | ||
|
|
eb7bed9601 | ||
|
|
fa09521012 | ||
|
|
bb30f322a3 | ||
|
|
0e35c93ae5 | ||
|
|
603224e553 | ||
|
|
9b82063d52 | ||
|
|
c210a523e3 | ||
|
|
e33151d482 | ||
|
|
835f67a106 | ||
|
|
a50f6ec602 | ||
|
|
4a49dbc6b4 | ||
|
|
05c843397b | ||
|
|
e4871eb340 | ||
|
|
0e696ff2dd | ||
|
|
9f15773a9b | ||
|
|
a00984f95a | ||
|
|
c7e9632f18 | ||
|
|
7080712501 | ||
|
|
03b574434c | ||
|
|
6a46744073 | ||
|
|
7e52c510b3 | ||
|
|
9bf060af9a | ||
|
|
b5973fcf8c | ||
|
|
ac7d06d4fe | ||
|
|
75e9137e3a | ||
|
|
5168940422 | ||
|
|
cfd2dafa53 | ||
|
|
188b0a0edd | ||
|
|
206c418ebc | ||
|
|
b0acf8d1ae | ||
|
|
f279ea41e6 | ||
|
|
d2a929f35d | ||
|
|
6f5258b5dd | ||
|
|
4f223a9439 | ||
|
|
ea98eb3d44 | ||
|
|
cdb8f85620 | ||
|
|
f459dcb8b3 | ||
|
|
967a539e71 | ||
|
|
db615da0ee | ||
|
|
c4b420bd31 | ||
|
|
a6c4730c44 | ||
|
|
eb1f4c5a14 | ||
|
|
b303af738c | ||
|
|
af5e11a265 | ||
|
|
8d7627069c | ||
|
|
9e94c0d67d | ||
|
|
55ddacf978 | ||
|
|
005e0552b6 | ||
|
|
54b28c42e2 | ||
|
|
2659ddb76b | ||
|
|
c85873c6ce | ||
|
|
6e32f3f915 | ||
|
|
b8891a5727 | ||
|
|
fcb6f5a6af | ||
|
|
0365f3194d | ||
|
|
76e2ec6429 | ||
|
|
a5d0a202a5 | ||
|
|
def752632f | ||
|
|
f296048063 | ||
|
|
1c1b816292 | ||
|
|
fbd463e18b | ||
|
|
9e01363648 | ||
|
|
67bf7e9775 | ||
|
|
d8c2100b24 | ||
|
|
d1a3e39f17 | ||
|
|
3d5c081333 | ||
|
|
e1085fb770 | ||
|
|
c294c19be7 | ||
|
|
87726fb0a7 | ||
|
|
8bd429db4c |
4
.vscode/settings.json
vendored
@@ -4,7 +4,7 @@
|
|||||||
"qevent": "cpp"
|
"qevent": "cpp"
|
||||||
},
|
},
|
||||||
"cmake.configureSettings": {
|
"cmake.configureSettings": {
|
||||||
"OPTION_DEVELOPER_MODE" : "ON",
|
"KDDockWidgets_DEVELOPER_MODE" : "ON",
|
||||||
"OPTION_QTQUICK" : true
|
"KDDockWidgets_QTQUICK" : true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,19 +27,24 @@
|
|||||||
# Build the API documentation.
|
# Build the API documentation.
|
||||||
# Default=false
|
# Default=false
|
||||||
#
|
#
|
||||||
# -DOPTION_DEVELOPER_MODE=[true|false]
|
# -DKDDockWidgets_DEVELOPER_MODE=[true|false]
|
||||||
# Configure the build for a developer setup.
|
# Configure the build for a developer setup.
|
||||||
# Enables some features that are not geared towards end-users.
|
# Enables some features that are not geared towards end-users.
|
||||||
# Forces the test harness to be built.
|
# Forces the test harness to be built.
|
||||||
# Default=false
|
# Default=false
|
||||||
#
|
#
|
||||||
# -DOPTION_BUILD_PYTHON_BINDINGS=[true|false]
|
# -DKDDockWidgets_QTQUICK == IN DEVELOPMENT. DO NOT USE! ==
|
||||||
|
# Build for QtQuick instead of QtWidgets
|
||||||
|
# Default=false
|
||||||
|
#
|
||||||
|
# -DKDDockWidgets_PYTHON_BINDINGS=[true|false]
|
||||||
# Build/Generate python bindings. Always false for Debug builds
|
# Build/Generate python bindings. Always false for Debug builds
|
||||||
# Default=false
|
# Default=false
|
||||||
#
|
#
|
||||||
# -DPYTHON_BINDINGS_INSTALL_PREFIX=[path]
|
# -DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=[path]
|
||||||
# alternative install path for python bindings
|
# alternative install path for python bindings
|
||||||
# Default=CMAKE_INSTALL_PREFIX
|
# Default=CMAKE_INSTALL_PREFIX
|
||||||
|
#
|
||||||
|
|
||||||
cmake_minimum_required(VERSION 3.7)
|
cmake_minimum_required(VERSION 3.7)
|
||||||
if(POLICY CMP0020)
|
if(POLICY CMP0020)
|
||||||
@@ -49,10 +54,12 @@ if(POLICY CMP0042)
|
|||||||
cmake_policy(SET CMP0042 NEW)
|
cmake_policy(SET CMP0042 NEW)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "")
|
set(KDAB_INSTALL True)
|
||||||
set(USE_DEFAULT_INSTALL_LOCATION True)
|
if((NOT DEFINED ${USE_DEFAULT_INSTALL_LOCATION}) OR (NOT ${USE_DEFAULT_INSTALL_LOCATION}))
|
||||||
else()
|
if(NOT "${CMAKE_INSTALL_PREFIX}" STREQUAL "")
|
||||||
set(USE_DEFAULT_INSTALL_LOCATION False)
|
set(KDAB_INSTALL False)
|
||||||
|
endif()
|
||||||
|
set(USE_DEFAULT_INSTALL_LOCATION ${KDAB_INSTALL} CACHE INTERNAL "Install to default KDAB Location" FORCE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
|
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
|
||||||
@@ -65,16 +72,17 @@ else()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(${PROJECT_NAME}_VERSION_MAJOR 1)
|
set(${PROJECT_NAME}_VERSION_MAJOR 1)
|
||||||
set(${PROJECT_NAME}_VERSION_MINOR 0)
|
set(${PROJECT_NAME}_VERSION_MINOR 1)
|
||||||
set(${PROJECT_NAME}_VERSION_PATCH 95)
|
set(${PROJECT_NAME}_VERSION_PATCH 95)
|
||||||
|
|
||||||
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.1")
|
set(${PROJECT_NAME}_SOVERSION "1.2")
|
||||||
|
|
||||||
include(FeatureSummary)
|
include(FeatureSummary)
|
||||||
|
|
||||||
option(OPTION_DEVELOPER_MODE "Developer Mode" OFF)
|
option(${PROJECT_NAME}_DEVELOPER_MODE "Developer Mode" OFF)
|
||||||
option(OPTION_BUILD_PYTHON_BINDINGS "Build python bindings" OFF)
|
option(${PROJECT_NAME}_PYTHON_BINDINGS "Build python bindings" OFF)
|
||||||
if(OPTION_BUILD_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)
|
||||||
@@ -82,11 +90,11 @@ 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)
|
||||||
|
|
||||||
#Always build the test harness in developer-mode
|
#Always build the test harness in developer-mode
|
||||||
if(OPTION_DEVELOPER_MODE)
|
if(${PROJECT_NAME}_DEVELOPER_MODE)
|
||||||
set(${PROJECT_NAME}_TESTS ON)
|
set(${PROJECT_NAME}_TESTS ON)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# option(OPTION_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)
|
find_package(Qt5Widgets 5.9 REQUIRED)
|
||||||
|
|
||||||
@@ -102,15 +110,18 @@ include(InstallLocation)
|
|||||||
include(QtInstallPaths) #to set QT_INSTALL_FOO variables
|
include(QtInstallPaths) #to set QT_INSTALL_FOO variables
|
||||||
|
|
||||||
macro(set_compiler_flags targetName)
|
macro(set_compiler_flags targetName)
|
||||||
if(OPTION_DEVELOPER_MODE)
|
if(${PROJECT_NAME}_DEVELOPER_MODE)
|
||||||
target_compile_definitions(${targetName} PRIVATE DOCKS_DEVELOPER_MODE QT_FORCE_ASSERTS)
|
target_compile_definitions(${targetName} PRIVATE DOCKS_DEVELOPER_MODE QT_FORCE_ASSERTS)
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
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)
|
||||||
|
target_compile_options(${targetName} PRIVATE -Wweak-vtables)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|
||||||
if(OPTION_QTQUICK)
|
if(${PROJECT_NAME}_QTQUICK)
|
||||||
find_package(Qt5Quick)
|
find_package(Qt5Quick)
|
||||||
find_package(Qt5QuickControls2)
|
find_package(Qt5QuickControls2)
|
||||||
add_definitions(-DKDDOCKWIDGETS_QTQUICK)
|
add_definitions(-DKDDOCKWIDGETS_QTQUICK)
|
||||||
@@ -145,12 +156,12 @@ install(FILES LICENSE.txt README.md DESTINATION ${INSTALL_DOC_DIR})
|
|||||||
install(DIRECTORY LICENSES DESTINATION ${INSTALL_DOC_DIR})
|
install(DIRECTORY LICENSES DESTINATION ${INSTALL_DOC_DIR})
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
if(OPTION_BUILD_PYTHON_BINDINGS)
|
if(${PROJECT_NAME}_PYTHON_BINDINGS)
|
||||||
add_subdirectory(python)
|
add_subdirectory(python)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(${PROJECT_NAME}_EXAMPLES)
|
if(${PROJECT_NAME}_EXAMPLES)
|
||||||
if (OPTION_QTQUICK)
|
if (${PROJECT_NAME}_QTQUICK)
|
||||||
add_subdirectory(examples/qtquick)
|
add_subdirectory(examples/qtquick)
|
||||||
set_compiler_flags(kddockwidgets_example_quick)
|
set_compiler_flags(kddockwidgets_example_quick)
|
||||||
else()
|
else()
|
||||||
@@ -161,13 +172,13 @@ if(${PROJECT_NAME}_EXAMPLES)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(OPTION_DEVELOPER_MODE)
|
if(${PROJECT_NAME}_DEVELOPER_MODE)
|
||||||
include(ECMEnableSanitizers)
|
include(ECMEnableSanitizers)
|
||||||
if(${PROJECT_NAME}_TESTS)
|
if(${PROJECT_NAME}_TESTS)
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
if (NOT OPTION_QTQUICK)
|
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 (140 tests), so split it in 6 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.
|
||||||
|
|||||||
11
Changelog
@@ -1,19 +1,24 @@
|
|||||||
|
* v1.2.0 (unreleased)
|
||||||
|
- QtQuick support
|
||||||
|
|
||||||
* v1.1.0 (unreleased)
|
* v1.1.0 (unreleased)
|
||||||
- New drop indicator style type: Segmented Indicators
|
- New drop indicator style type: Segmented Indicators
|
||||||
|
- Windows: Drop Shadow for floating windows
|
||||||
|
- Added AutoHide / SideBar support
|
||||||
- Added FocusScope support
|
- Added FocusScope support
|
||||||
- Added DockWidget::isFocused() and DockWidgetBase::isFocusedChanged()
|
- Added DockWidget::isFocused() and DockWidgetBase::isFocusedChanged()
|
||||||
- Added Config::Flag_AlwaysTitleBarWhenFloating, which complements Flag_HideTitleBarWhenTabsVisible
|
- Added Config::Flag_AlwaysTitleBarWhenFloating, which complements Flag_HideTitleBarWhenTabsVisible
|
||||||
- Added Config::Flag_DontUseUtilityWindowsForFloating
|
- Added Config::Flag_DontUseUtilityWindowsForFloating
|
||||||
- Added Config::Flag_TitleBarHasMinimizeButton
|
- Added Config::Flag_TitleBarHasMinimizeButton
|
||||||
|
- Added Config::Flag_TitleBarNoFloatButton
|
||||||
|
- Added Config::Flag_AutoHideSupport
|
||||||
- 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)
|
||||||
- Don't center floating windows if the user set a custom position (#75)
|
- Don't center floating windows if the user set a custom position (#75)
|
||||||
- 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.
|
||||||
* Roadmap
|
|
||||||
- QtQuick support
|
|
||||||
|
|
||||||
* v1.0.1 (unreleased)
|
* v1.0.1 (unreleased)
|
||||||
- cmake/Python - don't require pkg-config, only use if available (#68)
|
- cmake/Python - don't require pkg-config, only use if available (#68)
|
||||||
|
|||||||
15
README.md
@@ -64,8 +64,7 @@ Features
|
|||||||
|
|
||||||
Roadmap
|
Roadmap
|
||||||
========
|
========
|
||||||
- QtQuick support for v1.1
|
- QtQuick support
|
||||||
- "Minimization bar" for v1.2
|
|
||||||
|
|
||||||
Trying out the examples
|
Trying out the examples
|
||||||
=======================
|
=======================
|
||||||
@@ -82,15 +81,15 @@ Build and install the KDDockWidgets framework:
|
|||||||
|
|
||||||
```
|
```
|
||||||
$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/path/where/to/install ../path/to/kddockwidgets
|
$ cmake -G Ninja -DCMAKE_INSTALL_PREFIX=/path/where/to/install ../path/to/kddockwidgets
|
||||||
$ make
|
$ cmake --build .
|
||||||
$ make install
|
$ cmake --build . --target install
|
||||||
```
|
```
|
||||||
|
|
||||||
Now build and run the example:
|
Now build and run the example:
|
||||||
```
|
```
|
||||||
$ cd path/to/kddockwidgets/examples/dockwidgets/
|
$ cd path/to/kddockwidgets/examples/dockwidgets/
|
||||||
$ cmake -DCMAKE_PREFIX_PATH=/path/where/to/install
|
$ cmake -G Ninja -DCMAKE_PREFIX_PATH=/path/where/to/install
|
||||||
$ make
|
$ cmake --build .
|
||||||
$ ./kddockwidgets_example
|
$ ./kddockwidgets_example
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -115,13 +114,13 @@ For more info visit https://doc.qt.io/qtforpython/shiboken2/gettingstarted.html
|
|||||||
Once QtForPython is installed you are ready to generate the PySide bindings
|
Once QtForPython is installed you are ready to generate the PySide bindings
|
||||||
for KDDockwWidgets.
|
for KDDockwWidgets.
|
||||||
|
|
||||||
Next pass `-DOPTION_BUILD_PYTHON_BINDINGS=ON` to CMake, followed by the
|
Next pass `-DKDDockWidgets_PYTHON_BINDINGS=ON` to CMake, followed by the
|
||||||
make command.
|
make command.
|
||||||
|
|
||||||
The bindings will be installed to the passed `-DCMAKE_INSTALL_PREFIX`, which
|
The bindings will be installed to the passed `-DCMAKE_INSTALL_PREFIX`, which
|
||||||
might require setting the `PYTHONPATH` env variable to point to that path when
|
might require setting the `PYTHONPATH` env variable to point to that path when
|
||||||
running applications. Alternatively, configure the bindings install location
|
running applications. Alternatively, configure the bindings install location
|
||||||
by passing `-DPYTHON_BINDINGS_INSTALL_PREFIX=/usr/lib/python3.8/site-packages`
|
by passing `-DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=/usr/lib/python3.8/site-packages`
|
||||||
to CMake (adjust to the python path on your system).
|
to CMake (adjust to the python path on your system).
|
||||||
|
|
||||||
To run the KDDW python example
|
To run the KDDW python example
|
||||||
|
|||||||
@@ -115,7 +115,6 @@ else()
|
|||||||
set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PATH})
|
set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PATH})
|
||||||
list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_BASEDIR})
|
list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_BASEDIR})
|
||||||
list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_GENERATOR_BASEDIR})
|
list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_GENERATOR_BASEDIR})
|
||||||
message(STATUS "BOO: ${SHIBOKEN_SEARCH_PATHS}")
|
|
||||||
find_file(SHIBOKEN_LIBRARY
|
find_file(SHIBOKEN_LIBRARY
|
||||||
${SHIBOKEN_LIBRARY_BASENAMES}
|
${SHIBOKEN_LIBRARY_BASENAMES}
|
||||||
PATHS ${SHIBOKEN_SEARCH_PATHS}
|
PATHS ${SHIBOKEN_SEARCH_PATHS}
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
#
|
#
|
||||||
|
|
||||||
if (NOT PYTHON_BINDINGS_INSTALL_PREFIX)
|
if (NOT ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX)
|
||||||
SET(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 ${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 ${PYTHON_BINDINGS_INSTALL_PREFIX}/${TARGET_NAME})
|
LIBRARY DESTINATION ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/${TARGET_NAME})
|
||||||
endmacro()
|
endmacro()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from conans import ConanFile, CMake, tools
|
|||||||
|
|
||||||
class KDDockWidgetsConan(ConanFile):
|
class KDDockWidgetsConan(ConanFile):
|
||||||
name = "kddockwidgets"
|
name = "kddockwidgets"
|
||||||
version = "1.0.0"
|
version = "1.1.95"
|
||||||
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",
|
||||||
@@ -51,7 +51,7 @@ class KDDockWidgetsConan(ConanFile):
|
|||||||
self.cmake.definitions["KDDockWidgets_STATIC"] = self.options.build_static
|
self.cmake.definitions["KDDockWidgets_STATIC"] = self.options.build_static
|
||||||
self.cmake.definitions["KDDockWidgets_EXAMPLES"] = self.options.build_examples
|
self.cmake.definitions["KDDockWidgets_EXAMPLES"] = self.options.build_examples
|
||||||
self.cmake.definitions["KDDockWidgets_TESTS"] = self.options.build_tests
|
self.cmake.definitions["KDDockWidgets_TESTS"] = self.options.build_tests
|
||||||
self.cmake.definitions["OPTION_BUILD_PYTHON_BINDINGS"] = self.options.build_python_bindings
|
self.cmake.definitions["KDDockWidgets_PYTHON_BINDINGS"] = self.options.build_python_bindings
|
||||||
self.cmake.configure()
|
self.cmake.configure()
|
||||||
self.cmake.build()
|
self.cmake.build()
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ find_package(Doxygen)
|
|||||||
set_package_properties(Doxygen PROPERTIES
|
set_package_properties(Doxygen PROPERTIES
|
||||||
TYPE OPTIONAL
|
TYPE OPTIONAL
|
||||||
DESCRIPTION "API Documentation system"
|
DESCRIPTION "API Documentation system"
|
||||||
URL "http://www.doxygen.org"
|
URL "https://www.doxygen.org"
|
||||||
PURPOSE "Needed to build the API documentation."
|
PURPOSE "Needed to build the API documentation."
|
||||||
)
|
)
|
||||||
if(DOXYGEN_DOT_EXECUTABLE)
|
if(DOXYGEN_DOT_EXECUTABLE)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<img src="kdab-logo-16x16.png">
|
<img src="kdab-logo-16x16.png">
|
||||||
<font style="font-weight: bold;">Klarälvdalens Datakonsult AB (KDAB)</font>
|
<font style="font-weight: bold;">Klarälvdalens Datakonsult AB (KDAB)</font>
|
||||||
<br>
|
<br>
|
||||||
"The Qt Experts"<br>
|
"The Qt, C++ and OpenGL Experts"<br>
|
||||||
<a href="https://www.kdab.com/">https://www.kdab.com/</a>
|
<a href="https://www.kdab.com/">https://www.kdab.com/</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
@@ -32,6 +32,8 @@ public:
|
|||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~MyTitleBar() override;
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
setFixedHeight(60);
|
setFixedHeight(60);
|
||||||
@@ -56,6 +58,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MyTitleBar::~MyTitleBar() = default;
|
||||||
|
|
||||||
// Inheriting from SeparatorWidget instead of Separator as it handles moving and mouse cursor changing
|
// Inheriting from SeparatorWidget instead of Separator as it handles moving and mouse cursor changing
|
||||||
class MySeparator : public Layouting::SeparatorWidget
|
class MySeparator : public Layouting::SeparatorWidget
|
||||||
{
|
{
|
||||||
@@ -65,6 +69,8 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~MySeparator() override;
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *) override
|
void paintEvent(QPaintEvent *) override
|
||||||
{
|
{
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
@@ -72,6 +78,8 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MySeparator::~MySeparator() = default;
|
||||||
|
|
||||||
KDDockWidgets::TitleBar * CustomWidgetFactory::createTitleBar(KDDockWidgets::Frame *frame) const
|
KDDockWidgets::TitleBar * CustomWidgetFactory::createTitleBar(KDDockWidgets::Frame *frame) const
|
||||||
{
|
{
|
||||||
return new MyTitleBar(frame);
|
return new MyTitleBar(frame);
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ int main(int argc, char **argv)
|
|||||||
parser.setApplicationDescription("KDDockWidgets example application");
|
parser.setApplicationDescription("KDDockWidgets example application");
|
||||||
parser.addHelpOption();
|
parser.addHelpOption();
|
||||||
|
|
||||||
|
// Fusion looks better in general, but feel free to change
|
||||||
qApp->setStyle(QStyleFactory::create(QStringLiteral("Fusion")));
|
qApp->setStyle(QStyleFactory::create(QStringLiteral("Fusion")));
|
||||||
|
|
||||||
QCommandLineOption customStyle("p", QCoreApplication::translate("main", "Shows how to style framework internals via FrameworkWidgetFactory"));
|
QCommandLineOption customStyle("p", QCoreApplication::translate("main", "Shows how to style framework internals via FrameworkWidgetFactory"));
|
||||||
@@ -102,6 +103,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
QCommandLineOption centralFrame("f", QCoreApplication::translate("main", "Persistent central frame"));
|
QCommandLineOption centralFrame("f", QCoreApplication::translate("main", "Persistent central frame"));
|
||||||
|
|
||||||
|
QCommandLineOption autoHideSupport("w", QCoreApplication::translate("main", "Enables auto-hide/minimization to side-bar support"));
|
||||||
|
parser.addOption(autoHideSupport);
|
||||||
|
|
||||||
#if defined(DOCKS_DEVELOPER_MODE)
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
parser.addOption(centralFrame);
|
parser.addOption(centralFrame);
|
||||||
|
|
||||||
@@ -149,6 +153,9 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (parser.isSet(autoHideSupport))
|
||||||
|
flags |= Config::Flag_AutoHideSupport;
|
||||||
|
|
||||||
if (parser.isSet(noTitleBars))
|
if (parser.isSet(noTitleBars))
|
||||||
flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible;
|
flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible;
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include <kddockwidgets/DockWidget.h>
|
#include <kddockwidgets/DockWidget.h>
|
||||||
#include <kddockwidgets/MainWindow.h>
|
#include <kddockwidgets/MainWindow.h>
|
||||||
|
|
||||||
|
#include <QStyleFactory>
|
||||||
|
|
||||||
// clazy:excludeall=qstring-allocations
|
// clazy:excludeall=qstring-allocations
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
@@ -27,6 +29,9 @@ int main(int argc, char **argv)
|
|||||||
app.setOrganizationName(QStringLiteral("KDAB"));
|
app.setOrganizationName(QStringLiteral("KDAB"));
|
||||||
app.setApplicationName(QStringLiteral("Test app"));
|
app.setApplicationName(QStringLiteral("Test app"));
|
||||||
|
|
||||||
|
// Fusion looks better in general, but feel free to change
|
||||||
|
qApp->setStyle(QStyleFactory::create(QStringLiteral("Fusion")));
|
||||||
|
|
||||||
// # 1. Create our main window
|
// # 1. Create our main window
|
||||||
|
|
||||||
KDDockWidgets::MainWindow mainWindow(QStringLiteral("MyMainWindow"));
|
KDDockWidgets::MainWindow mainWindow(QStringLiteral("MyMainWindow"));
|
||||||
|
|||||||
@@ -22,12 +22,15 @@ int main(int argc, char *argv[])
|
|||||||
QGuiApplication app(argc, argv);
|
QGuiApplication app(argc, argv);
|
||||||
|
|
||||||
QQuickView view;
|
QQuickView view;
|
||||||
|
view.setObjectName("MainWindow QQuickView");
|
||||||
KDDockWidgets::Config::self().setQmlEngine(view.engine());
|
KDDockWidgets::Config::self().setQmlEngine(view.engine());
|
||||||
view.resize(1000, 800);
|
view.resize(1000, 800);
|
||||||
view.show();
|
view.show();
|
||||||
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
view.setResizeMode(QQuickView::SizeRootObjectToView);
|
||||||
|
|
||||||
auto dw1 = new KDDockWidgets::DockWidgetQuick("Dock #1");
|
auto dw1 = new KDDockWidgets::DockWidgetQuick("Dock #1");
|
||||||
|
view.setSource(QUrl("qrc:/main.qml"));
|
||||||
|
|
||||||
dw1->setWidget(QStringLiteral("qrc:/Guest1.qml"));
|
dw1->setWidget(QStringLiteral("qrc:/Guest1.qml"));
|
||||||
dw1->resize(QSize(800, 800));
|
dw1->resize(QSize(800, 800));
|
||||||
dw1->show();
|
dw1->show();
|
||||||
@@ -42,8 +45,6 @@ int main(int argc, char *argv[])
|
|||||||
dw3->resize(QSize(800, 800));
|
dw3->resize(QSize(800, 800));
|
||||||
dw3->show();
|
dw3->show();
|
||||||
|
|
||||||
view.setSource(QUrl("qrc:/main.qml"));
|
|
||||||
|
|
||||||
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();
|
||||||
|
|||||||
@@ -78,4 +78,4 @@ create_python_bindings(
|
|||||||
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 ${PYTHON_BINDINGS_INSTALL_PREFIX}/PyKDDockWidgets)
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py DESTINATION ${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/PyKDDockWidgets)
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
<!-- this is used in a public virtual pure function we need to declare it
|
<!-- this is used in a public virtual pure function we need to declare it
|
||||||
otherwise shiboken will ignore the function and will fail to create a wrapper -->
|
otherwise shiboken will ignore the function and will fail to create a wrapper -->
|
||||||
<primitive-type name="DropAreaWithCentralFrame"/>
|
<primitive-type name="DropAreaWithCentralFrame"/>
|
||||||
|
<primitive-type name="SideBar"/>
|
||||||
|
|
||||||
<!-- Some plublic enum and flags -->
|
<!-- Some plublic enum and flags -->
|
||||||
<enum-type name="Location"/>
|
<enum-type name="Location"/>
|
||||||
@@ -19,6 +20,9 @@
|
|||||||
<enum-type name="RestoreOption" flags="RestoreOptions"/>
|
<enum-type name="RestoreOption" flags="RestoreOptions"/>
|
||||||
<enum-type name="DefaultSizeMode"/>
|
<enum-type name="DefaultSizeMode"/>
|
||||||
<enum-type name="FrameOption" flags="FrameOptions"/>
|
<enum-type name="FrameOption" flags="FrameOptions"/>
|
||||||
|
<enum-type name="DropIndicatorType"/>
|
||||||
|
<enum-type name="SideBarLocation"/>
|
||||||
|
<enum-type name="TitleBarButtonType"/>
|
||||||
|
|
||||||
<!-- our classes
|
<!-- our classes
|
||||||
For class we can use two types:
|
For class we can use two types:
|
||||||
@@ -32,6 +36,7 @@
|
|||||||
<!-- this class contains a internal enum, so it should be declared
|
<!-- this class contains a internal enum, so it should be declared
|
||||||
inside of the object-type -->
|
inside of the object-type -->
|
||||||
<enum-type name="Option" flags="Options" />
|
<enum-type name="Option" flags="Options" />
|
||||||
|
<enum-type name="IconPlace" flags="IconPlaces" />
|
||||||
</object-type>
|
</object-type>
|
||||||
|
|
||||||
<object-type name="DockWidget" />
|
<object-type name="DockWidget" />
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ set(DOCKSLIBS_SRCS
|
|||||||
private/FloatingWindow.cpp
|
private/FloatingWindow.cpp
|
||||||
private/Logging.cpp
|
private/Logging.cpp
|
||||||
private/TitleBar.cpp
|
private/TitleBar.cpp
|
||||||
|
private/SideBar.cpp
|
||||||
private/DockRegistry.cpp
|
private/DockRegistry.cpp
|
||||||
private/Draggable.cpp
|
private/Draggable.cpp
|
||||||
private/WindowBeingDragged.cpp
|
private/WindowBeingDragged.cpp
|
||||||
@@ -61,16 +62,20 @@ set(DOCKS_INSTALLABLE_INCLUDES
|
|||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_PRIVATE_INCLUDES
|
set(DOCKS_INSTALLABLE_PRIVATE_INCLUDES
|
||||||
|
private/DragController_p.h
|
||||||
private/Draggable_p.h
|
private/Draggable_p.h
|
||||||
private/DropIndicatorOverlayInterface_p.h
|
private/DropIndicatorOverlayInterface_p.h
|
||||||
private/FloatingWindow_p.h
|
private/FloatingWindow_p.h
|
||||||
private/Frame_p.h
|
private/Frame_p.h
|
||||||
|
private/SideBar_p.h
|
||||||
private/TitleBar_p.h
|
private/TitleBar_p.h
|
||||||
|
private/WindowBeingDragged_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
||||||
private/widgets/QWidgetAdapter_widgets_p.h
|
private/widgets/QWidgetAdapter_widgets_p.h
|
||||||
private/widgets/TitleBarWidget_p.h
|
private/widgets/TitleBarWidget_p.h
|
||||||
|
private/widgets/SideBarWidget_p.h
|
||||||
private/widgets/FloatingWindowWidget_p.h
|
private/widgets/FloatingWindowWidget_p.h
|
||||||
private/widgets/FrameWidget_p.h
|
private/widgets/FrameWidget_p.h
|
||||||
private/widgets/TabBarWidget_p.h
|
private/widgets/TabBarWidget_p.h
|
||||||
@@ -78,7 +83,7 @@ set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
|||||||
private/widgets/TabWidget_p.h
|
private/widgets/TabWidget_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if(OPTION_QTQUICK)
|
if(${PROJECT_NAME}_QTQUICK)
|
||||||
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
||||||
private/quick/DockWidgetQuick.cpp
|
private/quick/DockWidgetQuick.cpp
|
||||||
private/quick/QWidgetAdapter_quick.cpp
|
private/quick/QWidgetAdapter_quick.cpp
|
||||||
@@ -99,6 +104,7 @@ else()
|
|||||||
private/widgets/TabBarWidget.cpp
|
private/widgets/TabBarWidget.cpp
|
||||||
private/widgets/FloatingWindowWidget.cpp
|
private/widgets/FloatingWindowWidget.cpp
|
||||||
private/widgets/FrameWidget.cpp
|
private/widgets/FrameWidget.cpp
|
||||||
|
private/widgets/SideBarWidget.cpp
|
||||||
private/widgets/TabWidgetWidget.cpp
|
private/widgets/TabWidgetWidget.cpp
|
||||||
private/widgets/TitleBarWidget.cpp
|
private/widgets/TitleBarWidget.cpp
|
||||||
private/widgets/DockWidget.cpp
|
private/widgets/DockWidget.cpp
|
||||||
@@ -161,15 +167,17 @@ if(CMAKE_COMPILER_IS_GNUCXX OR IS_CLANG_BUILD)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(OPTION_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 Qt5::Widgets Qt5::Quick Qt5::QuickControls2 kddockwidgets_multisplitter PRIVATE Qt5::GuiPrivate)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(kddockwidgets PUBLIC Qt5::Widgets kddockwidgets_multisplitter PRIVATE Qt5::GuiPrivate)
|
target_link_libraries(kddockwidgets PUBLIC Qt5::Widgets kddockwidgets_multisplitter PRIVATE Qt5::GuiPrivate)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(NOT WIN32 AND NOT APPLE)
|
if (WIN32)
|
||||||
find_package(Qt5X11Extras)
|
target_link_libraries(kddockwidgets PRIVATE Dwmapi)
|
||||||
target_link_libraries(kddockwidgets PUBLIC Qt5::X11Extras)
|
elseif(NOT APPLE)
|
||||||
|
find_package(Qt5X11Extras)
|
||||||
|
target_link_libraries(kddockwidgets PUBLIC Qt5::X11Extras)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set_target_properties(kddockwidgets PROPERTIES VERSION ${${PROJECT_NAME}_SOVERSION})
|
set_target_properties(kddockwidgets PROPERTIES VERSION ${${PROJECT_NAME}_SOVERSION})
|
||||||
@@ -224,11 +232,11 @@ install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgetsConfig.cmake"
|
|||||||
DESTINATION ${INSTALL_LIBRARY_DIR}/cmake/KDDockWidgets
|
DESTINATION ${INSTALL_LIBRARY_DIR}/cmake/KDDockWidgets
|
||||||
)
|
)
|
||||||
|
|
||||||
if(OPTION_DEVELOPER_MODE)
|
if(${PROJECT_NAME}_DEVELOPER_MODE)
|
||||||
# Under developer mode since kddw might be a sub-folder of a project setting a different value for QT_DISABLE_DEPRECATED_BEFORE
|
# Under developer mode since kddw might be a sub-folder of a project setting a different value for QT_DISABLE_DEPRECATED_BEFORE
|
||||||
target_compile_definitions(kddockwidgets PRIVATE QT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
target_compile_definitions(kddockwidgets PRIVATE QT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
||||||
|
|
||||||
if (NOT OPTION_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 kddockwidgets_multisplitter Qt5::Widgets)
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include "multisplitter/Widget_qwidget.h"
|
#include "multisplitter/Widget_qwidget.h"
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
|
#include "Utils_p.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -83,8 +84,11 @@ Config::Flags Config::flags() const
|
|||||||
|
|
||||||
void Config::setFlags(Flags f)
|
void Config::setFlags(Flags f)
|
||||||
{
|
{
|
||||||
if (!DockRegistry::self()->isEmpty()) {
|
auto dr = DockRegistry::self();
|
||||||
qWarning() << Q_FUNC_INFO << "Only use this function at startup before creating any DockWidget or MainWindow";
|
if (!dr->isEmpty(/*excludeBeingDeleted=*/ true)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Only use this function at startup before creating any DockWidget or MainWindow"
|
||||||
|
<< "; These are already created: " << dr->mainWindowsNames()
|
||||||
|
<< dr->dockWidgetNames() << dr->floatingWindows();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -135,7 +139,7 @@ int Config::separatorThickness() const
|
|||||||
|
|
||||||
void Config::setSeparatorThickness(int value)
|
void Config::setSeparatorThickness(int value)
|
||||||
{
|
{
|
||||||
if (!DockRegistry::self()->isEmpty()) {
|
if (!DockRegistry::self()->isEmpty(/*excludeBeingDeleted=*/ true)) {
|
||||||
qWarning() << Q_FUNC_INFO << "Only use this function at startup before creating any DockWidget or MainWindow";
|
qWarning() << Q_FUNC_INFO << "Only use this function at startup before creating any DockWidget or MainWindow";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -174,6 +178,9 @@ void Config::Private::fixFlags()
|
|||||||
if (QOperatingSystemVersion::current().majorVersion() < 10) {
|
if (QOperatingSystemVersion::current().majorVersion() < 10) {
|
||||||
// Aero-snap requires Windows 10
|
// Aero-snap requires Windows 10
|
||||||
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
||||||
|
} else {
|
||||||
|
// Unconditional now
|
||||||
|
m_flags |= Flag_AeroSnapWithClientDecos;
|
||||||
}
|
}
|
||||||
|
|
||||||
// These are mutually exclusive:
|
// These are mutually exclusive:
|
||||||
@@ -185,10 +192,18 @@ void Config::Private::fixFlags()
|
|||||||
// Not supported on macOS:
|
// Not supported on macOS:
|
||||||
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
||||||
#else
|
#else
|
||||||
// Not supported on linux.
|
if (KDDockWidgets::isWayland()) {
|
||||||
// On Linux, dragging the title bar of a window doesn't generate NonClientMouseEvents
|
// Native title bar is forced on Wayland. Needed for moving the window.
|
||||||
m_flags = m_flags & ~Flag_NativeTitleBar;
|
// The inner KDDW title bar is used for DnD.
|
||||||
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
m_flags |= Flag_NativeTitleBar;
|
||||||
|
} else {
|
||||||
|
// Not supported on linux/X11
|
||||||
|
// On Linux, dragging the title bar of a window doesn't generate NonClientMouseEvents
|
||||||
|
// at least with KWin anyway. We can make this more granular and allow it for other
|
||||||
|
// X11 window managers
|
||||||
|
m_flags = m_flags & ~Flag_NativeTitleBar;
|
||||||
|
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
#if !defined(Q_OS_WIN) && !defined(Q_OS_MACOS)
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
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, ///> Enables AeroSnap even if we're not using the native title bar. Only supported on Windows 10.
|
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,
|
||||||
@@ -72,6 +72,9 @@ public:
|
|||||||
|
|
||||||
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_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.
|
||||||
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
|
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "private/Position_p.h"
|
#include "private/Position_p.h"
|
||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
|
#include "SideBar_p.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
@@ -57,10 +58,12 @@ public:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
q->connect(floatAction, &QAction::toggled, q, [this] (bool enabled) {
|
q->connect(floatAction, &QAction::toggled, q, [this] (bool checked) {
|
||||||
if (!m_updatingFloatAction) { // guard against recursiveness
|
if (!m_updatingFloatAction) { // guard against recursiveness
|
||||||
q->setFloating(enabled);
|
q->setFloating(checked);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Q_EMIT q->isFloatingChanged(checked);
|
||||||
});
|
});
|
||||||
|
|
||||||
toggleAction->setCheckable(true);
|
toggleAction->setCheckable(true);
|
||||||
@@ -107,7 +110,7 @@ public:
|
|||||||
void onDockWidgetHidden();
|
void onDockWidgetHidden();
|
||||||
void show();
|
void show();
|
||||||
void close();
|
void close();
|
||||||
void restoreToPreviousPosition();
|
bool restoreToPreviousPosition();
|
||||||
void maybeRestoreToPreviousPosition();
|
void maybeRestoreToPreviousPosition();
|
||||||
int currentTabIndex() const;
|
int currentTabIndex() const;
|
||||||
|
|
||||||
@@ -264,15 +267,12 @@ bool DockWidgetBase::isFloating() const
|
|||||||
return fw && fw->hasSingleDockWidget();
|
return fw && fw->hasSingleDockWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::setFloating(bool floats)
|
bool DockWidgetBase::setFloating(bool floats)
|
||||||
{
|
{
|
||||||
const bool alreadyFloating = isFloating();
|
const bool alreadyFloating = isFloating();
|
||||||
|
|
||||||
qCDebug(docking) << Q_FUNC_INFO << "yes=" << floats
|
|
||||||
<< "; already floating=" << alreadyFloating;
|
|
||||||
|
|
||||||
if ((floats && alreadyFloating) || (!floats && !alreadyFloating))
|
if ((floats && alreadyFloating) || (!floats && !alreadyFloating))
|
||||||
return; // Nothing to do
|
return true; // Nothing to do
|
||||||
|
|
||||||
if (floats) {
|
if (floats) {
|
||||||
d->saveTabIndex();
|
d->saveTabIndex();
|
||||||
@@ -282,6 +282,7 @@ void DockWidgetBase::setFloating(bool floats)
|
|||||||
qWarning() << "DockWidget::setFloating: Tabbed but no frame exists"
|
qWarning() << "DockWidget::setFloating: Tabbed but no frame exists"
|
||||||
<< this;
|
<< this;
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame->detachTab(this);
|
frame->detachTab(this);
|
||||||
@@ -294,9 +295,10 @@ void DockWidgetBase::setFloating(bool floats)
|
|||||||
if (auto fw = floatingWindow())
|
if (auto fw = floatingWindow())
|
||||||
fw->setSuggestedGeometry(lastGeo, /*preserveCenter=*/true);
|
fw->setSuggestedGeometry(lastGeo, /*preserveCenter=*/true);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
saveLastFloatingGeometry();
|
saveLastFloatingGeometry();
|
||||||
d->restoreToPreviousPosition();
|
return d->restoreToPreviousPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -489,6 +491,30 @@ void DockWidgetBase::setAffinities(const QStringList &affinityNames)
|
|||||||
d->affinities = affinities;
|
d->affinities = affinities;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::moveToSideBar()
|
||||||
|
{
|
||||||
|
if (MainWindowBase *m = mainWindow())
|
||||||
|
m->moveToSideBar(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DockWidgetBase::isOverlayed() const
|
||||||
|
{
|
||||||
|
if (MainWindowBase *m = mainWindow())
|
||||||
|
return m->overlayedDockWidget() == this;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SideBarLocation DockWidgetBase::sideBarLocation() const
|
||||||
|
{
|
||||||
|
return DockRegistry::self()->sideBarLocationForDockWidget(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DockWidgetBase::hasPreviousDockedLocation() const
|
||||||
|
{
|
||||||
|
return d->m_lastPositions.isValid();
|
||||||
|
}
|
||||||
|
|
||||||
FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
|
FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
|
||||||
{
|
{
|
||||||
qCDebug(creation) << "DockWidget::morphIntoFloatingWindow() this=" << this
|
qCDebug(creation) << "DockWidget::morphIntoFloatingWindow() this=" << this
|
||||||
@@ -651,19 +677,24 @@ void DockWidgetBase::Private::close()
|
|||||||
if (Frame *frame = q->frame()) {
|
if (Frame *frame = q->frame()) {
|
||||||
frame->removeWidget(q);
|
frame->removeWidget(q);
|
||||||
q->setParent(nullptr);
|
q->setParent(nullptr);
|
||||||
|
|
||||||
|
if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
|
||||||
|
sb->removeDockWidget(q);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::restoreToPreviousPosition()
|
bool DockWidgetBase::Private::restoreToPreviousPosition()
|
||||||
{
|
{
|
||||||
if (!m_lastPositions.isValid())
|
if (!m_lastPositions.isValid())
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
Layouting::Item *item = m_lastPositions.lastItem();
|
Layouting::Item *item = m_lastPositions.lastItem();
|
||||||
|
|
||||||
MultiSplitter *layout = DockRegistry::self()->layoutForItem(item);
|
MultiSplitter *layout = DockRegistry::self()->layoutForItem(item);
|
||||||
Q_ASSERT(layout);
|
Q_ASSERT(layout);
|
||||||
layout->restorePlaceholder(q, item, m_lastPositions.lastTabIndex());
|
layout->restorePlaceholder(q, item, m_lastPositions.lastTabIndex());
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
|
void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
|
||||||
@@ -755,7 +786,7 @@ void DockWidgetBase::onHidden(bool spontaneous)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::onClosed(QCloseEvent *e)
|
void DockWidgetBase::onCloseEvent(QCloseEvent *e)
|
||||||
{
|
{
|
||||||
e->accept(); // By default we accept, means DockWidget closes
|
e->accept(); // By default we accept, means DockWidget closes
|
||||||
if (d->widget)
|
if (d->widget)
|
||||||
|
|||||||
@@ -61,6 +61,8 @@ class DOCKS_EXPORT DockWidgetBase : public QWidget
|
|||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(bool isFocused READ isFocused NOTIFY isFocusedChanged)
|
||||||
|
Q_PROPERTY(bool isFloating READ isFloating WRITE setFloating NOTIFY isFloatingChanged)
|
||||||
public:
|
public:
|
||||||
typedef QVector<DockWidgetBase *> List;
|
typedef QVector<DockWidgetBase *> List;
|
||||||
|
|
||||||
@@ -137,7 +139,7 @@ public:
|
|||||||
* call setWidget(A) followed by setWidget(B) then A will have to be deleted by you, while B is
|
* call setWidget(A) followed by setWidget(B) then A will have to be deleted by you, while B is
|
||||||
* owned by the dock widget.
|
* owned by the dock widget.
|
||||||
*/
|
*/
|
||||||
void setWidget(QWidgetOrQuick *widget);
|
virtual void setWidget(QWidgetOrQuick *widget);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns the widget which this dock widget hosts
|
* @brief returns the widget which this dock widget hosts
|
||||||
@@ -156,8 +158,10 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief setter to make the dock widget float or dock.
|
* @brief setter to make the dock widget float or dock.
|
||||||
* @param floats If true makes the dock widget float, otherwise docks it.
|
* @param floats If true makes the dock widget float, otherwise docks it.
|
||||||
|
*
|
||||||
|
* Returns true if the request was accomplished
|
||||||
*/
|
*/
|
||||||
void setFloating(bool floats);
|
bool setFloating(bool floats);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the QAction that allows to hide/show the dock widget
|
* @brief Returns the QAction that allows to hide/show the dock widget
|
||||||
@@ -338,6 +342,32 @@ public:
|
|||||||
///@sa isFocusedChanged()
|
///@sa isFocusedChanged()
|
||||||
bool isFocused() const;
|
bool isFocused() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Minimizes this dock widget to the MainWindow's side-bar.
|
||||||
|
*
|
||||||
|
* It will be undocked from current layout. It's previous docked position will be remembered.
|
||||||
|
*
|
||||||
|
* This action is only available if the dock widget is docked into a MainWindow.
|
||||||
|
* The dockwidget will initially be visible and overlayed on top of the current layout (this is
|
||||||
|
* the auto-hide feature).
|
||||||
|
*/
|
||||||
|
void moveToSideBar();
|
||||||
|
|
||||||
|
/// @brief Returns whether this dock widget is overlayed on top of the main window, instead of
|
||||||
|
/// docked into the layout. This is only relevant when using the auto-hide and side-bar feature.
|
||||||
|
bool isOverlayed() const;
|
||||||
|
|
||||||
|
///@brief Returns whether this dock widget is in a side bar, and which.
|
||||||
|
/// SideBarLocation::None is returned if it's not in a sidebar.
|
||||||
|
/// This is only relevant when using the auto-hide and side-bar feature.
|
||||||
|
SideBarLocation sideBarLocation() const;
|
||||||
|
|
||||||
|
/// @brief Returns whether this floating dock widget knows its previous docked location
|
||||||
|
/// Result only makes sense if it's floating.
|
||||||
|
///
|
||||||
|
/// When you call dockWidget->setFloating(false) it will only dock if it knows where to.
|
||||||
|
bool hasPreviousDockedLocation() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
///@brief signal emitted when the parent changed
|
///@brief signal emitted when the parent changed
|
||||||
void parentChanged();
|
void parentChanged();
|
||||||
@@ -366,11 +396,24 @@ Q_SIGNALS:
|
|||||||
///@sa isFocused
|
///@sa isFocused
|
||||||
void isFocusedChanged(bool);
|
void isFocusedChanged(bool);
|
||||||
|
|
||||||
|
///@brief emitted when isOverlayed changes
|
||||||
|
///@sa isOverlayed
|
||||||
|
void isOverlayedChanged(bool);
|
||||||
|
|
||||||
|
///@brief emitted when isFloating changes
|
||||||
|
bool isFloatingChanged(bool);
|
||||||
|
|
||||||
|
///@brief emitted when this dock widget is removed from a side-bar.
|
||||||
|
///Only relevant for the auto-hide/sidebar feature
|
||||||
|
void removedFromSideBar();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onParentChanged();
|
void onParentChanged();
|
||||||
void onShown(bool spontaneous);
|
void onShown(bool spontaneous);
|
||||||
void onHidden(bool spontaneous);
|
void onHidden(bool spontaneous);
|
||||||
void onClosed(QCloseEvent *e);
|
#ifndef PYTHON_BINDINGS //Pyside bug: https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1327
|
||||||
|
void onCloseEvent(QCloseEvent *e) override;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(DOCKS_DEVELOPER_MODE)
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
@@ -403,6 +446,7 @@ private:
|
|||||||
friend class KDDockWidgets::DragController;
|
friend class KDDockWidgets::DragController;
|
||||||
friend class KDDockWidgets::DockRegistry;
|
friend class KDDockWidgets::DockRegistry;
|
||||||
friend class KDDockWidgets::LayoutSaver;
|
friend class KDDockWidgets::LayoutSaver;
|
||||||
|
friend class KDDockWidgets::MainWindowBase;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief the Frame which contains this dock widgets.
|
* @brief the Frame which contains this dock widgets.
|
||||||
|
|||||||
@@ -40,6 +40,8 @@ public:
|
|||||||
m_inCtor = false;
|
m_inCtor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Private() override;
|
||||||
|
|
||||||
void setIsFocused(bool);
|
void setIsFocused(bool);
|
||||||
void onFocusObjectChanged(QObject *);
|
void onFocusObjectChanged(QObject *);
|
||||||
bool isInFocusScope(WidgetType *) const;
|
bool isInFocusScope(WidgetType *) const;
|
||||||
@@ -51,6 +53,9 @@ public:
|
|||||||
QPointer<WidgetType> m_lastFocusedInScope;
|
QPointer<WidgetType> m_lastFocusedInScope;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FocusScope::Private::~Private()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
FocusScope::FocusScope(QWidgetAdapter *thisWidget)
|
FocusScope::FocusScope(QWidgetAdapter *thisWidget)
|
||||||
: d(new Private(this, thisWidget))
|
: d(new Private(this, thisWidget))
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ class FocusScope
|
|||||||
public:
|
public:
|
||||||
///@brief constructor
|
///@brief constructor
|
||||||
explicit FocusScope(QWidgetAdapter *thisWidget);
|
explicit FocusScope(QWidgetAdapter *thisWidget);
|
||||||
~FocusScope();
|
virtual ~FocusScope();
|
||||||
|
|
||||||
///@brief Returns true if this FocusScope is focused.
|
///@brief Returns true if this FocusScope is focused.
|
||||||
///This is similar to the QWidget::hasFocus(), except that it counts with the children being focused too.
|
///This is similar to the QWidget::hasFocus(), except that it counts with the children being focused too.
|
||||||
|
|||||||
@@ -23,11 +23,14 @@
|
|||||||
# include "widgets/FrameWidget_p.h"
|
# include "widgets/FrameWidget_p.h"
|
||||||
# include "widgets/TitleBarWidget_p.h"
|
# include "widgets/TitleBarWidget_p.h"
|
||||||
# include "widgets/TabBarWidget_p.h"
|
# include "widgets/TabBarWidget_p.h"
|
||||||
|
# include "widgets/SideBarWidget_p.h"
|
||||||
# include "widgets/TabWidgetWidget_p.h"
|
# include "widgets/TabWidgetWidget_p.h"
|
||||||
# include "multisplitter/Separator_qwidget.h"
|
# include "multisplitter/Separator_qwidget.h"
|
||||||
# include "widgets/FloatingWindowWidget_p.h"
|
# include "widgets/FloatingWindowWidget_p.h"
|
||||||
# include "indicators/SegmentedIndicators_p.h"
|
# include "indicators/SegmentedIndicators_p.h"
|
||||||
|
|
||||||
# include <QRubberBand>
|
# include <QRubberBand>
|
||||||
|
# include <QToolButton>
|
||||||
#else
|
#else
|
||||||
# include "quick/FrameQuick_p.h"
|
# include "quick/FrameQuick_p.h"
|
||||||
# include "quick/DockWidgetQuick.h"
|
# include "quick/DockWidgetQuick.h"
|
||||||
@@ -102,6 +105,24 @@ QWidgetOrQuick *DefaultWidgetFactory::createRubberBand(QWidgetOrQuick *parent) c
|
|||||||
return new QRubberBand(QRubberBand::Rectangle, parent);
|
return new QRubberBand(QRubberBand::Rectangle, parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SideBar *DefaultWidgetFactory::createSideBar(SideBarLocation loc, MainWindowBase *parent) const
|
||||||
|
{
|
||||||
|
return new SideBarWidget(loc, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
QAbstractButton* DefaultWidgetFactory::createTitleBarButton(QWidget *parent, TitleBarButtonType type) const
|
||||||
|
{
|
||||||
|
if (!parent) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Parent not provided";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto button = new Button(parent);
|
||||||
|
button->setIcon(iconForButtonType(type, parent->devicePixelRatioF()));
|
||||||
|
|
||||||
|
return button;
|
||||||
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
Frame *DefaultWidgetFactory::createFrame(QWidgetOrQuick *parent, FrameOptions options) const
|
Frame *DefaultWidgetFactory::createFrame(QWidgetOrQuick *parent, FrameOptions options) const
|
||||||
@@ -163,4 +184,69 @@ QWidgetOrQuick *DefaultWidgetFactory::createRubberBand(QWidgetOrQuick *parent) c
|
|||||||
return new QWidgetOrQuick(parent);
|
return new QWidgetOrQuick(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SideBar *DefaultWidgetFactory::createSideBar(SideBarLocation loc, MainWindowBase *parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(loc);
|
||||||
|
Q_UNUSED(parent);
|
||||||
|
|
||||||
|
qWarning() << Q_FUNC_INFO << "Not implemented yet";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // QtQuick
|
||||||
|
|
||||||
|
// iconForButtonType impl is the same for QtQuick and QtWidgets
|
||||||
|
QIcon DefaultWidgetFactory::iconForButtonType(TitleBarButtonType type, qreal dpr) const
|
||||||
|
{
|
||||||
|
QString iconName;
|
||||||
|
switch (type) {
|
||||||
|
case TitleBarButtonType::AutoHide:
|
||||||
|
iconName = QStringLiteral("auto-hide");
|
||||||
|
break;
|
||||||
|
case TitleBarButtonType::UnautoHide:
|
||||||
|
iconName = QStringLiteral("unauto-hide");
|
||||||
|
break;
|
||||||
|
case TitleBarButtonType::Close:
|
||||||
|
iconName = QStringLiteral("close");
|
||||||
|
break;
|
||||||
|
case TitleBarButtonType::Minimize:
|
||||||
|
iconName = QStringLiteral("min");
|
||||||
|
break;
|
||||||
|
case TitleBarButtonType::Maximize:
|
||||||
|
iconName = QStringLiteral("max");
|
||||||
|
break;
|
||||||
|
case TitleBarButtonType::Normal:
|
||||||
|
// We're using the same icon as dock/float
|
||||||
|
iconName = QStringLiteral("dock-float");
|
||||||
|
break;
|
||||||
|
case TitleBarButtonType::Float:
|
||||||
|
iconName = QStringLiteral("dock-float");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iconName.isEmpty())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
QIcon icon(QStringLiteral(":/img/%1.png").arg(iconName));
|
||||||
|
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
|
||||||
|
const bool isFractional = int(dpr) != dpr;
|
||||||
|
if (isFractional) {
|
||||||
|
// 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
|
||||||
|
// Will enable for fractional later.
|
||||||
|
// QTBUG-86170
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
// Not using Qt's sugar syntax, which doesn't support 1.5x anyway when we need it.
|
||||||
|
// Simply add the high-res files and Qt will pick them when needed
|
||||||
|
|
||||||
|
icon.addFile(QStringLiteral(":/img/%1-1.5x.png").arg(iconName));
|
||||||
|
Q_UNUSED(dpr);
|
||||||
#endif
|
#endif
|
||||||
|
icon.addFile(QStringLiteral(":/img/%1-2x.png").arg(iconName));
|
||||||
|
|
||||||
|
return icon;
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,10 @@
|
|||||||
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QAbstractButton;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
namespace Layouting {
|
namespace Layouting {
|
||||||
class Separator;
|
class Separator;
|
||||||
class Widget;
|
class Widget;
|
||||||
@@ -37,6 +41,7 @@ class TabWidget;
|
|||||||
class TitleBar;
|
class TitleBar;
|
||||||
class Frame;
|
class Frame;
|
||||||
class DropArea;
|
class DropArea;
|
||||||
|
class SideBar;
|
||||||
class TabBar;
|
class TabBar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -121,6 +126,23 @@ public:
|
|||||||
///@brief Called internally by the framework to create a RubberBand to show as drop zone
|
///@brief Called internally by the framework to create a RubberBand to show as drop zone
|
||||||
///Returns a rubber band
|
///Returns a rubber band
|
||||||
virtual QWidgetOrQuick *createRubberBand(QWidgetOrQuick *parent) const = 0;
|
virtual QWidgetOrQuick *createRubberBand(QWidgetOrQuick *parent) const = 0;
|
||||||
|
|
||||||
|
///@brief Called internally by the framework to create a SideBar
|
||||||
|
///@param loc The side-bar location without the main window. Just forward into your SideBar sub-class ctor.
|
||||||
|
///@param parent The MainWindow. Just forward into your SideBar sub-class ctor.
|
||||||
|
virtual SideBar *createSideBar(SideBarLocation loc, MainWindowBase *parent) const = 0;
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
///@brief Called internally by the framework to create a title bar button
|
||||||
|
///@parent the button's parent
|
||||||
|
virtual QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const = 0;
|
||||||
|
#else
|
||||||
|
// QtQuick will have some other base class for buttons
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// @brief Returns the icon to be used with the specified @p type
|
||||||
|
/// @param dpr the device pixel ratio of the button
|
||||||
|
virtual QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const = 0;
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(FrameworkWidgetFactory)
|
Q_DISABLE_COPY(FrameworkWidgetFactory)
|
||||||
};
|
};
|
||||||
@@ -142,6 +164,13 @@ public:
|
|||||||
FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr) const override;
|
FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr) const override;
|
||||||
DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea*) const override;
|
DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea*) const override;
|
||||||
QWidgetOrQuick *createRubberBand(QWidgetOrQuick *parent) const override;
|
QWidgetOrQuick *createRubberBand(QWidgetOrQuick *parent) const override;
|
||||||
|
SideBar *createSideBar(SideBarLocation loc, MainWindowBase *parent) const override;
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const override;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const override;
|
||||||
|
|
||||||
static DropIndicatorType s_dropIndicatorType;
|
static DropIndicatorType s_dropIndicatorType;
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ namespace KDDockWidgets
|
|||||||
enum FrameOption {
|
enum FrameOption {
|
||||||
FrameOption_None = 0,
|
FrameOption_None = 0,
|
||||||
FrameOption_AlwaysShowsTabs = 1,
|
FrameOption_AlwaysShowsTabs = 1,
|
||||||
FrameOption_IsCentralFrame = 2
|
FrameOption_IsCentralFrame = 2,
|
||||||
|
FrameOption_IsOverlayed = 4
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(FrameOptions, FrameOption)
|
Q_DECLARE_FLAGS(FrameOptions, FrameOption)
|
||||||
|
|
||||||
@@ -96,6 +97,32 @@ namespace KDDockWidgets
|
|||||||
|
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// @brief Each main window supports 4 sidebars
|
||||||
|
enum class SideBarLocation {
|
||||||
|
None,
|
||||||
|
North,
|
||||||
|
East,
|
||||||
|
West,
|
||||||
|
South
|
||||||
|
};
|
||||||
|
|
||||||
|
///@brief describes a type of button you can have in the title bar
|
||||||
|
enum class TitleBarButtonType {
|
||||||
|
Close,
|
||||||
|
Float,
|
||||||
|
Minimize,
|
||||||
|
Maximize,
|
||||||
|
Normal, // Restore from maximized state
|
||||||
|
AutoHide,
|
||||||
|
UnautoHide
|
||||||
|
};
|
||||||
|
|
||||||
|
///@internal
|
||||||
|
inline uint qHash(SideBarLocation loc, uint seed)
|
||||||
|
{
|
||||||
|
return ::qHash(static_cast<uint>(loc), seed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(KDDockWidgets::FrameOptions)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(KDDockWidgets::FrameOptions)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
include(CMakeFindDependencyMacro)
|
include(CMakeFindDependencyMacro)
|
||||||
|
|
||||||
find_dependency(Qt5Widgets REQUIRED)
|
find_dependency(Qt5Widgets REQUIRED)
|
||||||
if (@OPTION_QTQUICK@)
|
if (@KDDockWidgets_QTQUICK@)
|
||||||
find_dependency(Qt5Quick REQUIRED)
|
find_dependency(Qt5Quick REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
|||||||
@@ -163,7 +163,7 @@ QByteArray LayoutSaver::serializeLayout() const
|
|||||||
layout.mainWindows.push_back(mainWindow->serialize());
|
layout.mainWindows.push_back(mainWindow->serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<KDDockWidgets::FloatingWindow*> floatingWindows = d->m_dockRegistry->nestedwindows();
|
const QVector<KDDockWidgets::FloatingWindow*> floatingWindows = d->m_dockRegistry->floatingWindows();
|
||||||
layout.floatingWindows.reserve(floatingWindows.size());
|
layout.floatingWindows.reserve(floatingWindows.size());
|
||||||
for (KDDockWidgets::FloatingWindow *floatingWindow : floatingWindows) {
|
for (KDDockWidgets::FloatingWindow *floatingWindow : floatingWindows) {
|
||||||
if (d->matchesAffinity(floatingWindow->affinities()))
|
if (d->matchesAffinity(floatingWindow->affinities()))
|
||||||
|
|||||||
@@ -17,10 +17,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
|
#include "Config.h"
|
||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
|
#include "SideBar_p.h"
|
||||||
#include "DropAreaWithCentralFrame_p.h"
|
#include "DropAreaWithCentralFrame_p.h"
|
||||||
|
#include "FrameworkWidgetFactory.h"
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
@@ -31,11 +34,21 @@ using namespace KDDockWidgets;
|
|||||||
class MainWindow::Private
|
class MainWindow::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Private(MainWindowOptions, MainWindowBase *)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
explicit Private(MainWindowOptions, MainWindowBase *mainWindow)
|
||||||
|
: m_supportsAutoHide(Config::self().flags() & Config::Flag_AutoHideSupport)
|
||||||
|
{
|
||||||
|
if (m_supportsAutoHide) {
|
||||||
|
for (auto location : { SideBarLocation::North, SideBarLocation::East,
|
||||||
|
SideBarLocation::West, SideBarLocation::South}) {
|
||||||
|
m_sideBars.insert(location, Config::self().frameworkWidgetFactory()->createSideBar(location, mainWindow) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool m_supportsAutoHide;
|
||||||
|
QHash<SideBarLocation, SideBar*> m_sideBars;
|
||||||
|
};
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
class MyCentralWidget : public QWidget
|
class MyCentralWidget : public QWidget
|
||||||
@@ -67,9 +80,24 @@ MainWindow::MainWindow(const QString &name, MainWindowOptions options,
|
|||||||
, d(new Private(options, this))
|
, d(new Private(options, this))
|
||||||
{
|
{
|
||||||
auto centralWidget = new MyCentralWidget(this);
|
auto centralWidget = new MyCentralWidget(this);
|
||||||
auto layout = new QVBoxLayout(centralWidget);
|
auto layout = new QHBoxLayout(centralWidget); // 1 level of indirection so we can add some margins
|
||||||
layout->setContentsMargins(1, 5, 1, 1);
|
layout->setSpacing(0);
|
||||||
layout->addWidget(dropArea()); // 1 level of indirection so we can add some margins
|
layout->setContentsMargins(centerWidgetMargins());
|
||||||
|
|
||||||
|
if (d->m_supportsAutoHide) {
|
||||||
|
layout->addWidget(sideBar(SideBarLocation::West));
|
||||||
|
auto innerVLayout = new QVBoxLayout();
|
||||||
|
innerVLayout->setSpacing(0);
|
||||||
|
innerVLayout->setContentsMargins(0, 0, 0, 0);
|
||||||
|
innerVLayout->addWidget(sideBar(SideBarLocation::North));
|
||||||
|
innerVLayout->addWidget(dropArea());
|
||||||
|
innerVLayout->addWidget(sideBar(SideBarLocation::South));
|
||||||
|
layout->addLayout(innerVLayout);
|
||||||
|
layout->addWidget(sideBar(SideBarLocation::East));
|
||||||
|
} else {
|
||||||
|
layout->addWidget(dropArea());
|
||||||
|
}
|
||||||
|
|
||||||
setCentralWidget(centralWidget);
|
setCentralWidget(centralWidget);
|
||||||
|
|
||||||
// qApp->installEventFilter(this);
|
// qApp->installEventFilter(this);
|
||||||
@@ -84,3 +112,24 @@ void MainWindow::setCentralWidget(QWidget *w)
|
|||||||
{
|
{
|
||||||
QMainWindow::setCentralWidget(w);
|
QMainWindow::setCentralWidget(w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SideBar *MainWindow::sideBar(SideBarLocation location) const
|
||||||
|
{
|
||||||
|
return d->m_sideBars.value(location);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::resizeEvent(QResizeEvent *ev)
|
||||||
|
{
|
||||||
|
MainWindowBase::resizeEvent(ev);
|
||||||
|
onResized(ev); // Also call our own handler, since QtQuick doesn't have resizeEvent()
|
||||||
|
}
|
||||||
|
|
||||||
|
QMargins MainWindow::centerWidgetMargins() const
|
||||||
|
{
|
||||||
|
return { 1, 5, 1, 1};
|
||||||
|
}
|
||||||
|
|
||||||
|
QRect MainWindow::centralAreaGeometry() const
|
||||||
|
{
|
||||||
|
return centralWidget()->geometry();
|
||||||
|
}
|
||||||
|
|||||||
@@ -23,6 +23,8 @@
|
|||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
class SideBar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The QMainwindow sub-class that the application should use to be able
|
* @brief The QMainwindow sub-class that the application should use to be able
|
||||||
* to dock KDDockWidget::DockWidget instances.
|
* to dock KDDockWidget::DockWidget instances.
|
||||||
@@ -45,6 +47,13 @@ public:
|
|||||||
///@brief Destructor
|
///@brief Destructor
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
|
///@brief returns the sidebar for the specified location
|
||||||
|
SideBar *sideBar(SideBarLocation) const override;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void resizeEvent(QResizeEvent *) override;
|
||||||
|
QMargins centerWidgetMargins() const override;
|
||||||
|
QRect centralAreaGeometry() const override;
|
||||||
private:
|
private:
|
||||||
using QMainWindow::setCentralWidget;
|
using QMainWindow::setCentralWidget;
|
||||||
void setCentralWidget(QWidget *); // overridden just to make it private
|
void setCentralWidget(QWidget *); // overridden just to make it private
|
||||||
|
|||||||
@@ -22,7 +22,10 @@
|
|||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
|
#include "SideBar_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
|
#include "Item_p.h"
|
||||||
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "DropAreaWithCentralFrame_p.h"
|
#include "DropAreaWithCentralFrame_p.h"
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
@@ -42,15 +45,20 @@ public:
|
|||||||
return m_options & MainWindowOption_HasCentralFrame;
|
return m_options & MainWindowOption_HasCentralFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect rectForOverlay(Frame *, SideBarLocation) const;
|
||||||
|
SideBarLocation preferredSideBar(DockWidgetBase *) const;
|
||||||
|
void updateOverlayGeometry();
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
QStringList affinities;
|
QStringList affinities;
|
||||||
const MainWindowOptions m_options;
|
const MainWindowOptions m_options;
|
||||||
MainWindowBase *const q;
|
MainWindowBase *const q;
|
||||||
|
QPointer<DockWidgetBase> m_overlayedDockWidget;
|
||||||
DropAreaWithCentralFrame *const m_dropArea;
|
DropAreaWithCentralFrame *const m_dropArea;
|
||||||
};
|
};
|
||||||
|
|
||||||
MainWindowBase::MainWindowBase(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
MainWindowBase::MainWindowBase(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
||||||
QWidgetOrQuick *parent, Qt::WindowFlags flags)
|
WidgetType *parent, Qt::WindowFlags flags)
|
||||||
: QMainWindowOrQuick(parent, flags)
|
: QMainWindowOrQuick(parent, flags)
|
||||||
, d(new Private(this, options))
|
, d(new Private(this, options))
|
||||||
{
|
{
|
||||||
@@ -149,6 +157,295 @@ void MainWindowBase::layoutParentContainerEqually(DockWidgetBase *dockWidget)
|
|||||||
dropArea()->layoutParentContainerEqually(dockWidget);
|
dropArea()->layoutParentContainerEqually(dockWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QRect MainWindowBase::Private::rectForOverlay(Frame *frame, SideBarLocation location) const
|
||||||
|
{
|
||||||
|
SideBar *sb = q->sideBar(location);
|
||||||
|
if (!sb)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const QRect centralAreaGeo = q->centralAreaGeometry();
|
||||||
|
const QMargins centerWidgetMargins = q->centerWidgetMargins();
|
||||||
|
|
||||||
|
QRect rect;
|
||||||
|
const int margin = 1;
|
||||||
|
switch (location) {
|
||||||
|
case SideBarLocation::North:
|
||||||
|
case SideBarLocation::South: {
|
||||||
|
|
||||||
|
SideBar *leftSideBar = q->sideBar(SideBarLocation::West);
|
||||||
|
SideBar *rightSideBar = q->sideBar(SideBarLocation::East);
|
||||||
|
const int leftSideBarWidth = (leftSideBar && leftSideBar->isVisible()) ? leftSideBar->width()
|
||||||
|
: 0;
|
||||||
|
const int rightSideBarWidth = (rightSideBar && rightSideBar->isVisible()) ? rightSideBar->width()
|
||||||
|
: 0;
|
||||||
|
rect.setHeight(qMax(300, frame->minSize().height()));
|
||||||
|
rect.setWidth(centralAreaGeo.width() - margin * 2 - leftSideBarWidth - rightSideBarWidth);
|
||||||
|
rect.moveLeft(margin + leftSideBarWidth);
|
||||||
|
if (location == SideBarLocation::South) {
|
||||||
|
rect.moveTop(centralAreaGeo.bottom() - centerWidgetMargins.bottom() - rect.height() - sb->height());
|
||||||
|
} else {
|
||||||
|
rect.moveTop(centralAreaGeo.y() + sb->height() + centerWidgetMargins.top());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SideBarLocation::West:
|
||||||
|
case SideBarLocation::East: {
|
||||||
|
SideBar *topSideBar = q->sideBar(SideBarLocation::North);
|
||||||
|
SideBar *bottomSideBar = q->sideBar(SideBarLocation::South);
|
||||||
|
const int topSideBarHeight = (topSideBar && topSideBar->isVisible()) ? topSideBar->height()
|
||||||
|
: 0;
|
||||||
|
const int bottomSideBarHeight = (bottomSideBar && bottomSideBar->isVisible()) ? bottomSideBar->height()
|
||||||
|
: 0;
|
||||||
|
rect.setWidth(qMax(300, frame->minSize().width()));
|
||||||
|
rect.setHeight(centralAreaGeo.height() - topSideBarHeight - bottomSideBarHeight - centerWidgetMargins.top() - centerWidgetMargins.bottom());
|
||||||
|
rect.moveTop(sb->mapTo(q, QPoint(0, 0)).y() + topSideBarHeight - 1);
|
||||||
|
if (location == SideBarLocation::East) {
|
||||||
|
rect.moveLeft(centralAreaGeo.width() - rect.width() - sb->width() - centerWidgetMargins.right() - margin);
|
||||||
|
} else {
|
||||||
|
rect.moveLeft(margin + centralAreaGeo.x() + centerWidgetMargins.left() + sb->width());
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case SideBarLocation::None:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return rect;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SideBarLocation opposedSideBarLocationForBorder(Layouting::Item::LayoutBorderLocation loc)
|
||||||
|
{
|
||||||
|
switch (loc) {
|
||||||
|
case Layouting::Item::LayoutBorderLocation_North:
|
||||||
|
return SideBarLocation::South;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_East:
|
||||||
|
return SideBarLocation::West;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_West:
|
||||||
|
return SideBarLocation::East;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_South:
|
||||||
|
return SideBarLocation::North;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_All:
|
||||||
|
case Layouting::Item::LayoutBorderLocation_Verticals:
|
||||||
|
case Layouting::Item::LayoutBorderLocation_Horizontals:
|
||||||
|
case Layouting::Item::LayoutBorderLocation_None:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << Q_FUNC_INFO << "Unknown loc" << loc;
|
||||||
|
return SideBarLocation::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
static SideBarLocation sideBarLocationForBorder(Layouting::Item::LayoutBorderLocations loc)
|
||||||
|
{
|
||||||
|
switch (loc) {
|
||||||
|
case Layouting::Item::LayoutBorderLocation_North:
|
||||||
|
return SideBarLocation::North;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_East:
|
||||||
|
return SideBarLocation::East;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_West:
|
||||||
|
return SideBarLocation::West;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_South:
|
||||||
|
return SideBarLocation::South;
|
||||||
|
case Layouting::Item::LayoutBorderLocation_All:
|
||||||
|
case Layouting::Item::LayoutBorderLocation_Verticals:
|
||||||
|
case Layouting::Item::LayoutBorderLocation_Horizontals:
|
||||||
|
case Layouting::Item::LayoutBorderLocation_None:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return SideBarLocation::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
SideBarLocation MainWindowBase::Private::preferredSideBar(DockWidgetBase *dw) const
|
||||||
|
{
|
||||||
|
// TODO: Algorithm can still be made smarter
|
||||||
|
|
||||||
|
Layouting::Item *item = q->multiSplitter()->itemForFrame(dw->frame());
|
||||||
|
if (!item) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "No item for dock widget";
|
||||||
|
return SideBarLocation::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Layouting::Item::LayoutBorderLocations borders = item->adjacentLayoutBorders();
|
||||||
|
const qreal aspectRatio = dw->width() / (dw->height() * 1.0);
|
||||||
|
|
||||||
|
/// 1. It's touching all borders
|
||||||
|
if (borders == Layouting::Item::LayoutBorderLocation_All) {
|
||||||
|
return aspectRatio > 1.0 ? SideBarLocation::South
|
||||||
|
: SideBarLocation::East;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 2. It's touching 3 borders
|
||||||
|
for (auto borderLoc : { Layouting::Item::LayoutBorderLocation_North, Layouting::Item::LayoutBorderLocation_East,
|
||||||
|
Layouting::Item::LayoutBorderLocation_West, Layouting::Item::LayoutBorderLocation_South }) {
|
||||||
|
if (borders == (Layouting::Item::LayoutBorderLocation_All & ~borderLoc))
|
||||||
|
return opposedSideBarLocationForBorder(borderLoc);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 3. It's touching left and right borders
|
||||||
|
if ((borders & Layouting::Item::LayoutBorderLocation_Verticals) == Layouting::Item::LayoutBorderLocation_Verticals) {
|
||||||
|
// We could measure the distance to the top though.
|
||||||
|
return SideBarLocation::South;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// 4. It's touching top and bottom borders
|
||||||
|
if ((borders & Layouting::Item::LayoutBorderLocation_Horizontals) == Layouting::Item::LayoutBorderLocation_Horizontals) {
|
||||||
|
// We could measure the distance to the left though.
|
||||||
|
return SideBarLocation::East;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 5. It's in a corner
|
||||||
|
if (borders == (Layouting::Item::LayoutBorderLocation_West | Layouting::Item::LayoutBorderLocation_South)) {
|
||||||
|
return aspectRatio > 1.0 ? SideBarLocation::South
|
||||||
|
: SideBarLocation::West;
|
||||||
|
} else if (borders == (Layouting::Item::LayoutBorderLocation_East | Layouting::Item::LayoutBorderLocation_South)) {
|
||||||
|
return aspectRatio > 1.0 ? SideBarLocation::South
|
||||||
|
: SideBarLocation::East;
|
||||||
|
} else if (borders == (Layouting::Item::LayoutBorderLocation_West | Layouting::Item::LayoutBorderLocation_North)) {
|
||||||
|
return aspectRatio > 1.0 ? SideBarLocation::North
|
||||||
|
: SideBarLocation::West;
|
||||||
|
} else if (borders == (Layouting::Item::LayoutBorderLocation_East | Layouting::Item::LayoutBorderLocation_North)) {
|
||||||
|
return aspectRatio > 1.0 ? SideBarLocation::North
|
||||||
|
: SideBarLocation::East;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
// 6. It's only touching 1 border
|
||||||
|
SideBarLocation loc = sideBarLocationForBorder(borders);
|
||||||
|
if (loc != SideBarLocation::None)
|
||||||
|
return loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's not touching any border, use aspect ratio.
|
||||||
|
return aspectRatio > 1.0 ? SideBarLocation::South
|
||||||
|
: SideBarLocation::West;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::Private::updateOverlayGeometry()
|
||||||
|
{
|
||||||
|
if (!m_overlayedDockWidget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SideBar *sb = q->sideBarForDockWidget(m_overlayedDockWidget);
|
||||||
|
if (!sb) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Expected a sidebar";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_overlayedDockWidget->frame()->QWidgetAdapter::setGeometry(rectForOverlay(m_overlayedDockWidget->frame(), sb->location()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::moveToSideBar(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
moveToSideBar(dw, d->preferredSideBar(dw));
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::moveToSideBar(DockWidgetBase *dw, SideBarLocation location)
|
||||||
|
{
|
||||||
|
if (SideBar *sb = sideBar(location)) {
|
||||||
|
dw->forceClose();
|
||||||
|
sb->addDockWidget(dw);
|
||||||
|
} else {
|
||||||
|
// Shouldn't happen
|
||||||
|
qWarning() << Q_FUNC_INFO << "Minimization supported, probably disabled in Config::self().flags()";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::restoreFromSideBar(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
// First un-overlay it, if it's overlayed
|
||||||
|
if (dw == d->m_overlayedDockWidget)
|
||||||
|
clearSideBarOverlay();
|
||||||
|
|
||||||
|
SideBar *sb = sideBarForDockWidget(dw);
|
||||||
|
if (!sb) {
|
||||||
|
// Doesn't happen
|
||||||
|
qWarning() << Q_FUNC_INFO << "Dock widget isn't in any sidebar";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sb->removeDockWidget(dw);
|
||||||
|
dw->setFloating(false); // dock it
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::overlayOnSideBar(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
if (!dw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const SideBar *sb = sideBarForDockWidget(dw);
|
||||||
|
if (sb == nullptr) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "You need to add the dock widget to the sidebar before you can overlay it";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (d->m_overlayedDockWidget == dw) {
|
||||||
|
// Already overlayed
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We only support one overlay at a time, remove any existing overlay
|
||||||
|
clearSideBarOverlay();
|
||||||
|
|
||||||
|
auto frame = Config::self().frameworkWidgetFactory()->createFrame(this, FrameOption_IsOverlayed);
|
||||||
|
d->m_overlayedDockWidget = dw;
|
||||||
|
frame->addWidget(dw);
|
||||||
|
d->updateOverlayGeometry();
|
||||||
|
frame->QWidgetAdapter::show();
|
||||||
|
|
||||||
|
Q_EMIT dw->isOverlayedChanged(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::toggleOverlayOnSideBar(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
const bool wasOverlayed = d->m_overlayedDockWidget == dw;
|
||||||
|
clearSideBarOverlay();
|
||||||
|
if (!wasOverlayed) {
|
||||||
|
overlayOnSideBar(dw);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::clearSideBarOverlay()
|
||||||
|
{
|
||||||
|
if (!d->m_overlayedDockWidget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
Frame *frame = d->m_overlayedDockWidget->frame();
|
||||||
|
d->m_overlayedDockWidget->setParent(nullptr);
|
||||||
|
Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false);
|
||||||
|
d->m_overlayedDockWidget = nullptr;
|
||||||
|
delete frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
SideBar *MainWindowBase::sideBarForDockWidget(const DockWidgetBase *dw) const
|
||||||
|
{
|
||||||
|
for (auto loc : { SideBarLocation::North, SideBarLocation::South,
|
||||||
|
SideBarLocation::East, SideBarLocation::West }) {
|
||||||
|
|
||||||
|
if (SideBar *sb = sideBar(loc)) {
|
||||||
|
if (sb->contains(const_cast<DockWidgetBase *>(dw)))
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DockWidgetBase *MainWindowBase::overlayedDockWidget() const
|
||||||
|
{
|
||||||
|
return d->m_overlayedDockWidget;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool MainWindowBase::sideBarIsVisible(SideBarLocation loc) const
|
||||||
|
{
|
||||||
|
if (SideBar *sb = sideBar(loc))
|
||||||
|
return sb->isVisible();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void MainWindowBase::setUniqueName(const QString &uniqueName)
|
void MainWindowBase::setUniqueName(const QString &uniqueName)
|
||||||
{
|
{
|
||||||
if (uniqueName.isEmpty())
|
if (uniqueName.isEmpty())
|
||||||
@@ -163,6 +460,12 @@ void MainWindowBase::setUniqueName(const QString &uniqueName)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::onResized(QResizeEvent *)
|
||||||
|
{
|
||||||
|
if (d->m_overlayedDockWidget)
|
||||||
|
d->updateOverlayGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
|
bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
|
||||||
{
|
{
|
||||||
if (mw.options != options()) {
|
if (mw.options != options()) {
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
#include "LayoutSaver_p.h"
|
#include "LayoutSaver_p.h"
|
||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
#include <QMargins>
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
@@ -34,6 +35,7 @@ class Frame;
|
|||||||
class DropArea;
|
class DropArea;
|
||||||
class MultiSplitter;
|
class MultiSplitter;
|
||||||
class DropAreaWithCentralFrame;
|
class DropAreaWithCentralFrame;
|
||||||
|
class SideBar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The MainWindow base-class. MainWindow and MainWindowBase are only
|
* @brief The MainWindow base-class. MainWindow and MainWindowBase are only
|
||||||
@@ -52,7 +54,7 @@ class DOCKS_EXPORT MainWindowBase : public QMainWindow
|
|||||||
public:
|
public:
|
||||||
typedef QVector<MainWindowBase*> List;
|
typedef QVector<MainWindowBase*> List;
|
||||||
explicit MainWindowBase(const QString &uniqueName, MainWindowOptions options = MainWindowOption_HasCentralFrame,
|
explicit MainWindowBase(const QString &uniqueName, MainWindowOptions options = MainWindowOption_HasCentralFrame,
|
||||||
QWidgetOrQuick *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
WidgetType *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||||
|
|
||||||
~MainWindowBase() override;
|
~MainWindowBase() override;
|
||||||
|
|
||||||
@@ -131,8 +133,45 @@ public:
|
|||||||
/// sub-tree.
|
/// sub-tree.
|
||||||
void layoutParentContainerEqually(DockWidgetBase *dockWidget);
|
void layoutParentContainerEqually(DockWidgetBase *dockWidget);
|
||||||
|
|
||||||
|
///@brief Moves the dock widget into one of the MainWindow's sidebar.
|
||||||
|
/// Means the dock widget is removed from the layout, and the sidebar shows a button that if pressed
|
||||||
|
/// will toggle the dock widget's visibility as an overlay over the layout. This is the auto-hide
|
||||||
|
/// functionality.
|
||||||
|
///
|
||||||
|
/// The chosen side bar will depend on some heuristics, mostly proximity.
|
||||||
|
void moveToSideBar(DockWidgetBase *);
|
||||||
|
|
||||||
|
/// @brief overload that allows to specify which sidebar to use, instead of using heuristics.
|
||||||
|
void moveToSideBar(DockWidgetBase *, SideBarLocation);
|
||||||
|
|
||||||
|
/// @brief Removes the dock widget from the sidebar and docks it into the main window again
|
||||||
|
void restoreFromSideBar(DockWidgetBase *);
|
||||||
|
|
||||||
|
///@brief Shows the dock widget overlayed on top of the main window, placed next to the sidebar
|
||||||
|
void overlayOnSideBar(DockWidgetBase *);
|
||||||
|
|
||||||
|
///@brief Shows or hides an overlay. It's assumed the dock widget is already in a side-bar.
|
||||||
|
void toggleOverlayOnSideBar(DockWidgetBase *);
|
||||||
|
|
||||||
|
/// @brief closes any overlayed dock widget. The sidebar still displays them as button.
|
||||||
|
void clearSideBarOverlay();
|
||||||
|
|
||||||
|
/// @brief Returns the sidebar this dockwidget is in. nullptr if not in any.
|
||||||
|
SideBar *sideBarForDockWidget(const DockWidgetBase *) const;
|
||||||
|
|
||||||
|
/// @brief returns the dock widget which is currently overlayed. nullptr if none.
|
||||||
|
/// This is only relevant when using the auto-hide and side-bar feature.
|
||||||
|
DockWidgetBase *overlayedDockWidget() const;
|
||||||
|
|
||||||
|
/// @brief Returns whether the specified sidebar is visible
|
||||||
|
bool sideBarIsVisible(SideBarLocation) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setUniqueName(const QString &uniqueName);
|
void setUniqueName(const QString &uniqueName);
|
||||||
|
void onResized(QResizeEvent *); // Because QtQuick doesn't have resizeEvent()
|
||||||
|
virtual QMargins centerWidgetMargins() const = 0;
|
||||||
|
virtual SideBar* sideBar(SideBarLocation) const = 0;
|
||||||
|
virtual QRect centralAreaGeometry() const { return {}; }
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void uniqueNameChanged();
|
void uniqueNameChanged();
|
||||||
|
|||||||
@@ -79,6 +79,8 @@ public:
|
|||||||
, LayoutGuestWidgetBase(this)
|
, LayoutGuestWidgetBase(this)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~LayoutGuestWidget() override;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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/widgets/SideBarWidget_p.h"
|
||||||
BIN
src/img/auto-hide-1.5x.png
Normal file
|
After Width: | Height: | Size: 473 B |
BIN
src/img/auto-hide-2x.png
Normal file
|
After Width: | Height: | Size: 477 B |
BIN
src/img/auto-hide.png
Normal file
|
After Width: | Height: | Size: 208 B |
|
Before Width: | Height: | Size: 1.7 KiB After Width: | Height: | Size: 2.2 KiB |
BIN
src/img/close-1.5x.png
Normal file
|
After Width: | Height: | Size: 496 B |
BIN
src/img/close-2x.png
Normal file
|
After Width: | Height: | Size: 543 B |
BIN
src/img/close.png
Normal file
|
After Width: | Height: | Size: 405 B |
BIN
src/img/dock-float-1.5x.png
Normal file
|
After Width: | Height: | Size: 438 B |
BIN
src/img/dock-float-2x.png
Normal file
|
After Width: | Height: | Size: 482 B |
BIN
src/img/dock-float.png
Normal file
|
After Width: | Height: | Size: 286 B |
BIN
src/img/max-1.5x.png
Normal file
|
After Width: | Height: | Size: 385 B |
BIN
src/img/max-2x.png
Normal file
|
After Width: | Height: | Size: 445 B |
BIN
src/img/max.png
Normal file
|
After Width: | Height: | Size: 274 B |
BIN
src/img/min-1.5x.png
Normal file
|
After Width: | Height: | Size: 317 B |
BIN
src/img/min-2x.png
Normal file
|
After Width: | Height: | Size: 386 B |
BIN
src/img/min.png
Normal file
|
After Width: | Height: | Size: 239 B |
BIN
src/img/unauto-hide-1.5x.png
Normal file
|
After Width: | Height: | Size: 461 B |
BIN
src/img/unauto-hide-2x.png
Normal file
|
After Width: | Height: | Size: 482 B |
BIN
src/img/unauto-hide.png
Normal file
|
After Width: | Height: | Size: 218 B |
@@ -200,7 +200,7 @@ DebugWindow::DebugWindow(QWidget *parent)
|
|||||||
mainWindow->multiSplitter()->checkSanity();
|
mainWindow->multiSplitter()->checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto floatingWindows = DockRegistry::self()->nestedwindows();
|
const auto floatingWindows = DockRegistry::self()->floatingWindows();
|
||||||
for (FloatingWindow *floatingWindow : floatingWindows) {
|
for (FloatingWindow *floatingWindow : floatingWindows) {
|
||||||
floatingWindow->multiSplitter()->checkSanity();
|
floatingWindow->multiSplitter()->checkSanity();
|
||||||
}
|
}
|
||||||
@@ -308,7 +308,7 @@ void DebugWindow::repaintWidgetRecursive(QWidget *w)
|
|||||||
|
|
||||||
void DebugWindow::dumpDockWidgetInfo()
|
void DebugWindow::dumpDockWidgetInfo()
|
||||||
{
|
{
|
||||||
const QVector<FloatingWindow*> floatingWindows = DockRegistry::self()->nestedwindows();
|
const QVector<FloatingWindow*> floatingWindows = DockRegistry::self()->floatingWindows();
|
||||||
const MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
const MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
||||||
const DockWidgetBase::List dockWidgets = DockRegistry::self()->dockwidgets();
|
const DockWidgetBase::List dockWidgets = DockRegistry::self()->dockwidgets();
|
||||||
|
|
||||||
|
|||||||
@@ -16,6 +16,8 @@
|
|||||||
#include "MultiSplitter_p.h"
|
#include "MultiSplitter_p.h"
|
||||||
#include "QWidgetAdapter.h"
|
#include "QWidgetAdapter.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "SideBar_p.h"
|
||||||
|
#include "WindowBeingDragged_p.h"
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -99,9 +101,13 @@ void DockRegistry::onFocusObjectChanged(QObject *obj)
|
|||||||
Q_EMIT m_focusedDockWidget->isFocusedChanged(true);
|
Q_EMIT m_focusedDockWidget->isFocusedChanged(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockRegistry::isEmpty() const
|
bool DockRegistry::isEmpty(bool excludeBeingDeleted) const
|
||||||
{
|
{
|
||||||
return m_dockWidgets.isEmpty() && m_mainWindows.isEmpty() && m_nestedWindows.isEmpty();
|
if (!m_dockWidgets.isEmpty() || !m_mainWindows.isEmpty())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return excludeBeingDeleted ? !hasFloatingWindows()
|
||||||
|
: m_floatingWindows.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::checkSanityAll(bool dumpLayout)
|
void DockRegistry::checkSanityAll(bool dumpLayout)
|
||||||
@@ -159,7 +165,7 @@ bool DockRegistry::isProbablyObscured(QWindow *window, FloatingWindow *exclude)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
const QRect geo = window->geometry();
|
const QRect geo = window->geometry();
|
||||||
for (FloatingWindow *fw : m_nestedWindows) {
|
for (FloatingWindow *fw : m_floatingWindows) {
|
||||||
QWindow *fwWindow = fw->QWidgetAdapter::windowHandle();
|
QWindow *fwWindow = fw->QWidgetAdapter::windowHandle();
|
||||||
if (fw == exclude || fwWindow == window)
|
if (fw == exclude || fwWindow == window)
|
||||||
continue;
|
continue;
|
||||||
@@ -185,6 +191,32 @@ bool DockRegistry::isProbablyObscured(QWindow *window, FloatingWindow *exclude)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockRegistry::isProbablyObscured(QWindow *target, WindowBeingDragged *exclude) const
|
||||||
|
{
|
||||||
|
FloatingWindow *fw = exclude ? exclude->floatingWindow()
|
||||||
|
: nullptr; // It's null on Wayland. On wayland obscuring never happens anyway, so not a problem.
|
||||||
|
|
||||||
|
return isProbablyObscured(target, fw);
|
||||||
|
}
|
||||||
|
|
||||||
|
SideBarLocation DockRegistry::sideBarLocationForDockWidget(const DockWidgetBase *dw) const
|
||||||
|
{
|
||||||
|
if (SideBar *sb = sideBarForDockWidget(dw))
|
||||||
|
return sb->location();
|
||||||
|
|
||||||
|
return SideBarLocation::None;
|
||||||
|
}
|
||||||
|
|
||||||
|
SideBar *DockRegistry::sideBarForDockWidget(const DockWidgetBase *dw) const
|
||||||
|
{
|
||||||
|
for (auto mw : m_mainWindows) {
|
||||||
|
if (SideBar *sb = mw->sideBarForDockWidget(dw))
|
||||||
|
return sb;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
MainWindowBase::List DockRegistry::mainWindowsWithAffinity(const QStringList &affinities) const
|
MainWindowBase::List DockRegistry::mainWindowsWithAffinity(const QStringList &affinities) const
|
||||||
{
|
{
|
||||||
MainWindowBase::List result;
|
MainWindowBase::List result;
|
||||||
@@ -203,7 +235,7 @@ MultiSplitter *DockRegistry::layoutForItem(const Layouting::Item *item) const
|
|||||||
if (!item->hostWidget())
|
if (!item->hostWidget())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
if (auto ms = qobject_cast<MultiSplitter*>(item->hostWidget()->asQWidget()))
|
if (auto ms = qobject_cast<MultiSplitter*>(item->hostWidget()->asQObject()))
|
||||||
return ms;
|
return ms;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -241,6 +273,9 @@ void DockRegistry::registerDockWidget(DockWidgetBase *dock)
|
|||||||
|
|
||||||
void DockRegistry::unregisterDockWidget(DockWidgetBase *dock)
|
void DockRegistry::unregisterDockWidget(DockWidgetBase *dock)
|
||||||
{
|
{
|
||||||
|
if (m_focusedDockWidget == dock)
|
||||||
|
m_focusedDockWidget = nullptr;
|
||||||
|
|
||||||
m_dockWidgets.removeOne(dock);
|
m_dockWidgets.removeOne(dock);
|
||||||
maybeDelete();
|
maybeDelete();
|
||||||
}
|
}
|
||||||
@@ -262,14 +297,14 @@ void DockRegistry::unregisterMainWindow(MainWindowBase *mainWindow)
|
|||||||
maybeDelete();
|
maybeDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::registerNestedWindow(FloatingWindow *window)
|
void DockRegistry::registerFloatingWindow(FloatingWindow *window)
|
||||||
{
|
{
|
||||||
m_nestedWindows << window;
|
m_floatingWindows << window;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::unregisterNestedWindow(FloatingWindow *window)
|
void DockRegistry::unregisterFloatingWindow(FloatingWindow *window)
|
||||||
{
|
{
|
||||||
m_nestedWindows.removeOne(window);
|
m_floatingWindows.removeOne(window);
|
||||||
maybeDelete();
|
maybeDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -421,12 +456,12 @@ const Frame::List DockRegistry::frames() const
|
|||||||
return m_frames;
|
return m_frames;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<FloatingWindow *> DockRegistry::nestedwindows() const
|
const QVector<FloatingWindow *> DockRegistry::floatingWindows() const
|
||||||
{
|
{
|
||||||
// Returns all the FloatingWindow which aren't being deleted
|
// Returns all the FloatingWindow which aren't being deleted
|
||||||
QVector<FloatingWindow *> result;
|
QVector<FloatingWindow *> result;
|
||||||
result.reserve(m_nestedWindows.size());
|
result.reserve(m_floatingWindows.size());
|
||||||
for (FloatingWindow *fw : m_nestedWindows) {
|
for (FloatingWindow *fw : m_floatingWindows) {
|
||||||
if (!fw->beingDeleted())
|
if (!fw->beingDeleted())
|
||||||
result.push_back(fw);
|
result.push_back(fw);
|
||||||
}
|
}
|
||||||
@@ -434,11 +469,11 @@ const QVector<FloatingWindow *> DockRegistry::nestedwindows() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<QWindow *> DockRegistry::floatingWindows() const
|
const QVector<QWindow *> DockRegistry::floatingQWindows() const
|
||||||
{
|
{
|
||||||
QVector<QWindow *> windows;
|
QVector<QWindow *> windows;
|
||||||
windows.reserve(m_nestedWindows.size());
|
windows.reserve(m_floatingWindows.size());
|
||||||
for (FloatingWindow *fw : m_nestedWindows) {
|
for (FloatingWindow *fw : m_floatingWindows) {
|
||||||
if (!fw->beingDeleted()) {
|
if (!fw->beingDeleted()) {
|
||||||
if (QWindow *window = fw->windowHandle()) {
|
if (QWindow *window = fw->windowHandle()) {
|
||||||
window->setProperty("kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick*>(fw)); // Since QWidgetWindow is private API
|
window->setProperty("kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick*>(fw)); // Since QWidgetWindow is private API
|
||||||
@@ -452,9 +487,16 @@ const QVector<QWindow *> DockRegistry::floatingWindows() const
|
|||||||
return windows;
|
return windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockRegistry::hasFloatingWindows() const
|
||||||
|
{
|
||||||
|
return std::any_of(m_floatingWindows.begin(), m_floatingWindows.end(), [] (FloatingWindow *fw) {
|
||||||
|
return !fw->beingDeleted();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
FloatingWindow *DockRegistry::floatingWindowForHandle(QWindow *windowHandle) const
|
FloatingWindow *DockRegistry::floatingWindowForHandle(QWindow *windowHandle) const
|
||||||
{
|
{
|
||||||
for (FloatingWindow *fw : m_nestedWindows) {
|
for (FloatingWindow *fw : m_floatingWindows) {
|
||||||
if (fw->windowHandle() == windowHandle)
|
if (fw->windowHandle() == windowHandle)
|
||||||
return fw;
|
return fw;
|
||||||
}
|
}
|
||||||
@@ -465,10 +507,10 @@ FloatingWindow *DockRegistry::floatingWindowForHandle(QWindow *windowHandle) con
|
|||||||
QVector<QWindow *> DockRegistry::topLevels(bool excludeFloatingDocks) const
|
QVector<QWindow *> DockRegistry::topLevels(bool excludeFloatingDocks) const
|
||||||
{
|
{
|
||||||
QVector<QWindow *> windows;
|
QVector<QWindow *> windows;
|
||||||
windows.reserve(m_nestedWindows.size() + m_mainWindows.size());
|
windows.reserve(m_floatingWindows.size() + m_mainWindows.size());
|
||||||
|
|
||||||
if (!excludeFloatingDocks) {
|
if (!excludeFloatingDocks) {
|
||||||
for (FloatingWindow *fw : m_nestedWindows) {
|
for (FloatingWindow *fw : m_floatingWindows) {
|
||||||
if (fw->isVisible()) {
|
if (fw->isVisible()) {
|
||||||
if (QWindow *window = fw->windowHandle()) {
|
if (QWindow *window = fw->windowHandle()) {
|
||||||
window->setProperty("kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick*>(fw)); // Since QWidgetWindow is private API
|
window->setProperty("kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick*>(fw)); // Since QWidgetWindow is private API
|
||||||
@@ -537,11 +579,39 @@ bool DockRegistry::eventFilter(QObject *watched, QEvent *event)
|
|||||||
if (auto windowHandle = qobject_cast<QWindow*>(watched)) {
|
if (auto windowHandle = qobject_cast<QWindow*>(watched)) {
|
||||||
if (FloatingWindow *fw = floatingWindowForHandle(windowHandle)) {
|
if (FloatingWindow *fw = floatingWindowForHandle(windowHandle)) {
|
||||||
// This floating window was exposed
|
// This floating window was exposed
|
||||||
m_nestedWindows.removeOne(fw);
|
m_floatingWindows.removeOne(fw);
|
||||||
m_nestedWindows.append(fw);
|
m_floatingWindows.append(fw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else if (event->type() == QEvent::MouseButtonPress) {
|
||||||
|
if (!(Config::self().flags() & Config::Flag_AutoHideSupport))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto p = watched;
|
||||||
|
while (p) {
|
||||||
|
if (auto dw = qobject_cast<DockWidgetBase*>(p)) {
|
||||||
|
onDockWidgetPressed(dw);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = p->parent();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockRegistry::onDockWidgetPressed(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
// Here we implement "auto-hide". If there's a overlayed dock widget, we hide it if some other
|
||||||
|
// dock widget is clicked.
|
||||||
|
|
||||||
|
MainWindowBase *mainWindow = dw->mainWindow();
|
||||||
|
if (!mainWindow) // Only docked widgets are interesting
|
||||||
|
return;
|
||||||
|
|
||||||
|
DockWidgetBase *overlayedDockWidget = mainWindow->overlayedDockWidget();
|
||||||
|
if (overlayedDockWidget && dw != overlayedDockWidget) {
|
||||||
|
mainWindow->clearSideBarOverlay();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -28,6 +28,8 @@
|
|||||||
namespace KDDockWidgets
|
namespace KDDockWidgets
|
||||||
{
|
{
|
||||||
|
|
||||||
|
class SideBar;
|
||||||
|
|
||||||
class DOCKS_EXPORT DockRegistry : public QObject
|
class DOCKS_EXPORT DockRegistry : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -40,8 +42,8 @@ public:
|
|||||||
void registerMainWindow(MainWindowBase *);
|
void registerMainWindow(MainWindowBase *);
|
||||||
void unregisterMainWindow(MainWindowBase *);
|
void unregisterMainWindow(MainWindowBase *);
|
||||||
|
|
||||||
void registerNestedWindow(FloatingWindow *);
|
void registerFloatingWindow(FloatingWindow *);
|
||||||
void unregisterNestedWindow(FloatingWindow *);
|
void unregisterFloatingWindow(FloatingWindow *);
|
||||||
|
|
||||||
void registerLayout(MultiSplitter *);
|
void registerLayout(MultiSplitter *);
|
||||||
void unregisterLayout(MultiSplitter *);
|
void unregisterLayout(MultiSplitter *);
|
||||||
@@ -82,10 +84,13 @@ public:
|
|||||||
|
|
||||||
///@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.
|
||||||
const QVector<FloatingWindow*> nestedwindows() const;
|
const QVector<FloatingWindow*> floatingWindows() const;
|
||||||
|
|
||||||
///@brief overload that returns list of QWindow. This is more friendly for supporting both QtWidgets and QtQuick
|
///@brief overload that returns list of QWindow. This is more friendly for supporting both QtWidgets and QtQuick
|
||||||
const QVector<QWindow*> floatingWindows() const;
|
const QVector<QWindow*> floatingQWindows() const;
|
||||||
|
|
||||||
|
///@brief returns whether if there's at least one floating window
|
||||||
|
bool hasFloatingWindows() const;
|
||||||
|
|
||||||
///@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;
|
||||||
@@ -125,8 +130,10 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns true if there's 0 dockwidgets, 0 main windows
|
* @brief returns true if there's 0 dockwidgets, 0 main windows
|
||||||
|
*
|
||||||
|
* @param excludeBeingDeleted if true, any window currently being deleted won't count
|
||||||
*/
|
*/
|
||||||
bool isEmpty() const;
|
bool isEmpty(bool excludeBeingDeleted = false) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calls MultiSplitter::checkSanity() on all layouts.
|
* @brief Calls MultiSplitter::checkSanity() on all layouts.
|
||||||
@@ -172,17 +179,29 @@ public:
|
|||||||
/// @param exclude This window should not be counted as an obscurer. (It's being dragged).
|
/// @param exclude This window should not be counted as an obscurer. (It's being dragged).
|
||||||
bool isProbablyObscured(QWindow *target, FloatingWindow *exclude) const;
|
bool isProbablyObscured(QWindow *target, FloatingWindow *exclude) const;
|
||||||
|
|
||||||
|
/// @overload
|
||||||
|
bool isProbablyObscured(QWindow *target, WindowBeingDragged *exclude) const;
|
||||||
|
|
||||||
|
///@brief Returns whether the specified dock widget is in a side bar, and which.
|
||||||
|
/// SideBarLocation::None is returned if it's not in a sidebar.
|
||||||
|
/// This is only relevant when using the auto-hide and side-bar feature.
|
||||||
|
SideBarLocation sideBarLocationForDockWidget(const DockWidgetBase *) const;
|
||||||
|
|
||||||
|
///@brief Overload that returns the SideBar itself
|
||||||
|
SideBar* sideBarForDockWidget(const DockWidgetBase *) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||||
private:
|
private:
|
||||||
explicit DockRegistry(QObject *parent = nullptr);
|
explicit DockRegistry(QObject *parent = nullptr);
|
||||||
|
void onDockWidgetPressed(DockWidgetBase *dw);
|
||||||
void maybeDelete();
|
void maybeDelete();
|
||||||
void onFocusObjectChanged(QObject *);
|
void onFocusObjectChanged(QObject *);
|
||||||
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;
|
Frame::List m_frames;
|
||||||
QVector<FloatingWindow*> m_nestedWindows;
|
QVector<FloatingWindow*> m_floatingWindows;
|
||||||
QVector<MultiSplitter*> m_layouts;
|
QVector<MultiSplitter*> m_layouts;
|
||||||
QPointer<DockWidgetBase> m_focusedDockWidget;
|
QPointer<DockWidgetBase> m_focusedDockWidget;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,6 +89,11 @@ StateBase::StateBase(DragController *parent)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool StateBase::isActiveState() const
|
||||||
|
{
|
||||||
|
return q->activeState() == this;
|
||||||
|
}
|
||||||
|
|
||||||
StateBase::~StateBase() = default;
|
StateBase::~StateBase() = default;
|
||||||
|
|
||||||
StateNone::StateNone(DragController *parent)
|
StateNone::StateNone(DragController *parent)
|
||||||
@@ -175,6 +180,27 @@ void StateDragging::onEntry(QEvent *)
|
|||||||
|
|
||||||
q->m_windowBeingDragged = q->m_draggable->makeWindow();
|
q->m_windowBeingDragged = q->m_draggable->makeWindow();
|
||||||
if (q->m_windowBeingDragged) {
|
if (q->m_windowBeingDragged) {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 15, 0)
|
||||||
|
# ifdef Q_OS_WIN
|
||||||
|
if (!q->m_nonClientDrag && KDDockWidgets::usesNativeDraggingAndResizing()) {
|
||||||
|
// Started as a client move, as the dock widget was docked,
|
||||||
|
// but now that we're dragging it as a floating window, switch to native drag
|
||||||
|
FloatingWindow *fw = q->m_windowBeingDragged->floatingWindow();
|
||||||
|
q->m_nonClientDrag = true;
|
||||||
|
q->m_windowBeingDragged.reset();
|
||||||
|
const HWND hwnd = HWND(fw->windowHandle()->winId());
|
||||||
|
q->m_windowBeingDragged = fw->makeWindow();
|
||||||
|
|
||||||
|
QWindow *window = fw->windowHandle();
|
||||||
|
window->startSystemMove();
|
||||||
|
|
||||||
|
// Mouse press was done in another window, so we need to ungrab
|
||||||
|
ReleaseCapture();
|
||||||
|
PostMessage(hwnd, WM_SYSCOMMAND, 0xF012, 0); // SC_DRAGMOVE
|
||||||
|
}
|
||||||
|
# endif
|
||||||
|
#endif
|
||||||
|
|
||||||
qCDebug(state) << "StateDragging entered. m_draggable=" << q->m_draggable << "; m_windowBeingDragged=" << q->m_windowBeingDragged->floatingWindow();
|
qCDebug(state) << "StateDragging entered. m_draggable=" << q->m_draggable << "; m_windowBeingDragged=" << q->m_windowBeingDragged->floatingWindow();
|
||||||
|
|
||||||
auto fw = q->m_windowBeingDragged->floatingWindow();
|
auto fw = q->m_windowBeingDragged->floatingWindow();
|
||||||
@@ -212,7 +238,7 @@ bool StateDragging::handleMouseButtonRelease(QPoint globalPos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (q->m_currentDropArea) {
|
if (q->m_currentDropArea) {
|
||||||
if (q->m_currentDropArea->drop(floatingWindow, globalPos)) {
|
if (q->m_currentDropArea->drop(q->m_windowBeingDragged.get(), globalPos)) {
|
||||||
Q_EMIT q->dropped();
|
Q_EMIT q->dropped();
|
||||||
} else {
|
} else {
|
||||||
qCDebug(state) << "StateDragging: Bailling out, drop not accepted";
|
qCDebug(state) << "StateDragging: Bailling out, drop not accepted";
|
||||||
@@ -260,7 +286,7 @@ bool StateDragging::handleMouseMove(QPoint globalPos)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dropArea->hover(fw, globalPos);
|
dropArea->hover(q->m_windowBeingDragged.get(), globalPos);
|
||||||
}
|
}
|
||||||
|
|
||||||
q->m_currentDropArea = dropArea;
|
q->m_currentDropArea = dropArea;
|
||||||
@@ -268,13 +294,39 @@ bool StateDragging::handleMouseMove(QPoint globalPos)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StateDraggingWayland::StateDraggingWayland(DragController *parent)
|
||||||
|
: StateDragging(parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
StateDraggingWayland::~StateDraggingWayland()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void StateDraggingWayland::onEntry(QEvent *)
|
||||||
|
{
|
||||||
|
// Create a QDrag here
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StateDraggingWayland::handleMouseButtonRelease(QPoint /*globalPos*/)
|
||||||
|
{
|
||||||
|
Q_EMIT q->dragCanceled();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool StateDraggingWayland::handleMouseMove(QPoint /*globalPos*/)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
DragController::DragController(QObject *)
|
DragController::DragController(QObject *)
|
||||||
{
|
{
|
||||||
qCDebug(creation) << "DragController()";
|
qCDebug(creation) << "DragController()";
|
||||||
|
|
||||||
auto stateNone = new StateNone(this);
|
auto stateNone = new StateNone(this);
|
||||||
auto statepreDrag = new StatePreDrag(this);
|
auto statepreDrag = new StatePreDrag(this);
|
||||||
auto stateDragging = new StateDragging(this);
|
auto stateDragging = isWayland() ? new StateDraggingWayland(this)
|
||||||
|
: new StateDragging(this);
|
||||||
|
|
||||||
stateNone->addTransition(this, &DragController::mousePressed, statepreDrag);
|
stateNone->addTransition(this, &DragController::mousePressed, statepreDrag);
|
||||||
statepreDrag->addTransition(this, &DragController::dragCanceled, stateNone);
|
statepreDrag->addTransition(this, &DragController::dragCanceled, stateNone);
|
||||||
@@ -337,12 +389,23 @@ void DragController::releaseMouse(QWidgetOrQuick *target)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingWindow *DragController::windowBeingDragged() const
|
FloatingWindow *DragController::floatingWindowBeingDragged() const
|
||||||
{
|
{
|
||||||
return m_windowBeingDragged ? m_windowBeingDragged->floatingWindow()
|
return m_windowBeingDragged ? m_windowBeingDragged->floatingWindow()
|
||||||
: nullptr;
|
: nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DragController::enableFallbackMouseGrabber()
|
||||||
|
{
|
||||||
|
if (!m_fallbackMouseGrabber)
|
||||||
|
m_fallbackMouseGrabber = new FallbackMouseGrabber(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
WindowBeingDragged *DragController::windowBeingDragged() const
|
||||||
|
{
|
||||||
|
return m_windowBeingDragged.get();
|
||||||
|
}
|
||||||
|
|
||||||
static QMouseEvent *mouseEvent(QEvent *e)
|
static QMouseEvent *mouseEvent(QEvent *e)
|
||||||
{
|
{
|
||||||
switch (e->type()) {
|
switch (e->type()) {
|
||||||
@@ -377,7 +440,8 @@ bool DragController::eventFilter(QObject *o, QEvent *e)
|
|||||||
if (!w)
|
if (!w)
|
||||||
return QStateMachine::eventFilter(o, e);
|
return QStateMachine::eventFilter(o, e);
|
||||||
|
|
||||||
qCDebug(mouseevents) << "DragController::eventFilter e=" << e->type() << "; o=" << o;
|
qCDebug(mouseevents) << "DragController::eventFilter e=" << e->type() << "; o=" << o
|
||||||
|
<< "; m_nonClientDrag=" << m_nonClientDrag;
|
||||||
|
|
||||||
switch (e->type()) {
|
switch (e->type()) {
|
||||||
case QEvent::NonClientAreaMouseButtonPress: {
|
case QEvent::NonClientAreaMouseButtonPress: {
|
||||||
@@ -506,7 +570,7 @@ WidgetType *DragController::qtTopLevelUnderCursor() const
|
|||||||
// The floating window list is sorted by z-order, as we catch QEvent::Expose and move it to last of the list
|
// The floating window list is sorted by z-order, as we catch QEvent::Expose and move it to last of the list
|
||||||
|
|
||||||
FloatingWindow *tlwBeingDragged = m_windowBeingDragged->floatingWindow();
|
FloatingWindow *tlwBeingDragged = m_windowBeingDragged->floatingWindow();
|
||||||
if (auto tl = qtTopLevelUnderCursor_impl(globalPos, DockRegistry::self()->floatingWindows(), tlwBeingDragged))
|
if (auto tl = qtTopLevelUnderCursor_impl(globalPos, DockRegistry::self()->floatingQWindows(), tlwBeingDragged))
|
||||||
return tl;
|
return tl;
|
||||||
|
|
||||||
return qtTopLevelUnderCursor_impl<WidgetType*>(globalPos,
|
return qtTopLevelUnderCursor_impl<WidgetType*>(globalPos,
|
||||||
|
|||||||
@@ -12,6 +12,8 @@
|
|||||||
#ifndef KD_DRAGCONTROLLER_P_H
|
#ifndef KD_DRAGCONTROLLER_P_H
|
||||||
#define KD_DRAGCONTROLLER_P_H
|
#define KD_DRAGCONTROLLER_P_H
|
||||||
|
|
||||||
|
#include "docks_export.h"
|
||||||
|
|
||||||
#include "TitleBar_p.h"
|
#include "TitleBar_p.h"
|
||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
|
|
||||||
@@ -26,7 +28,7 @@ class DropArea;
|
|||||||
class Draggable;
|
class Draggable;
|
||||||
class FallbackMouseGrabber;
|
class FallbackMouseGrabber;
|
||||||
|
|
||||||
class DragController : public QStateMachine
|
class DOCKS_EXPORT DragController : public QStateMachine
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -50,7 +52,13 @@ public:
|
|||||||
void grabMouseFor(QWidgetOrQuick *);
|
void grabMouseFor(QWidgetOrQuick *);
|
||||||
void releaseMouse(QWidgetOrQuick *);
|
void releaseMouse(QWidgetOrQuick *);
|
||||||
|
|
||||||
FloatingWindow *windowBeingDragged() const;
|
FloatingWindow *floatingWindowBeingDragged() const;
|
||||||
|
|
||||||
|
///@brief Returns the window being dragged
|
||||||
|
WindowBeingDragged* windowBeingDragged() const;
|
||||||
|
|
||||||
|
/// Experimental, internal, not for general use.
|
||||||
|
void enableFallbackMouseGrabber();
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void mousePressed();
|
void mousePressed();
|
||||||
@@ -96,6 +104,9 @@ public:
|
|||||||
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; }
|
||||||
|
|
||||||
|
// Returns whether this is the current state
|
||||||
|
bool isActiveState() const;
|
||||||
|
|
||||||
DragController *const q;
|
DragController *const q;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -120,6 +131,7 @@ public:
|
|||||||
bool handleMouseButtonRelease(QPoint) override;
|
bool handleMouseButtonRelease(QPoint) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Used on all platforms except Wayland. @see StateDraggingWayland
|
||||||
class StateDragging : public StateBase
|
class StateDragging : public StateBase
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -131,6 +143,18 @@ public:
|
|||||||
bool handleMouseMove(QPoint globalPos) override;
|
bool handleMouseMove(QPoint globalPos) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Used on wayland only to use QDrag instead of setting geometry on mouse-move.
|
||||||
|
class StateDraggingWayland : public StateDragging
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit StateDraggingWayland(DragController *parent);
|
||||||
|
~StateDraggingWayland() override;
|
||||||
|
void onEntry(QEvent *) override;
|
||||||
|
bool handleMouseButtonRelease(QPoint globalPos) override;
|
||||||
|
bool handleMouseMove(QPoint globalPos) override;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -71,6 +71,13 @@ Frame *DropArea::frameContainingPos(QPoint globalPos) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DropArea::updateFloatingActions()
|
||||||
|
{
|
||||||
|
const Frame::List frames = this->frames();
|
||||||
|
for (Frame *frame : frames)
|
||||||
|
frame->updateFloatingActions();
|
||||||
|
}
|
||||||
|
|
||||||
Layouting::Item *DropArea::centralFrame() const
|
Layouting::Item *DropArea::centralFrame() const
|
||||||
{
|
{
|
||||||
for (Layouting::Item *item : this->items()) {
|
for (Layouting::Item *item : this->items()) {
|
||||||
@@ -103,6 +110,8 @@ void DropArea::addDockWidget(DockWidgetBase *dw, Location location, DockWidgetBa
|
|||||||
|
|
||||||
dw->saveLastFloatingGeometry();
|
dw->saveLastFloatingGeometry();
|
||||||
|
|
||||||
|
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 (contains(dw)) {
|
||||||
Frame *oldFrame = dw->frame();
|
Frame *oldFrame = dw->frame();
|
||||||
@@ -124,6 +133,12 @@ void DropArea::addDockWidget(DockWidgetBase *dw, Location location, DockWidgetBa
|
|||||||
} else {
|
} else {
|
||||||
addWidget(frame, location, relativeToFrame, DefaultSizeMode::Fair, option);
|
addWidget(frame, location, relativeToFrame, DefaultSizeMode::Fair, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hadSingleFloatingFrame && !hasSingleFloatingFrame()) {
|
||||||
|
// The dock widgets that already existed in our layout need to have their floatAction() updated
|
||||||
|
// otherwise it's still checked. Only the dropped dock widget got updated
|
||||||
|
updateFloatingActions();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DropArea::contains(DockWidgetBase *dw) const
|
bool DropArea::contains(DockWidgetBase *dw) const
|
||||||
@@ -131,6 +146,12 @@ bool DropArea::contains(DockWidgetBase *dw) const
|
|||||||
return dw->frame() && MultiSplitter::contains(dw->frame());
|
return dw->frame() && MultiSplitter::contains(dw->frame());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DropArea::hasSingleFloatingFrame() const
|
||||||
|
{
|
||||||
|
const Frame::List frames = this->frames();
|
||||||
|
return frames.size() == 1 && frames.first()->isFloating();
|
||||||
|
}
|
||||||
|
|
||||||
QStringList DropArea::affinities() const
|
QStringList DropArea::affinities() const
|
||||||
{
|
{
|
||||||
if (auto mw = mainWindow()) {
|
if (auto mw = mainWindow()) {
|
||||||
@@ -153,7 +174,7 @@ void DropArea::layoutParentContainerEqually(DockWidgetBase *dw)
|
|||||||
layoutEqually(item->parentContainer());
|
layoutEqually(item->parentContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropArea::hover(FloatingWindow *floatingWindow, QPoint globalPos)
|
void DropArea::hover(WindowBeingDragged *floatingWindow, QPoint globalPos)
|
||||||
{
|
{
|
||||||
if (!validateAffinity(floatingWindow))
|
if (!validateAffinity(floatingWindow))
|
||||||
return;
|
return;
|
||||||
@@ -164,7 +185,7 @@ void DropArea::hover(FloatingWindow *floatingWindow, QPoint globalPos)
|
|||||||
}
|
}
|
||||||
|
|
||||||
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);
|
m_dropIndicatorOverlay->setWindowBeingDragged(floatingWindow != nullptr);
|
||||||
m_dropIndicatorOverlay->setHoveredFrame(frame);
|
m_dropIndicatorOverlay->setHoveredFrame(frame);
|
||||||
m_dropIndicatorOverlay->hover(globalPos);
|
m_dropIndicatorOverlay->hover(globalPos);
|
||||||
}
|
}
|
||||||
@@ -182,9 +203,12 @@ static bool isOutterLocation(DropIndicatorOverlayInterface::DropLocation locatio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DropArea::drop(FloatingWindow *droppedWindow, QPoint globalPos)
|
bool DropArea::drop(WindowBeingDragged *droppedWindow, QPoint globalPos)
|
||||||
{
|
{
|
||||||
if (droppedWindow == window()) {
|
FloatingWindow *floatingWindow = droppedWindow ? droppedWindow->floatingWindow()
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
if (floatingWindow == window()) {
|
||||||
qWarning() << "Refusing to drop onto itself"; // Doesn't happen
|
qWarning() << "Refusing to drop onto itself"; // Doesn't happen
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -197,15 +221,24 @@ bool DropArea::drop(FloatingWindow *droppedWindow, QPoint globalPos)
|
|||||||
qCDebug(dropping) << "DropArea::drop:" << droppedWindow;
|
qCDebug(dropping) << "DropArea::drop:" << droppedWindow;
|
||||||
|
|
||||||
hover(droppedWindow, globalPos);
|
hover(droppedWindow, globalPos);
|
||||||
|
auto droploc = m_dropIndicatorOverlay->currentDropLocation();
|
||||||
Frame *acceptingFrame = m_dropIndicatorOverlay->hoveredFrame();
|
Frame *acceptingFrame = m_dropIndicatorOverlay->hoveredFrame();
|
||||||
if (!(acceptingFrame || isOutterLocation(m_dropIndicatorOverlay->currentDropLocation()))) {
|
if (!(acceptingFrame || isOutterLocation(m_dropIndicatorOverlay->currentDropLocation()))) {
|
||||||
qWarning() << "DropArea::drop: asserted with frame=" << acceptingFrame << "; Location=" << m_dropIndicatorOverlay->currentDropLocation();
|
qWarning() << "DropArea::drop: asserted with frame=" << acceptingFrame << "; Location=" << m_dropIndicatorOverlay->currentDropLocation();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool result = true;
|
return drop(floatingWindow, acceptingFrame, droploc);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DropArea::drop(FloatingWindow *droppedWindow, Frame *acceptingFrame,
|
||||||
|
DropIndicatorOverlayInterface::DropLocation droploc)
|
||||||
|
{
|
||||||
|
bool result = true;
|
||||||
|
const bool needToFocusNewlyDroppedWidgets = Config::self().flags() & Config::Flag_TitleBarIsFocusable;
|
||||||
|
const DockWidgetBase::List droppedDockWidgets = needToFocusNewlyDroppedWidgets ? droppedWindow->multiSplitter()->dockWidgets()
|
||||||
|
: DockWidgetBase::List(); // just so save some memory allocations for the case where this variable isn't used
|
||||||
|
|
||||||
auto droploc = m_dropIndicatorOverlay->currentDropLocation();
|
|
||||||
switch (droploc) {
|
switch (droploc) {
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Left:
|
case DropIndicatorOverlayInterface::DropLocation_Left:
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Top:
|
case DropIndicatorOverlayInterface::DropLocation_Top:
|
||||||
@@ -221,7 +254,7 @@ bool DropArea::drop(FloatingWindow *droppedWindow, QPoint globalPos)
|
|||||||
break;
|
break;
|
||||||
case DropIndicatorOverlayInterface::DropLocation_Center:
|
case DropIndicatorOverlayInterface::DropLocation_Center:
|
||||||
qCDebug(hovering) << "Tabbing" << droppedWindow << "into" << acceptingFrame;
|
qCDebug(hovering) << "Tabbing" << droppedWindow << "into" << acceptingFrame;
|
||||||
if (!validateAffinity(droppedWindow))
|
if (!validateAffinity(droppedWindow, acceptingFrame))
|
||||||
return false;
|
return false;
|
||||||
acceptingFrame->addWidget(droppedWindow);
|
acceptingFrame->addWidget(droppedWindow);
|
||||||
break;
|
break;
|
||||||
@@ -232,9 +265,23 @@ bool DropArea::drop(FloatingWindow *droppedWindow, QPoint globalPos)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result)
|
if (result) {
|
||||||
|
// Window receiving the drop gets raised:
|
||||||
raiseAndActivate();
|
raiseAndActivate();
|
||||||
|
|
||||||
|
if (needToFocusNewlyDroppedWidgets) {
|
||||||
|
// Let's also focus the newly dropped dock widget
|
||||||
|
if (droppedDockWidgets.size() > 0) {
|
||||||
|
// If more than 1 was dropped, we only focus the first one
|
||||||
|
Frame *frame = droppedDockWidgets.first()->frame();
|
||||||
|
frame->FocusScope::focus(Qt::MouseFocusReason);
|
||||||
|
} else {
|
||||||
|
// Doesn't happen.
|
||||||
|
qWarning() << Q_FUNC_INFO << "Nothing was dropped?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -253,7 +300,11 @@ bool DropArea::drop(QWidgetOrQuick *droppedWindow, KDDockWidgets::Location locat
|
|||||||
if (!validateAffinity(floatingWindow))
|
if (!validateAffinity(floatingWindow))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
const bool hadSingleFloatingFrame = hasSingleFloatingFrame();
|
||||||
addMultiSplitter(floatingWindow->dropArea(), location, relativeTo, DefaultSizeMode::FairButFloor);
|
addMultiSplitter(floatingWindow->dropArea(), location, relativeTo, DefaultSizeMode::FairButFloor);
|
||||||
|
if (hadSingleFloatingFrame != hasSingleFloatingFrame())
|
||||||
|
updateFloatingActions();
|
||||||
|
|
||||||
floatingWindow->scheduleDeleteLater();
|
floatingWindow->scheduleDeleteLater();
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
@@ -266,19 +317,24 @@ bool DropArea::drop(QWidgetOrQuick *droppedWindow, KDDockWidgets::Location locat
|
|||||||
|
|
||||||
void DropArea::removeHover()
|
void DropArea::removeHover()
|
||||||
{
|
{
|
||||||
m_dropIndicatorOverlay->setWindowBeingDragged(nullptr);
|
m_dropIndicatorOverlay->setWindowBeingDragged(false);
|
||||||
m_dropIndicatorOverlay->setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation_None);
|
m_dropIndicatorOverlay->setCurrentDropLocation(DropIndicatorOverlayInterface::DropLocation_None);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
bool DropArea::validateAffinity(T *window) const
|
bool DropArea::validateAffinity(T *window, Frame *acceptingFrame) const
|
||||||
{
|
{
|
||||||
if (!DockRegistry::self()->affinitiesMatch(window->affinities(), affinities())) {
|
if (!DockRegistry::self()->affinitiesMatch(window->affinities(), affinities())) {
|
||||||
// Commented the warning, so we don't warn when hovering over
|
|
||||||
//qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
|
|
||||||
//<< window->affinityName() << affinityName();
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (acceptingFrame) {
|
||||||
|
// We're dropping into another frame (as tabbed), so also check the affinity of the frame
|
||||||
|
// not only of the main window, which might be more forgiving
|
||||||
|
if (!DockRegistry::self()->affinitiesMatch(window->affinities(), acceptingFrame->affinities())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,11 +25,12 @@
|
|||||||
#include "MultiSplitter_p.h"
|
#include "MultiSplitter_p.h"
|
||||||
#include "DropIndicatorOverlayInterface_p.h"
|
#include "DropIndicatorOverlayInterface_p.h"
|
||||||
|
|
||||||
|
class TestCommon;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class Frame;
|
class Frame;
|
||||||
class Draggable;
|
class Draggable;
|
||||||
class DropIndicatorOverlayInterface;
|
|
||||||
struct WindowBeingDragged;
|
struct WindowBeingDragged;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -43,9 +44,9 @@ public:
|
|||||||
~DropArea();
|
~DropArea();
|
||||||
|
|
||||||
void removeHover();
|
void removeHover();
|
||||||
void hover(FloatingWindow *floatingWindow, QPoint globalPos);
|
void hover(WindowBeingDragged *floatingWindow, QPoint globalPos);
|
||||||
bool drop(FloatingWindow *droppedWindow, QPoint globalPos);
|
///@brief Called when a user drops a widget via DND
|
||||||
bool drop(QWidgetOrQuick *droppedwindow, KDDockWidgets::Location location, Frame *relativeTo);
|
bool drop(WindowBeingDragged *droppedWindow, QPoint globalPos);
|
||||||
int numFrames() const;
|
int numFrames() const;
|
||||||
Frame::List frames() const;
|
Frame::List frames() const;
|
||||||
|
|
||||||
@@ -55,17 +56,28 @@ public:
|
|||||||
|
|
||||||
bool contains(DockWidgetBase *) const;
|
bool contains(DockWidgetBase *) const;
|
||||||
|
|
||||||
|
/// 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
|
||||||
|
bool hasSingleFloatingFrame() const;
|
||||||
|
|
||||||
QStringList affinities() const;
|
QStringList affinities() const;
|
||||||
void layoutParentContainerEqually(DockWidgetBase *);
|
void layoutParentContainerEqually(DockWidgetBase *);
|
||||||
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;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool validateAffinity(T *) const;
|
bool validateAffinity(T *, Frame *acceptingFrame = nullptr) const;
|
||||||
|
bool drop(FloatingWindow *droppedWindow, Frame *acceptingFrame, DropIndicatorOverlayInterface::DropLocation);
|
||||||
|
bool drop(QWidgetOrQuick *droppedwindow, KDDockWidgets::Location location, Frame *relativeTo);
|
||||||
Frame *frameContainingPos(QPoint globalPos) const;
|
Frame *frameContainingPos(QPoint globalPos) const;
|
||||||
|
void updateFloatingActions();
|
||||||
|
|
||||||
bool m_inDestructor = false;
|
bool m_inDestructor = false;
|
||||||
QString m_affinityName;
|
QString m_affinityName;
|
||||||
DropIndicatorOverlayInterface *m_dropIndicatorOverlay = nullptr;
|
DropIndicatorOverlayInterface *m_dropIndicatorOverlay = nullptr;
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
|
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
#include "FloatingWindow_p.h"
|
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
@@ -25,20 +24,20 @@ DropIndicatorOverlayInterface::DropIndicatorOverlayInterface(DropArea *dropArea)
|
|||||||
setObjectName(QStringLiteral("DropIndicatorOverlayInterface"));
|
setObjectName(QStringLiteral("DropIndicatorOverlayInterface"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void DropIndicatorOverlayInterface::setWindowBeingDragged(const FloatingWindow *window)
|
void DropIndicatorOverlayInterface::setWindowBeingDragged(bool is)
|
||||||
{
|
{
|
||||||
if (window == m_windowBeingDragged)
|
if (is == m_draggedWindowIsHovering)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
m_windowBeingDragged = window;
|
m_draggedWindowIsHovering = is;
|
||||||
if (m_windowBeingDragged) {
|
if (is) {
|
||||||
setGeometry(m_dropArea->QWidgetAdapter::rect());
|
setGeometry(m_dropArea->QWidgetAdapter::rect());
|
||||||
raise();
|
raise();
|
||||||
} else {
|
} else {
|
||||||
setHoveredFrame(nullptr);
|
setHoveredFrame(nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
setVisible(m_windowBeingDragged != nullptr);
|
setVisible(is);
|
||||||
updateVisibility();
|
updateVisibility();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +69,7 @@ void DropIndicatorOverlayInterface::setHoveredFrame(Frame *frame)
|
|||||||
|
|
||||||
bool DropIndicatorOverlayInterface::isHovered() const
|
bool DropIndicatorOverlayInterface::isHovered() const
|
||||||
{
|
{
|
||||||
return m_windowBeingDragged != nullptr;
|
return m_draggedWindowIsHovering;
|
||||||
}
|
}
|
||||||
|
|
||||||
DropIndicatorOverlayInterface::DropLocation DropIndicatorOverlayInterface::currentDropLocation() const
|
DropIndicatorOverlayInterface::DropLocation DropIndicatorOverlayInterface::currentDropLocation() const
|
||||||
|
|||||||
@@ -19,7 +19,6 @@
|
|||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class FloatingWindow;
|
|
||||||
class DropArea;
|
class DropArea;
|
||||||
|
|
||||||
class DOCKS_EXPORT DropIndicatorOverlayInterface : public QWidgetAdapter
|
class DOCKS_EXPORT DropIndicatorOverlayInterface : public QWidgetAdapter
|
||||||
@@ -47,7 +46,7 @@ public:
|
|||||||
|
|
||||||
explicit DropIndicatorOverlayInterface(DropArea *dropArea);
|
explicit DropIndicatorOverlayInterface(DropArea *dropArea);
|
||||||
void setHoveredFrame(Frame *);
|
void setHoveredFrame(Frame *);
|
||||||
void setWindowBeingDragged(const FloatingWindow *);
|
void setWindowBeingDragged(bool);
|
||||||
QRect hoveredFrameRect() const;
|
QRect hoveredFrameRect() const;
|
||||||
bool isHovered() const;
|
bool isHovered() const;
|
||||||
DropLocation currentDropLocation() const;
|
DropLocation currentDropLocation() const;
|
||||||
@@ -77,8 +76,8 @@ protected:
|
|||||||
virtual void updateVisibility() {};
|
virtual void updateVisibility() {};
|
||||||
|
|
||||||
Frame *m_hoveredFrame = nullptr;
|
Frame *m_hoveredFrame = nullptr;
|
||||||
QPointer<const FloatingWindow> m_windowBeingDragged;
|
|
||||||
DropArea *const m_dropArea;
|
DropArea *const m_dropArea;
|
||||||
|
bool m_draggedWindowIsHovering = false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,11 @@
|
|||||||
#include <QCloseEvent>
|
#include <QCloseEvent>
|
||||||
#include <QAbstractNativeEventFilter>
|
#include <QAbstractNativeEventFilter>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
#include <QScopedValueRollback>
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
#if defined(Q_OS_WIN)
|
||||||
# include <Windows.h>
|
# include <Windows.h>
|
||||||
|
# include <dwmapi.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
@@ -132,23 +134,30 @@ FloatingWindow::FloatingWindow(MainWindowBase *parent)
|
|||||||
, m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
|
, m_titleBar(Config::self().frameworkWidgetFactory()->createTitleBar(this))
|
||||||
{
|
{
|
||||||
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
||||||
|
// 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()) {
|
if (KDDockWidgets::usesAeroSnapWithCustomDecos()) {
|
||||||
m_nchittestFilter = new NCHITTESTEventFilter(this);
|
m_nchittestFilter = new NCHITTESTEventFilter(this);
|
||||||
qApp->installNativeEventFilter(m_nchittestFilter);
|
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
|
#endif
|
||||||
|
|
||||||
DockRegistry::self()->registerNestedWindow(this);
|
DockRegistry::self()->registerFloatingWindow(this);
|
||||||
qCDebug(creation) << "FloatingWindow()" << this;
|
qCDebug(creation) << "FloatingWindow()" << this;
|
||||||
|
|
||||||
#if defined(Q_OS_WIN) && defined(KDDOCKWIDGETS_QTWIDGETS)
|
|
||||||
# if QT_VERSION < 0x051000
|
|
||||||
// On Windows with Qt 5.9 (and maybe later but we don't care), 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();
|
|
||||||
# endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
maybeCreateResizeHandler();
|
maybeCreateResizeHandler();
|
||||||
|
|
||||||
updateTitleBarVisibility();
|
updateTitleBarVisibility();
|
||||||
@@ -175,7 +184,7 @@ FloatingWindow::~FloatingWindow()
|
|||||||
disconnect(m_layoutDestroyedConnection);
|
disconnect(m_layoutDestroyedConnection);
|
||||||
delete m_nchittestFilter;
|
delete m_nchittestFilter;
|
||||||
|
|
||||||
DockRegistry::self()->unregisterNestedWindow(this);
|
DockRegistry::self()->unregisterFloatingWindow(this);
|
||||||
qCDebug(creation) << "~FloatingWindow";
|
qCDebug(creation) << "~FloatingWindow";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -250,7 +259,7 @@ void FloatingWindow::setSuggestedGeometry(QRect suggestedRect, bool preserveCent
|
|||||||
void FloatingWindow::scheduleDeleteLater()
|
void FloatingWindow::scheduleDeleteLater()
|
||||||
{
|
{
|
||||||
m_deleteScheduled = true;
|
m_deleteScheduled = true;
|
||||||
DockRegistry::self()->unregisterNestedWindow(this);
|
DockRegistry::self()->unregisterFloatingWindow(this);
|
||||||
deleteLater();
|
deleteLater();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -261,7 +270,7 @@ MultiSplitter *FloatingWindow::multiSplitter() const
|
|||||||
|
|
||||||
bool FloatingWindow::isInDragArea(QPoint globalPoint) const
|
bool FloatingWindow::isInDragArea(QPoint globalPoint) const
|
||||||
{
|
{
|
||||||
return dragRect().adjusted(8, 8, 0, 0).contains(globalPoint);
|
return dragRect().contains(globalPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FloatingWindow::anyNonClosable() const
|
bool FloatingWindow::anyNonClosable() const
|
||||||
@@ -318,6 +327,8 @@ void FloatingWindow::onFrameCountChanged(int count)
|
|||||||
scheduleDeleteLater();
|
scheduleDeleteLater();
|
||||||
} else {
|
} else {
|
||||||
updateTitleBarVisibility();
|
updateTitleBarVisibility();
|
||||||
|
if (count == 1) // if something was removed, then our single dock widget is floating, we need to check the QAction
|
||||||
|
dropArea()->updateFloatingActions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,13 +342,15 @@ void FloatingWindow::onVisibleFrameCountChanged(int count)
|
|||||||
|
|
||||||
void FloatingWindow::updateTitleBarVisibility()
|
void FloatingWindow::updateTitleBarVisibility()
|
||||||
{
|
{
|
||||||
|
if (m_updatingTitleBarVisibility)
|
||||||
|
return; // Break recursion
|
||||||
|
|
||||||
|
QScopedValueRollback<bool> guard(m_updatingTitleBarVisibility, true);
|
||||||
updateTitleAndIcon();
|
updateTitleAndIcon();
|
||||||
|
|
||||||
bool visible = true;
|
bool visible = true;
|
||||||
|
|
||||||
if (KDDockWidgets::usesNativeTitleBar()) {
|
if (KDDockWidgets::usesClientTitleBar()) {
|
||||||
visible = false;
|
|
||||||
} else {
|
|
||||||
const auto flags = Config::self().flags();
|
const auto flags = Config::self().flags();
|
||||||
if ((flags & Config::Flag_HideTitleBarWhenTabsVisible) && !(flags & Config::Flag_AlwaysTitleBarWhenFloating)) {
|
if ((flags & Config::Flag_HideTitleBarWhenTabsVisible) && !(flags & Config::Flag_AlwaysTitleBarWhenFloating)) {
|
||||||
if (hasSingleFrame()) {
|
if (hasSingleFrame()) {
|
||||||
@@ -347,6 +360,8 @@ void FloatingWindow::updateTitleBarVisibility()
|
|||||||
|
|
||||||
for (Frame *frame : frames())
|
for (Frame *frame : frames())
|
||||||
frame->updateTitleBarVisibility();
|
frame->updateTitleBarVisibility();
|
||||||
|
} else {
|
||||||
|
visible = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_titleBar->setVisible(visible);
|
m_titleBar->setVisible(visible);
|
||||||
|
|||||||
@@ -145,6 +145,7 @@ private:
|
|||||||
bool m_disableSetVisible = false;
|
bool m_disableSetVisible = false;
|
||||||
bool m_deleteScheduled = false;
|
bool m_deleteScheduled = false;
|
||||||
bool m_inDtor = false;
|
bool m_inDtor = false;
|
||||||
|
bool m_updatingTitleBarVisibility = false;
|
||||||
QMetaObject::Connection m_layoutDestroyedConnection;
|
QMetaObject::Connection m_layoutDestroyedConnection;
|
||||||
QAbstractNativeEventFilter *m_nchittestFilter = nullptr;
|
QAbstractNativeEventFilter *m_nchittestFilter = nullptr;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ Frame::Frame(QWidgetOrQuick *parent, FrameOptions options)
|
|||||||
qCDebug(creation) << "Frame" << ((void*)this) << s_dbg_numFrames;
|
qCDebug(creation) << "Frame" << ((void*)this) << s_dbg_numFrames;
|
||||||
|
|
||||||
connect(this, &Frame::currentDockWidgetChanged, this, &Frame::updateTitleAndIcon);
|
connect(this, &Frame::currentDockWidgetChanged, this, &Frame::updateTitleAndIcon);
|
||||||
|
setDropArea(qobject_cast<DropArea *>(QWidgetAdapter::parentWidget()));
|
||||||
m_inCtor = false;
|
m_inCtor = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,6 +94,16 @@ void Frame::updateTitleAndIcon()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Frame::onDockWidgetTitleChanged()
|
||||||
|
{
|
||||||
|
updateTitleAndIcon();
|
||||||
|
|
||||||
|
if (!m_inCtor) { // don't call pure virtual in ctor
|
||||||
|
if (auto dw = qobject_cast<DockWidgetBase*>(sender()))
|
||||||
|
renameTab(indexOfDockWidget(dw), dw->title());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Frame::addWidget(DockWidgetBase *dockWidget, AddingOption addingOption)
|
void Frame::addWidget(DockWidgetBase *dockWidget, AddingOption addingOption)
|
||||||
{
|
{
|
||||||
insertWidget(dockWidget, dockWidgetCount(), addingOption); // append
|
insertWidget(dockWidget, dockWidgetCount(), addingOption); // append
|
||||||
@@ -149,14 +160,14 @@ void Frame::insertWidget(DockWidgetBase *dockWidget, int index, AddingOption add
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(dockWidget, &DockWidgetBase::titleChanged, this, &Frame::updateTitleAndIcon);
|
connect(dockWidget, &DockWidgetBase::titleChanged, this, &Frame::onDockWidgetTitleChanged);
|
||||||
connect(dockWidget, &DockWidgetBase::iconChanged, this, &Frame::updateTitleAndIcon);
|
connect(dockWidget, &DockWidgetBase::iconChanged, this, &Frame::onDockWidgetTitleChanged);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frame::removeWidget(DockWidgetBase *dw)
|
void Frame::removeWidget(DockWidgetBase *dw)
|
||||||
{
|
{
|
||||||
disconnect(dw, &DockWidgetBase::titleChanged, this, &Frame::updateTitleAndIcon);
|
disconnect(dw, &DockWidgetBase::titleChanged, this, &Frame::onDockWidgetTitleChanged);
|
||||||
disconnect(dw, &DockWidgetBase::iconChanged, this, &Frame::updateTitleAndIcon);
|
disconnect(dw, &DockWidgetBase::iconChanged, this, &Frame::onDockWidgetTitleChanged);
|
||||||
removeWidget_impl(dw);
|
removeWidget_impl(dw);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +294,13 @@ void Frame::updateTitleBarVisibility()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Frame::updateFloatingActions()
|
||||||
|
{
|
||||||
|
const QVector<DockWidgetBase *> widgets = dockWidgets();
|
||||||
|
for (DockWidgetBase *dw : widgets)
|
||||||
|
dw->updateFloatAction();
|
||||||
|
}
|
||||||
|
|
||||||
bool Frame::containsMouse(QPoint globalPos) const
|
bool Frame::containsMouse(QPoint globalPos) const
|
||||||
{
|
{
|
||||||
return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
|
return QWidgetAdapter::rect().contains(KDDockWidgets::QWidgetAdapter::mapFromGlobal(globalPos));
|
||||||
@@ -500,23 +518,26 @@ QStringList Frame::affinities() const
|
|||||||
|
|
||||||
void Frame::setDropArea(DropArea *dt)
|
void Frame::setDropArea(DropArea *dt)
|
||||||
{
|
{
|
||||||
if (dt != m_dropArea) {
|
if (dt == m_dropArea)
|
||||||
qCDebug(docking) << "Frame::setDropArea dt=" << dt;
|
return;
|
||||||
const bool wasInMainWindow = dt && isInMainWindow();
|
|
||||||
if (m_dropArea)
|
|
||||||
disconnect(m_visibleWidgetCountChangedConnection);
|
|
||||||
|
|
||||||
m_dropArea = dt;
|
|
||||||
|
|
||||||
if (m_dropArea) {
|
qCDebug(docking) << "Frame::setDropArea dt=" << dt;
|
||||||
// We keep the connect result so we don't dereference m_dropArea at shutdown
|
const bool wasInMainWindow = dt && isInMainWindow();
|
||||||
m_visibleWidgetCountChangedConnection = connect(m_dropArea, &MultiSplitter::visibleWidgetCountChanged,
|
if (m_dropArea)
|
||||||
this, &Frame::updateTitleBarVisibility);
|
disconnect(m_visibleWidgetCountChangedConnection);
|
||||||
updateTitleBarVisibility();
|
|
||||||
if (wasInMainWindow != isInMainWindow())
|
m_dropArea = dt;
|
||||||
Q_EMIT isInMainWindowChanged();
|
|
||||||
}
|
if (m_dropArea) {
|
||||||
|
// We keep the connect result so we don't dereference m_dropArea at shutdown
|
||||||
|
m_visibleWidgetCountChangedConnection = connect(m_dropArea, &MultiSplitter::visibleWidgetCountChanged,
|
||||||
|
this, &Frame::updateTitleBarVisibility);
|
||||||
|
updateTitleBarVisibility();
|
||||||
|
if (wasInMainWindow != isInMainWindow())
|
||||||
|
Q_EMIT isInMainWindowChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Frame::isTheOnlyFrame() const
|
bool Frame::isTheOnlyFrame() const
|
||||||
@@ -526,6 +547,11 @@ bool Frame::isTheOnlyFrame() const
|
|||||||
return m_dropArea && m_dropArea->numFrames() == 1;
|
return m_dropArea && m_dropArea->numFrames() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Frame::isOverlayed() const
|
||||||
|
{
|
||||||
|
return m_options & FrameOption_IsOverlayed;
|
||||||
|
}
|
||||||
|
|
||||||
bool Frame::isFloating() const
|
bool Frame::isFloating() const
|
||||||
{
|
{
|
||||||
if (isInMainWindow())
|
if (isInMainWindow())
|
||||||
|
|||||||
@@ -105,7 +105,9 @@ public:
|
|||||||
int dockWidgetCount() const;
|
int dockWidgetCount() const;
|
||||||
|
|
||||||
void updateTitleAndIcon();
|
void updateTitleAndIcon();
|
||||||
|
void onDockWidgetTitleChanged();
|
||||||
void updateTitleBarVisibility();
|
void updateTitleBarVisibility();
|
||||||
|
void updateFloatingActions();
|
||||||
bool containsMouse(QPoint globalPos) const;
|
bool containsMouse(QPoint globalPos) const;
|
||||||
TitleBar *titleBar() const;
|
TitleBar *titleBar() const;
|
||||||
TitleBar *actualTitleBar() const;
|
TitleBar *actualTitleBar() const;
|
||||||
@@ -120,6 +122,9 @@ public:
|
|||||||
|
|
||||||
bool isTheOnlyFrame() const;
|
bool isTheOnlyFrame() const;
|
||||||
|
|
||||||
|
///@brief Returns whether this frame is overlayed on top of the MainWindow (auto-hide feature);
|
||||||
|
bool isOverlayed() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns whether this frame is floating. A floating frame isn't attached to any other MainWindow,
|
* @brief Returns whether this frame is floating. A floating frame isn't attached to any other MainWindow,
|
||||||
* and if it's attached to a FloatingWindow then it's considered floating if it's the only frame in that Window.
|
* and if it's attached to a FloatingWindow then it's considered floating if it's the only frame in that Window.
|
||||||
@@ -239,6 +244,8 @@ Q_SIGNALS:
|
|||||||
void focusedWidgetChanged() override;
|
void focusedWidgetChanged() override;
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
|
virtual void renameTab(int index, const QString &) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the minimum size of the dock widgets.
|
* @brief Returns the minimum size of the dock widgets.
|
||||||
* This might be slightly smaller than Frame::minSize() due to the QTabWidget having some margins
|
* This might be slightly smaller than Frame::minSize() due to the QTabWidget having some margins
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "multisplitter/Widget_qwidget.h"
|
#include "multisplitter/Widget_qwidget.h"
|
||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
|
#include "WindowBeingDragged_p.h"
|
||||||
|
|
||||||
#include <QScopedValueRollback>
|
#include <QScopedValueRollback>
|
||||||
|
|
||||||
@@ -92,6 +93,9 @@ MainWindowBase *MultiSplitter::mainWindow() const
|
|||||||
// Note that if pw is a FloatingWindow then pw->parentWidget() can be a MainWindow too, as it's parented
|
// Note that if pw is a FloatingWindow then pw->parentWidget() can be a MainWindow too, as it's parented
|
||||||
if (pw->objectName() == QLatin1String("MyCentralWidget"))
|
if (pw->objectName() == QLatin1String("MyCentralWidget"))
|
||||||
return qobject_cast<MainWindowBase*>(pw->parentWidget());
|
return qobject_cast<MainWindowBase*>(pw->parentWidget());
|
||||||
|
|
||||||
|
if (auto mw = qobject_cast<MainWindowBase*>(pw))
|
||||||
|
return mw;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -200,7 +204,17 @@ void MultiSplitter::addWidget(QWidgetOrQuick *w, Location location,
|
|||||||
} else if (auto ms = qobject_cast<MultiSplitter*>(w)) {
|
} else if (auto ms = qobject_cast<MultiSplitter*>(w)) {
|
||||||
newItem = ms->rootItem();
|
newItem = ms->rootItem();
|
||||||
newItem->setHostWidget(this);
|
newItem->setHostWidget(this);
|
||||||
|
|
||||||
|
if (FloatingWindow *fw = ms->floatingWindow()) {
|
||||||
|
newItem->setSize_recursive(fw->size());
|
||||||
|
}
|
||||||
|
|
||||||
delete ms;
|
delete ms;
|
||||||
|
} else {
|
||||||
|
// This doesn't happen but let's make coverity happy.
|
||||||
|
// Tests will fail if this is ever printed.
|
||||||
|
qWarning() << Q_FUNC_INFO << "Unknown widget added" << w;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(!newItem->geometry().isEmpty());
|
Q_ASSERT(!newItem->geometry().isEmpty());
|
||||||
@@ -288,6 +302,16 @@ Layouting::Item *MultiSplitter::itemForFrame(const Frame *frame) const
|
|||||||
return m_rootItem->itemForWidget(frame);
|
return m_rootItem->itemForWidget(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DockWidgetBase::List MultiSplitter::dockWidgets() const
|
||||||
|
{
|
||||||
|
DockWidgetBase::List dockWidgets;
|
||||||
|
const Frame::List frames = this->frames();
|
||||||
|
for (Frame *frame : frames)
|
||||||
|
dockWidgets << frame->dockWidgets();
|
||||||
|
|
||||||
|
return dockWidgets;
|
||||||
|
}
|
||||||
|
|
||||||
Frame::List MultiSplitter::framesFrom(QWidgetOrQuick *frameOrMultiSplitter) const
|
Frame::List MultiSplitter::framesFrom(QWidgetOrQuick *frameOrMultiSplitter) const
|
||||||
{
|
{
|
||||||
if (auto frame = qobject_cast<Frame*>(frameOrMultiSplitter))
|
if (auto frame = qobject_cast<Frame*>(frameOrMultiSplitter))
|
||||||
@@ -413,17 +437,16 @@ Layouting::ItemContainer *MultiSplitter::rootItem() const
|
|||||||
return m_rootItem;
|
return m_rootItem;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect MultiSplitter::rectForDrop(const FloatingWindow *fw, Location location,
|
QRect MultiSplitter::rectForDrop(const WindowBeingDragged *wbd, Location location,
|
||||||
const Layouting::Item *relativeTo) const
|
const Layouting::Item *relativeTo) const
|
||||||
{
|
{
|
||||||
Layouting::Item item(nullptr);
|
Layouting::Item item(nullptr);
|
||||||
if (!fw)
|
if (!wbd)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
Layouting::ItemContainer *root = fw->dropArea()->rootItem();
|
item.setSize(wbd->size().boundedTo(wbd->maxSize()));
|
||||||
item.setSize(root->size());
|
item.setMinSize(wbd->minSize());
|
||||||
item.setMinSize(root->minSize());
|
item.setMaxSizeHint(wbd->maxSize());
|
||||||
item.setMaxSizeHint(root->maxSizeHint());
|
|
||||||
|
|
||||||
Layouting::ItemContainer *container = relativeTo ? relativeTo->parentContainer()
|
Layouting::ItemContainer *container = relativeTo ? relativeTo->parentContainer()
|
||||||
: m_rootItem;
|
: m_rootItem;
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace KDDockWidgets {
|
|||||||
class MainWindowBase;
|
class MainWindowBase;
|
||||||
class FloatingWindow;
|
class FloatingWindow;
|
||||||
class Frame;
|
class Frame;
|
||||||
|
class 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
|
||||||
@@ -53,7 +53,7 @@ class Frame;
|
|||||||
* It supports adding a widget to the left/top/bottom/right of the whole MultiSplitter or adding
|
* It supports adding a widget to the left/top/bottom/right of the whole MultiSplitter or adding
|
||||||
* relative to a single widget.
|
* relative to a single widget.
|
||||||
*/
|
*/
|
||||||
class DOCKS_EXPORT_FOR_UNIT_TESTS MultiSplitter
|
class DOCKS_EXPORT MultiSplitter
|
||||||
: public LayoutGuestWidget
|
: public LayoutGuestWidget
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -131,7 +131,7 @@ public:
|
|||||||
* Excludes the Separator thickness, result is actually smaller than what needed. In other words,
|
* Excludes the Separator thickness, result is actually smaller than what needed. In other words,
|
||||||
* the result will be exactly the same as the geometry the widget will get.
|
* the result will be exactly the same as the geometry the widget will get.
|
||||||
*/
|
*/
|
||||||
QRect rectForDrop(const FloatingWindow *, KDDockWidgets::Location location,
|
QRect rectForDrop(const WindowBeingDragged *wbd, KDDockWidgets::Location location,
|
||||||
const Layouting::Item *relativeTo) const;
|
const Layouting::Item *relativeTo) const;
|
||||||
|
|
||||||
bool deserialize(const LayoutSaver::MultiSplitter &);
|
bool deserialize(const LayoutSaver::MultiSplitter &);
|
||||||
@@ -188,10 +188,13 @@ public:
|
|||||||
Layouting::Item *itemForFrame(const Frame *frame) const;
|
Layouting::Item *itemForFrame(const Frame *frame) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a list of Frame objects contained in this layout
|
* @brief Returns this list of Frame objects contained in this layout
|
||||||
*/
|
*/
|
||||||
QList<Frame*> frames() const;
|
QList<Frame*> frames() const;
|
||||||
|
|
||||||
|
/// @brief Returns the list of dock widgets contained in this layout
|
||||||
|
QVector<DockWidgetBase*> dockWidgets() const;
|
||||||
|
|
||||||
/// @brief restores the dockwidget @p dw to its previous position
|
/// @brief restores the dockwidget @p dw to its previous position
|
||||||
void restorePlaceholder(DockWidgetBase *dw, Layouting::Item *, int tabIndex);
|
void restorePlaceholder(DockWidgetBase *dw, Layouting::Item *, int tabIndex);
|
||||||
|
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ void Position::deserialize(const LayoutSaver::Position &lp)
|
|||||||
if (index == -1) {
|
if (index == -1) {
|
||||||
continue; // Skip
|
continue; // Skip
|
||||||
} else {
|
} else {
|
||||||
const auto floatingWindows = DockRegistry::self()->nestedwindows();
|
const auto floatingWindows = DockRegistry::self()->floatingWindows();
|
||||||
if (index >= 0 && index < floatingWindows.size()) {
|
if (index >= 0 && index < floatingWindows.size()) {
|
||||||
FloatingWindow *fw = floatingWindows.at(index);
|
FloatingWindow *fw = floatingWindows.at(index);
|
||||||
layout = fw->multiSplitter();
|
layout = fw->multiSplitter();
|
||||||
@@ -170,7 +170,7 @@ LayoutSaver::Position Position::serialize() const
|
|||||||
p.isFloatingWindow = fw;
|
p.isFloatingWindow = fw;
|
||||||
|
|
||||||
if (p.isFloatingWindow) {
|
if (p.isFloatingWindow) {
|
||||||
p.indexOfFloatingWindow = fw->beingDeleted() ? -1 : DockRegistry::self()->nestedwindows().indexOf(fw); // TODO: Remove once we stop using deleteLater with FloatingWindow. delete would be better
|
p.indexOfFloatingWindow = fw->beingDeleted() ? -1 : DockRegistry::self()->floatingWindows().indexOf(fw); // TODO: Remove once we stop using deleteLater with FloatingWindow. delete would be better
|
||||||
} else {
|
} else {
|
||||||
p.mainWindowUniqueName = mainWindow->uniqueName();
|
p.mainWindowUniqueName = mainWindow->uniqueName();
|
||||||
Q_ASSERT(!p.mainWindowUniqueName.isEmpty());
|
Q_ASSERT(!p.mainWindowUniqueName.isEmpty());
|
||||||
|
|||||||
109
src/private/SideBar.cpp
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio 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 "SideBar_p.h"
|
||||||
|
#include "DockWidgetBase.h"
|
||||||
|
#include "MainWindowBase.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
SideBar::SideBar(SideBarLocation location, MainWindowBase *parent)
|
||||||
|
: QWidgetAdapter(parent)
|
||||||
|
, m_mainWindow(parent)
|
||||||
|
, m_location(location)
|
||||||
|
, m_orientation((location == SideBarLocation::North || location == SideBarLocation::South) ? Qt::Horizontal
|
||||||
|
: Qt::Vertical)
|
||||||
|
{
|
||||||
|
updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideBar::addDockWidget(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
if (!dw)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_dockWidgets.contains(dw)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Already contains dock widget" << dw->title();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(dw, &QObject::destroyed, this, &SideBar::onDockWidgetDestroyed);
|
||||||
|
|
||||||
|
m_dockWidgets << dw;
|
||||||
|
addDockWidget_Impl(dw);
|
||||||
|
updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideBar::removeDockWidget(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
if (!m_dockWidgets.contains(dw)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Doesn't contain dock widget" << dw->title();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
disconnect(dw, &QObject::destroyed, this, &SideBar::onDockWidgetDestroyed);
|
||||||
|
m_dockWidgets.removeOne(dw);
|
||||||
|
removeDockWidget_Impl(dw);
|
||||||
|
Q_EMIT dw->removedFromSideBar();
|
||||||
|
updateSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SideBar::contains(DockWidgetBase *dw) const
|
||||||
|
{
|
||||||
|
return m_dockWidgets.contains(dw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideBar::onButtonClicked(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
toggleOverlay(dw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideBar::onDockWidgetDestroyed(QObject *dw)
|
||||||
|
{
|
||||||
|
removeDockWidget(static_cast<DockWidgetBase*>(dw));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideBar::updateSize()
|
||||||
|
{
|
||||||
|
const int thickness = isEmpty() ? 0 : 30;
|
||||||
|
if (isVertical()) {
|
||||||
|
setFixedWidth(thickness);
|
||||||
|
} else {
|
||||||
|
setFixedHeight(thickness);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::Orientation SideBar::orientation() const
|
||||||
|
{
|
||||||
|
return m_orientation;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SideBar::isEmpty() const
|
||||||
|
{
|
||||||
|
return m_dockWidgets.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
SideBarLocation SideBar::location() const
|
||||||
|
{
|
||||||
|
return m_location;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowBase *SideBar::mainWindow() const
|
||||||
|
{
|
||||||
|
return m_mainWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SideBar::toggleOverlay(DockWidgetBase *dw)
|
||||||
|
{
|
||||||
|
m_mainWindow->toggleOverlayOnSideBar(dw);
|
||||||
|
}
|
||||||
70
src/private/SideBar_p.h
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KD_SIDEBAR_P_H
|
||||||
|
#define KD_SIDEBAR_P_H
|
||||||
|
|
||||||
|
#include "docks_export.h"
|
||||||
|
#include "KDDockWidgets.h"
|
||||||
|
#include "QWidgetAdapter.h"
|
||||||
|
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
class DockWidgetBase;
|
||||||
|
class MainWindowBase;
|
||||||
|
|
||||||
|
class DOCKS_EXPORT SideBar : public QWidgetAdapter
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit SideBar(SideBarLocation, MainWindowBase *parent = nullptr);
|
||||||
|
|
||||||
|
void addDockWidget(DockWidgetBase *dw);
|
||||||
|
void removeDockWidget(DockWidgetBase *dw);
|
||||||
|
bool contains(DockWidgetBase *) const;
|
||||||
|
|
||||||
|
/// @brief Returns this side bar's orientation
|
||||||
|
Qt::Orientation orientation() const;
|
||||||
|
|
||||||
|
/// @brief returns if this side bar has vertical orientation
|
||||||
|
bool isVertical() const { return m_orientation == Qt::Vertical; }
|
||||||
|
|
||||||
|
/// @brief returns whether there's no dock widgets
|
||||||
|
bool isEmpty() const;
|
||||||
|
|
||||||
|
/// @brief returns the sidebar's location in the main window
|
||||||
|
SideBarLocation location() const;
|
||||||
|
|
||||||
|
/// @brief Returns the main window this side bar belongs to
|
||||||
|
MainWindowBase *mainWindow() const;
|
||||||
|
|
||||||
|
/// @brief Toggles the dock widget overlay. Equivalent to the user clicking on the button.
|
||||||
|
void toggleOverlay(DockWidgetBase *);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
virtual void addDockWidget_Impl(DockWidgetBase *dock) = 0;
|
||||||
|
virtual void removeDockWidget_Impl(DockWidgetBase *dock) = 0;
|
||||||
|
|
||||||
|
void onButtonClicked(DockWidgetBase *dw);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void onDockWidgetDestroyed(QObject *dw);
|
||||||
|
void updateSize();
|
||||||
|
|
||||||
|
MainWindowBase *const m_mainWindow;
|
||||||
|
QVector<DockWidgetBase *> m_dockWidgets;
|
||||||
|
const SideBarLocation m_location;
|
||||||
|
const Qt::Orientation m_orientation;
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -16,7 +16,10 @@
|
|||||||
#include "WindowBeingDragged_p.h"
|
#include "WindowBeingDragged_p.h"
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
|
#include "Config.h"
|
||||||
|
#include "MainWindowBase.h"
|
||||||
|
|
||||||
|
#include <QTimer>
|
||||||
#include <QWindowStateChangeEvent>
|
#include <QWindowStateChangeEvent>
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
@@ -26,14 +29,19 @@ TitleBar::TitleBar(Frame *parent)
|
|||||||
, Draggable(this)
|
, Draggable(this)
|
||||||
, m_frame(parent)
|
, m_frame(parent)
|
||||||
, m_floatingWindow(nullptr)
|
, m_floatingWindow(nullptr)
|
||||||
|
, m_supportsAutoHide(Config::self().flags() & Config::Flag_AutoHideSupport)
|
||||||
{
|
{
|
||||||
connect(m_frame, &Frame::numDockWidgetsChanged, this, &TitleBar::updateCloseButton);
|
connect(m_frame, &Frame::numDockWidgetsChanged, this, &TitleBar::updateCloseButton);
|
||||||
connect(m_frame, &Frame::isFocusedChanged, this, &TitleBar::isFocusedChanged);
|
connect(m_frame, &Frame::isFocusedChanged, this, &TitleBar::isFocusedChanged);
|
||||||
|
connect(m_frame, &Frame::isInMainWindowChanged, this, &TitleBar::updateAutoHideButton);
|
||||||
|
|
||||||
init();
|
init();
|
||||||
|
|
||||||
if (Config::self().flags() & Config::Flag_TitleBarIsFocusable)
|
if (Config::self().flags() & Config::Flag_TitleBarIsFocusable)
|
||||||
setFocusPolicy(Qt::StrongFocus);
|
setFocusPolicy(Qt::StrongFocus);
|
||||||
|
|
||||||
|
QTimer::singleShot(0, this, &TitleBar::updateAutoHideButton); // have to wait after the frame is constructed
|
||||||
|
updateAutoHideButton();
|
||||||
}
|
}
|
||||||
|
|
||||||
TitleBar::TitleBar(FloatingWindow *parent)
|
TitleBar::TitleBar(FloatingWindow *parent)
|
||||||
@@ -41,6 +49,7 @@ TitleBar::TitleBar(FloatingWindow *parent)
|
|||||||
, Draggable(this)
|
, Draggable(this)
|
||||||
, m_frame(nullptr)
|
, m_frame(nullptr)
|
||||||
, m_floatingWindow(parent)
|
, m_floatingWindow(parent)
|
||||||
|
, m_supportsAutoHide(Config::self().flags() & Config::Flag_AutoHideSupport)
|
||||||
{
|
{
|
||||||
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateCloseButton);
|
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateCloseButton);
|
||||||
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateFloatButton);
|
connect(m_floatingWindow, &FloatingWindow::numFramesChanged, this, &TitleBar::updateFloatButton);
|
||||||
@@ -49,6 +58,7 @@ TitleBar::TitleBar(FloatingWindow *parent)
|
|||||||
connect(m_floatingWindow, &FloatingWindow::windowStateChanged, this, &TitleBar::updateMaximizeButton);
|
connect(m_floatingWindow, &FloatingWindow::windowStateChanged, this, &TitleBar::updateMaximizeButton);
|
||||||
connect(m_floatingWindow, &FloatingWindow::activatedChanged , this, &TitleBar::isFocusedChanged);
|
connect(m_floatingWindow, &FloatingWindow::activatedChanged , this, &TitleBar::isFocusedChanged);
|
||||||
init();
|
init();
|
||||||
|
updateAutoHideButton(); // always hidden when we're in a FloatingWindow.
|
||||||
}
|
}
|
||||||
|
|
||||||
void TitleBar::init()
|
void TitleBar::init()
|
||||||
@@ -101,6 +111,11 @@ void TitleBar::focusInEvent(QFocusEvent *ev)
|
|||||||
m_frame->FocusScope::focus(ev->reason());
|
m_frame->FocusScope::focus(ev->reason());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TitleBar::isOverlayed() const
|
||||||
|
{
|
||||||
|
return m_frame && m_frame->isOverlayed();
|
||||||
|
}
|
||||||
|
|
||||||
void TitleBar::setTitle(const QString &title)
|
void TitleBar::setTitle(const QString &title)
|
||||||
{
|
{
|
||||||
if (title != m_title) {
|
if (title != m_title) {
|
||||||
@@ -151,7 +166,7 @@ std::unique_ptr<WindowBeingDragged> TitleBar::makeWindow()
|
|||||||
|
|
||||||
QRect r = m_frame->QWidgetAdapter::geometry();
|
QRect r = m_frame->QWidgetAdapter::geometry();
|
||||||
qCDebug(hovering) << "TitleBar::makeWindow original geometry" << r;
|
qCDebug(hovering) << "TitleBar::makeWindow original geometry" << r;
|
||||||
r.moveTopLeft(m_frame->mapToGlobal(QPoint(0, 0))); // TODO: Remove static_cast if it compiles. Ambiguous base for now
|
r.moveTopLeft(m_frame->mapToGlobal(QPoint(0, 0)));
|
||||||
|
|
||||||
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(m_frame);
|
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(m_frame);
|
||||||
floatingWindow->setSuggestedGeometry(r);
|
floatingWindow->setSuggestedGeometry(r);
|
||||||
@@ -178,6 +193,11 @@ bool TitleBar::supportsFloatingButton() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (Config::self().flags() & Config::Flag_TitleBarNoFloatButton) {
|
||||||
|
// Was explicitly disabled
|
||||||
|
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();
|
||||||
@@ -199,6 +219,12 @@ bool TitleBar::supportsMinimizeButton() const
|
|||||||
return m_floatingWindow != nullptr;
|
return m_floatingWindow != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TitleBar::supportsAutoHideButton() const
|
||||||
|
{
|
||||||
|
// Only dock widgets docked into the MainWindow can minimize
|
||||||
|
return m_supportsAutoHide && m_frame && m_frame->isInMainWindow();
|
||||||
|
}
|
||||||
|
|
||||||
bool TitleBar::hasIcon() const
|
bool TitleBar::hasIcon() const
|
||||||
{
|
{
|
||||||
return !m_icon.isNull();
|
return !m_icon.isNull();
|
||||||
@@ -235,7 +261,6 @@ void TitleBar::onCloseClicked()
|
|||||||
|
|
||||||
bool TitleBar::isFloating() const
|
bool TitleBar::isFloating() const
|
||||||
{
|
{
|
||||||
|
|
||||||
if (m_floatingWindow)
|
if (m_floatingWindow)
|
||||||
return m_floatingWindow->hasSingleDockWidget(); // Debatable! Maybe it's always floating.
|
return m_floatingWindow->hasSingleDockWidget(); // Debatable! Maybe it's always floating.
|
||||||
|
|
||||||
@@ -316,3 +341,23 @@ void TitleBar::onMinimizeClicked()
|
|||||||
|
|
||||||
m_floatingWindow->showMinimized();
|
m_floatingWindow->showMinimized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TitleBar::onAutoHideClicked()
|
||||||
|
{
|
||||||
|
if (!m_frame) {
|
||||||
|
// Doesn't happen
|
||||||
|
qWarning() << Q_FUNC_INFO << "Minimize not supported on floating windows";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &dockwidgets = m_frame->dockWidgets();
|
||||||
|
for (DockWidgetBase *dw : dockwidgets) {
|
||||||
|
if (dw->isOverlayed()) {
|
||||||
|
// restore
|
||||||
|
MainWindowBase *mainWindow = dw->mainWindow();
|
||||||
|
mainWindow->restoreFromSideBar(dw);
|
||||||
|
} else {
|
||||||
|
dw->moveToSideBar();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -27,6 +27,8 @@ class QHBoxLayout;
|
|||||||
class QLabel;
|
class QLabel;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class TestCommon;
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class DockWidgetBase;
|
class DockWidgetBase;
|
||||||
@@ -41,6 +43,7 @@ class DOCKS_EXPORT TitleBar : public QWidgetAdapter
|
|||||||
Q_PROPERTY(bool hasIcon READ hasIcon NOTIFY iconChanged)
|
Q_PROPERTY(bool hasIcon READ hasIcon NOTIFY iconChanged)
|
||||||
public:
|
public:
|
||||||
typedef QVector<TitleBar *> List;
|
typedef QVector<TitleBar *> List;
|
||||||
|
|
||||||
explicit TitleBar(Frame *parent);
|
explicit TitleBar(Frame *parent);
|
||||||
explicit TitleBar(FloatingWindow *parent);
|
explicit TitleBar(FloatingWindow *parent);
|
||||||
~TitleBar() override;
|
~TitleBar() override;
|
||||||
@@ -69,6 +72,9 @@ public:
|
|||||||
///@brief returns whether this title bar supports a minimize button
|
///@brief returns whether this title bar supports a minimize button
|
||||||
bool supportsMinimizeButton() const;
|
bool supportsMinimizeButton() const;
|
||||||
|
|
||||||
|
///@brief returns whether this title bar supports the auto-hide button
|
||||||
|
bool supportsAutoHideButton() const;
|
||||||
|
|
||||||
///@brief returns whether this title bar has an icon
|
///@brief returns whether this title bar has an icon
|
||||||
bool hasIcon() const;
|
bool hasIcon() const;
|
||||||
|
|
||||||
@@ -97,15 +103,19 @@ Q_SIGNALS:
|
|||||||
void isFocusedChanged();
|
void isFocusedChanged();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
Q_INVOKABLE void onCloseClicked();
|
Q_INVOKABLE void onCloseClicked();
|
||||||
Q_INVOKABLE void onFloatClicked();
|
Q_INVOKABLE void onFloatClicked();
|
||||||
Q_INVOKABLE void onMaximizeClicked();
|
Q_INVOKABLE void onMaximizeClicked();
|
||||||
Q_INVOKABLE void onMinimizeClicked();
|
Q_INVOKABLE void onMinimizeClicked();
|
||||||
Q_INVOKABLE void toggleMaximized();
|
Q_INVOKABLE void toggleMaximized();
|
||||||
|
Q_INVOKABLE void onAutoHideClicked();
|
||||||
|
|
||||||
virtual void updateFloatButton() {}
|
virtual void updateFloatButton() {}
|
||||||
virtual void updateMaximizeButton() {}
|
virtual void updateMaximizeButton() {}
|
||||||
|
|
||||||
virtual void updateMinimizeButton() {}
|
virtual void updateMinimizeButton() {}
|
||||||
|
virtual void updateAutoHideButton() {}
|
||||||
|
|
||||||
// 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 { return true; }
|
||||||
@@ -115,8 +125,11 @@ protected:
|
|||||||
|
|
||||||
void focusInEvent(QFocusEvent *event) override;
|
void focusInEvent(QFocusEvent *event) override;
|
||||||
|
|
||||||
|
bool isOverlayed() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class TestDocks;
|
friend class TestDocks;
|
||||||
|
friend class ::TestCommon;
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
@@ -126,6 +139,7 @@ private:
|
|||||||
|
|
||||||
Frame *const m_frame;
|
Frame *const m_frame;
|
||||||
FloatingWindow *const m_floatingWindow;
|
FloatingWindow *const m_floatingWindow;
|
||||||
|
const bool m_supportsAutoHide;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -30,6 +30,11 @@
|
|||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
inline bool isWayland()
|
||||||
|
{
|
||||||
|
return qApp->platformName() == QLatin1String("wayland");
|
||||||
|
}
|
||||||
|
|
||||||
inline bool isLeftButtonPressed()
|
inline bool isLeftButtonPressed()
|
||||||
{
|
{
|
||||||
return qApp->mouseButtons() & Qt::LeftButton;
|
return qApp->mouseButtons() & Qt::LeftButton;
|
||||||
@@ -40,6 +45,17 @@ inline bool usesNativeTitleBar()
|
|||||||
return Config::self().flags() & Config::Flag_NativeTitleBar;
|
return Config::self().flags() & Config::Flag_NativeTitleBar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool usesClientTitleBar()
|
||||||
|
{
|
||||||
|
if (isWayland()) {
|
||||||
|
// Wayland has both client and native title bars, due to limitations.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// All other platforms have either the OS native title bar or a Qt title bar (aka client title bar).
|
||||||
|
return !usesNativeTitleBar();
|
||||||
|
}
|
||||||
|
|
||||||
inline bool usesAeroSnapWithCustomDecos()
|
inline bool usesAeroSnapWithCustomDecos()
|
||||||
{
|
{
|
||||||
return Config::self().flags() & Config::Flag_AeroSnapWithClientDecos;
|
return Config::self().flags() & Config::Flag_AeroSnapWithClientDecos;
|
||||||
|
|||||||
@@ -24,6 +24,7 @@
|
|||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
#include <QAbstractButton>
|
#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>
|
||||||
@@ -253,7 +254,8 @@ bool WidgetResizeHandler::handleWindowsNativeEvent(FloatingWindow *w, const QByt
|
|||||||
const QRect htCaptionRect = w->dragRect(); // The rect on which we allow for Windows to do Ba 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);
|
QWidget *hoveredWidget = qApp->widgetAt(globalPosQt);
|
||||||
if (!qobject_cast<QAbstractButton*>(hoveredWidget)) {
|
if (!qobject_cast<QAbstractButton*>(hoveredWidget) &&
|
||||||
|
!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.
|
// User clicked on the title bar, let's allow it, so we get Aero-Snap.
|
||||||
*result = HTCAPTION;
|
*result = HTCAPTION;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,11 +13,15 @@
|
|||||||
#include "DragController_p.h"
|
#include "DragController_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
|
#include "DropArea_p.h"
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
static Draggable* bestDraggable(Draggable *draggable)
|
static Draggable* bestDraggable(Draggable *draggable)
|
||||||
{
|
{
|
||||||
|
if (!draggable)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
// When de detach a title bar it will get hidden and we only the title bar of the FloatingWindow is visible
|
// When de detach a title bar it will get hidden and we only the title bar of the FloatingWindow is visible
|
||||||
/// Apparently that causes problems with grabbing the mouse, so instead use a visible draggable.
|
/// Apparently that causes problems with grabbing the mouse, so instead use a visible draggable.
|
||||||
// grabbing mouse on an hidden window works usually, it's some edge case on Windows with MFC.
|
// grabbing mouse on an hidden window works usually, it's some edge case on Windows with MFC.
|
||||||
@@ -45,6 +49,7 @@ 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)->asWidget())
|
||||||
|
, m_affinities(fw->affinities())
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
|
|
||||||
@@ -53,6 +58,17 @@ WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw, Draggable *draggable)
|
|||||||
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
if (!qIsNaN(opacity) && !qFuzzyCompare(1.0, opacity))
|
||||||
fw->setWindowOpacity(opacity);
|
fw->setWindowOpacity(opacity);
|
||||||
}
|
}
|
||||||
|
#if DOCKS_DEVELOPER_MODE
|
||||||
|
|
||||||
|
// Just used by tests
|
||||||
|
WindowBeingDragged::WindowBeingDragged(FloatingWindow *fw)
|
||||||
|
: m_floatingWindow(fw)
|
||||||
|
, m_draggable(nullptr)
|
||||||
|
, m_affinities(fw->affinities())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
WindowBeingDragged::~WindowBeingDragged()
|
WindowBeingDragged::~WindowBeingDragged()
|
||||||
{
|
{
|
||||||
@@ -82,3 +98,36 @@ void WindowBeingDragged::grabMouse(bool grab)
|
|||||||
else
|
else
|
||||||
DragController::instance()->releaseMouse(m_draggable);
|
DragController::instance()->releaseMouse(m_draggable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStringList WindowBeingDragged::affinities() const
|
||||||
|
{
|
||||||
|
return m_affinities;
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize WindowBeingDragged::size() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow)
|
||||||
|
return m_floatingWindow->size();
|
||||||
|
|
||||||
|
return QSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize WindowBeingDragged::minSize() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow) {
|
||||||
|
Layouting::ItemContainer *root = m_floatingWindow->dropArea()->rootItem();
|
||||||
|
return root->minSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QSize WindowBeingDragged::maxSize() const
|
||||||
|
{
|
||||||
|
if (m_floatingWindow) {
|
||||||
|
Layouting::ItemContainer *root = m_floatingWindow->dropArea()->rootItem();
|
||||||
|
return root->maxSizeHint();
|
||||||
|
}
|
||||||
|
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,6 +26,11 @@ 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
|
||||||
|
// For tests.
|
||||||
|
explicit WindowBeingDragged(FloatingWindow *fw);
|
||||||
|
#endif
|
||||||
|
|
||||||
~WindowBeingDragged();
|
~WindowBeingDragged();
|
||||||
void init();
|
void init();
|
||||||
|
|
||||||
@@ -34,10 +39,23 @@ public:
|
|||||||
///@brief grabs or releases the mouse
|
///@brief grabs or releases the mouse
|
||||||
void grabMouse(bool grab);
|
void grabMouse(bool grab);
|
||||||
|
|
||||||
|
///@brief returns the affinities of the window being dragged
|
||||||
|
QStringList affinities() const;
|
||||||
|
|
||||||
|
///@brief size of the window being dragged contents
|
||||||
|
QSize size() const;
|
||||||
|
|
||||||
|
/// @brief returns the min-size of the window being dragged contents
|
||||||
|
QSize minSize() const;
|
||||||
|
|
||||||
|
/// @brief returns the max-size of the window being dragged contents
|
||||||
|
QSize maxSize() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Q_DISABLE_COPY(WindowBeingDragged)
|
Q_DISABLE_COPY(WindowBeingDragged)
|
||||||
QPointer<FloatingWindow> m_floatingWindow;
|
QPointer<FloatingWindow> m_floatingWindow;
|
||||||
QPointer<QWidgetOrQuick> m_draggable;
|
QPointer<QWidgetOrQuick> m_draggable;
|
||||||
|
const QStringList m_affinities;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,11 @@ bool ClassicIndicators::outterIndicatorsVisible() const
|
|||||||
return m_outterIndicatorsVisible;
|
return m_outterIndicatorsVisible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool ClassicIndicators::tabIndicatorVisible() const
|
||||||
|
{
|
||||||
|
return m_tabIndicatorVisible;
|
||||||
|
}
|
||||||
|
|
||||||
bool ClassicIndicators::onResize(QSize)
|
bool ClassicIndicators::onResize(QSize)
|
||||||
{
|
{
|
||||||
m_indicatorWindow->resize(window()->size());
|
m_indicatorWindow->resize(window()->size());
|
||||||
@@ -83,15 +88,21 @@ void ClassicIndicators::updateVisibility()
|
|||||||
|
|
||||||
void ClassicIndicators::updateIndicatorsVisibility(bool visible)
|
void ClassicIndicators::updateIndicatorsVisibility(bool visible)
|
||||||
{
|
{
|
||||||
Frame *hoveredFrame = m_hoveredFrame;
|
const bool isTheOnlyFrame = m_hoveredFrame && m_hoveredFrame->isTheOnlyFrame();
|
||||||
const bool isTheOnlyFrame = hoveredFrame && hoveredFrame->isTheOnlyFrame();
|
|
||||||
|
|
||||||
m_innerIndicatorsVisible = visible && hoveredFrame;
|
m_innerIndicatorsVisible = visible && m_hoveredFrame;
|
||||||
|
|
||||||
|
WindowBeingDragged *windowBeingDragged = DragController::instance()->windowBeingDragged();
|
||||||
|
|
||||||
// If there's only 1 frame in the layout, the outter indicators are redundant, as they do the same thing as the internal ones.
|
// If there's only 1 frame in the layout, the outter indicators are redundant, as they do the same thing as the internal ones.
|
||||||
// But there might be another window obscuring our target, so it's useful to show the outter indicators in this case
|
// But there might be another window obscuring our target, so it's useful to show the outter indicators in this case
|
||||||
m_outterIndicatorsVisible = visible && (!isTheOnlyFrame ||
|
m_outterIndicatorsVisible = visible && (!isTheOnlyFrame ||
|
||||||
DockRegistry::self()->isProbablyObscured(hoveredFrame->window()->windowHandle(), DragController::instance()->windowBeingDragged()));
|
DockRegistry::self()->isProbablyObscured(m_hoveredFrame->window()->windowHandle(), windowBeingDragged));
|
||||||
|
|
||||||
|
|
||||||
|
// Only allow to dock to center if the affinities match
|
||||||
|
m_tabIndicatorVisible = m_innerIndicatorsVisible && windowBeingDragged &&
|
||||||
|
DockRegistry::self()->affinitiesMatch(m_hoveredFrame->affinities(), windowBeingDragged->affinities());
|
||||||
|
|
||||||
Q_EMIT innerIndicatorsVisibleChanged();
|
Q_EMIT innerIndicatorsVisibleChanged();
|
||||||
Q_EMIT outterIndicatorsVisibleChanged();
|
Q_EMIT outterIndicatorsVisibleChanged();
|
||||||
@@ -152,7 +163,7 @@ void ClassicIndicators::setDropLocation(ClassicIndicators::DropLocation location
|
|||||||
case DropLocation_Bottom:
|
case DropLocation_Bottom:
|
||||||
if (!m_hoveredFrame) {
|
if (!m_hoveredFrame) {
|
||||||
qWarning() << "ClassicIndicators::setCurrentDropLocation: frame is null. location=" << location
|
qWarning() << "ClassicIndicators::setCurrentDropLocation: frame is null. location=" << location
|
||||||
<< "; windowBeingDragged=" << m_windowBeingDragged
|
<< "; isHovered=" << isHovered()
|
||||||
<< "; dropArea->widgets=" << m_dropArea->items();
|
<< "; dropArea->widgets=" << m_dropArea->items();
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
return;
|
return;
|
||||||
@@ -168,7 +179,9 @@ void ClassicIndicators::setDropLocation(ClassicIndicators::DropLocation location
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect rect = m_dropArea->rectForDrop(m_windowBeingDragged, multisplitterLocation,
|
auto windowBeingDragged = DragController::instance()->windowBeingDragged();
|
||||||
|
|
||||||
|
QRect rect = m_dropArea->rectForDrop(windowBeingDragged, multisplitterLocation,
|
||||||
m_dropArea->itemForFrame(relativeToFrame));
|
m_dropArea->itemForFrame(relativeToFrame));
|
||||||
|
|
||||||
m_rubberBand->setGeometry(rect);
|
m_rubberBand->setGeometry(rect);
|
||||||
|
|||||||
@@ -176,12 +176,14 @@ void IndicatorWindow::resizeEvent(QResizeEvent *ev)
|
|||||||
|
|
||||||
void IndicatorWindow::updateIndicatorVisibility()
|
void IndicatorWindow::updateIndicatorVisibility()
|
||||||
{
|
{
|
||||||
for (Indicator *indicator : { m_center, m_left, m_right, m_bottom, m_top })
|
for (Indicator *indicator : { m_left, m_right, m_bottom, m_top })
|
||||||
indicator->setVisible(classicIndicators->innerIndicatorsVisible());
|
indicator->setVisible(classicIndicators->innerIndicatorsVisible());
|
||||||
|
|
||||||
for (Indicator *indicator : { m_outterTop, m_outterLeft, m_outterRight, m_outterBottom })
|
for (Indicator *indicator : { m_outterTop, m_outterLeft, m_outterRight, m_outterBottom })
|
||||||
indicator->setVisible(classicIndicators->outterIndicatorsVisible());
|
indicator->setVisible(classicIndicators->outterIndicatorsVisible());
|
||||||
|
|
||||||
|
m_center->setVisible(classicIndicators->tabIndicatorVisible());
|
||||||
|
|
||||||
updateMask();
|
updateMask();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,8 +241,9 @@ IndicatorWindow::IndicatorWindow(KDDockWidgets::ClassicIndicators *classicIndica
|
|||||||
: QQuickView()
|
: QQuickView()
|
||||||
, m_classicIndicators(classicIndicators)
|
, m_classicIndicators(classicIndicators)
|
||||||
{
|
{
|
||||||
|
setFlags(flags() | Qt::FramelessWindowHint | Qt::BypassWindowManagerHint | Qt::Tool);
|
||||||
setColor(Qt::transparent);
|
setColor(Qt::transparent);
|
||||||
setFlags(flags() | Qt::FramelessWindowHint);
|
|
||||||
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")));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,9 @@ public:
|
|||||||
bool innerIndicatorsVisible() const;
|
bool innerIndicatorsVisible() const;
|
||||||
bool outterIndicatorsVisible() const;
|
bool outterIndicatorsVisible() const;
|
||||||
|
|
||||||
|
// The tab/center indicator
|
||||||
|
bool tabIndicatorVisible() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool onResize(QSize newSize) override;
|
bool onResize(QSize newSize) override;
|
||||||
void updateVisibility() override;
|
void updateVisibility() override;
|
||||||
@@ -53,6 +56,7 @@ private:
|
|||||||
IndicatorWindow *const m_indicatorWindow;
|
IndicatorWindow *const m_indicatorWindow;
|
||||||
bool m_innerIndicatorsVisible = false;
|
bool m_innerIndicatorsVisible = false;
|
||||||
bool m_outterIndicatorsVisible = false;
|
bool m_outterIndicatorsVisible = false;
|
||||||
|
bool m_tabIndicatorVisible = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ set(MULTISPLITTER_SRCS_QTQUICK
|
|||||||
)
|
)
|
||||||
|
|
||||||
option(BUILD_MULTISPLITTER_QTWIDGETS_FRONTEND "Build support for QtWidgets" ON)
|
option(BUILD_MULTISPLITTER_QTWIDGETS_FRONTEND "Build support for QtWidgets" ON)
|
||||||
if (OPTION_QTQUICK)
|
if (${PROJECT_NAME}_QTQUICK)
|
||||||
# We're building the layouting engine as part of KDDW. If KDDW has set to build with QtQuick
|
# We're building the layouting engine as part of KDDW. If KDDW has set to build with QtQuick
|
||||||
# then so does the layouting engine
|
# then so does the layouting engine
|
||||||
SET(BUILD_MULTISPLITTER_QTQUICK_FRONTEND ON)
|
SET(BUILD_MULTISPLITTER_QTQUICK_FRONTEND ON)
|
||||||
@@ -79,7 +79,7 @@ else()
|
|||||||
target_compile_definitions(kddockwidgets_multisplitter PRIVATE BUILDING_MULTISPLITTER_LIBRARY)
|
target_compile_definitions(kddockwidgets_multisplitter PRIVATE BUILDING_MULTISPLITTER_LIBRARY)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(OPTION_DEVELOPER_MODE)
|
if(${PROJECT_NAME}_DEVELOPER_MODE)
|
||||||
# Under developer mode since kddw might be a sub-folder of a project setting a different value for QT_DISABLE_DEPRECATED_BEFORE
|
# Under developer mode since kddw might be a sub-folder of a project setting a different value for QT_DISABLE_DEPRECATED_BEFORE
|
||||||
target_compile_definitions(kddockwidgets_multisplitter PRIVATE QT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
target_compile_definitions(kddockwidgets_multisplitter PRIVATE QT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
||||||
|
|
||||||
|
|||||||
@@ -279,7 +279,12 @@ QObject *Item::host() const
|
|||||||
|
|
||||||
void Item::restore(Widget *guest)
|
void Item::restore(Widget *guest)
|
||||||
{
|
{
|
||||||
Q_ASSERT(!isVisible() && !guestAsQObject());
|
if (isVisible() || guestAsQObject()) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Hitting assert. visible="
|
||||||
|
<< isVisible() << "; guest=" << guestAsQObject();
|
||||||
|
Q_ASSERT(false);
|
||||||
|
}
|
||||||
|
|
||||||
if (isContainer()) {
|
if (isContainer()) {
|
||||||
qWarning() << Q_FUNC_INFO << "Containers can't be restored";
|
qWarning() << Q_FUNC_INFO << "Containers can't be restored";
|
||||||
} else {
|
} else {
|
||||||
@@ -634,9 +639,14 @@ bool Item::checkSanity()
|
|||||||
|
|
||||||
if (m_guest) {
|
if (m_guest) {
|
||||||
if (m_guest->parent() != hostWidget()->asQObject()) {
|
if (m_guest->parent() != hostWidget()->asQObject()) {
|
||||||
qWarning() << Q_FUNC_INFO << "Unexpected parent for our guest"
|
if (root())
|
||||||
<< m_guest->parent() << "; host=" << hostWidget()
|
root()->dumpLayout();
|
||||||
<< m_guest->asQObject() << this;
|
qWarning() << Q_FUNC_INFO << "Unexpected parent for our guest. guest.parent="
|
||||||
|
<< m_guest->parent() << "; host=" << hostWidget()->asQObject()
|
||||||
|
<< "; guest.asObj=" << m_guest->asQObject()
|
||||||
|
<< "; this=" << this
|
||||||
|
<< "; item.parentContainer=" << parentContainer()
|
||||||
|
<< "; item.root.parent=" << (root() ? root()->parent() : nullptr);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -660,13 +670,6 @@ bool Item::checkSanity()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
if (!isVisible()) {
|
|
||||||
if (m_guest && m_guest->isVisible()) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Item is not visible but guest is visible";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -843,6 +846,75 @@ bool Item::isRoot() const
|
|||||||
return m_parent == nullptr;
|
return m_parent == nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Item::LayoutBorderLocations Item::adjacentLayoutBorders() const
|
||||||
|
{
|
||||||
|
if (isRoot()) {
|
||||||
|
return Item::LayoutBorderLocation_All;
|
||||||
|
}
|
||||||
|
|
||||||
|
ItemContainer *c = parentContainer();
|
||||||
|
if (!c)
|
||||||
|
return Item::LayoutBorderLocation_None;
|
||||||
|
|
||||||
|
const int indexInParent = c->indexOfVisibleChild(this);
|
||||||
|
const int numVisibleChildren = c->numVisibleChildren();
|
||||||
|
const bool isFirst = indexInParent == 0;
|
||||||
|
const bool isLast = indexInParent == numVisibleChildren - 1;
|
||||||
|
if (indexInParent == -1)
|
||||||
|
return Item::LayoutBorderLocation_None;
|
||||||
|
|
||||||
|
Item::LayoutBorderLocations locations = Item::LayoutBorderLocation_None;
|
||||||
|
if (c->isRoot()) {
|
||||||
|
if (c->isVertical()) {
|
||||||
|
locations |= Item::LayoutBorderLocation_West;
|
||||||
|
locations |= Item::LayoutBorderLocation_East;
|
||||||
|
|
||||||
|
if (isFirst)
|
||||||
|
locations |= Item::LayoutBorderLocation_North;
|
||||||
|
if (isLast)
|
||||||
|
locations |= Item::LayoutBorderLocation_South;
|
||||||
|
} else {
|
||||||
|
locations |= Item::LayoutBorderLocation_North;
|
||||||
|
locations |= Item::LayoutBorderLocation_South;
|
||||||
|
|
||||||
|
if (isFirst)
|
||||||
|
locations |= Item::LayoutBorderLocation_West;
|
||||||
|
if (isLast)
|
||||||
|
locations |= Item::LayoutBorderLocation_East;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const Item::LayoutBorderLocations parentBorders = c->adjacentLayoutBorders();
|
||||||
|
if (c->isVertical()) {
|
||||||
|
if (parentBorders & Item::LayoutBorderLocation_West)
|
||||||
|
locations |= Item::LayoutBorderLocation_West;
|
||||||
|
|
||||||
|
if (parentBorders & Item::LayoutBorderLocation_East)
|
||||||
|
locations |= Item::LayoutBorderLocation_East;
|
||||||
|
|
||||||
|
if (isFirst && (parentBorders & Item::LayoutBorderLocation_North))
|
||||||
|
locations |= Item::LayoutBorderLocation_North;
|
||||||
|
|
||||||
|
if (isLast && (parentBorders & Item::LayoutBorderLocation_South))
|
||||||
|
locations |= Item::LayoutBorderLocation_South;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (parentBorders & Item::LayoutBorderLocation_North)
|
||||||
|
locations |= Item::LayoutBorderLocation_North;
|
||||||
|
|
||||||
|
if (parentBorders & Item::LayoutBorderLocation_South)
|
||||||
|
locations |= Item::LayoutBorderLocation_South;
|
||||||
|
|
||||||
|
if (isFirst && (parentBorders & Item::LayoutBorderLocation_West))
|
||||||
|
locations |= Item::LayoutBorderLocation_West;
|
||||||
|
|
||||||
|
if (isLast && (parentBorders & Item::LayoutBorderLocation_East))
|
||||||
|
locations |= Item::LayoutBorderLocation_East;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return locations;
|
||||||
|
}
|
||||||
|
|
||||||
int Item::visibleCount_recursive() const
|
int Item::visibleCount_recursive() const
|
||||||
{
|
{
|
||||||
return isVisible() ? 1 : 0;
|
return isVisible() ? 1 : 0;
|
||||||
@@ -856,6 +928,12 @@ struct ItemContainer::Private
|
|||||||
(void) Config::self(); // Ensure Config ctor runs, as it registers qml types
|
(void) Config::self(); // Ensure Config ctor runs, as it registers qml types
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~Private()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_separators);
|
||||||
|
m_separators.clear();
|
||||||
|
}
|
||||||
|
|
||||||
int defaultLengthFor(Item *item, DefaultSizeMode) const;
|
int defaultLengthFor(Item *item, DefaultSizeMode) const;
|
||||||
bool isOverflowing() const;
|
bool isOverflowing() const;
|
||||||
void relayoutIfNeeded();
|
void relayoutIfNeeded();
|
||||||
@@ -3133,8 +3211,8 @@ void ItemContainer::simplify()
|
|||||||
childContainer->simplify(); // recurse down the hierarchy
|
childContainer->simplify(); // recurse down the hierarchy
|
||||||
|
|
||||||
if (childContainer->orientation() == d->m_orientation || childContainer->d->m_children.size() == 1) {
|
if (childContainer->orientation() == d->m_orientation || childContainer->d->m_children.size() == 1) {
|
||||||
// This sub-container is reduntant, as it has the same orientation as its parent
|
// This sub-container is redundant, as it has the same orientation as its parent
|
||||||
// Canibalize it.
|
// Cannibalize it.
|
||||||
for (Item *child2 : childContainer->childItems()) {
|
for (Item *child2 : childContainer->childItems()) {
|
||||||
child2->setParentContainer(this);
|
child2->setParentContainer(this);
|
||||||
newChildren.push_back(child2);
|
newChildren.push_back(child2);
|
||||||
@@ -3270,7 +3348,7 @@ void ItemContainer::fillFromVariantMap(const QVariantMap &map,
|
|||||||
|
|
||||||
for (const QVariant &childV : childrenV) {
|
for (const QVariant &childV : childrenV) {
|
||||||
const QVariantMap childMap = childV.toMap();
|
const QVariantMap childMap = childV.toMap();
|
||||||
const bool isContainer = childMap[QStringLiteral("isContainer")].toBool();
|
const bool isContainer = childMap.value(QStringLiteral("isContainer")).toBool();
|
||||||
Item *child = isContainer ? new ItemContainer(hostWidget(), this)
|
Item *child = isContainer ? new ItemContainer(hostWidget(), this)
|
||||||
: new Item(hostWidget(), this);
|
: new Item(hostWidget(), this);
|
||||||
child->fillFromVariantMap(childMap, widgets);
|
child->fillFromVariantMap(childMap, widgets);
|
||||||
|
|||||||
@@ -229,6 +229,19 @@ public:
|
|||||||
};
|
};
|
||||||
Q_ENUM(Location)
|
Q_ENUM(Location)
|
||||||
|
|
||||||
|
enum LayoutBorderLocation {
|
||||||
|
LayoutBorderLocation_None = 0,
|
||||||
|
LayoutBorderLocation_North = 1,
|
||||||
|
LayoutBorderLocation_East = 2,
|
||||||
|
LayoutBorderLocation_West = 4,
|
||||||
|
LayoutBorderLocation_South = 8,
|
||||||
|
LayoutBorderLocation_All = LayoutBorderLocation_North | LayoutBorderLocation_East |
|
||||||
|
LayoutBorderLocation_West | LayoutBorderLocation_South,
|
||||||
|
LayoutBorderLocation_Verticals = LayoutBorderLocation_West | LayoutBorderLocation_East,
|
||||||
|
LayoutBorderLocation_Horizontals = LayoutBorderLocation_North | LayoutBorderLocation_South,
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(LayoutBorderLocations, LayoutBorderLocation)
|
||||||
|
|
||||||
enum AddingOption {
|
enum AddingOption {
|
||||||
AddingOption_None = 0, ///> No option set
|
AddingOption_None = 0, ///> No option set
|
||||||
AddingOption_StartHidden ///< Don't show the dock widget when adding it
|
AddingOption_StartHidden ///< Don't show the dock widget when adding it
|
||||||
@@ -249,6 +262,10 @@ public:
|
|||||||
|
|
||||||
bool isRoot() const;
|
bool isRoot() const;
|
||||||
|
|
||||||
|
///@brief Returns whether the item is touching the layout's borders.
|
||||||
|
///Returns Location_None if it's not touching a border.
|
||||||
|
LayoutBorderLocations adjacentLayoutBorders() const;
|
||||||
|
|
||||||
virtual int visibleCount_recursive() const;
|
virtual int visibleCount_recursive() const;
|
||||||
virtual void insertItem(Item *item, Location,
|
virtual void insertItem(Item *item, Location,
|
||||||
DefaultSizeMode defaultSizeMode = DefaultSizeMode::Fair,
|
DefaultSizeMode defaultSizeMode = DefaultSizeMode::Fair,
|
||||||
@@ -400,11 +417,16 @@ public:
|
|||||||
QVariantMap toVariantMap() const override;
|
QVariantMap toVariantMap() const override;
|
||||||
void fillFromVariantMap(const QVariantMap &map, const QHash<QString, Widget *> &widgets) override;
|
void fillFromVariantMap(const QVariantMap &map, const QHash<QString, Widget *> &widgets) override;
|
||||||
void clear();
|
void clear();
|
||||||
private:
|
Qt::Orientation orientation() const;
|
||||||
bool isEmpty() const;
|
bool isVertical() const;
|
||||||
bool hasOrientation() const;
|
bool isHorizontal() const;
|
||||||
int numChildren() const;
|
int numChildren() const;
|
||||||
int numVisibleChildren() const;
|
int numVisibleChildren() const;
|
||||||
|
bool isEmpty() const;
|
||||||
|
int length() const;
|
||||||
|
QRect rect() const;
|
||||||
|
private:
|
||||||
|
bool hasOrientation() const;
|
||||||
bool hasChildren() const;
|
bool hasChildren() const;
|
||||||
bool hasVisibleChildren(bool excludeBeingInserted = false) const;
|
bool hasVisibleChildren(bool excludeBeingInserted = false) const;
|
||||||
int indexOfVisibleChild(const Item *) const;
|
int indexOfVisibleChild(const Item *) const;
|
||||||
@@ -420,8 +442,6 @@ private:
|
|||||||
bool hasSingleVisibleItem() const;
|
bool hasSingleVisibleItem() const;
|
||||||
void setChildren(const Item::List &children, Qt::Orientation o);
|
void setChildren(const Item::List &children, Qt::Orientation o);
|
||||||
void setOrientation(Qt::Orientation);
|
void setOrientation(Qt::Orientation);
|
||||||
int length() const;
|
|
||||||
QRect rect() const;
|
|
||||||
void updateChildPercentages();
|
void updateChildPercentages();
|
||||||
void updateChildPercentages_recursive();
|
void updateChildPercentages_recursive();
|
||||||
void updateWidgetGeometries() override;
|
void updateWidgetGeometries() override;
|
||||||
@@ -485,9 +505,6 @@ private:
|
|||||||
void setLength_recursive(int length, Qt::Orientation) override;
|
void setLength_recursive(int length, Qt::Orientation) override;
|
||||||
void applyGeometries(const SizingInfo::List &sizes, ChildrenResizeStrategy = ChildrenResizeStrategy::Percentage);
|
void applyGeometries(const SizingInfo::List &sizes, ChildrenResizeStrategy = ChildrenResizeStrategy::Percentage);
|
||||||
void applyPositions(const SizingInfo::List &sizes);
|
void applyPositions(const SizingInfo::List &sizes);
|
||||||
Qt::Orientation orientation() const;
|
|
||||||
bool isVertical() const;
|
|
||||||
bool isHorizontal() const;
|
|
||||||
|
|
||||||
int indexOf(Separator *) const;
|
int indexOf(Separator *) const;
|
||||||
bool isInSimplify() const;
|
bool isInSimplify() const;
|
||||||
|
|||||||
@@ -25,6 +25,9 @@ using namespace Layouting;
|
|||||||
|
|
||||||
Separator* Separator::s_separatorBeingDragged = nullptr;
|
Separator* Separator::s_separatorBeingDragged = nullptr;
|
||||||
|
|
||||||
|
/// @brief internal counter just for unit-tests
|
||||||
|
static int s_numSeparators = 0;
|
||||||
|
|
||||||
struct Separator::Private
|
struct Separator::Private
|
||||||
{
|
{
|
||||||
// Only set when anchor is moved through mouse. Side1 if going towards left or top, Side2 otherwise.
|
// Only set when anchor is moved through mouse. Side1 if going towards left or top, Side2 otherwise.
|
||||||
@@ -46,10 +49,12 @@ struct Separator::Private
|
|||||||
Separator::Separator(Widget *hostWidget)
|
Separator::Separator(Widget *hostWidget)
|
||||||
: d(new Private(hostWidget))
|
: d(new Private(hostWidget))
|
||||||
{
|
{
|
||||||
|
s_numSeparators++;
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator::~Separator()
|
Separator::~Separator()
|
||||||
{
|
{
|
||||||
|
s_numSeparators--;
|
||||||
delete d;
|
delete d;
|
||||||
if (isBeingDragged())
|
if (isBeingDragged())
|
||||||
s_separatorBeingDragged = nullptr;
|
s_separatorBeingDragged = nullptr;
|
||||||
@@ -136,7 +141,7 @@ void Separator::onMouseMove(QPoint pos)
|
|||||||
|
|
||||||
d->lastMoveDirection = positionToGoTo < position() ? Side1
|
d->lastMoveDirection = positionToGoTo < position() ? Side1
|
||||||
: (positionToGoTo > position() ? Side2
|
: (positionToGoTo > position() ? Side2
|
||||||
: Side2); // Last case shouldn't happen though.
|
: Side1); // Last case shouldn't happen though.
|
||||||
|
|
||||||
if (d->lazyResizeRubberBand)
|
if (d->lazyResizeRubberBand)
|
||||||
setLazyPosition(positionToGoTo);
|
setLazyPosition(positionToGoTo);
|
||||||
@@ -216,6 +221,11 @@ bool Separator::isResizing()
|
|||||||
return s_separatorBeingDragged != nullptr;
|
return s_separatorBeingDragged != nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int Separator::numSeparators()
|
||||||
|
{
|
||||||
|
return s_numSeparators;
|
||||||
|
}
|
||||||
|
|
||||||
void Separator::setLazyPosition(int pos)
|
void Separator::setLazyPosition(int pos)
|
||||||
{
|
{
|
||||||
if (d->lazyPosition != pos) {
|
if (d->lazyPosition != pos) {
|
||||||
|
|||||||
@@ -47,6 +47,10 @@ public:
|
|||||||
static bool isResizing();
|
static bool isResizing();
|
||||||
virtual Widget* asWidget() = 0;
|
virtual Widget* asWidget() = 0;
|
||||||
|
|
||||||
|
/// @internal Just for the unit-tests.
|
||||||
|
/// Returns the total amount of Separator() instances currently alive.
|
||||||
|
static int numSeparators();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
explicit Separator(Widget *hostWidget);
|
explicit Separator(Widget *hostWidget);
|
||||||
virtual Widget* createRubberBand(Widget *parent) { Q_UNUSED(parent); return nullptr; }
|
virtual Widget* createRubberBand(Widget *parent) { Q_UNUSED(parent); return nullptr; }
|
||||||
|
|||||||
@@ -51,7 +51,10 @@ public:
|
|||||||
virtual void setLayoutItem(Item *) = 0;
|
virtual void setLayoutItem(Item *) = 0;
|
||||||
|
|
||||||
// Not strickly necessary, but it's nice conveniance for kddw which is widget based.
|
// Not strickly necessary, but it's nice conveniance for kddw which is widget based.
|
||||||
virtual QWidget *asQWidget() const { return nullptr; }
|
virtual QWidget *asQWidget() const {
|
||||||
|
Q_ASSERT(false); // Only wanted for QtWidgets. All other should not call this.
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
virtual QSize sizeHint() const { return {}; }
|
virtual QSize sizeHint() const { return {}; }
|
||||||
virtual QSize minSize() const = 0;
|
virtual QSize minSize() const = 0;
|
||||||
|
|||||||
@@ -45,8 +45,8 @@ void Widget_quick::setParent(Widget *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (auto qquickitem = qobject_cast<QQuickItem*>(parent->asQObject())) {
|
if (auto qquickitem = qobject_cast<QQuickItem*>(parent->asQObject())) {
|
||||||
m_thisWidget->setParentItem(qquickitem);
|
|
||||||
m_thisWidget->setParent(qquickitem);
|
m_thisWidget->setParent(qquickitem);
|
||||||
|
m_thisWidget->setParentItem(qquickitem);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << Q_FUNC_INFO << "parent is not a widget, you have a bug" << parent->asQObject();
|
qWarning() << Q_FUNC_INFO << "parent is not a widget, you have a bug" << parent->asQObject();
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
|
|||||||
@@ -193,6 +193,7 @@ private Q_SLOTS:
|
|||||||
void tst_requestEqualSize();
|
void tst_requestEqualSize();
|
||||||
void tst_maxSizeHonouredWhenAnotherRemoved();
|
void tst_maxSizeHonouredWhenAnotherRemoved();
|
||||||
void tst_simplify();
|
void tst_simplify();
|
||||||
|
void tst_adjacentLayoutBorders();
|
||||||
};
|
};
|
||||||
|
|
||||||
class MyHostWidget : public QWidget
|
class MyHostWidget : public QWidget
|
||||||
@@ -206,9 +207,7 @@ class MyHostWidget : public QWidget
|
|||||||
s_testObject->m_hostWidgets << this;
|
s_testObject->m_hostWidgets << this;
|
||||||
}
|
}
|
||||||
|
|
||||||
~MyHostWidget() {
|
~MyHostWidget() override;
|
||||||
s_testObject->m_hostWidgets.removeOne(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *) override
|
void paintEvent(QPaintEvent *) override
|
||||||
{
|
{
|
||||||
@@ -217,6 +216,10 @@ class MyHostWidget : public QWidget
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
MyHostWidget::~MyHostWidget() {
|
||||||
|
s_testObject->m_hostWidgets.removeOne(this);
|
||||||
|
}
|
||||||
|
|
||||||
static bool serializeDeserializeTest(const std::unique_ptr<ItemContainer> &root)
|
static bool serializeDeserializeTest(const std::unique_ptr<ItemContainer> &root)
|
||||||
{
|
{
|
||||||
// Serializes and deserializes a layout
|
// Serializes and deserializes a layout
|
||||||
@@ -1835,8 +1838,51 @@ void TestMultiSplitter::tst_simplify()
|
|||||||
|
|
||||||
root->simplify();
|
root->simplify();
|
||||||
|
|
||||||
for (Item *item : root->childItems())
|
for (Item *item : root->childItems()) {
|
||||||
QVERIFY(!item->isContainer());
|
QVERIFY(!item->isContainer());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void TestMultiSplitter::tst_adjacentLayoutBorders()
|
||||||
|
{
|
||||||
|
auto root = createRoot();
|
||||||
|
auto item1 = createItem();
|
||||||
|
auto item2 = createItem();
|
||||||
|
auto item3 = createItem();
|
||||||
|
auto item4 = createItem();
|
||||||
|
auto item5 = createItem();
|
||||||
|
|
||||||
|
root->insertItem(item1, Item::Location_OnTop);
|
||||||
|
const int allBorders = int(Item::LayoutBorderLocation_All);
|
||||||
|
|
||||||
|
auto borders1 = item1->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders1, allBorders);
|
||||||
|
root->insertItem(item2, Item::Location_OnBottom);
|
||||||
|
|
||||||
|
borders1 = item1->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders1, allBorders & ~Item::LayoutBorderLocation_South);
|
||||||
|
|
||||||
|
auto borders2 = item2->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders2, allBorders & ~Item::LayoutBorderLocation_North);
|
||||||
|
|
||||||
|
root->insertItem(item3, Item::Location_OnRight);
|
||||||
|
|
||||||
|
borders1 = item1->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders1, Item::LayoutBorderLocation_North | Item::LayoutBorderLocation_West);
|
||||||
|
|
||||||
|
borders2 = item2->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders2, Item::LayoutBorderLocation_South | Item::LayoutBorderLocation_West);
|
||||||
|
|
||||||
|
auto borders3 = item3->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders3, allBorders & ~(Item::LayoutBorderLocation_West));
|
||||||
|
|
||||||
|
item3->insertItem(item4, Item::Location_OnBottom);
|
||||||
|
auto borders4 = item4->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders4, Item::LayoutBorderLocation_East | Item::LayoutBorderLocation_South);
|
||||||
|
|
||||||
|
root->insertItem(item5, Item::Location_OnRight);
|
||||||
|
borders4 = item4->adjacentLayoutBorders();
|
||||||
|
QCOMPARE(borders4, Item::LayoutBorderLocation_South);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
|||||||
@@ -44,6 +44,8 @@ DockWidgetQuick::DockWidgetQuick(const QString &name, Options options)
|
|||||||
: DockWidgetBase(name, options)
|
: DockWidgetBase(name, options)
|
||||||
, d(new Private(this))
|
, d(new Private(this))
|
||||||
{
|
{
|
||||||
|
// To mimic what QtWidgets does when creating a new QWidget.
|
||||||
|
setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
DockWidgetQuick::~DockWidgetQuick()
|
DockWidgetQuick::~DockWidgetQuick()
|
||||||
@@ -60,9 +62,15 @@ void DockWidgetQuick::setWidget(const QString &qmlFilename)
|
|||||||
auto adapter = new QWidgetAdapter(this);
|
auto adapter = new QWidgetAdapter(this);
|
||||||
guest->setParentItem(adapter);
|
guest->setParentItem(adapter);
|
||||||
guest->setParent(adapter);
|
guest->setParent(adapter);
|
||||||
QWidgetAdapter::makeItemFillParent(adapter);
|
|
||||||
|
|
||||||
DockWidgetBase::setWidget(adapter);
|
setWidget(adapter);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockWidgetQuick::setWidget(QWidgetOrQuick *widget)
|
||||||
|
{
|
||||||
|
widget->QWidgetAdapter::setParent(this);
|
||||||
|
QWidgetAdapter::makeItemFillParent(widget);
|
||||||
|
DockWidgetBase::setWidget(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockWidgetQuick::event(QEvent *e)
|
bool DockWidgetQuick::event(QEvent *e)
|
||||||
@@ -74,7 +82,7 @@ bool DockWidgetQuick::event(QEvent *e)
|
|||||||
} else if (e->type() == QEvent::Hide) {
|
} else if (e->type() == QEvent::Hide) {
|
||||||
onHidden(e->spontaneous());
|
onHidden(e->spontaneous());
|
||||||
} else if (e->type() == QEvent::Close) {
|
} else if (e->type() == QEvent::Close) {
|
||||||
onClosed(static_cast<QCloseEvent*>(e));
|
onCloseEvent(static_cast<QCloseEvent*>(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
return DockWidgetBase::event(e);
|
return DockWidgetBase::event(e);
|
||||||
|
|||||||
@@ -54,6 +54,9 @@ public:
|
|||||||
/// Similar to DockWidgetBase::setWidget(QQuickItem*)
|
/// Similar to DockWidgetBase::setWidget(QQuickItem*)
|
||||||
void setWidget(const QString &qmlFilename);
|
void setWidget(const QString &qmlFilename);
|
||||||
|
|
||||||
|
/// @reimp
|
||||||
|
void setWidget(QWidgetOrQuick *widget) override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool event(QEvent *e) override;
|
bool event(QEvent *e) override;
|
||||||
|
|
||||||
|
|||||||
@@ -58,7 +58,14 @@ FloatingWindowQuick::FloatingWindowQuick(Frame *frame, MainWindowBase *parent)
|
|||||||
|
|
||||||
FloatingWindowQuick::~FloatingWindowQuick()
|
FloatingWindowQuick::~FloatingWindowQuick()
|
||||||
{
|
{
|
||||||
m_quickWindow->deleteLater();
|
QWidgetAdapter::setParent(nullptr);
|
||||||
|
delete m_quickWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FloatingWindowQuick::setGeometry(QRect geo)
|
||||||
|
{
|
||||||
|
parentItem()->setSize(geo.size());
|
||||||
|
m_quickWindow->setGeometry(geo);
|
||||||
}
|
}
|
||||||
|
|
||||||
QWindow *FloatingWindowQuick::candidateParentWindow() const
|
QWindow *FloatingWindowQuick::candidateParentWindow() const
|
||||||
@@ -78,13 +85,17 @@ void FloatingWindowQuick::init()
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
m_quickWindow->setResizeMode(QQuickView::SizeViewToRootObject);
|
const QSize minSize(100, 100);
|
||||||
|
m_quickWindow->resize(minSize);
|
||||||
|
m_quickWindow->contentItem()->setSize(minSize);
|
||||||
|
|
||||||
|
|
||||||
m_quickWindow->setTransientParent(candidateParentWindow());
|
m_quickWindow->setTransientParent(candidateParentWindow());
|
||||||
|
|
||||||
QWidgetAdapter::setParent(m_quickWindow->contentItem());
|
QWidgetAdapter::setParent(m_quickWindow->contentItem());
|
||||||
QWidgetAdapter::makeItemFillParent(this);
|
QWidgetAdapter::makeItemFillParent(this);
|
||||||
|
|
||||||
|
m_quickWindow->setResizeMode(QQuickView::SizeViewToRootObject);
|
||||||
|
|
||||||
QQuickItem *visualItem = createItem(Config::self().qmlEngine(), QStringLiteral("qrc:/kddockwidgets/private/quick/qml/FloatingWindow.qml"));
|
QQuickItem *visualItem = createItem(Config::self().qmlEngine(), QStringLiteral("qrc:/kddockwidgets/private/quick/qml/FloatingWindow.qml"));
|
||||||
Q_ASSERT(visualItem);
|
Q_ASSERT(visualItem);
|
||||||
visualItem->setParent(this);
|
visualItem->setParent(this);
|
||||||
@@ -92,5 +103,4 @@ void FloatingWindowQuick::init()
|
|||||||
|
|
||||||
m_quickWindow->setFlags(windowFlags());
|
m_quickWindow->setFlags(windowFlags());
|
||||||
m_quickWindow->show();
|
m_quickWindow->show();
|
||||||
m_quickWindow->setGeometry(200, 200, 800, 800); // TODO: remove
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,9 @@ public:
|
|||||||
explicit FloatingWindowQuick(Frame *frame, MainWindowBase *parent = nullptr);
|
explicit FloatingWindowQuick(Frame *frame, MainWindowBase *parent = nullptr);
|
||||||
~FloatingWindowQuick();
|
~FloatingWindowQuick();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void setGeometry(QRect) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QWindow *candidateParentWindow() const;
|
QWindow *candidateParentWindow() const;
|
||||||
void init();
|
void init();
|
||||||
|
|||||||
@@ -30,13 +30,13 @@ FrameQuick::FrameQuick(QWidgetAdapter *parent, FrameOptions options)
|
|||||||
connect(m_dockWidgetModel, &DockWidgetModel::countChanged,
|
connect(m_dockWidgetModel, &DockWidgetModel::countChanged,
|
||||||
this, &FrameQuick::onDockWidgetCountChanged);
|
this, &FrameQuick::onDockWidgetCountChanged);
|
||||||
|
|
||||||
auto component = new QQmlComponent(Config::self().qmlEngine(),
|
QQmlComponent component(Config::self().qmlEngine(),
|
||||||
QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/Frame.qml")));
|
QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/Frame.qml")));
|
||||||
|
|
||||||
auto visualItem = static_cast<QQuickItem*>(component->create());
|
auto visualItem = static_cast<QQuickItem*>(component.create());
|
||||||
|
|
||||||
if (!visualItem) {
|
if (!visualItem) {
|
||||||
qWarning() << Q_FUNC_INFO << "Failed to create item" << component->errorString();
|
qWarning() << Q_FUNC_INFO << "Failed to create item" << component.errorString();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,6 +121,11 @@ int FrameQuick::dockWidgetCount_impl() const
|
|||||||
return m_dockWidgetModel->count();
|
return m_dockWidgetModel->count();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FrameQuick::renameTab(int, const QString &)
|
||||||
|
{
|
||||||
|
// Not needed for QtQuick. Our model reacts to titleChanged()
|
||||||
|
}
|
||||||
|
|
||||||
void FrameQuick::setStackLayout(QQuickItem *stackLayout)
|
void FrameQuick::setStackLayout(QQuickItem *stackLayout)
|
||||||
{
|
{
|
||||||
if (m_stackLayout || !stackLayout) {
|
if (m_stackLayout || !stackLayout) {
|
||||||
@@ -165,7 +170,7 @@ QVariant DockWidgetModel::data(const QModelIndex &index, int role) const
|
|||||||
DockWidgetBase *DockWidgetModel::dockWidgetAt(int index) const
|
DockWidgetBase *DockWidgetModel::dockWidgetAt(int index) const
|
||||||
{
|
{
|
||||||
if (index < 0 || index >= m_dockWidgets.size()) {
|
if (index < 0 || index >= m_dockWidgets.size()) {
|
||||||
qWarning() << Q_FUNC_INFO << "Shouldn't happen" << index << m_dockWidgets.size();
|
// Can happen. Benign.
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ protected:
|
|||||||
DockWidgetBase *dockWidgetAt_impl(int index) const override;
|
DockWidgetBase *dockWidgetAt_impl(int index) const override;
|
||||||
DockWidgetBase *currentDockWidget_impl() const override;
|
DockWidgetBase *currentDockWidget_impl() const override;
|
||||||
int dockWidgetCount_impl() const override;
|
int dockWidgetCount_impl() const override;
|
||||||
|
void renameTab(int index, const QString &) override;
|
||||||
Q_INVOKABLE void setStackLayout(QQuickItem *);
|
Q_INVOKABLE void setStackLayout(QQuickItem *);
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
|
|||||||
@@ -17,9 +17,21 @@
|
|||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
MainWindowQuick::MainWindowQuick(const QString &uniqueName, MainWindowOptions options,
|
MainWindowQuick::MainWindowQuick(const QString &uniqueName, MainWindowOptions options,
|
||||||
QWidgetAdapter *parent)
|
QQuickItem *parent)
|
||||||
: MainWindowBase(uniqueName, options, parent)
|
: MainWindowBase(uniqueName, options, parent)
|
||||||
{
|
{
|
||||||
QWidgetAdapter::makeItemFillParent(this);
|
QWidgetAdapter::makeItemFillParent(this);
|
||||||
QWidgetAdapter::makeItemFillParent(dropArea());
|
QWidgetAdapter::makeItemFillParent(dropArea());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SideBar *MainWindowQuick::sideBar(SideBarLocation) const
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "SideBar hasn't been implemented yet";
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
QMargins MainWindowQuick::centerWidgetMargins() const
|
||||||
|
{
|
||||||
|
qDebug() << Q_FUNC_INFO << "SideBar hasn't been implemented yet";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|||||||
@@ -26,7 +26,11 @@ class DOCKS_EXPORT MainWindowQuick : public MainWindowBase
|
|||||||
public:
|
public:
|
||||||
explicit MainWindowQuick(const QString &uniqueName,
|
explicit MainWindowQuick(const QString &uniqueName,
|
||||||
MainWindowOptions options = MainWindowOption_HasCentralFrame,
|
MainWindowOptions options = MainWindowOption_HasCentralFrame,
|
||||||
QWidgetAdapter *parent = nullptr);
|
QQuickItem *parent = nullptr);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
SideBar *sideBar(SideBarLocation) const override;
|
||||||
|
QMargins centerWidgetMargins() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ using namespace KDDockWidgets;
|
|||||||
|
|
||||||
QWidgetAdapter::QWidgetAdapter(QQuickItem *parent, Qt::WindowFlags flags)
|
QWidgetAdapter::QWidgetAdapter(QQuickItem *parent, Qt::WindowFlags flags)
|
||||||
: QQuickItem(parent)
|
: QQuickItem(parent)
|
||||||
, m_requestedWindowFlags(flags)
|
, m_windowFlags(flags)
|
||||||
{
|
{
|
||||||
this->setParent(parent); // also set parentItem
|
this->setParent(parent); // also set parentItem
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ void QWidgetAdapter::itemChange(QQuickItem::ItemChange change, const QQuickItem:
|
|||||||
switch (change) {
|
switch (change) {
|
||||||
case QQuickItem::ItemParentHasChanged: {
|
case QQuickItem::ItemParentHasChanged: {
|
||||||
QEvent ev(QEvent::ParentChange);
|
QEvent ev(QEvent::ParentChange);
|
||||||
event(&ev);
|
qApp->sendEvent(this, &ev); // Not calling event() directly, otherwise it would skip event filters
|
||||||
Q_EMIT parentChanged();
|
Q_EMIT parentChanged();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -93,6 +93,24 @@ void QWidgetAdapter::itemChange(QQuickItem::ItemChange change, const QQuickItem:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
|
||||||
|
{
|
||||||
|
// Send a few events manually, since QQuickItem doesn't do it for us.
|
||||||
|
QQuickItem::geometryChanged(newGeometry, oldGeometry);
|
||||||
|
|
||||||
|
// Not calling event() directly, otherwise it would skip event filters
|
||||||
|
|
||||||
|
if (newGeometry.size() != oldGeometry.size()) {
|
||||||
|
QEvent ev(QEvent::Resize);
|
||||||
|
qApp->sendEvent(this, &ev);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newGeometry.topLeft() != oldGeometry.topLeft()) {
|
||||||
|
QEvent ev(QEvent::Move);
|
||||||
|
qApp->sendEvent(this, &ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::raise()
|
void QWidgetAdapter::raise()
|
||||||
{
|
{
|
||||||
if (QWindow *w = windowHandle())
|
if (QWindow *w = windowHandle())
|
||||||
@@ -141,8 +159,7 @@ void QWidgetAdapter::setGeometry(QRect rect)
|
|||||||
{
|
{
|
||||||
setWidth(rect.width());
|
setWidth(rect.width());
|
||||||
setHeight(rect.height());
|
setHeight(rect.height());
|
||||||
setX(rect.x());
|
move(rect.topLeft());
|
||||||
setY(rect.y());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::grabMouse()
|
void QWidgetAdapter::grabMouse()
|
||||||
@@ -196,6 +213,12 @@ void QWidgetAdapter::showMaximized()
|
|||||||
w->showMaximized();
|
w->showMaximized();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::showMinimized()
|
||||||
|
{
|
||||||
|
if (QWindow *w = windowHandle())
|
||||||
|
w->showMinimized();
|
||||||
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::showNormal()
|
void QWidgetAdapter::showNormal()
|
||||||
{
|
{
|
||||||
if (QWindow *w = windowHandle())
|
if (QWindow *w = windowHandle())
|
||||||
@@ -240,6 +263,27 @@ QPoint QWidgetAdapter::mapFromGlobal(QPoint pt) const
|
|||||||
return QQuickItem::mapFromGlobal(pt).toPoint();
|
return QQuickItem::mapFromGlobal(pt).toPoint();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPoint QWidgetAdapter::mapTo(const QQuickItem *parent, const QPoint &pos) const
|
||||||
|
{
|
||||||
|
if (!parent)
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return parent->mapFromGlobal(QQuickItem::mapToGlobal(pos)).toPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool QWidgetAdapter::testAttribute(Qt::WidgetAttribute attr) const
|
||||||
|
{
|
||||||
|
return m_widgetAttributes & attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::setAttribute(Qt::WidgetAttribute attr, bool enable)
|
||||||
|
{
|
||||||
|
if (enable)
|
||||||
|
m_widgetAttributes |= attr;
|
||||||
|
else
|
||||||
|
m_widgetAttributes &= ~attr;
|
||||||
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::setWindowTitle(const QString &title)
|
void QWidgetAdapter::setWindowTitle(const QString &title)
|
||||||
{
|
{
|
||||||
if (QWindow *window = windowHandle())
|
if (QWindow *window = windowHandle())
|
||||||
@@ -267,10 +311,16 @@ QQuickItem *QWidgetAdapter::childAt(QPoint p) const
|
|||||||
return QQuickItem::childAt(p.x(), p.y());
|
return QQuickItem::childAt(p.x(), p.y());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QWidgetAdapter::move(QPoint pt)
|
||||||
|
{
|
||||||
|
move(pt.x(), pt.y());
|
||||||
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::move(int x, int y)
|
void QWidgetAdapter::move(int x, int y)
|
||||||
{
|
{
|
||||||
setX(x);
|
setX(x);
|
||||||
setY(y);
|
setY(y);
|
||||||
|
setAttribute(Qt::WA_Moved);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QWidgetAdapter::setParent(QQuickItem *p)
|
void QWidgetAdapter::setParent(QQuickItem *p)
|
||||||
@@ -302,10 +352,7 @@ QSize QWidgetAdapter::sizeHint() const
|
|||||||
|
|
||||||
Qt::WindowFlags QWidgetAdapter::windowFlags() const
|
Qt::WindowFlags QWidgetAdapter::windowFlags() const
|
||||||
{
|
{
|
||||||
if (QWindow *w = windowHandle())
|
return m_windowFlags;
|
||||||
return w->flags();
|
|
||||||
|
|
||||||
return m_requestedWindowFlags;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** static */
|
/** static */
|
||||||
@@ -347,15 +394,10 @@ void QWidgetAdapter::makeItemFillParent(QQuickItem *item)
|
|||||||
|
|
||||||
void QWidgetAdapter::setFlag(Qt::WindowType f, bool on)
|
void QWidgetAdapter::setFlag(Qt::WindowType f, bool on)
|
||||||
{
|
{
|
||||||
if (QWindow *w = windowHandle()) {
|
if (on) {
|
||||||
w->setFlag(f, on);
|
m_windowFlags |= f;
|
||||||
} else {
|
} else {
|
||||||
// When we create a QWindow we'll set these
|
m_windowFlags &= ~f;
|
||||||
if (on) {
|
|
||||||
m_requestedWindowFlags |= f;
|
|
||||||
} else {
|
|
||||||
m_requestedWindowFlags &= ~f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ public:
|
|||||||
int width() const { return int(QQuickItem::width()); }
|
int width() const { return int(QQuickItem::width()); }
|
||||||
int height() const { return int(QQuickItem::height()); }
|
int height() const { return int(QQuickItem::height()); }
|
||||||
|
|
||||||
void setGeometry(QRect);
|
virtual void setGeometry(QRect);
|
||||||
QRect geometry() const;
|
QRect geometry() const;
|
||||||
QRect rect() const;
|
QRect rect() const;
|
||||||
void show();
|
void show();
|
||||||
@@ -115,6 +115,7 @@ public:
|
|||||||
bool isMaximized() const;
|
bool isMaximized() const;
|
||||||
bool isActiveWindow() const;
|
bool isActiveWindow() const;
|
||||||
void showMaximized();
|
void showMaximized();
|
||||||
|
void showMinimized();
|
||||||
void showNormal();
|
void showNormal();
|
||||||
|
|
||||||
QWindow *windowHandle() const;
|
QWindow *windowHandle() const;
|
||||||
@@ -122,13 +123,16 @@ public:
|
|||||||
QWidgetAdapter *parentWidget() const;
|
QWidgetAdapter *parentWidget() const;
|
||||||
QPoint mapToGlobal(QPoint pt) const;
|
QPoint mapToGlobal(QPoint pt) const;
|
||||||
QPoint mapFromGlobal(QPoint) const;
|
QPoint mapFromGlobal(QPoint) const;
|
||||||
bool testAttribute(Qt::WidgetAttribute) { return false; }
|
QPoint mapTo(const QQuickItem *parent, const QPoint &pos) const;
|
||||||
|
bool testAttribute(Qt::WidgetAttribute) const;
|
||||||
|
void setAttribute(Qt::WidgetAttribute, bool enabled = true);
|
||||||
|
|
||||||
void setWindowTitle(const QString &);
|
void setWindowTitle(const QString &);
|
||||||
void setWindowIcon(const QIcon &);
|
void setWindowIcon(const QIcon &);
|
||||||
void close();
|
void close();
|
||||||
QQuickItem *childAt(QPoint) const;
|
QQuickItem *childAt(QPoint) const;
|
||||||
void move(int x, int y);
|
void move(int x, int y);
|
||||||
|
void move(QPoint);
|
||||||
|
|
||||||
void setParent(QQuickItem*);
|
void setParent(QQuickItem*);
|
||||||
void activateWindow();
|
void activateWindow();
|
||||||
@@ -147,6 +151,7 @@ public:
|
|||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
void parentChanged();
|
void parentChanged();
|
||||||
protected:
|
protected:
|
||||||
|
void geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) override;
|
||||||
void raiseAndActivate();
|
void raiseAndActivate();
|
||||||
virtual bool onResize(QSize newSize);
|
virtual bool onResize(QSize newSize);
|
||||||
virtual void onLayoutRequest();
|
virtual void onLayoutRequest();
|
||||||
@@ -160,7 +165,8 @@ private:
|
|||||||
QSizePolicy m_sizePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
QSizePolicy m_sizePolicy = QSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
|
||||||
QSize m_minimumSize = {KDDOCKWIDGETS_MIN_WIDTH, KDDOCKWIDGETS_MIN_HEIGHT};
|
QSize m_minimumSize = {KDDOCKWIDGETS_MIN_WIDTH, KDDOCKWIDGETS_MIN_HEIGHT};
|
||||||
QSize m_maximumSize = {KDDOCKWIDGETS_MAX_WIDTH, KDDOCKWIDGETS_MAX_HEIGHT};
|
QSize m_maximumSize = {KDDOCKWIDGETS_MAX_WIDTH, KDDOCKWIDGETS_MAX_HEIGHT};
|
||||||
Qt::WindowFlags m_requestedWindowFlags;
|
Qt::WindowFlags m_windowFlags;
|
||||||
|
int m_widgetAttributes = 0; // Qt::WidgetAttribute
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,6 @@
|
|||||||
|
|
||||||
void KDDockWidgets::registerQmlTypes()
|
void KDDockWidgets::registerQmlTypes()
|
||||||
{
|
{
|
||||||
qDebug() << "Registering types";
|
|
||||||
qmlRegisterType<DropAreaWithCentralFrame>("com.kdab.dockwidgets", 1, 0, "DropAreaWithCentralFrame");
|
qmlRegisterType<DropAreaWithCentralFrame>("com.kdab.dockwidgets", 1, 0, "DropAreaWithCentralFrame");
|
||||||
qmlRegisterType<MainWindowWrapper>("com.kdab.dockwidgets", 1, 0, "MainWindow");
|
qmlRegisterType<MainWindowWrapper>("com.kdab.dockwidgets", 1, 0, "MainWindow");
|
||||||
|
|
||||||
|
|||||||
@@ -23,44 +23,33 @@ TitleBarBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
TitleBarButton {
|
||||||
id: floatButton
|
id: floatButton
|
||||||
color: "red"
|
imageSource: "qrc:/img/dock-float.png"
|
||||||
anchors {
|
anchors {
|
||||||
top: parent ? parent.top : undefined
|
verticalCenter: parent ? parent.verticalCenter : undefined
|
||||||
bottom: parent ? parent.bottom : undefined
|
|
||||||
right: closeButton.left
|
right: closeButton.left
|
||||||
topMargin: 5
|
topMargin: 5
|
||||||
bottomMargin: 5
|
bottomMargin: 5
|
||||||
rightMargin: 5
|
rightMargin: 5
|
||||||
}
|
}
|
||||||
width: height
|
onClicked: {
|
||||||
|
titleBarCpp.onFloatClicked();
|
||||||
MouseArea {
|
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
titleBarCpp.onFloatClicked();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectangle {
|
TitleBarButton {
|
||||||
id: closeButton
|
id: closeButton
|
||||||
color: "red"
|
imageSource: "qrc:/img/close.png"
|
||||||
anchors {
|
anchors {
|
||||||
top: parent ? parent.top : undefined
|
verticalCenter: parent ? parent.verticalCenter : undefined
|
||||||
bottom: parent ? parent.bottom : undefined
|
|
||||||
right: parent ? parent.right : undefined
|
right: parent ? parent.right : undefined
|
||||||
topMargin: 5
|
topMargin: 5
|
||||||
bottomMargin: 5
|
bottomMargin: 5
|
||||||
leftMargin: 5
|
leftMargin: 5
|
||||||
}
|
}
|
||||||
width: height
|
onClicked: {
|
||||||
MouseArea {
|
titleBarCpp.onCloseClicked();
|
||||||
anchors.fill: parent
|
|
||||||
onClicked: {
|
|
||||||
titleBarCpp.onCloseClicked();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/private/quick/qml/TitleBarButton.qml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio 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
|
||||||
|
|
||||||
|
Rectangle {
|
||||||
|
id: root
|
||||||
|
|
||||||
|
signal clicked()
|
||||||
|
property alias imageSource: image.source
|
||||||
|
|
||||||
|
color: "transparent"
|
||||||
|
height: 16
|
||||||
|
width: 16
|
||||||
|
|
||||||
|
radius: 3
|
||||||
|
border {
|
||||||
|
color: "#666666"
|
||||||
|
width: mouseArea.containsMouse ? 1 : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
Image {
|
||||||
|
id: image
|
||||||
|
anchors.centerIn: parent
|
||||||
|
anchors {
|
||||||
|
verticalCenterOffset: 1
|
||||||
|
horizontalCenterOffset: 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MouseArea {
|
||||||
|
id: mouseArea
|
||||||
|
hoverEnabled: true
|
||||||
|
anchors.fill: parent
|
||||||
|
onClicked: {
|
||||||
|
root.clicked();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||