Compare commits

...

721 Commits

Author SHA1 Message Date
Allen Winter
9a784f1222 ready for 1.4.0 release 2021-07-16 11:13:13 -04:00
Allen Winter
4a390696d5 CMakeLists.txt - Set default CMAKE_BUILD_TYPE to Release for non-dev
In non-developer situations default CMAKE_BUILD_TYPE=Release
2021-07-16 09:42:43 -04:00
Allen Winter
68aaccadab CMakeLists.txt - move the python bindings buildtype check 2021-07-16 09:38:56 -04:00
Allen Winter
3940228b59 various cmake files - minor coding style 2021-07-16 09:18:03 -04:00
Allen Winter
f8abe48c82 CMakeLists.txt - add more doc 2021-07-16 09:11:00 -04:00
Sergio Martins
86db81e5b7 README-QtQuick: Remove sentence about failing Qt6 tests
It was a false-positive, everything passes
2021-07-15 23:53:01 +01:00
Sergio Martins
34676f016f qtquick: Blacklist a Qt6 test
Works fine manually.
Qt6 refactored input event handling, which broke our Tests::doubleClickOn(QWindow).
2021-07-15 23:50:06 +01:00
Sergio Martins
4448891315 tests: Increase timeout when trying to active dock widgets
When running with ASAN everything is slower.
Added a warning to tests fail sooner if this happens.
2021-07-15 20:50:58 +01:00
Sergio Martins
fc1f12b77c cmake: Qt6 QtQuick clangcl preset needs help finding Qt6 plugins
The same was already done to the regular msvc one
2021-07-15 20:18:55 +01:00
Sergio Martins
a50057f5d2 cmake: Fix running the clangcl Qt6 presets on Windows
They need to set PATH
2021-07-15 20:14:48 +01:00
Sergio Martins
d7b32e475e cmake: Normalize preset build dir of my clangcl preset 2021-07-15 20:11:30 +01:00
Allen Winter
8b695eec79 .codespellrc - codespell config 2021-07-15 10:26:20 -04:00
Allen Winter
c85904c67e 2 more misspelling fixes for contractions. 2021-07-15 10:25:53 -04:00
Allen Winter
22a709a39e fix more misspellings 2021-07-15 10:14:04 -04:00
Allen Winter
4f4a5de700 fix misspellings found by codespell 2021-07-15 09:46:53 -04:00
Sergio Martins
08ecbb2ca6 qtquick: Mention Qt6+qtquick has failing tests 2021-07-15 10:59:23 +01:00
Sergio Martins
048b494874 cmake: Fix dev-qtquick6 preset
When running it, we need to set the correct qml import path,
otherwise it picks up Qt 5.
2021-07-14 23:31:57 +01:00
Allen Winter
1539d7233b make/ECMGenerateHeaders.cmake - avoid uninit value
see upstream MR at:
https://invent.kde.org/frameworks/extra-cmake-modules/-/merge_requests/161
2021-07-14 16:00:32 -04:00
Sergio Martins
214dbdf359 qtquick: Fix clazy-connect-not-normalized 2021-07-14 16:10:07 +01:00
Allen Winter
473ce60340 cmake/ECM/modules/ECMGenerateHeaders.cmake - add missing 2021-07-13 18:39:58 -04:00
Allen Winter
74ba8c6bd2 src/CMakeLists.txt - coding style
consistent indentation, etc.
2021-07-13 16:59:53 -04:00
Allen Winter
11a1023e79 src/CMakeLists.txt - generate and install camelcase headers
for public headers and exported classes only
2021-07-13 16:58:25 -04:00
Sergio Martins
3c5f07ac79 Update ChangeLog 2021-07-13 17:34:00 +01:00
Renato Araujo Oliveira Filho
ec4a4d1c86 Python: Create bindings for InitialOption
Added bindings for missing enums
Added InitialOption as value type

Task-Id: #198
2021-07-13 17:33:09 +01:00
Sergio Martins
5ef330f479 vscode: Fix the build dir paths
They changed in the cmake preset
2021-07-13 17:32:54 +01:00
Allen Winter
bbdbadd630 CMakeLists.txt - add missing option() and feature_summary()
also some minor coding style and some more comments
2021-07-13 08:20:50 -04:00
Allen Winter
80a1483617 QtQuick support is no longer expermental 2021-07-13 08:06:30 -04:00
Sergio Martins
8800c02403 Fix persistent central frame becoming invisible
Wouldn't affect functionality but would have a different color.
Fixes #220
2021-07-13 08:19:05 +01:00
Allen Winter
dd9ec48979 DragController.cpp - fix multi-line comment [-Werror=comment]
caused by clang-format
2021-07-12 17:37:59 -04:00
Allen Winter
262d703608 cmake/ECM - sync with upstream
except for ECMEnableSanitizers.cmake which has local
changes we intend to upstream, if accepted.
2021-07-12 17:21:15 -04:00
Allen Winter
5629e1dfc2 .clang-format - set ColumnLimit to 0
else clang-format grows lines for you
2021-07-12 17:07:55 -04:00
Allen Winter
7001aa58ce clang-format on code base 2021-07-12 17:05:37 -04:00
Allen Winter
d87898b59e private/DragController.cpp - don't include QWindow more than once 2021-07-12 17:04:15 -04:00
Allen Winter
d1078adad2 .clang-format - SortIncludes: false 2021-07-12 16:41:32 -04:00
Allen Winter
e4f0fae7e5 .clang-format - ColumnLimit: 150
because SPDX tag lines are longer than 100 already
2021-07-12 16:38:08 -04:00
Sergio Martins
4b06706d61 Port away from deprecated QWidget::isTopLevel()
Fixes Qt6 warnings about it
2021-07-10 07:18:27 -07:00
Sergio Martins
7e1331bd76 cmake|Qt6: Add presets for clang-cl 2021-07-10 06:56:36 -07:00
Sergio Martins
f735f25fb0 cmake|qtquick: Add a preset for building with clang-cl 2021-07-10 06:52:35 -07:00
Sergio Martins
750c089ab0 windows: Use -Werror for clang-cl too 2021-07-10 06:49:14 -07:00
Sergio Martins
3088f33837 Fix non-windows build 2021-07-10 06:44:48 -07:00
Sergio Martins
1d598d2585 windows: Fix all clang-cl warnings
Mostly int vs uint conversions.
In preparation to add -Werror
2021-07-10 06:43:04 -07:00
Sergio Martins
768c51f01c windows: Fix a -Wunused-lambda-capture warning 2021-07-10 06:27:23 -07:00
Sergio Martins
a2e2b32fc3 cmake: Don't pass -fvisibility=hidden to clang-cl
It's not supported
2021-07-10 06:22:24 -07:00
Sergio Martins
a6abf73669 cmake: Add a preset for clang-cl
clang has different warnings, so would like to build with it in
CI too.
2021-07-10 13:57:48 +01:00
Sergio Martins
a6e62ec74d qtquick|tests: trying to stabilize a test in CI
Can't repro locally.
2021-07-10 13:44:15 +01:00
Sergio Martins
93441a5754 cmake: Use unity build for our release builds
Unity is much faster to build, specially on Windows
2021-07-10 13:38:24 +01:00
Sergio Martins
fe57686715 cmake: Remove "-qtwidgets" suffix from preset names
Only variants need a suffix (python, qtquick, static, etc).
The default is a qtwidgets build
2021-07-10 13:22:27 +01:00
Sergio Martins
330f5aebdf cmake: Add -Wundef 2021-07-09 22:26:01 +01:00
Sergio Martins
02c17e59dd relax a warning about not finding dock widget to restore
If the user provided a factory and it returns nullptr on purpose
then don't warn, it's intentional by the user
2021-07-06 23:12:49 +01:00
Sergio Martins
be8af12a90 cmake: Remove unneeded custom preset settings
I have this locally now, as it didn't have any kddw specific config
and I'm using it cross project, so makes more sense to have it
in a central location outside of kddw.
2021-07-05 22:51:09 +01:00
Sergio Martins
238193f56b qtquick: DockWidget now receives QQmlEngine as param
If nullptr then the usual Config::qmlEngine() will be used.
2021-07-04 18:41:52 +01:00
Sergio Martins
54233085a4 tests: Add a warning to the blacklist
Don't abort on:
"Populating font family aliases took"
2021-07-03 21:51:02 +01:00
Sergio Martins
2241b938c9 qtquick|minor: Decouple a bit more from Config::self().qmlEngine()
Moves it up one layer, will be easier to remove
2021-07-03 17:26:59 +01:00
Sergio Martins
631d036c26 qtquick: Exclude two clazy-old-style-connect warnings
Those two cases are fine and required
2021-07-03 16:44:04 +01:00
Sergio Martins
d70f795dea qtquick: Fix a -Wclazy-func-args-by-value 2021-07-03 16:39:25 +01:00
Sergio Martins
0be99d3e79 qtquick: Fix -Wclazy-missing-qobject-macro 2021-07-03 16:33:21 +01:00
Sergio Martins
45aab49be7 qtquick: Fix -Wclazy-fully-qualified-moc-types
Might even fix a few bugs as QML is very picky about this
2021-07-03 16:31:15 +01:00
Sergio Martins
2c66238791 qtquick: Fix a -Wclazy-returning-void-expression and missing Q_EMIT 2021-07-03 16:27:36 +01:00
Sergio Martins
bec1ddae67 qtquick: Fix a -Wclazy-range-loop-reference 2021-07-03 16:27:30 +01:00
Sergio Martins
913d3b263d cmake: Don't build the examples when using the clazy preset
The clazy warning set is more strict for the library than for the
examples. For CI purposes and -Werror it's the library that matters.
2021-07-03 16:24:15 +01:00
Sergio Martins
614e20a183 cmake: Add a preset for clazy qtquick 2021-07-03 16:19:28 +01:00
Sergio Martins
f9f270980d tests: Fix flaky test
The center indicator isn't exactly at the center of the window,
so this would fail sometimes. This is a quick workaround.
Will all API to the dock indicator interface if this isn't enough.
2021-07-03 10:46:26 +01:00
Sergio Martins
763b878ca1 qtquick|README: Mention that C++17 is required 2021-07-02 22:58:03 +01:00
Sergio Martins
d3d040adee qtquick: Fix tab current widget being wrong when current is removed
When the current dock widget is removed we need to assign another
one. QTabBar does this automatically.

Fixes #215
2021-07-02 22:54:20 +01:00
Sergio Martins
31f5cc10cf qtquick: Add qWarning() when there's no current index in tabWidget 2021-07-02 22:34:46 +01:00
Sergio Martins
38c9a3d9c6 qtquick: Require C++17
Fixes build due to not finding <optional>
2021-07-02 22:33:34 +01:00
Sergio Martins
362f2d5750 qtquick: Add a failing test for #215 2021-07-02 16:56:40 +01:00
Sergio Martins
463b6a1322 qtquick: Fix using initial visibility option
Needs to be fully qualified.
Added an example.

Fixes #212
2021-07-02 16:41:49 +01:00
Sergio Martins
00a95ac468 Fix invisible tabbar from eating hover events
Fixes #214
2021-07-02 16:15:04 +01:00
Sergio Martins
966f30e356 qtquick: Fix dock widgets not getting title
Title can be set before onComplete(), so we need to remember it

Fixes #218
2021-07-02 15:05:55 +01:00
Sergio Martins
f0217f53c2 qtquick: Update README with warning against QtGraphicalEffects 2021-07-02 00:02:23 +01:00
Sergio Martins
ced1c4dcc8 TabWidgetWidget: Don't hardcode margins, so we support DPI != 96
For people using font DPI instead of DPR
2021-07-01 22:17:31 +01:00
Sergio Martins
e1578436d0 Added Flag_ShowButtonsOnTabBarIfTitleBarHidden 2021-07-01 18:08:41 +01:00
Sergio Martins
701df72db6 Remove some ifdefs regarding 5.9
The one missing QT_VERSION_CHECK was even wrong and triggering
even with Qt 5.15.
2021-07-01 16:54:44 +01:00
Sergio Martins
c4ebef1f1e Remove an ifdef only relevant to older Qt 2021-07-01 16:50:01 +01:00
Allen Winter
6f0eb7a2f2 Merge branch '1.3' 2021-06-30 12:19:37 -04:00
Allen Winter
be6c3ca2df move OBS files into a distro folder, add qt6 project 2021-06-30 12:19:09 -04:00
Sergio Martins
18b49686f1 tests|qtquick: Remove the XFAIL, fixed by #211 2021-06-29 00:15:48 +01:00
Eism
02d4611501 Fixed toggling dock widgets 2021-06-29 00:16:14 +01:00
Sergio Martins
2fe8117e80 tests: Add a QVERIFY 2021-06-28 23:46:58 +01:00
Sergio Martins
457ea402d5 qtquick|example: Fix toggling not working on non-current tab
A non-current tab isn't visible, its dock widget is however opened.
Relates to #211
2021-06-28 23:30:05 +01:00
Sergio Martins
89623eb8b4 tests|qtquick: Add a test for weirdness reported in #211
Not the exact issue from #211, but more tests will follow
2021-06-28 22:27:11 +01:00
Sergio Martins
df02382387 cmake: Add a personal preset config
So I can build on my mac from my linux box
2021-06-28 21:04:07 +01:00
Allen Winter
7470d62b7c Merge branch '1.3' 2021-06-26 09:42:06 -04:00
Allen Winter
9eb9018f47 docs/api/CMakeLists.txt - fix link from mainpage to README-bindings 2021-06-26 09:40:44 -04:00
Allen Winter
d7bcbe666c Require Qt5.12 or higher 2021-06-26 08:46:52 -04:00
Sergio Martins
aaa5b4ba26 README: Mention 6.1 is the first Qt6 version we support
Nobody is using 6.0 in production, so let's forget about it
2021-06-25 23:28:28 +01:00
Allen Winter
720dad1ed6 clean comment of double words "to to" and "the the" 2021-06-25 10:21:33 -04:00
Sergio Martins
6417db6d91 Added Config::InternalFlag_DisableTranslucency
In case one doesn't want to use the env variable
2021-06-25 14:38:19 +01:00
Sergio Martins
ec681e99ca Disable translucency when KDDW_NO_TRANSLUCENCY env var is set
Useful for running on weird window managers which don't support
transparent windows.
2021-06-25 14:31:00 +01:00
Sergio Martins
47ef203643 qtquick|minor: Remove a call to Config::self().qmlEngine() 2021-06-23 19:03:40 +01:00
Sergio Martins
844aa2f36a qtquick|minor: Move qml engine one level up 2021-06-23 18:37:34 +01:00
Sergio Martins
e2e8f10948 Fix QtQuick tests 2021-06-22 23:40:40 +01:00
Sergio Martins
1c49e2297a Fix QtQuick build 2021-06-22 23:22:02 +01:00
Sergio Martins
6f031e3c33 Windows: Fix initial FloatingWindow size in HDPI
When:
- Screen A (100%), B (150%)
- MainWindow on screen B
- Trying to open a floating window on screen A (via setGeometry())

The Qt Windows QPA would error out when setting the geometry and it
would be too small.

The solution is to call setGeometry() before we create the QWindow.

Too much of an edge case to risk putting this on 1.3 branch.
Will be in 1.4.0.

Fixes #191
2021-06-22 23:09:38 +01:00
Sergio Martins
f74fd52d53 DebugWindow: When dumping windows don't dump the DebugWindow itself 2021-06-22 17:27:27 +01:00
Sergio Martins
2d4cef670b Fix build with qtquick 2021-06-21 08:50:36 +01:00
Sergio Martins
dfaf455624 Add support for the rubber bands to be top-level
Worksaround a bug where they can't be transparent when embedded
in a MFC application
2021-06-20 21:26:43 +01:00
Allen Winter
5d2e09de36 .reuse/dep5 - add more files 2021-06-19 10:34:45 -04:00
Allen Winter
c86de50032 .resuse/dep5 - REUSE copyright+license for artwork, etc 2021-06-19 09:55:48 -04:00
Sergio Martins
5ff720f432 Export DropArea, has some useful symbols 2021-06-18 17:51:36 +01:00
Sergio Martins
6f7e47324c Minor: improve an include 2021-06-18 17:50:42 +01:00
Sergio Martins
b68f81779c Fix possible crash
Observed with an MFC application
2021-06-18 16:02:33 +01:00
Sergio Martins
4c1b433269 Fix a -Wclazy-fully-qualified-moc-types error 2021-06-17 22:02:35 +01:00
Sergio Martins
7c63da18ed Remove some dead code
Both if branches already return something
2021-06-17 13:03:00 +01:00
Sergio Martins
6f2e5ecc3b Add a missing qglobal.h include 2021-06-17 13:00:48 +01:00
Sergio Martins
759cf33f08 Windows: Link to Dwmapi.lib via pragma
So I don't have to figure out some exotic non-cmake build systems

It's more self-contained this way anyway.
2021-06-16 12:41:40 +01:00
Sergio Martins
77279d21ef Fixed a MSVC warning about unreachable code 2021-06-16 12:32:25 +01:00
Sergio Martins
46872fdfe8 Fix build if each header is built individually, probably
This header is included by QWidgetAdapter.h, but if some exotic
build system builds QWidgetAdapter_widgets_p.h individially then
we need to forward declare some functions
2021-06-15 21:35:55 +01:00
Sergio Martins
79fe9c2875 cmake: Remove private/ from our PRIVATE include path
Because some build systems don't support public/private includes,
and would require us to add private/ to the public include path.

This allows for an easier integration with some more exotic
build systems
2021-06-15 19:53:05 +01:00
Allen Winter
f04ea37ac2 appveyor.yml - disable email notification on build_success 2021-06-15 12:04:01 -04:00
Sergio Martins
d2db92f1e7 Remove private/multisplitter/ from private include path
It's not needed.
Even wrong since then ../LayoutSaver_p.h would work
2021-06-15 16:46:07 +01:00
Sergio Martins
206433e430 Fix embedding in non-KDDW QMainWindow
Supports the case of having our KDDW MainWindow parented to another
main window. Was broken on Windows.
2021-06-14 06:43:06 +01:00
Allen Winter
fb1f3fa931 CMakeLists.txt - ECM doesn't support generating pri files for Qt6 yet 2021-06-09 09:12:14 -04:00
Allen Winter
3d106ae2f1 python/CMakeLists.txt - fix for Qt6Widgets_VERSION 2021-06-08 19:01:31 -04:00
Sergio Martins
05f0a6463b Remove unnused AnimatedIndicators 2021-06-08 16:53:12 +01:00
Allen Winter
7b5d5d0f31 buildsystem - fix some --warn-uninitialized 2021-06-08 10:44:33 -04:00
Allen Winter
20174989a6 Merge branch '1.3' 2021-06-08 09:20:33 -04:00
Allen Winter
80d48adc07 docs/api/Doxyfile.cmake - set PROJECT_NUMBER to major.minor
don't use the patch level in the PROJECT_NUMBER
2021-06-08 09:19:53 -04:00
Allen Winter
3454185df4 Merge branch '1.3' 2021-06-07 17:14:25 -04:00
Allen Winter
9de0868c74 open for 1.3.2 (unknown yet if there will be such a thing) 2021-06-07 17:13:07 -04:00
Allen Winter
66cb6c7dee kddockwidgets.spec - fix for CentOS 2021-06-07 16:32:17 -04:00
Allen Winter
1ce67b1c8f prep for 1.3.1 release 2021-06-07 16:09:03 -04:00
Allen Winter
a9bb5b2f42 README.md - in Using section talk about CMAKE_PREFIX_PATH
was mistakenly CMAKE_MODULE_PATH
2021-06-07 16:01:27 -04:00
Allen Winter
97ca7fd2a0 CONTRIBUTORS: sync with master 2021-06-07 15:32:42 -04:00
Roman Pudashkin
b85e291d40 need to remove the old filter instead of the new one 2021-06-05 16:09:04 +01:00
Allen Winter
b3e3752789 .travis.yml, appveyor.yml - tweak email notification
notify on failures only
2021-05-28 08:41:16 -04:00
Sergio Martins
7cd6928b87 README: Add a travis "Build Passing" label 2021-05-25 22:07:33 +01:00
Sergio Martins
bb1b3c7b7b Fix non-windows developer build
Build was complaining about unused function
2021-05-25 14:06:14 +01:00
Allen Winter
49c7cea3a5 .travis.yml - apt install libqt5x11extras5-dev 2021-05-25 08:54:33 -04:00
Allen Winter
64f5009297 .travis.yml appveyor.yml - add travis-ci and appveyor CI 2021-05-25 08:48:01 -04:00
Eism
0ab701bab6 qtquick: Fix detecting top level geometry
For QtQuick we want the QWindow geometry. For QtWidget it just works,
as the top level widget as the same geometry as the window, unlike
QQuickItem.

Fixes issue #199
2021-05-24 11:45:37 +01:00
Sergio Martins
1721415799 Fix more warnings at shutdown 2021-05-23 22:42:26 +01:00
Sergio Martins
26269459db qtquick: Fix some warnings at shutdown 2021-05-23 22:37:42 +01:00
Sergio Martins
675da6b2e2 qtquick: Fix test on linux
Querying drop indicator doesn't work if indicator window
isn't visible, so actually do a full drag.

For issue #199
2021-05-23 22:06:05 +01:00
Sergio Martins
517bfca259 Add a unit-test for issue #199 2021-05-23 12:20:20 +01:00
Eism
3e30685eb4 Expose MainWindowBase::windowGeometry(), so it can be used
Just moves the code from private to public.
For issue #199
2021-05-23 11:34:53 +01:00
Roman Pudashkin
95cbba4618 qtquick: Fix crash by using deleteLater()
For issue #200
2021-05-22 10:22:58 +01:00
Sergio Martins
d89c6b9c06 qtquick|windows: Fix potential crash with offscreen QPA
Which also fixes a test. Now all tests pass.
The explanation was added in a comment.
2021-05-21 23:46:42 +01:00
Sergio Martins
4bda994d5c qtquick: Fix Qt6 warning about "mouse" being injected 2021-05-21 16:44:30 +01:00
Sergio Martins
2b4f6f33af qtquick: Fix Qt6 build 2021-05-21 16:38:12 +01:00
Sergio Martins
62500a322f qtquick: Fix calling titleBarFilename() function
Probably worked before, but the argument was bogus, as the
function doesn't accept arguments
2021-05-21 09:47:09 +01:00
Sergio Martins
ae58a8b9df Fix boolean variables being accessed before initialization
As detected by ASAN:
ClassicIndicators.cpp:66:12: runtime error: load of value 190, which is not a valid value for type 'bool'
2021-05-21 09:24:58 +01:00
Sergio Martins
2a8732fdcd cmake: Add preset for qtquick developer-build 2021-05-20 23:40:23 +01:00
Sergio Martins
19931ec18e cmake: Fix my Qt6 builds 2021-05-20 23:38:47 +01:00
Sergio Martins
b981fc4b7d qtquick: Fix tst_dockWindowWithTwoSideBySideFramesIntoCenter()
Moving windows around is async for QtQuick and needs a wait
2021-05-20 22:44:58 +01:00
Sergio Martins
4b2f268921 qtquick: fix tst_positionWhenShown on Windows 2021-05-20 22:44:26 +01:00
Sergio Martins
7fb5a8d444 Merge branch '1.3' 2021-05-20 18:54:18 +01:00
Sergio Martins
913cc16371 Fix failing test on Windows due to the button hack
During tests, our mouse button isn't really pressed, as we
send fake press events. Only use the workaround in production.
2021-05-20 18:47:32 +01:00
Sergio Martins
4e8a9ff8ed tests: fix a flaky test on Windows
The drop area doesn't fill the floating window, so the
center was off and the drop didn't happen

Additionally, disabled AeroSnap, for debugging purposes, so we can
actually see the window moving, otherwise it doesn't move, since
we can't fake a native drag. It's just a visual bonus, doesn't
affect the correctness.
2021-05-20 18:28:23 +01:00
Sergio Martins
68034de1a7 cmake: Fix ASAN not actually being enabled
Was only enabled for the tests.
Needed to move it up.
2021-05-20 16:41:10 +01:00
Sergio Martins
f67d8615ca cmake: Remove manually setting ASAN on Windows
It's done by ECM now
2021-05-20 16:30:23 +01:00
Sergio Martins
4483c921ea ECM: Added MSVC sanitizer support
Written by me, will squash it once upstream has it.
There's some patches in review upstream.
2021-05-20 16:19:48 +01:00
Sergio Martins
e8732ecfc0 ECM: sync sanitizers with upstream 2021-05-20 16:19:06 +01:00
Sergio Martins
71a538651a Enable ASAN on Windows too 2021-05-18 16:00:54 -07:00
Sergio Martins
18c9963124 qtquick|tests: Fix tst_lastFloatingPositionIsRestored
We need to compare the position of the Window
2021-05-18 15:00:21 -07:00
Sergio Martins
cd0f2f4e33 Introduced Config::setDropIndicatorsInhibited(bool)
Allows you to disable support for drop indicators while dragging
2021-05-18 18:00:04 +01:00
Sergio Martins
fc028ec0be Minor refactoring 2021-05-18 17:49:14 +01:00
Sergio Martins
2dbdb9f7eb qtquick: Fix restoring QWindow's geometry
We need to resize the QWindow.

Fixes issue #196
2021-05-17 22:46:56 +01:00
Sergio Martins
50f6e76e81 qtquick|examples: Don't call them "MainWindow"
Rather "main layout", as they are not top-levels, unlike for
QWidgets

As suggested in issue #196
2021-05-17 22:27:34 +01:00
Sergio Martins
c6af93adcb qtquick: When saving geometry, save the QWindow geometry
As that's what we'll restore. The "MainWindow" isn't an actual
main window, and it's parented in some QtQuick hierarchy.

Will help with issue #196, which isn't fixed yet.
Should be fixed in the restore part next.
2021-05-17 22:20:44 +01:00
Sergio Martins
bd985781b9 Minor refactoring 2021-05-17 22:13:17 +01:00
Sergio Martins
70ecdaf54c Add a failing test for issue #196 2021-05-17 21:12:59 +01:00
Allen Winter
a04287b9b3 README - adjust copyright date 2021-05-16 11:08:08 -04:00
Allen Winter
be8d00f0c8 buildsystem - KD namespace the KDAB cmake modules 2021-05-16 11:03:21 -04:00
Allen Winter
b08797c400 docs/api/footer.html - add Copyright and generatedby 2021-05-16 10:58:01 -04:00
Sergio Martins
2836edd32d qtquick: Add a test to see that main window position is restored
Will improve it with QtQuick corner cases
2021-05-10 23:04:37 +01:00
Allen Winter
92f6886217 Merge branch '1.3' 2021-05-10 15:40:46 -04:00
Allen Winter
0c9518dc74 .krazy - skip CMakePresets.json
the json formatter saves it without a trailing newline
no need to test this generated file
2021-05-10 15:40:00 -04:00
Allen Winter
944ee7c7dc Merge branch '1.3' 2021-05-10 12:58:13 -04:00
Allen Winter
917dbf09f6 README.md, README-bindings.md - breakout python bindings readme.
The python bindings info is getting long and detailed
so move to its own README.
2021-05-10 12:56:59 -04:00
Sergio Martins
d732be4e17 Merge branch '1.3' into master 2021-05-04 23:41:23 +01:00
Sergio Martins
18dbbb291a Cancel drag when Qt doesn't detect that mouse was released
On Windows there can be a case where Qt doesn't receive the mouse
release event. When releasing very fast after starting the drag.

Fixes #166
2021-05-04 23:36:50 +01:00
Sergio Martins
3bb7922f2c comments++ 2021-05-02 13:05:27 +01:00
Sergio Martins
4aedba3b2b Minor: Pass QPoint by value, as it's a small POD class 2021-05-02 13:01:27 +01:00
Eism
99c0e99b26 Implemented the method for adjusting the position of a dragged item 2021-05-02 13:00:43 +01:00
Sergio Martins
28ab554cb3 comments++ 2021-05-02 12:49:07 +01:00
Sergio Martins
cd80a47c93 qtquick|tests: Fix tst_layoutEqually
Resizing QtQuick's QWindow is async, doesn't propagate the size
immediately to the content QQuickItem.

Meaning we were passing a too small/old size to the layout.
Add qMin() so we don't pass sizes that are smaller than the layout's
min-size.
2021-05-02 12:30:53 +01:00
Sergio Martins
eb05b54b0e Added DockWidgetInstantiator::close() 2021-05-02 11:35:16 +01:00
Sergio Martins
bbbce6f694 qtquick: Fix close() not hidding the widget
QtQuick will emit a "visibleChanged(true)" when setting nullptr,
which we need to inhibit so it behaves like QtWidgets.
2021-05-02 11:22:26 +01:00
Sergio Martins
ba0d515330 qtquick: Don't run tst_maxSizedFloatingWindow
We only support max-size constraints for QtWidgets, for now.
2021-05-02 00:19:47 +01:00
Sergio Martins
69154c0384 qtquick: Make setParent(nullptr) to hide the widget too
As done for QtWidgets.

Fixes a case where closing the dock widget wouldn't hide it.

As reported by Roman
2021-05-02 00:11:58 +01:00
Sergio Martins
66ac5e9d2f qtquick: Install DockWidgetQuick.h too 2021-05-01 20:46:01 +01:00
Sergio Martins
4924b951cc qtquick: Don't include private header in public header
Q_PROPERTIES in Qt6 don't support forward declarations.
Return a QObject instead.
2021-05-01 20:38:06 +01:00
Allen Winter
96f7def396 Merge branch '1.3' 2021-05-01 15:38:38 -04:00
Sergio Martins
4556f1c949 quick|cmake: Don't install a few qtwidgets includes
Install their qtquick counterparts instead
2021-05-01 20:20:59 +01:00
Sergio Martins
a4cca3bcc2 Merge pull request #195 from RomanPudashkin/setTabbingAllowedFunc_fix
Fixed the API for disabling the tab indicator
2021-05-01 20:10:44 +01:00
Sergio Martins
6254c2089f Add two new contributors 2021-05-01 20:05:46 +01:00
Sergio Martins
89f50769b6 cmake: Remove unneeded build presets
The default/implicit one is enough for those cases
2021-05-01 19:59:14 +01:00
Sergio Martins
a24f5e31b9 Merge pull request #192 from RomanPudashkin/setMaximumSize_fix
Fixed changing of the maximum size for widgets
2021-05-01 20:00:26 +01:00
Allen Winter
b338f183e1 CONTRIBUTORS.txt - added more contributors 2021-05-01 12:30:48 -04:00
Sergio Martins
8ab8e0524b Workaround Qt bug which broke the focus chain
Focusing a tab widget would focus an hidden tab bar, which makes
the propagation stop

Fixes #180
2021-04-30 15:59:27 +01:00
Sergio Martins
affb48f44d Fix restoring side-bar widget when it was deleted previously
We need to consult the user's widget factory, just as we do
for other cases where the dock widget is missing
2021-04-29 21:36:56 +01:00
Sergio Martins
d5b2336b69 refactoring: Move the dockWidgetFactoryFunc() call
It's now an impl-detail of DockRegistry::dockByName().
Just pass DockByNameFlag::CreateIfNotFound.

Allows this functionality to be used in other places
2021-04-29 21:29:58 +01:00
Sergio Martins
580e3a6a2c Coding style: Replace a bool argument with an enum
Since we'll be adding more enumerators
2021-04-29 21:20:26 +01:00
Roman Pudashkin
e3d5203f1a fixed the API for disabling the tab indicator 2021-04-29 21:50:17 +02:00
Sergio Martins
9e42b11272 Minor coding styling 2021-04-29 18:15:45 +01:00
Sergio Martins
ce93c3b739 qtquick: Fix memory leak 2021-04-29 18:15:33 +01:00
Sergio Martins
6a8e00bfa2 tests: Test restoring with DeleteOnClose and sidebar widgets
sidebar dock widgets which were deleted should still call
the user's dock widget factory

To be done next
2021-04-29 18:06:41 +01:00
Sergio Martins
0b5a99860f qtquick: Fix calling QWindow::setTitle()
For QtWidgets, it happens fine in FloatingWindow's constructor,
because we get the corresponding QWindow already. But for QtQuick
the QWindow is only created afterwards, so we have to delay
setting the title.
2021-04-29 17:18:35 +01:00
Sergio Martins
3f012a2ef1 Remove a bogus setWindowTitle()
Setting a widget would change the top-level window title!
By luck people set the widget before docking, but doesn't have
to be that way.
2021-04-29 16:23:22 +01:00
RomanPudashkin
a102e4ae1e fixed changing of the maximum size 2021-04-29 13:20:56 +02:00
Sergio Martins
03f5817488 Merge branch '1.3' 2021-04-28 22:08:57 +01:00
Sergio Martins
0f2edfdb4e Fix hidding the pin/auto-hide icon when side-by-side in floating
An else {} branch was missing.

Also just simplify the code, and call supportsAutoHideButton()
which wasn't being used.

Also removed some bogus updateAutoHideButton() calls from
the CTOR, needs to use singleShot() since the method is virtual,
the derived class isn't constructed yet
2021-04-28 22:06:42 +01:00
Sergio Martins
d289134b15 Add a unit-test for disabling RelativeFloatingWindowGeometry
Fixes #175
2021-04-28 21:27:47 +01:00
Sergio Martins
7475c7cc71 Remove unneeded include 2021-04-28 21:15:08 +01:00
Sergio Martins
7958eeeded Fully qualify LayoutSaver_p.h includes
Now that it's installed
2021-04-28 21:13:44 +01:00
Sergio Martins
f29f773555 Add a LayoutSaver_p.h fwd header 2021-04-28 21:10:23 +01:00
Sergio Martins
a113205881 Install LayoutSaver_p.h
Moved it into private/ too, not sure why it was in src/

For issue #175
2021-04-28 21:08:41 +01:00
Sergio Martins
7830ccb017 Move LayoutSaver::Private to the header 2021-04-28 21:00:26 +01:00
Sergio Martins
6a205a5406 Move some Layout::Private method definitions out of the class
In preparation to move the class to an header
2021-04-28 20:55:16 +01:00
Sergio Martins
d91a42930d Expose LayoutSaver::Private 2021-04-28 18:01:37 +01:00
Sergio Martins
6f3df707f4 Split RestoreOption_RelativeToMainWindow into more granular options
Mostly so we can have RestoreOption_RelativeToMainWindow but
without restoring floating windows

Said options are internal (for now?), we'll need more feedback before
turning them public (since once public forever public)

For issue #175

We'll add some private API so users can change the flags in the next
commit
2021-04-28 17:43:24 +01:00
Sergio Martins
f388b11d0d Added MainWindowBase::frameCountChanged()
So you can know when the layout added or removed dock widgets
Fixes #190
2021-04-28 16:28:04 +01:00
Sergio Martins
66d12fef82 fix build 2021-04-27 23:56:58 +01:00
Sergio Martins
83c744041e Merge branch '1.3' 2021-04-27 23:52:17 +01:00
Sergio Martins
dcac39a35f Don't restore window's maximized state when using RestoreOption_RelativeToMainWindow
We don't restore main window's geometry either
Fixes issue #184
2021-04-27 23:50:40 +01:00
Sergio Martins
c4d3ba71b2 Fix crash due to MainWindow not clearing m_overlayedDockWidget
When we close the overlayed widget we need to clear this variable

Added 1 real fix and a prophylactic check too.
2021-04-27 23:49:26 +01:00
Sergio Martins
74c74593e2 Don't restore window's maximized state when using RestoreOption_RelativeToMainWindow
We don't restore main window's geometry either
Fixes issue #184
2021-04-26 19:19:06 +01:00
Sergio Martins
62591bc360 quick: Use logical dpi factor of 1 for now
Only physical dpi scaling suported currently
2021-04-25 21:24:56 +01:00
Sergio Martins
1fca162fb2 quick|example: Enable hpdi scaling 2021-04-25 10:47:07 +01:00
Sergio Martins
82967435ea Added QtQuickHelpers::logicalDpiFactor() 2021-04-25 10:37:47 +01:00
Sergio Martins
7738354be1 Minor coding style fix 2021-04-25 10:26:09 +01:00
Sergio Martins
0d2166770e quick: Add a QtQuickHelpers class into the context
Will have some useful stuff there. Don't have a better place to put them.
2021-04-25 10:24:07 +01:00
Sergio Martins
9d7de9ea4d Fix sizing of widgets that skip LayoutSaver's restore
LayoutWidget::onResize() was bailing out early, but the actual
restore hadn't even started
2021-04-23 19:39:07 +01:00
Sergio Martins
5aa3ba25cc cmake: Add a Gammaray friendly preset
ASAN doesn't like Gammaray injection
2021-04-23 19:01:10 +01:00
Sergio Martins
b330f902fd tests: Move class into the header
File is getting too big
2021-04-23 18:03:49 +01:00
Sergio Martins
aa76dfba02 LayoutSaver: Support the user's factory func doing remapping
While restoring a layout, we expect all widgets to exist already,
but we allow the user to create them delayed, by providing
us a factory function.

What we're supporting in this commit is the ability of the user's
factory function returning a dock widget with an ID different
than the one that was requested. We then save that mapping so the
rest of the layout restore works with the new ID.
2021-04-23 14:55:01 +01:00
Sergio Martins
b3c2d87a9b Remove unused MULTISPLITTER_LAYOUT_MAGIC_MARKER 2021-04-23 14:35:29 +01:00
Sergio Martins
cc1347adf8 qtquick: Don't use native windows drop shadow with round corners
When using the Windows native drop shadow, the client area needs
to be rectangular, otherwise a white line appears at the top
2021-04-23 11:47:37 +01:00
Sergio Martins
df0a80b320 qtquick: Config::InternalFlag_UseTransparentFloatingWindow
Don't use a transparent floating window by default.
This matches QtWidgets behaviour.

It's only use would be to get round corners, but doesn't work well
with Window's drop shadow
2021-04-23 11:39:57 +01:00
Sergio Martins
26f7557834 cmake: Disable CCACHE when running the clazy preset 2021-04-23 09:50:51 +01:00
Sergio Martins
e6c2f29532 cmake: Specify which clazy checks to use
Trivial now with cmake presets
2021-04-22 15:44:16 +01:00
Sergio Martins
37cc16fe17 Fix a -Wsign-conversion warning
error: implicit conversion changes signedness: 'int' to 'unsigned long' [-Werror,-Wsign-conversion]
2021-04-21 20:35:56 +01:00
Sergio Martins
c7ac88836a Fix some clazy errors
Mostly about using qualified names for methods called from QML
2021-04-21 20:25:45 +01:00
Sergio Martins
536e048f1c Fix build with Qt 5.9
The needed overload was introduced in Qt 5.10 only
2021-04-21 19:08:30 +01:00
Sergio Martins
4671848428 vscode: Also add C_Cpp.autocompleteAddParentheses to the other workspaces 2021-04-20 23:03:36 +01:00
Sergio Martins
4449785e2c vscode: Enable C_Cpp.autocompleteAddParentheses 2021-04-20 23:02:35 +01:00
Sergio Martins
39deb9ee83 tests: Minor refactoring, reduce copy-paste 2021-04-20 23:02:07 +01:00
Sergio Martins
2266f4a75c Fix FloatingWindow max size when there's tabbed dock widget
We don't support this case yet
2021-04-20 22:56:26 +01:00
Sergio Martins
06b680f603 Also update FloatingWindow's max size when children change constraints
A dock widget can change its max size later in life, so we need
to react to that
2021-04-20 22:52:08 +01:00
Sergio Martins
ec6be7d1a5 Fix potential crash 2021-04-20 22:51:43 +01:00
Sergio Martins
37040bfc9e Also update FloatingWindow max-size when adding nested dock widgets
We only support FLoatingWindow max-size when there's 1 frame.
When adding more, we need to remove the max size
2021-04-20 22:34:36 +01:00
Sergio Martins
1f4f7ec0e5 FloatingWindow now honours max size of the docked widget
Only if there's a single dock widget though.
Tabbed cases are more complicated as QStackedLayout doesn't
propagate size constraints
2021-04-20 21:00:33 +01:00
Sergio Martins
a31571ab2c Bound FloatingWindow::maxSizeHint()
Can't be bigger than Qt's hardcoded limit
Fixes a warning emitted by Qt
2021-04-20 20:57:14 +01:00
Sergio Martins
714ef2adb8 cmake: Fix a preset name
We don't have dev-qtquick6.
Should probably be added.
2021-04-20 20:22:24 +01:00
Sergio Martins
e447bbf03b vscode: Don't specify tasks
The cmake extension takes care of this
2021-04-20 20:18:32 +01:00
Sergio Martins
3846b638fb cmake: Add build presets too
This is new in cmake 3.20 and makes the vscode experience much better
2021-04-20 20:16:44 +01:00
Sergio Martins
6ae8a203d9 qtquick: Fix build 2021-04-20 19:43:26 +01:00
Sergio Martins
1dbd491738 Minor: Move a comment to another place 2021-04-20 19:16:14 +01:00
Sergio Martins
e8693edb33 Minor refactoring: Factor out the FloatingWindow max size code
Created FloatingWindow::maxSizeHint()
2021-04-20 19:13:32 +01:00
Sergio Martins
5cbad00cb5 Minor coding style: bail out early 2021-04-20 18:47:34 +01:00
Sergio Martins
c6e4deb0ca Merge branch '1.3' 2021-04-19 09:47:43 +01:00
Sergio Martins
693fb84a3e Fix DockWidgetBase::isFocusChanged() not being emitted
The previous commit fixed that the dock widget wasn't
getting focused on tab change, but didn't fix the signal.

When changing tabs, FocusScope::setFocused() would bailout
early because it was already focused, so never emitted
the signal for the new focused dock widget.

Refactored the code a bit and it's more robust now.
Setting the current focused widget is now centralized in
DockRegistry. Before it was split in two different places.

Fixes issue #188
2021-04-19 09:42:59 +01:00
Sergio Martins
b0a7d5d4a0 Merge branch '1.3' 2021-04-19 00:16:39 +01:00
Sergio Martins
818acc0ff1 Fix edge case when focusing FocusScope and tab bar is focused
When we focus a FocusScope we focus the last focused widget
inside that scope. But it could happen that the last focused widget
was the tab bar itself, which isn't very useful.

Fixes issue #188
2021-04-19 00:15:15 +01:00
Sergio Martins
819fec6061 Implement missing function body 2021-04-18 23:56:21 +01:00
Allen Winter
4ea8c98243 cmake/QtInstallPaths.cmake - don't cache the QT_FOO variables
makes changing Qt versions easier
2021-04-16 07:55:40 -04:00
Sergio Martins
95317a7336 Add signal DockWidget::aboutToDeleteOnClose()
It's emitted when the dock widget is going about deleted due to
the DeleteOnClose functionality
2021-04-14 15:24:15 +01:00
Allen Winter
9b6abfbbc3 src/private/quick/MainWindowInstantiator_p.h - fix include guard 2021-04-12 08:41:13 -04:00
Sergio Martins
4bee3023d2 SegmentedIndicators: Don't show inner segments when having only 1 frame 2021-04-12 10:52:48 +01:00
Sergio Martins
45f12db8d3 windows: Fix place of export macro for namespace 2021-04-12 10:02:50 +01:00
Sergio Martins
9956b3fed3 qt6: Fix KDDW build on Windows
Namespace needs to be exported due to Q_NAMESPACE
2021-04-12 09:57:49 +01:00
Sergio Martins
374e837aa9 Allow to style SegmentedIndicator 2021-04-09 17:01:20 +01:00
Sergio Martins
6ffd3e574f qtquick: Add support for LayoutSaver
You can now instantiate LayoutSaver {} in QML and save/restore
layouts
2021-04-08 23:23:24 +01:00
Sergio Martins
8a3706f6cb docs: document LayoutSaver's internals
explains the 2-phase restore
2021-04-08 20:46:13 +01:00
Sergio Martins
faa16ad910 docs: Add some doxygen to LayoutSaver 2021-04-08 20:39:23 +01:00
Sergio Martins
eb69e25622 qtquick: More invokables 2021-04-08 20:33:48 +01:00
Sergio Martins
b006bb0c3c vscode: Remove empty MIModes
On MSVC they are not required, and the editor highlights them
as wrong
2021-04-08 19:58:00 +01:00
Sergio Martins
02ed50b336 vscode: Add launches for qtwidgets 2021-04-08 19:47:39 +01:00
Sergio Martins
f0023bc084 README-QtQuick: Mention workaround for lagging windows 2021-04-08 12:23:26 +01:00
Sergio Martins
6502f7760d README-QtQuick: Mention there's some slowness in some rare setups 2021-04-08 11:53:42 +01:00
Sergio Martins
7606691ea3 QtQuick: Add more properties to DockWidgetInstantiator 2021-04-08 10:28:21 +01:00
Sergio Martins
257a1e9474 vscode: Remove tests_launcher from launchers
It's not something devs need to run manually
2021-04-07 22:44:36 +01:00
Sergio Martins
9f02ccbb48 qtquick: Add more properties to DockWidgetBase.h 2021-04-07 22:42:33 +01:00
Sergio Martins
a18199e9a2 vscode: Add launches for qtquick 2021-04-07 22:41:44 +01:00
Sergio Martins
cdd6f998c4 qtquick: Add a missing Q_ENUM 2021-04-07 22:20:15 +01:00
Sergio Martins
df21b6fc6f qtquick Add a bunch of invokables to the MainWindowInstantiator_p.h 2021-04-07 22:16:54 +01:00
Sergio Martins
edf7dee78e qtquick: Add more properties and Q_INVOKABLE to main window 2021-04-07 22:05:51 +01:00
Sergio Martins
f723e5ea59 qtquick: Add some properties to main window 2021-04-07 21:48:05 +01:00
Sergio Martins
748243f512 qtquick: Allow to call addDockWidget() from QML 2021-04-05 22:56:08 +01:00
Sergio Martins
e7d37402d7 Rename DefaultSizeMode::None
Fixes QtQuick warnings about two different enum class having an
enumerator called "None"

Known QML limitation with "enum class"
2021-04-05 22:33:11 +01:00
Sergio Martins
7c101ae3af qtquick: comments++ 2021-04-05 20:41:59 +01:00
Sergio Martins
cf9cdd8b3b qtquick: Add some Q_INVOKABLE to MainWindowBase 2021-04-05 20:37:58 +01:00
Sergio Martins
b18783c17a qtquick: Add some Q_ENUM_NS 2021-04-05 20:36:38 +01:00
Sergio Martins
201d06d878 qtquick: Use MainWindowOption instead of int for the property too 2021-04-05 20:32:11 +01:00
Sergio Martins
742ef7d529 qtquick: Use the MainWindowOptions enum instead of int 2021-04-05 20:28:57 +01:00
Sergio Martins
3d73fc10cd qtquick: Add some Q_INVOKABLE to DockWidgetBase.h
So these methods can be called from QML
2021-04-05 18:50:25 +01:00
Sergio Martins
075c1b06f7 qtquick: Add some Q_INVOKABLE to DockRegistry
So they can be called from QML if the user wants
2021-04-05 18:42:15 +01:00
Sergio Martins
2706a3d379 qtquick: Add "Close All" option in the example 2021-04-05 18:31:56 +01:00
Sergio Martins
e476dce1d4 qtquick: Fix some undefined warnings at shutdown 2021-04-05 18:06:07 +01:00
Sergio Martins
2f25657cfa Fix QtQuick build 2021-04-05 17:08:47 +01:00
Sergio Martins
1167545199 Update Changelog 2021-04-05 16:51:36 +01:00
Sergio Martins
fcd1fae77e qtquick: Add a MenuBar to the example, allows to toggle 2021-04-05 16:48:13 +01:00
Sergio Martins
06db10561c qtquick: Use QQmlApplicationEngine in the examples
So we can add menus and such
2021-04-05 16:41:45 +01:00
Sergio Martins
ead9e8945e qtquick: Allow to add the guest widget declaratively
This is an alternative to setting source
2021-04-05 16:22:56 +01:00
Sergio Martins
15d4f77d5d Revert "qtquick: Remove unused QQuickItem::classBegin()"
This reverts commit e4fdf33cfc.
Looks like it's needed.

Need to debug why calling QQuickItem::classBegin cause the main window
to not show anything
2021-04-05 15:59:59 +01:00
Sergio Martins
c903a64726 Use a QQuickItem as MainWindowInstantiator's parent
This is simpler, no need for QWidgetAdapter
2021-04-05 15:47:12 +01:00
Sergio Martins
8fa63a8773 qtquick: Remove unneeded private import 2021-04-05 15:06:57 +01:00
Sergio Martins
8a0e6c90b9 qtquick: the user will now use "MainWindowLayout" instead of "MainWindow"
As MainWindow wasn't actually a window.

While for QtWidgets it makes sense for it to be a QMainWindow, in
QtQuick let's make it easy to embed a dock widget layout.

Also, our MainWindowQuick doesn't have any menus and what not that
QMainWindow has.
2021-04-05 15:04:27 +01:00
Sergio Martins
e4fdf33cfc qtquick: Remove unused QQuickItem::classBegin()
No need to override it
2021-04-05 14:56:06 +01:00
Sergio Martins
548e38fca0 qtquick: Don't create two main windows with the same name 2021-04-05 14:48:51 +01:00
Sergio Martins
c804c806e1 Add DockRegistry::containsMainWindow(uniqueName) 2021-04-05 14:48:43 +01:00
Sergio Martins
7c291691aa qtquick: Fix customtitlebar example 2021-04-05 14:43:51 +01:00
Sergio Martins
cec8cf25ef Rename MainWindowWrapper to MainWindowInstantiator
Makes it consistent with DockWidgetInstantiator.
Creates the main window onComplete, no need for the user
to call init() explicitly anymore
2021-04-05 14:42:46 +01:00
Sergio Martins
5a2812ecf3 qtquick: Fix undefined variable error in example 2021-04-05 14:35:40 +01:00
Sergio Martins
0f09ba717f qtquick: Move the "Another" button into the main window 2021-04-05 14:09:59 +01:00
Sergio Martins
1026abbbf4 qtquick: Make DockWidgetInstantiator a QQuickItem instead of only QObject
Can be put in Repeater now
2021-04-05 13:57:57 +01:00
Sergio Martins
5b578c86e8 qtquick: Fix build 2021-04-05 13:50:15 +01:00
Sergio Martins
d7e4a782c1 qtquick: Add missing signal
Fixes tests
2021-04-05 06:43:59 +01:00
Sergio Martins
d65dfeceb0 Fix QtQuick developer build 2021-04-05 06:34:44 +01:00
Sergio Martins
e9a7a3a5f5 Merge branch '1.3' 2021-04-05 06:27:45 +01:00
Jacob Young
8504252142 Handle tab icon updates
Closes PR #135
2021-04-05 06:26:47 +01:00
Sergio Martins
19730ab6a4 Fix crash when using MainWindow::layoutEqually()
When distributing space we should honour the other widgets
min-size too, and not give too much

Since the layouting code is complex, this won't be backported to
1.3
2021-03-31 15:23:24 +01:00
Sergio Martins
44ae75110b Added MainWindowBase::closeAllDockWidgets() 2021-03-31 10:51:20 +01:00
Sergio Martins
4ab2a93d59 Merge branch '1.3' 2021-03-31 10:01:18 +01:00
Sergio Martins
f82ea82403 Harden Item::layoutEqually()
Could cause an infinit loop if the layout was corrupted
2021-03-31 10:00:28 +01:00
Sergio Martins
fff6c004e0 Pass -warn-uninitialized to cmake 2021-03-26 13:46:02 +00:00
Allen Winter
75c7744e59 move the class private header up in the include order 2021-03-23 08:36:24 -04:00
Allen Winter
1e8bdba2dd minor spelling fix 2021-03-23 07:47:31 -04:00
Allen Winter
2587831855 src/MainWindowMDI.cpp - add trailing newline 2021-03-23 07:46:27 -04:00
Allen Winter
f00a283722 fix SPDX-FileCopyrightText: and Author: lines 2021-03-23 07:44:37 -04:00
Sergio Martins
e3b333aca8 Make DockWidget::raise() raise the frame in MDI mode 2021-03-18 15:08:54 +00:00
Sergio Martins
c9602c2b0a Merge branch '1.3' into master 2021-03-15 18:25:25 +00:00
Sergio Martins
c660c80a15 Added DockWidgetBase::frameGeometryChanged() 2021-03-15 18:25:01 +00:00
Sergio Martins
6f889d1c3b Fix indicator overlay z-order when using Flag_KeepAboveIfNotUtilityWindow
The overlay window needs to be on top

Fixes #181
2021-03-15 18:23:00 +00:00
Sergio Martins
80577832d7 Add a file with QtQuick TODO items
Will be updating this as I go.

Mostly only more elegant API is needed at this point.

Closing #49 as all questions were answered.

Fixes #49
2021-03-14 15:41:57 +00:00
Allen Winter
7a18ef77cd buildsystem - fix more cmake --warn-unitialized
* PROJECT_VERSION - explicitly set for ECMSetupVersion
* SHIBOKEN_CUSTOM_PATH - init (rename to SHIBOKEN_CUSTOM_PREFIX)
* PYSIDE2_CUSTOM_PREFIX - init
* PYSIDE_EXTRA_INCLUDES (removed, not used)

Task-Id: KDDW-30
2021-03-13 17:27:47 -05:00
Allen Winter
e29f7cb1d3 CMakeLists.txt - fixup a bit of documentation 2021-03-13 17:08:55 -05:00
Sergio Martins
8970274810 cmake: Fix some --warn-uninitialized warning 2021-03-13 09:51:06 +00:00
Sergio Martins
d57fd8bfd3 cmake: Uncomment the QtQuick option
People can try it now
2021-03-13 09:39:23 +00:00
Sergio Martins
8507866891 cmake: Remove the fat warning about QtQuick
It can be tried now
2021-03-13 09:37:31 +00:00
Sergio Martins
425d53fbe3 cmake: Remove unused ${RESOURCES_QUICK} variable 2021-03-13 09:35:56 +00:00
Sergio Martins
b0cb983830 qtquick: relax the warning about removing dock widget twice
can happen due to benign reentrancy
2021-03-10 13:38:22 +00:00
Sergio Martins
02515d8956 MDI: Fix dock widget size getting out of sync with the layout item
When resizing with mouse, update the layout item too.

Wasn't a big deal, as this is MDI, layout doesn't do much. But
last used geometries werent being saved
2021-03-09 20:30:41 +00:00
Sergio Martins
447b4337dd Add DockWidget::frameGeometry() 2021-03-09 17:55:36 +00:00
Sergio Martins
633daf124e Fix some warnings about shadowing methods 2021-03-09 15:43:36 +00:00
Sergio Martins
446560931b MDI: Fix docked widget geometries not being remembered when floating
We shouldn't move the Frame directly. Instead, do it through the
layout, which will then remember the last docked geometry
2021-03-07 16:56:37 +00:00
Sergio Martins
9fe11a7ad5 qtwidgets|MDI: Fix showing resize handles
if there was no frame being resized it would be nullptr, and hence
enter that block.

QtQuick not affected since it uses mouse areas to change the cursor
shape
2021-03-05 12:19:16 +00:00
Sergio Martins
b099994ac5 qtquick|MDI: Remove the QtQuick special case
Now behaves as QtWidgets
2021-03-05 12:05:19 +00:00
Sergio Martins
a8d56ef4e6 qtquick6: Fix build 2021-03-04 13:57:25 +00:00
Sergio Martins
1f8d212dee Qt6: Fix build
Types in properties can't be forward declared anymore
2021-03-04 13:27:58 +00:00
Sergio Martins
64ea87f4cc Add missing fwd header for Frame_p.h 2021-03-04 13:27:32 +00:00
Sergio Martins
e6fef433d5 Added DockWidgetQuick::frame() 2021-03-03 17:59:43 +00:00
Sergio Martins
2f212031b3 qtquick|MDI: Don't set a size smaller than its min 2021-03-03 17:03:06 +00:00
Sergio Martins
586ab710f6 qtquick: Expose the tabbar height property 2021-03-03 16:36:23 +00:00
Sergio Martins
d263ae649e Allow to configure the MDI popup threshold 2021-03-03 16:33:32 +00:00
Sergio Martins
c81ca45e41 qtquick|MDI: Improvements for resizing 2021-03-03 15:21:22 +00:00
Sergio Martins
9ce50fa305 qtquick: Minor refactoring, deal in CursorPosition 2021-03-03 14:59:24 +00:00
Sergio Martins
f0240deaeb qtquick: Use Q_NAMESPACE for the KDDockWidgets namespace 2021-03-03 14:40:24 +00:00
Sergio Martins
017f06dcfb qtquick|MDI: Improvements for the resize handler
More margin, fixed sizes of some handlers and fixed z order
2021-03-03 13:47:14 +00:00
Sergio Martins
54f17cb546 qtquick: Remove unneeded mouse area from frame
Just to simplify things. Let's just have the resize handlers.
A target can have many event sources.
2021-03-03 13:22:12 +00:00
Sergio Martins
f174ab6ebc qtquick: Create ResizeHandlerHelper.qml to save some code 2021-03-03 12:57:37 +00:00
Sergio Martins
263f936690 Fix dock widgets in MDI getting bogus sizes
Setting the Item's min-size would resize the guest while the
guest was being set
2021-03-03 12:20:40 +00:00
Sergio Martins
bd903a0353 qtquick: Fix Frame's minimum size
It wasn't accounting for the margins, and the "heightWhenVisible"
property was Nan, making the entire expression be 0
2021-03-03 10:08:37 +00:00
Sergio Martins
5040d3a6b6 qtquick: Allow to update the size constraints from QML 2021-03-03 10:02:45 +00:00
Sergio Martins
3684da776d Added DockWidgetQuick::frameVisualItem() 2021-03-03 09:27:27 +00:00
Sergio Martins
bc17c8e5b3 MDI: Don't active other resize handlers when resize in progress
When we're resizing a docked dock widget, the other dock widget's
resize handlers should be disabled
2021-03-02 22:21:12 +00:00
Sergio Martins
778c647782 qtquick: Register Frame 2021-03-02 22:14:07 +00:00
Sergio Martins
2a91f6279b qtquick: Minor code refactoring
Uses less code
2021-03-02 22:05:48 +00:00
Sergio Martins
4ef2ddbfec Add DockRegistry::frameInMDIResize()
Only emitted in a MDI layout. Emitted when one dockwidget is
being resized
2021-03-02 22:00:54 +00:00
Sergio Martins
ff06f0cc73 Fix build 2021-03-02 21:06:57 +00:00
Sergio Martins
a37ab34fae qtquick|MDI: When dragging don't trigger the resize drag handlers
MouseArea.enabled, even if false, will change the cursor shape.
So explicitly change the cursor to ArrowShape
2021-03-02 20:58:44 +00:00
Sergio Martins
cb2ffe66af qtquick|MDI: Fix resizing inner MDI dock widgets
It was flaky. The mouse move events came from global event filter
but the mouse press came from the Frame's mouse area. Sometimes the
QQuickWindow wouldn't deliver the press to the frame if it was done
outside, while the moves were changing the cursor shape since
we had a treshold

Now we guarantee that whenever the cursor changes the resize
will really happen
2021-03-02 14:40:42 +00:00
Sergio Martins
16b0770d72 qtquick: Fix minor qml warning 2021-03-02 14:31:15 +00:00
Sergio Martins
3fe44ee735 qtquick: Enable transparency for the floating window
You can now have windows with round corners
2021-03-02 12:19:51 +00:00
Sergio Martins
40d1a72300 qtquick: Fix QtQuick min-sizes not working when wrapped 2021-03-02 11:02:15 +00:00
Sergio Martins
4d428d42f6 Added DockWidgetBase::setMDIZ(int z)
Sets the Z order of the dockwidget within the MDI layout
2021-03-02 10:43:07 +00:00
Sergio Martins
7e9896263b Update .gitignore 2021-03-02 10:22:57 +00:00
Sergio Martins
cf0665c9b6 Added DockWidgetBase::setMDISize()
Only for dock widgets in MDI layout, where they are freely resizable
2021-03-02 10:21:29 +00:00
Sergio Martins
93c011c69d Added DockWidgetBase::setMDIPosition(QPoint pos)
Moves the window within the layout.
Only applies to MDI layouts.
2021-03-01 23:41:53 +00:00
Sergio Martins
f50c0b9d06 qtquick: Fix typo 2021-03-01 23:24:29 +00:00
Sergio Martins
6fc79d942b qtquick: add a way to disable the default mouse redirectors
So user can use his own
2021-03-01 23:23:04 +00:00
Sergio Martins
d01228d9ff Fixes cases where actualTitleBarChanged() wasn't emitted 2021-03-01 23:02:56 +00:00
Sergio Martins
b58d766d54 qtquick: Add Q_INVOKABLE to DockWidgetBase::setFloating() 2021-03-01 22:38:23 +00:00
Sergio Martins
79cbb96a38 Remove some unneeded qDebug 2021-03-01 22:34:15 +00:00
Sergio Martins
aabaeacb81 Improve a warning 2021-03-01 22:30:31 +00:00
Sergio Martins
3ab3e6d41b qtquick: Don't allow to have two redirectors for the same source
One event source can only have one redirector
2021-03-01 22:23:46 +00:00
Sergio Martins
f2f4afd0bb qtquick: Allow the user to customize the titlebar margins 2021-03-01 20:50:46 +00:00
Sergio Martins
0d62c43b9e qtquick: keep the original parent of the guest around
For debug purposes
2021-03-01 19:58:00 +00:00
Sergio Martins
1614d5702c Allow to call DockWidget::setWidget(nullptr)
In case you need to change ownership
2021-03-01 19:56:46 +00:00
Sergio Martins
610b9542e9 qtquick: Expose the event source for debug purposes 2021-03-01 17:13:54 +00:00
Sergio Martins
946f32a274 qtquick: debug++ 2021-03-01 17:12:09 +00:00
Sergio Martins
c7a6bc015e qtquick: Minor performance optimization
Only check the properties for mouse events
2021-03-01 16:54:32 +00:00
Sergio Martins
19fd1635e6 Remove userType() from public API for now
If added, will need to be through overloads, to not break source
compat. Will add them once there's a need.
2021-03-01 16:34:22 +00:00
Sergio Martins
74b034a195 Merge branch '1.3'
Fixes #172
2021-03-01 15:48:45 +00:00
David Faure
581139d099 SideBarButton: use color roles from the widget palette 2021-03-01 16:42:59 +01:00
Sergio Martins
e5492ea906 qtquick: Allow to override the mouse redirector 2021-03-01 14:50:14 +00:00
Sergio Martins
623133a0dc qtquick: Add DockWidgetQuick::actualTitleBar()
It's a pointer o either Frame::titleBar() or FloatingWindow::titleBar().
It's the same as Frame::actualTitleBar().
2021-03-01 14:35:14 +00:00
Sergio Martins
6baa8f2dbb qtquicl: Fix invisible tab bar eating mouse events 2021-03-01 14:19:39 +00:00
Sergio Martins
d2739d7218 qtquick: disable tabbar mouse area if tabbar hidden 2021-03-01 13:15:30 +00:00
Sergio Martins
5702101935 Add a Q_PROPERTY for Frame::actualTitleBar() 2021-03-01 12:50:25 +00:00
Sergio Martins
35d45a7523 qtquick: Fix some places which weren't forwarding userType 2021-02-28 20:44:19 +00:00
Sergio Martins
e37c1f0e8c qtquick: Pass the userType all the way to titleBarFilename() 2021-02-28 20:33:46 +00:00
Sergio Martins
ac0d35ef12 Fix clazy warning 2021-02-28 19:03:16 +00:00
Sergio Martins
15e63381a9 Added DockWidgetBase::setUserType(int)
This is an opaque value which KDDW won't try to interpret or do
anything with it other than forward it to the FrameworkWidgetFactory.

Which if specialized by the user he can have different title bars
for different said "dock widget types"
2021-02-28 18:57:35 +00:00
Sergio Martins
aa49ddacd5 qtquick: Allow the user to change the contents margin for Frame 2021-02-28 18:13:55 +00:00
Sergio Martins
f68e876bcb qtquick: Make the setWidget(QQuickItem) overload also fill parent 2021-02-28 16:05:44 +00:00
Sergio Martins
6b82ded399 qtquick: Allow derived FloatingWindow to override margins 2021-02-28 16:04:28 +00:00
Sergio Martins
000e67a09e qtquick: Register DockWidgetBase 2021-02-28 15:26:05 +00:00
Sergio Martins
1b6aa4c3d1 qtquick: Inject the dock registry into the context
Useful to call from QML if needed
2021-02-28 15:01:05 +00:00
Sergio Martins
8912a2c842 Remove debug 2021-02-28 14:50:12 +00:00
Sergio Martins
4de50db68c Added DockWidgetQuick::setWidget(QQuickItem*) overload
And expose it to QML
2021-02-28 14:48:09 +00:00
Sergio Martins
6b95e4aac9 Allow to add to MDI area and start as hidden
It will remember its position
2021-02-28 00:51:12 +00:00
Sergio Martins
c27658822e Add MainWindowMDI::addDockWidget() taking QPointF 2021-02-28 00:24:08 +00:00
Sergio Martins
8ec980c1e8 Add convenience DockRegistry::mdiMainWindowByName() 2021-02-28 00:20:33 +00:00
Sergio Martins
a952c5829a qtquick: Add MainWindowMDI.qml
A convenience wrapper
2021-02-27 23:48:15 +00:00
Sergio Martins
20e1b55a8a qtquick: make sure our QML types are registered early on 2021-02-27 15:52:31 +00:00
Allen Winter
a2605868db Merge branch '1.3' 2021-02-26 18:30:03 -05:00
Allen Winter
67be35b9f8 CMakeLists.txt - don't create the dummy docs target
it can conflict when used as a submodule
2021-02-26 18:29:10 -05:00
Allen Winter
b15eb1e62f Merge branch '1.3' 2021-02-26 17:09:08 -05:00
Allen Winter
d2e3ec0448 buildsystem - add a 'docs' target
only available with cmake -DKDDockWidgets_DOCS=true
2021-02-26 17:07:58 -05:00
Allen Winter
828c403fe5 Merge branch '1.3' 2021-02-26 16:40:18 -05:00
Allen Winter
53d3bc86ea conan - support build_with_qt6 2021-02-26 16:35:33 -05:00
Allen Winter
6ed8742cc1 buildsystem - install library with "-qt6" when built for Qt6 2021-02-26 16:35:08 -05:00
Sergio Martins
7bd047f6e6 qtquick: Make DockWidget.qml be a Rectangle
So user can change its color
2021-02-26 19:29:30 +00:00
Sergio Martins
482757b1cc qtquick: Don't hardcode "FloatingWindow.qml"
Allow the user to specify their impl
2021-02-26 19:21:42 +00:00
Sergio Martins
c143f832c6 qtquick: Don't hardcode "Frame.qml"
Allow the user to specify their impl
2021-02-26 19:12:53 +00:00
Sergio Martins
67a173ef53 qtquick: Don't hardcode "DockWidget.qml"
Allow the user to specify their impl
2021-02-26 18:57:31 +00:00
Sergio Martins
c2c37488a3 Merge branch '1.3' 2021-02-26 17:26:35 +00:00
Sergio Martins
8c1840b9cf Fix popups in overlayed dockwidgets not working 2021-02-26 17:26:04 +00:00
Sergio Martins
1088e37cd4 Improve warning 2021-02-26 17:00:22 +00:00
Sergio Martins
4d6c3dac3d qtquick: Warn there's no QQmlEngine set 2021-02-26 16:58:58 +00:00
Sergio Martins
adf29873ef Define KDDOCKWIDGETS_QTQUICK when linking against QtQuick KDDW
This is added when building, but also needs to be in the public
interface
2021-02-26 16:47:04 +00:00
Sergio Martins
772afe29ea Merge branch '1.3' 2021-02-26 15:45:46 +00:00
Sergio Martins
9c78953800 Fix tests on linux
Native title bar is specific to Windows
2021-02-26 15:38:00 +00:00
Sergio Martins
ff67b9bcbc Merge branch '1.3' into master 2021-02-26 15:20:32 +00:00
Sergio Martins
103de4f910 Update ChangeLog 2021-02-26 15:15:29 +00:00
Sergio Martins
7c3f06f98f When using a native title bar make floating window geometry smaller
When undocking a dock widget, the size of the dock widget should
be maintained

Fixes #174
2021-02-26 15:12:43 +00:00
Sergio Martins
6ac77a7662 Use the flags instead of the enum 2021-02-26 14:36:22 +00:00
Sergio Martins
610b85d01a Minor readability improv: replace bool with enum
CC issue #174
2021-02-26 14:32:55 +00:00
Sergio Martins
d4d222ebd3 Update ChangeLog 2021-02-25 22:01:54 +00:00
Sergio Martins
5cbed1d34b if native title bar + Qt::Tool, double-click should redock
When using the native Windows title bar with Qt::Tool, double-clicking
the title bar should redock the window.

Fixes #173
2021-02-25 21:59:43 +00:00
Sergio Martins
ba4a2eef5c Also cancel a drag if we receive a non-client double click 2021-02-25 21:58:12 +00:00
Sergio Martins
acdf03fc84 Merge branch '1.3' into master 2021-02-24 13:56:28 +00:00
Sergio Martins
a6f19e07c4 Fixed Flag_NativeTitleBar not hidding the client title bars
When restoring the layout the native title bar would be visible
Fixes #170
2021-02-24 13:52:44 +00:00
Sergio Martins
f07301bb1e Update ChangeLog 2021-02-24 12:10:38 +00:00
Sergio Martins
2116e3741b Improve restoring layout when RestoreOption_RelativeToMainWindow is used
Doesn't make much sense to apply a scalling factor to the floating window's
position. Instead we should apply the factor to the delta position between
the main window and the floating window

Fixes #171
2021-02-23 21:02:01 +00:00
Sergio Martins
1f11c732ed Remove unused function 2021-02-23 20:16:32 +00:00
Sergio Martins
e42bee27a4 Remove unused function 2021-02-23 20:14:25 +00:00
Sergio Martins
b36dcf1325 Fix macOS developer-build due to unused variable 2021-02-22 10:46:56 +00:00
Sergio Martins
421746c943 Margins now honour logical dpi and update when changing screen 2021-02-22 00:02:57 +00:00
Sergio Martins
f544ac58e6 Apply the logical DPI factor to the MainWindow contents margins 2021-02-21 23:42:11 +00:00
Sergio Martins
6047275cfa Add a localDpiFactor helper
As we don't do everything via QStyle. layout margins for example
still need a manual factor
2021-02-21 23:02:49 +00:00
Sergio Martins
630d832f50 Emit DockRegistry::windowChangedScreen()
We now have a signal we can connect to adapt sizes to logical
dpi changes
2021-02-21 19:45:35 +00:00
Sergio Martins
e0a34465d8 MDI: Raise dock widget when clicking on it 2021-02-21 16:26:16 +00:00
Sergio Martins
443a4049c3 qtquick|MDI: Also support raising non top-level windows
If we drag mdi windows around they'll raise now
2021-02-21 15:44:56 +00:00
Sergio Martins
54980e7585 Fix Qt6 build on Windows 2021-02-20 21:42:44 +00:00
Sergio Martins
14ff8bb26b Fix mingw build 2021-02-19 11:33:01 +00:00
Sergio Martins
615bb0ee3f Fix linux developer-build 2021-02-19 11:25:02 +00:00
Sergio Martins
986fd8c13b CustomFrame: Don't use QWindow::fromWinId()
as that creates a new QWindow
2021-02-18 18:43:43 +00:00
Sergio Martins
ec1cc27815 Added DockRegistry::windowForHandle() 2021-02-18 18:39:35 +00:00
Sergio Martins
3874e2d886 CustomFrame: Added a recursion guard 2021-02-18 18:32:14 +00:00
Sergio Martins
1afcf21529 CustomFrame: Same some cpu cycles in case we don't care about the events 2021-02-18 18:21:32 +00:00
Sergio Martins
4c0f3bd7cb Fix build with older compilers 2021-02-18 17:50:14 +00:00
Sergio Martins
9aafa2a662 CustomFrame: the native event handling now honours the features 2021-02-18 15:50:12 +00:00
Sergio Martins
029ba1202e CustomFrame: Add a NativeFeatures enum
Replaces the htCaptionRect. As we don't want to pass many arguments,
instead just pass a struct which describes which native features
to enable
2021-02-18 15:14:52 +00:00
Sergio Martins
b5043b2b87 CustomFrame: Move the features enum up 1 level 2021-02-18 14:40:20 +00:00
Sergio Martins
52ce80fd97 CustomFrame: Use an enum instead of bool return in our callback 2021-02-18 14:22:26 +00:00
Sergio Martins
cd19c5eb38 CustomFrame: Allow to specify a callback for QWindow opt-in
Which QWindows should get a custom frame is up to you. Just
return true in the callback.
2021-02-18 14:10:40 +00:00
Sergio Martins
0d101d779f Fix unused variable warning 2021-02-18 11:29:02 +00:00
Milian Wolff
1ff6f43eac Allow disabling the uninstall target
Prevents clashes when kddockwidgets is included as a submodule
into a project that already defines an uninstall target.
2021-02-17 20:47:49 +01:00
Sergio Martins
98d892f643 CustomFrame: Apply the drop-shadow code initially 2021-02-17 19:46:56 +00:00
Milian Wolff
cc80afff7d Fix compile on Linux 2021-02-17 20:36:37 +01:00
Milian Wolff
91ad74e3ad Relay status tip events to the parent of FloatingWindow
That allows the status bar of the main window - if available - to
show the event contents.
2021-02-17 20:36:37 +01:00
Sergio Martins
b128d25fbe Added convenience FloatingWindow::mainWindow() 2021-02-17 19:35:54 +00:00
Sergio Martins
8b23769ccc Remove some debug code 2021-02-17 18:17:48 +00:00
Sergio Martins
13f84ab518 Fix QtQuick build 2021-02-17 18:14:57 +00:00
Sergio Martins
feadc1ff9e Add a CustomFrameHelper class
So we can reuse the custom frame for arbitrary windows
2021-02-17 18:02:51 +00:00
Sergio Martins
f75c3a123e Merge branch '1.3' into master 2021-02-17 17:44:05 +00:00
Sergio Martins
12dfe49d9b Fix unused variable warning 2021-02-17 17:14:10 +00:00
Sergio Martins
545618964d Only apply the async mouse compensation when undocking
Not needed when moving regular windows
2021-02-17 17:01:03 +00:00
Sergio Martins
a6f3f21b70 Added Draggable::isWindow() 2021-02-17 16:54:15 +00:00
Sergio Martins
e6135f49fb Make WidgetResizeHandler::handleWindowsNativeEvent() more generic
Decoupled it from the KDDW specific parts. Can now be used
by non FloatingWindow widgets
2021-02-16 20:28:59 +00:00
Sergio Martins
cd3a1c869e Add missing include 2021-02-16 19:32:00 +00:00
Sergio Martins
8bb21b12aa Add a fwd header for WidgetResizeHandler_p.h too 2021-02-16 19:29:19 +00:00
Sergio Martins
f500791ba3 FloatingWindow: This setup code is windows only 2021-02-15 22:15:26 +00:00
Sergio Martins
4ebc4e9546 Fix Linux build 2021-02-15 22:09:27 +00:00
Sergio Martins
94ee2e55fd Move FloatingWindow::setupWindow() into a reusable function
So other QWindow can use this
2021-02-15 22:03:44 +00:00
Sergio Martins
e3c370eb6b Revert "Move FloatingWindow::setupWindow() into a reusable function"
This reverts commit 6fea5af585.
Need to fix the windows build first
2021-02-15 10:43:15 -08:00
Sergio Martins
6fea5af585 Move FloatingWindow::setupWindow() into a reusable function
So other QWindow can use this
2021-02-15 18:29:19 +00:00
Sergio Martins
e9e149d55e Remove unused include 2021-02-15 17:48:13 +00:00
Sergio Martins
bb5d98164f fix windows build 2021-02-15 09:45:55 -08:00
Sergio Martins
8941f41d1c Moved NCHITTESTEventFilter to WidgetResizeHandler
It's a better fit there.
2021-02-15 17:36:22 +00:00
Sergio Martins
d45e17b603 Minor styling: Remove one level of ifdefing 2021-02-15 17:32:05 +00:00
Sergio Martins
c2b3e6b36e Remove some unneeded debug info 2021-02-15 17:28:29 +00:00
Sergio Martins
b8405c01f1 Export WidgetResizeHandler 2021-02-15 17:25:49 +00:00
Sergio Martins
3d191da07e Remove the unity build option, there's already a CMake way
-DCMAKE_UNITY_BUILD should do the same thing.
Disabling it by default since the project is too small for the gains,
and because it screws up the compile_commands.json which I need
for vscode
2021-02-14 23:28:46 +00:00
Sergio Martins
aeb61993a4 Use QT6_DIR in the presets file
Removes the hardcoded "gcc"
2021-02-14 23:08:06 +00:00
Sergio Martins
3679e1da3a Pass a QStyleOption in Button::sizeHint()
Allows to use the logical dpi of the screen the widget is in
2021-02-14 22:41:02 +00:00
Sergio Martins
52aefd23f0 Improve comments 2021-02-14 22:40:23 +00:00
Sergio Martins
76a2b84925 Windows: Support scalable icons without requiring AA_EnableHighDpiScaling 2021-02-14 22:22:04 +00:00
Sergio Martins
a89b2c7ed1 Add a comment 2021-02-14 19:54:49 +00:00
Sergio Martins
5dd4eb2d20 Honour the logical DPI for sizing title bar buttons
Some Linux window managers manipulate the logical DPI instead of
the device pixel ratio.
2021-02-14 19:39:05 +00:00
Sergio Martins
600661a570 Minor: Move Button::paintEvent() into the .cpp file 2021-02-14 19:22:41 +00:00
Sergio Martins
92f6453d26 Minor refactoring
Adds scalingFactorIsSupported(dpr) to utils, to workaround a bug
on earlier Qt
2021-02-14 19:17:15 +00:00
Sergio Martins
8bf3aa9b4d Use sizeHint() for title bar buttons
In preparation for using style pixel metrics, which is more
HDPI friendly
2021-02-14 18:43:49 +00:00
Sergio Martins
c52db1945b Minor rename for readability 2021-02-14 17:52:36 +00:00
Sergio Martins
09a10cd791 Minor rename for readability 2021-02-14 17:42:35 +00:00
Sergio Martins
07fd577894 MDI|qtquick: Fix resize cursor not being shown
the docked widgets were resizable but the cursor didn't change
shape
2021-02-14 17:41:01 +00:00
Sergio Martins
ed900b8531 MDI|qtquick: Allow to resize the docked windows with mouse
Was already possible for QtWidgets. For QtQuick we weren't
receiving the mouse events in Frame.
2021-02-14 17:26:03 +00:00
Sergio Martins
fa010357b3 Add Frame::isMDIChanged() signal 2021-02-14 17:21:28 +00:00
Sergio Martins
da6ffc85ef Fix transparency of QtQuick MDI example 2021-02-14 16:33:02 +00:00
Sergio Martins
b7c23087e1 MDI|qtquick: Don't use private API in the example 2021-02-14 13:30:34 +00:00
Sergio Martins
656f482cad qtquick: fix build 2021-02-14 13:17:45 +00:00
Sergio Martins
5e03003b94 Add MDI to the ChangeLog 2021-02-14 13:05:34 +00:00
Sergio Martins
48b5b27d42 Introduce MainWindowMDI
User no longer needs to use private API
2021-02-14 13:02:48 +00:00
Sergio Martins
fccb815d5a Fix QtQuick build 2021-02-13 18:56:18 +00:00
Sergio Martins
544d3b026a MDI windows will now poput into floating mode
when dragged behond the edges
Please enter the commit message for your changes. Lines starting
2021-02-13 18:30:59 +00:00
Sergio Martins
15ff882919 MDI: Raise window when we're dragging it
Otherwise it's appearing under others, possibly
2021-02-13 16:29:32 +00:00
Sergio Martins
18d405bdfb MDI: Don't let windows escape its parent 2021-02-13 16:19:05 +00:00
Sergio Martins
4379e7c544 MDI|Item: Allow widget to resize itself outside of the layout domain
With a normal KDDW layout, we don't allow the user to arbitrarily
resize widgets, all the resizes are done via dragging Separator,
which interacts closly with the layout.

With MDI however there's no separators. The user is resizing the
widget and the layout doesn't know about it, and it's fine for MDI
2021-02-13 14:17:42 +00:00
Sergio Martins
51e2be9b7b MDI: Don't paint the titlebar over the frame 2021-02-13 14:06:24 +00:00
Sergio Martins
f2b21d04b3 mdi example: Show KDAB logo 2021-02-13 14:02:22 +00:00
Sergio Martins
a73f35af22 MDI: Implement internal move
You can now move internal windows around without them becoming
floating
2021-02-13 13:03:14 +00:00
Sergio Martins
7b3ef03924 Add Draggable::isMDI() 2021-02-13 12:16:28 +00:00
Sergio Martins
a4d03c1514 Add a mdi-example
Don't want the main example to be too complex
2021-02-13 12:01:01 +00:00
Allen Winter
eccdee0081 buildsystem - add an uninstall target
uses the KDE extra-cmake-module ECMUninstallTarget.cmake
2021-02-12 15:18:01 -05:00
Sergio Martins
48f3390d71 Delete resize handler when floating a MDI dock widget
When it's floating it will use native resizing, or the resize handler
from the floating window. Not its own.
2021-02-11 20:09:22 +00:00
Sergio Martins
df6f1e6c8f Added Frame::isMDI() 2021-02-11 20:00:54 +00:00
Sergio Martins
3c95081aee MDI: Support internal resize
You can now resize docked MDI widgets
2021-02-11 19:37:05 +00:00
Sergio Martins
329a980510 WidgetResizeHandler: Fix case if parent's target wasn't top-level
By luck parentGeometry was in global space. Force it to be in global
space, as the target might be more nested.

Will be used by MDI, where Frame's parent is the MDI layout
2021-02-11 19:35:40 +00:00
Sergio Martins
d8605e9ce3 Minor styling: Reduce nesting, process invariant early 2021-02-11 19:15:36 +00:00
Sergio Martins
7dcc6dc114 Frame now takes care of its own resize handler
No need to set it from outside
2021-02-11 18:56:45 +00:00
Sergio Martins
64db52fd17 Move the CursorPositions header to the enums header instead
Otherwise will have to include WidgetResizeHandler_p.h
where I don't want to. And make it an installed header etc.
2021-02-11 18:52:21 +00:00
Sergio Martins
c0957024ec Remove some unneeded qDebug 2021-02-10 22:25:45 +00:00
Sergio Martins
649571a2eb Minor styling for the MDI example 2021-02-10 20:16:19 +00:00
Sergio Martins
60adb0d50b qtquick: Add a MDI example
Instead of poluting the normal example
2021-02-10 20:06:50 +00:00
Sergio Martins
f751d7c24e TitleBar is now HDPI aware even without the Qt::AA_ properties set
It will just query the style, which is already HDPI aware.
2021-02-10 15:17:04 +00:00
Sergio Martins
5ec5ade62f qtquick: Add a MDI example 2021-02-10 00:19:29 +00:00
Sergio Martins
788c497cbb Don't crash if it's a MDI layout 2021-02-10 00:01:47 +00:00
Sergio Martins
f6c274b82f qtquick: Remove unneeded dependency to DockArea 2021-02-09 23:50:52 +00:00
Sergio Martins
5a6b4a6fdd Don't use transparent titlebar if docked MDI
As the dock widgets can overlap over eachother
2021-02-09 23:27:10 +00:00
Sergio Martins
ef212b8c0f Added TitleBar::isMDI() 2021-02-09 22:38:16 +00:00
Sergio Martins
aa2f46fd00 Added TitleBar::mainWindow() 2021-02-09 22:15:31 +00:00
Sergio Martins
a30808e6b7 Implement ItemFreeContainer::removeItem() 2021-02-09 20:17:59 +00:00
Sergio Martins
f23c55dfec Implement ItemFreeContainer::restore() 2021-02-09 19:56:12 +00:00
Sergio Martins
583d3188ca Implement ItemFreeContainer::clear() 2021-02-09 19:51:53 +00:00
Sergio Martins
ae81f64d07 MDI: Comment that these methods don't make sense for MDI 2021-02-09 19:47:51 +00:00
Sergio Martins
8dca2e346c Add experimental MDI support 2021-02-09 19:25:28 +00:00
Sergio Martins
b995986318 Decouple MainWindow a bit more from DropArea 2021-02-09 18:04:11 +00:00
Sergio Martins
0579b6dcd3 Add a basic MDI layout
Not fully functional yet, and no API for end user yet.
2021-02-09 17:44:49 +00:00
Sergio Martins
4d147c7ff3 Remove two drop area dependencies 2021-02-09 17:34:40 +00:00
Sergio Martins
baf5f088dc Remove more unneeded references to DropArea
reference its base class instead
2021-02-09 16:58:24 +00:00
Sergio Martins
2adaacb922 Remove unused AnimatedIndicators files 2021-02-09 16:54:23 +00:00
Sergio Martins
bc6870f4ee Move the serialize/deserialize functions into base class 2021-02-09 16:52:16 +00:00
Sergio Martins
c6abaf22c1 Decouple WindowBeingDragged from DropArea 2021-02-09 16:41:26 +00:00
Sergio Martins
e04e066177 Remove unneeded DropArea::numFrames() 2021-02-09 16:34:58 +00:00
Sergio Martins
6ad01f4994 Make Frame deal in LayoutWidget instead of its derived class DropArea 2021-02-09 16:32:42 +00:00
Sergio Martins
f6ad75e214 Rename Frame::setDropArea() to Frame::setLayoutWidget()
Made it private too.
2021-02-09 16:29:29 +00:00
Sergio Martins
a76864450e Remove unneeded Frame::dropArea() 2021-02-09 16:25:56 +00:00
Sergio Martins
3fe9994322 Remove some debug statements which are unneeded 2021-02-09 16:25:19 +00:00
Sergio Martins
3bcfcc40c0 Minor decoupling between DropArea and DockWidgetBase 2021-02-09 16:23:49 +00:00
Sergio Martins
92b54f949b More MultiSplitter decoupling 2021-02-09 16:17:49 +00:00
Sergio Martins
a73746fe8b tests: Use the MultiSplitter base class in a few places 2021-02-09 16:12:22 +00:00
Sergio Martins
da1fddffe1 Decouple MultiSplitter from MainWindow and FloatingWidget
They deal in its base class instead (LayoutWidget)
2021-02-09 16:05:56 +00:00
Sergio Martins
e3b0feb967 DockWidgetBase.cpp uses MultiSplitter's base class now 2021-02-09 15:54:47 +00:00
Sergio Martins
4e6811cfdc qtquick: Fix build 2021-02-09 15:47:54 +00:00
Sergio Martins
cc47e46e1f Move lots of methods from MultiSplitter to its base class
Should be almost done now
2021-02-09 15:45:22 +00:00
Sergio Martins
4246d99b93 DockRegistry now deals in LayoutWidget
Instead of its derived class MultiSplitter
2021-02-09 15:40:44 +00:00
Sergio Martins
ba38e3c1aa Move lots of methods from MultiSplitter to its base class 2021-02-09 15:38:30 +00:00
Sergio Martins
83aa64928d Remove duplicate connect 2021-02-09 15:22:12 +00:00
Sergio Martins
5fbff7211b Move lots of methods from MultiSplitter to its base class 2021-02-09 15:09:07 +00:00
Sergio Martins
eb67f19e3e Placeholders now receive LayoutWidget instead of the derived class 2021-02-09 14:41:31 +00:00
Sergio Martins
2130a31dfd Add another base class to MultiSplitter
MultiSplitter is the QWidget that holds the layout. But we also
want to support other types of layouts, such as MDI.
2021-02-09 12:37:08 +00:00
Sergio Martins
f3ce208ec1 Merge branch '1.3' 2021-02-09 10:52:55 +00:00
Sergio Martins
146478eb5e cmake: No need to build the fuzzer during development 2021-02-09 10:52:28 +00:00
Sergio Martins
05413d5a99 Open master for 1.4 2021-02-09 10:44:28 +00:00
Allen Winter
eac726fcb8 open for 1.3.1 2021-02-08 17:05:21 -05:00
Allen Winter
b25af85234 kddockwidgets.spec - OBS fix 2021-02-08 16:42:51 -05:00
Allen Winter
02167a0788 CMakeLists.txt - ECMGeneratePriFile needs CMake v3.12 or above 2021-02-08 16:15:25 -05:00
Allen Winter
54cce9aa41 OBS - update for 1.3.0 release 2021-02-08 15:35:43 -05:00
Allen Winter
73cdc7136c README.md - a bit of formatting, spelling fixes 2021-02-08 15:25:06 -05:00
Allen Winter
1567a2b847 docs/api/CMakeLists.txt - copy some files needed by the markdown
The markdown to html conversion by doxygen doesn't copy
some files referred to in the README.md
2021-02-08 15:24:11 -05:00
Allen Winter
9fe795f8dd README.md, CONTRIBUTORS.txt - thank you contributors
those who have signed the KDAB Copyright License Agreement
2021-02-08 12:29:06 -05:00
Allen Winter
0d6cfd183d .krazy - exclude the postfix checker 2021-02-08 12:28:45 -05:00
Allen Winter
bba36d041b minor for Krazy 2021-02-08 12:11:46 -05:00
Sergio Martins
710716f658 Update ChangeLog regarding v1.3.0 release date 2021-02-08 12:15:30 +00:00
Sergio Martins
b39798ac24 qtquick: Fix build 2021-02-08 11:22:25 +00:00
Sergio Martins
1f8fbb8518 Export the DockWidgetBase pimpl for unit-tests 2021-02-08 03:16:50 -08:00
Sergio Martins
51dc666181 Added DockWidget::setFloatingGeometry()
Closes #144
2021-02-07 17:26:01 +00:00
Sergio Martins
2a6e716e07 Fix typo in README 2021-02-07 17:04:09 +00:00
Allen Winter
01d68f30e4 docs/api/Doxyfile.cmake - add reimp alias 2021-02-07 07:41:08 -05:00
Allen Winter
1b73d01de8 src/DockWidgetQuick.h - minor doxygen fix 2021-02-07 07:36:55 -05:00
Allen Winter
a421cb0b01 various - include private header first, remove header dupes 2021-02-07 07:07:49 -05:00
Allen Winter
2177336d65 minor spelling 2021-02-07 06:56:49 -05:00
Allen Winter
059a8cc38f TabWidgetQuick_p.h,TabWidgetQuick.cpp - update copyright year 2021-02-07 06:50:03 -05:00
Sergio Martins
4c33cd6409 Sidebar overlays now maintain their size when toggled
Fixes #155
2021-02-06 22:55:14 +00:00
Sergio Martins
ea48d52447 refactor MainWindowBase::updateOverlayGeometry()
Receives a size instead of a bool now.
2021-02-06 22:30:21 +00:00
Sergio Martins
85f4be750a Remove bogus sizing 2021-02-06 21:43:05 +00:00
Sergio Martins
0ba37a347b Save last overlayed location
For issue #155
2021-02-06 20:12:39 +00:00
Sergio Martins
6ee1900331 Add a test for issue #155 2021-02-06 19:43:26 +00:00
Sergio Martins
44bf1ef322 qtquick: Move dummy QAction class into the pimpl header
No need for it to be in the public header
2021-02-06 18:20:44 +00:00
Sergio Martins
863691c313 Remove some private API from DockWidgetBase.h
Moved it into the pimpl
2021-02-06 16:32:13 +00:00
Sergio Martins
97d7cbf657 ChangeLog: Mention we have experimental QtQuick support 2021-02-06 15:56:13 +00:00
Allen Winter
3089535de6 CMakeLists.txt, conan/conanfile.py - this is version 1.3.0 2021-02-06 10:31:17 -05:00
Sergio Martins
36818093c6 Merge branch '1.2' 2021-02-06 15:20:08 +00:00
Allen Winter
e5857df439 conan/conanfile.py - upgrade version number 2021-02-06 10:09:32 -05:00
Allen Winter
42d25dc1a5 fwd_headers/kddockwidgets/KDDockWidgets.h - update copyright year 2021-02-06 10:07:55 -05:00
Sergio Martins
3b5e78bfba ChangeLog: Add release date of 1.2.1 2021-02-06 13:02:50 +00:00
Sergio Martins
639dce7c53 Remove the QtQuick presets from the 1.2 branch
It's for master only
2021-02-06 12:46:18 +00:00
Sergio Martins
882f54647c ChangeLog removed mention to 1.3 from the 1.2 branch 2021-02-06 12:43:56 +00:00
Sergio Martins
38443048b8 Merge branch '1.2' 2021-02-05 16:42:07 +00:00
Sergio Martins
621c3dbeca Also clear the overlay internals when floating an overlay
Fixes a crash.

Relates to #162
2021-02-05 16:32:41 +00:00
Sergio Martins
f1e4f7ecda Add another test 2021-02-05 14:34:12 +00:00
Sergio Martins
249d1b6790 Remove from the sidebar when floating a widget
Fixes #162
2021-02-05 12:35:03 +00:00
Sergio Martins
894e0fd03a Added test for issue #162 2021-02-05 11:49:52 +00:00
Allen Winter
ec1f009914 CLA - switch to a form-fillable PDF version 2021-02-04 16:26:34 -05:00
Allen Winter
697417b906 CLA - switch to a form-fillable PDF version 2021-02-04 16:17:53 -05:00
Sergio Martins
dadf57c184 Merge branch '1.2' 2021-02-04 19:59:29 +00:00
Sergio Martins
7caa83be19 Also hide overlay when clicking on empty space of a main window 2021-02-04 19:56:35 +00:00
Sergio Martins
e745d38b1e Improve the test a bit
clicking on the bottom is not very effective as that's where the
bottom sidebar is
2021-02-04 19:52:21 +00:00
Sergio Martins
6d389315bf Add test for issue #157 2021-02-04 19:31:31 +00:00
Sergio Martins
024d56505a Merge branch '1.2' 2021-02-04 13:30:35 +00:00
Sergio Martins
daec97ad66 Don't require QtX11Extras for WASM
Fixes #163
2021-02-04 13:30:04 +00:00
Sergio Martins
a98daead1d README: Improve paragraph about reporting bugs
Mention that sha1 and which operating system are important too
2021-02-03 13:34:33 +00:00
Sergio Martins
2c5cf77cf2 Fix build with cmake Visual Studio generator
Fixes #156
2021-02-02 23:02:04 +00:00
Sergio Martins
a6b9a82e9c Fix crash when hosting QQuickWidget
There's no need to check if invisible widgets are candidates
for docking. There's usually no downside either, except that
QQuickWidget is very sensitive with when its platform window
is created, so don't force the creation.

Will cherry-pick to 1.2 if no regression is found

Fixes #150
2021-01-31 13:05:20 +00:00
Sergio Martins
02cf9d1cd2 Make FloatingWindowWidget::m_vlayout protected
So users can override
2021-01-30 14:28:30 +00:00
Sergio Martins
cde814b216 Add a static FloatingWindow::s_windowFlagsOverride member
The user can now change which window flags FloatingWindow will get,
as his own risk.

Not doing it via public API such as FrameworkWidgetFactory as I don't
want to encourage or support this. The amount of combinations that
can go wrong is open ended.

Fixes #149
2021-01-30 13:59:42 +00:00
Sergio Martins
5f435cd8c7 minor comment: Don't mention deprecated flag 2021-01-30 13:40:07 +00:00
Sergio Martins
6ccd98ca01 Move DockWidgetBase::eventFilter() into the private class
Fixes issue #151 where the user is overriding eventFilter too
and getting into some edge cases.

Could be worked around in user code, but it's always good to have
less protected and private API in public classes.
2021-01-29 20:20:01 +00:00
Sergio Martins
799f2a81a7 Remember previous tab position when toggling float
This was already the case, but didn't work in case the tabs
were re-oredered by the user manually

Fixes #154
2021-01-29 19:15:23 +00:00
Sergio Martins
eb9fa6f567 Add unit-test for issue #154 2021-01-29 19:07:32 +00:00
Sergio Martins
9ebd595202 Remove stray debug 2021-01-29 18:32:23 +00:00
Sergio Martins
b50d301f44 Add DockWidget::tabIndex() 2021-01-29 18:32:10 +00:00
Sergio Martins
b01b8908ea qtquick: Fix build
That test is QtWidgets only
2021-01-29 18:23:37 +00:00
Sergio Martins
78c2cdddc4 minor: Make indexOfDockWidget() take a const dock widget
So it can be called from const places
2021-01-29 18:22:20 +00:00
Sergio Martins
1eaac74fb0 README: reword the getting involved section a bit
Explain that patches as images are not good when reporting bugs
2021-01-29 12:02:14 +00:00
Sergio Martins
ee759a5459 Don't trigger "Delete on Close" when sending to the sidebar 2021-01-28 22:40:41 +00:00
Sergio Martins
e9d19805d7 Add a force close to DockWidgetBase::Private
So we can add an argument there, without changing public API
2021-01-28 22:19:21 +00:00
Sergio Martins
1f74ba43f0 Add some includes to DockWidgetBase_p.h
It's not included directly, but let's be nice to IDEs.
2021-01-28 21:54:45 +00:00
Sergio Martins
bc1e686455 Create DockWidgetBase_p.h and move the pimpl there
So we can reuse the pimpl and not have to expose public API
for implementation details
2021-01-28 21:44:12 +00:00
Allen Winter
5cc0552c57 Merge pull request #153 from KDAB/fix-missing-source
Added missing layout_saver wrapper file in the source list
2021-01-28 10:01:38 -05:00
Renato Araujo Oliveira Filho
6c06bc6af8 Added missing layout_saver wrapper file in the source list 2021-01-28 11:30:25 -03:00
Sergio Martins
2193c131a8 Merge branch '1.2'
Should fix #152
2021-01-27 23:38:51 +00:00
Sergio Martins
9a38626af5 Allow more private includes to be used from installed dir 2021-01-27 23:31:59 +00:00
Sergio Martins
f0c243f6d1 Add KDDockWidgets.h fwd_header 2021-01-27 23:27:04 +00:00
Sergio Martins
f0441f1a08 Normalize some dock_exports.h includes
In case these files are ever included from an installed location
2021-01-27 23:00:32 +00:00
Sergio Martins
8a9d9f9fce Merge branch '1.2' 2021-01-27 22:55:36 +00:00
Sergio Martins
db06c496cf Remove dependencies to LayoutSaver_p.h
Only the impl needs to include it
2021-01-27 22:51:41 +00:00
Sergio Martins
2aa97e6565 Add a fwd header for DragController_p.h 2021-01-27 22:28:57 +00:00
Sergio Martins
68597cac22 install two more private includes 2021-01-27 22:27:46 +00:00
Sergio Martins
afa543ec79 Fix .clang-format
Was complaining about Cpp14 not being a valid enumerator
2021-01-27 22:07:26 +00:00
Sergio Martins
d1df6e910b Add a .clang-format file 2021-01-27 22:00:06 +00:00
Sergio Martins
74ae567ced vscode: Update workspace files
formats code you've changed now
2021-01-27 21:32:06 +00:00
Allen Winter
8d657c5b18 Merge branch '1.2' 2021-01-27 11:59:27 -05:00
Allen Winter
802bdc102f src/CMakeLists.txt - fix Windows library versioning
was broken for RelWithDebInfo builds
2021-01-27 11:55:51 -05:00
Sergio Martins
218d18793d Remove some unneeded horizontal line from MyCentralWidget
The difference is minimal and probably looks very bad with dark
and custom themes.

Let's minimize the amount of hardcoded styling.
2021-01-26 19:32:10 +00:00
Sergio Martins
723c29e33b Merge pull request #119 from JPatriceR/add-LayoutSaver-python-binding
Add binding for LayoutSaver class
2021-01-26 14:58:56 +00:00
Sergio Martins
2e248c6658 README: Add a paragraph about versioning and API/ABI compat 2021-01-26 14:36:30 +00:00
Sergio Martins
7fbd66d54c Merge branch '1.2' 2021-01-26 14:26:26 +00:00
Sergio Martins
4bede063ae Make DockWidgetBase::eventFilter() protected
The users might want to override it

Fixes #148 and restores source compat with v1.1
2021-01-26 14:25:30 +00:00
Sergio Martins
cbc5fec119 Added Config::setDisabledPaintEvents()
Makes our internal widgets not override QWidget::paintEvent(),
which gives full power to the user to stylesheets.

Was already possible, but required the user to override the
internal widgets via the widget factory

For issue #146
2021-01-24 10:51:58 +00:00
Sergio Martins
81927b088b Add CustomizableWidget enum 2021-01-24 10:15:02 +00:00
Sergio Martins
5556edd83b vscode: prefix the vscode workspaces with "code."
Easier to open on command line if they have the same prefix
2021-01-23 12:41:31 +00:00
Sergio Martins
2834532b5f example: Add a keyboard shortcut to toggle dock widgets visiblity 2021-01-21 16:22:43 +00:00
Sergio Martins
17638bc29f Fix regression with DockWidget::toggleAction()
Added unit-test too.
While we're processing the toggle action triggering isOpen() is
always false.
2021-01-21 16:16:29 +00:00
Jean-Patrice Laude
67b48cc417 Add binding for LayoutSaver class 2021-01-20 16:53:32 +01:00
Sergio Martins
451996016a Merge pull request #128 from CE-Programming/fix/pri
Fix issues with pri file.
2021-01-19 22:38:37 +00:00
Sergio Martins
52b9a9223d Update ChangeLog 2021-01-19 22:25:00 +00:00
Sergio Martins
d5b80b0bbd Fix offset when dragging too fast
On Windows, when we start a drag, we switch to native dragging in
mid-flight, so that AeroSnap still works

Fixes #121
2021-01-19 22:23:20 +00:00
Sergio Martins
ae14e49338 Add a comment, explains why we switch to native drag 2021-01-19 21:53:35 +00:00
Sergio Martins
c23bce9829 Minor coding style: Remove nested ifdef 2021-01-19 21:50:31 +00:00
Sergio Martins
40a549ca29 Fix double delete screwing with lastPositions()
Fixes #141
2021-01-18 23:37:17 +00:00
Sergio Martins
cac435a2a5 tests: Add missing cleanup 2021-01-18 22:52:54 +00:00
Sergio Martins
b81f50402a qtquick: Fix build 2021-01-18 20:42:41 +00:00
Sergio Martins
44587cb947 Don't require LayoutSaver_p.h to be installed
It's impl detail that doesn't need to be installed
2021-01-18 20:37:22 +00:00
Sergio Martins
54314273a0 Merge branch '1.2' 2021-01-18 19:40:18 +00:00
Sergio Martins
de068dc6ff Use less relative includes, some of them were wrong
The example now includes them, so we can detect build failures
if they get wrong again

Fixes #140
2021-01-18 18:57:15 +00:00
Allen Winter
64f537ad1e Merge branch '1.2' 2021-01-18 10:15:07 -05:00
Allen Winter
312c89f884 src/CMakeLists.txt - fix kddockwidgets_version.h install destination 2021-01-18 10:14:37 -05:00
Renato Araujo Oliveira Filho
d9fd7eb3a5 Fix python bindings build
Task-Id: KDABCI-692
2021-01-18 10:10:51 -05:00
Allen Winter
af9206f350 Merge pull request #142 from KDAB/python-build-fix
Fix python bindings build
2021-01-18 10:07:04 -05:00
Allen Winter
7c99bb084e Merge branch '1.2' 2021-01-18 10:05:27 -05:00
Allen Winter
1a2757b00a Generate and install kddockwidgets_version.h
defines a version string and other useful versioning macros

Issue#138
2021-01-18 10:03:21 -05:00
Renato Araujo Oliveira Filho
1e7a2110b1 Fix python bindings build
Task-Id: KDABCI-692
2021-01-18 11:58:42 -03:00
Sergio Martins
243146fe49 Update ChangeLog 2021-01-17 23:24:58 +00:00
Sergio Martins
370d139dfc Fix Flag_NativeTitleBar
It shouldn't use the FloatingWindow::isInDragArea() code path
2021-01-17 23:11:41 +00:00
Sergio Martins
c4e7db34a4 Minor readability improvement 2021-01-17 22:51:37 +00:00
Sergio Martins
a4f6b72157 Fix FloatingWindow::isInDragArea() returning false even with HTCAPTION
If the last clicked position is HTCAPTION then we're sure we're
dragging. Problem with comparing the rect is that mouse events are
async, and by the time we use the mouse event pos the window is already
somewhere else. So just use HTCAPTION, which is 100% correct.

Fixes #103
2021-01-17 16:28:11 +00:00
Sergio Martins
de3ca6dba5 vscode: Remove launch.json
We'll do this per workspace file instead
2021-01-17 14:10:19 +00:00
Sergio Martins
bdfcfdd0fe Update ChangeLog 2021-01-16 22:39:11 +00:00
Sergio Martins
dbf357ce66 Fix restoring window maximized state
Fixes #81
2021-01-16 22:37:30 +00:00
Sergio Martins
e950cf7fc3 tests: Add a test for issue #81 2021-01-16 21:38:36 +00:00
Sergio Martins
8dfad1c910 vscode: Update the workspace files
Now autogenerated from CMakePresets.json.
Added the Qt6 one too.
2021-01-16 19:40:36 +00:00
Sergio Martins
107d4e973c Remove a script I'm no longer using 2021-01-16 15:50:27 +00:00
Sergio Martins
e33766a4fa examples: Illustrate Config::Flag_CloseOnlyCurrentTab 2021-01-16 13:19:37 +00:00
Sergio Martins
6a550c6c4a Added Config::Flag_CloseOnlyCurrentTab
When clicking on the TitleBar's close button it closes all the
dock widgets in the tab, by default. With the new option it will
close only the current tab
2021-01-16 13:06:29 +00:00
Sergio Martins
a0fc2a8ce7 Minor logic readability fix
They are mutually exclusive
2021-01-16 12:00:43 +00:00
Sergio Martins
ab257b3468 float docked widgets that have LayoutSaverOption::Skip before restore 2021-01-15 21:30:38 +00:00
Sergio Martins
e6bdb28484 Added convenience DockWidgetBase::skipsRestore() 2021-01-15 20:17:45 +00:00
Sergio Martins
c52446f3b0 Merge branch '1.2' 2021-01-15 09:27:17 +00:00
Sergio Martins
9cadfb26d9 Fix toggleAction() when dock widget is in the sidebar
It should toggle the overlay, not dock the widget

Fixes #139
2021-01-15 09:24:11 +00:00
Sergio Martins
7d5ea8f908 tests++ 2021-01-15 09:20:58 +00:00
Sergio Martins
161b33370e Add more tests 2021-01-15 09:04:05 +00:00
Sergio Martins
8dd7a90b34 Add convenience DockWidgetBase::isInSideBar() 2021-01-15 08:52:17 +00:00
Sergio Martins
7ff865a36f tests: Add test for #139 2021-01-15 08:44:21 +00:00
Sergio Martins
d0b8ee606a Honour LayoutSaverOption::Skip for floating windows with many dock widgets
If all dock widgets in the floating window have the Skip flag then the
FloatingWindow can too
2021-01-14 18:33:29 +00:00
Sergio Martins
c6c3b16fd2 LayoutSaver: Add some utility functions 2021-01-14 18:11:29 +00:00
Sergio Martins
64a6cbb2e4 Add all|anyDockWidgetsHave overloads taking a LayoutSaverOption 2021-01-14 18:01:54 +00:00
Sergio Martins
e1cf532437 tests: Add an XFAIL for a LayoutSaverOption::Skip case 2021-01-14 17:57:37 +00:00
Sergio Martins
67f2127710 Add one more unit-test regarding DeleteOnClose 2021-01-14 17:51:02 +00:00
Sergio Martins
9111b424a1 TitleBar: Also update the auto/hide button
For completeness, doesn't mean it's actually needed.
For issue #137.
2021-01-14 11:39:15 +00:00
Sergio Martins
772b51216f Merge branch '1.2' 2021-01-13 23:15:03 +00:00
Sergio Martins
a79a2f5ecb Fix restoring non-closable state
For issue #137

A simpler solution than on master, doesn't include the refactoring.
2021-01-13 23:13:39 +00:00
Sergio Martins
585c0d64ed Fix close button enable state not being restored with LayoutSaver
Fixes #137
2021-01-13 23:07:49 +00:00
Sergio Martins
7ddb95a417 Add a single TitleBar::updateButtons()
updateCloseButton() can now be private
2021-01-13 23:07:49 +00:00
Sergio Martins
02648eb54e Update ChangeLog re PySide6 2021-01-13 22:51:18 +00:00
Sergio Martins
54a1050fbb Add unit-test for issue #137 2021-01-13 22:23:44 +00:00
Sergio Martins
f997b2d2f0 qtquick: Fix build 2021-01-13 13:31:33 +00:00
Sergio Martins
8f61e57b57 Add DockWidget::Option::Option_DeleteOnClose 2021-01-13 12:54:18 +00:00
Sergio Martins
cfcff6f2d7 Minor rename 2021-01-12 22:49:07 +00:00
Sergio Martins
44d7cc0588 Add FloatingWindow::allDockWidgetsHave(option) and the any* variant 2021-01-12 22:42:38 +00:00
Sergio Martins
c91275d091 vscode: Use workspace files instead of project settings
So we can build for QtQuick too with different settings
2021-01-12 15:20:29 +00:00
Sergio Martins
69c88919c0 cmake: Export a compile_commands.json which helps vscode
Need to disable unity build otherwise intellisense can't find
our source files in the compile_commands.json. Only for the dev-*
presets anyway
2021-01-12 14:25:11 +00:00
Sergio Martins
e0e6f55868 Introduce DockWidgetBase::LayoutSaverOptions enum
The first enumerator is "Skip", meaning the dock widget won't
be affected by save/restore. It won't disappear while restoring,
and won't be shown if already hidden. (only applies to floating widgets)
2021-01-11 23:33:32 +00:00
Sergio Martins
7698584ee0 Fix potential invalid index when restoring layout
We save the index of each FloatingWindow when saving a layout,
but when restoring we might not want to restore all FloatingWindows,
for example, if we use a LayoutSaver with another affinity.

So, the index in Position::deserialize() should be a index to
LayoutSaver::Layout::floatingWindows, and not to DockRegistry::self()->floatingWindows()
since the later might be smaller.
2021-01-11 21:55:47 +00:00
Sergio Martins
d034722ba9 LayoutSaver: Add some utilities 2021-01-11 21:16:02 +00:00
Sergio Martins
e1e07c95ba Merge pull request #134 from KDAB/python6
Added PySide6 support
2021-01-11 19:35:53 +00:00
Jacob Young
b81c32b1c9 Fix issues with pri file. 2021-01-07 20:43:47 -05:00
258 changed files with 12153 additions and 4927 deletions

73
.clang-format Normal file
View File

@@ -0,0 +1,73 @@
---
BasedOnStyle: WebKit
Language: Cpp
Standard: Cpp11
IndentWidth: 4
SpacesBeforeTrailingComments: 1
TabWidth: 8
UseTab: Never
SortIncludes: false
ContinuationIndentWidth: 4
MaxEmptyLinesToKeep: 3
BreakBeforeBinaryOperators: NonAssignment
BreakBeforeTernaryOperators: true
BreakConstructorInitializers: BeforeColon
BreakConstructorInitializersBeforeComma: true
BreakBeforeBraces: Custom
BraceWrapping:
AfterClass: true
AfterControlStatement: false
AfterEnum: false
AfterFunction: true
AfterNamespace: false
AfterObjCDeclaration: false
AfterStruct: true
AfterUnion: false
BeforeCatch: false
BeforeElse: false
IndentBraces: false
ForEachMacros:
- forever # avoids { wrapped to next line
- foreach
- Q_FOREACH
AccessModifierOffset: -4
ConstructorInitializerIndentWidth: 4
AlignEscapedNewlinesLeft: false
AlignTrailingComments: false
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortIfStatementsOnASingleLine: false
AllowShortLoopsOnASingleLine: false
AllowShortFunctionsOnASingleLine: false
AllowShortEnumsOnASingleLine: false # requires clang-format 11
AlignAfterOpenBracket: true
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: true
BinPackParameters: true
ColumnLimit: 0
Cpp11BracedListStyle: false
DerivePointerBinding: false
ExperimentalAutoDetectBinPacking: false
IndentCaseLabels: false
NamespaceIndentation: None
ObjCSpaceBeforeProtocolList: true
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 60
PenaltyBreakFirstLessLess: 120
PenaltyBreakString: 1000
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 60
PointerBindsToType: false
SpaceAfterTemplateKeyword: false
IndentFunctionDeclarationAfterType: false
SpaceAfterControlStatementKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceInEmptyParentheses: false
SpacesInAngles: false
SpacesInCStyleCastParentheses: true
SpacesInParentheses: false
...

4
.codespellrc Normal file
View File

@@ -0,0 +1,4 @@
[codespell]
skip = ./build-*,.git
interactive = 3
ignore-words-list = overlay,overlayed

6
.gitignore vendored
View File

@@ -58,3 +58,9 @@ kddockwidgets_minimal_example
/CMakeDoxygenDefaults.cmake /CMakeDoxygenDefaults.cmake
/Testing /Testing
/layout_tst* /layout_tst*
/x64
/src/kddockwidgets_version.h
*.vcxproj*
*.sln
*.dir
.vscode

4
.krazy
View File

@@ -7,7 +7,7 @@ EXTRA kdabcopyright-reuse,kdabcontactus,fosslicense-reuse
#EXTRA defines,null #EXTRA defines,null
#exclude checks now being done by clazy or clang-tools #exclude checks now being done by clazy or clang-tools
EXCLUDE strings,explicit,normalize,passbyvalue,operators,nullstrcompare,nullstrassign,doublequote_chars,qobject,sigsandslots,staticobjects,dpointer,inline EXCLUDE strings,explicit,normalize,passbyvalue,operators,nullstrcompare,nullstrassign,doublequote_chars,qobject,sigsandslots,staticobjects,dpointer,inline,postfixop
#exclude more checks #exclude more checks
EXCLUDE style EXCLUDE style
@@ -16,6 +16,8 @@ SKIP Doxyfile.cmake
#skip CMake files #skip CMake files
SKIP /KDDockWidgetsConfig.cmake.in SKIP /KDDockWidgetsConfig.cmake.in
#skip more files
SKIP CMakePresets.json
#skip the borrowed code in the cmake subdir #skip the borrowed code in the cmake subdir
SKIP /cmake/Qt5Portability.cmake|/cmake/ECM/|/cmake/InstallLocation.cmake SKIP /cmake/Qt5Portability.cmake|/cmake/ECM/|/cmake/InstallLocation.cmake

18
.reuse/dep5 Normal file
View File

@@ -0,0 +1,18 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: KDDockWidgets
Upstream-Contact: <info@kdab.com>
Source: https://www.github.com/KDAB/KDDockWidgets
Files: *.qrc *.json *.xml *.html src/fwd_headers/*
Copyright: 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
License: GPL-2.0-only OR GPL-3.0-only
#artwork
Files: screencap.gif images/* src/img/* docs/api/*.png examples/dockwidgets/assets/*.png src/img/classic_indicators/*.png
Copyright: 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
License: GPL-2.0-only OR GPL-3.0-only
#3rdparty
Files: cmake/ECM/modules/*
Copyright:
License: BSD-3-Clause

66
.travis.yml Normal file
View File

@@ -0,0 +1,66 @@
env:
global:
- secure: "NlWO/NTPlOU6cowOMuPOvjAprXVwIjmpHHf9CoMR71E2c/eBFFKIHj10kXuyFwz2KihHAIExmo9OlGtGniNWobvIrVrabO3dsOSb6UGbPAQkzQiyQLKsDNQAZx3nMuWEKBtMsVRee6rd7/2uGTY4WB5Ot3VhrUYcN1FoRgQQ9gk="
branches:
only:
- master
matrix:
include:
- os: linux
dist: bionic
- os: osx
osx_image: xcode11.5
env:
- QT_SELECT=qt5
- CMAKE_PREFIX_PATH=/usr/local/opt/qt
language: cpp
compiler:
- gcc
- clang
script:
- mkdir build
- cd build
- cmake -DCMAKE_BUILD_TYPE=Release -DKDDockWidgets_TESTS=True -KDDockWidgets_EXAMPLES=True -DKDDockWidgets_DEVELOPER_MODE=True ..
- make
- make test
notifications:
email:
recipients:
- allen.winter@kdab.com
- sergio.martins@kdab.com
on_success: never
on_failure: always
dist: bionic
addons:
apt:
update: true
packages:
- qt5-default
- qtbase5-dev
- qtbase5-dev-tools
- qtbase5-private-dev
- qttools5-dev
- qttools5-dev-tools
- qtdeclarative5-dev
- qtdeclarative5-dev-tools
- libqt5xmlpatterns5-dev
- libqt5xmlpatterns5
- qtxmlpatterns5-dev-tools
- libqt5x11extras5-dev
homebrew:
update: true
packages:
- qt5
coverity_scan:
project:
name: KDAB/KDDockWidgets
notification_email: allen.winter@kdab.com
build_command_prepend: cd build && cmake ..
build_command: make
branch_pattern: coverity_scan

68
.vscode/launch.json vendored
View File

@@ -1,68 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": "(gdb) QtWidgets example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/kddockwidgets_example",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
{
"name": "(gdb) QtQuick example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/kddockwidgets_example_quick",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
]
},
{
"name": "(vs) kddockwidgets_example",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/kddockwidgets_example.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"sourceFileMap" : {
"C:\\Users\\qt\\work\\qt\\qtbase\\src" : "D:\\Qt\\5.14.2\\Src\\qtbase\\src"
}
},
{
"name": "(vs) tst_docks",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build/bin/tst_docks.exe",
"args": ["tst_moreTitleBarCornerCases", "-platform", "windows"],
"stopAtEntry": false,
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false
}
]
}

10
.vscode/settings.json vendored
View File

@@ -1,10 +0,0 @@
{
"C_Cpp.default.configurationProvider": "vector-of-bool.cmake-tools",
"files.associations": {
"qevent": "cpp"
},
"cmake.configureSettings": {
"KDDockWidgets_DEVELOPER_MODE" : "ON",
"KDDockWidgets_QTQUICK" : true
}
}

View File

@@ -19,9 +19,15 @@
# Build static versions of the libraries # Build static versions of the libraries
# Default=false # Default=false
# #
# -DKDDockWidgets_UNINSTALL=[true|false]
# Setup the uninstall target.
# You may want to disable the uninstall target when you are using KDDockWidgets
# as a submodule directly and have a custom uninstall target of your own.
# Default=true
#
# -DKDDockWidgets_TESTS=[true|false] # -DKDDockWidgets_TESTS=[true|false]
# Build the test harness. # Build the test harness.
# Currently does nothing unless you also set KDDockWidgets_DEVELOPER_MODE=True # Currently ignored unless you also set KDDockWidgets_DEVELOPER_MODE=True
# Default=false # Default=false
# #
# -DKDDockWidgets_EXAMPLES=[true|false] # -DKDDockWidgets_EXAMPLES=[true|false]
@@ -29,31 +35,45 @@
# Default=true # Default=true
# #
# -DKDDockWidgets_DOCS=[true|false] # -DKDDockWidgets_DOCS=[true|false]
# Build the API documentation. # Build the API documentation. Enables the 'docs' build target.
# Default=false # Default=false
# #
# -DKDDockWidgets_QTQUICK=[true|false]
# Build for QtQuick instead of QtWidgets.
# Default=false
#
# -DKDDockWidgets_PYTHON_BINDINGS=[true|false]
# Build/Generate python bindings. Always false for Debug builds
# (If your shiboken or pyside is installed in a non-standard locations
# try passing the SHIBOKEN_CUSTOM_PREFIX and PYSIDE2_CUSTOM_PREFIX variables.)
# Default=false
#
# -DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=[path]
# Set an alternative install path for Python bindings
# Default=CMAKE_INSTALL_PREFIX
# ## DO NOT USE IF YOU ARE AN END-USER. FOR THE DEVELOPERS ONLY!!
## Special CMake Options for Developers
#
# -DKDDockWidgets_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
# #
# -DKDDockWidgets_QTQUICK == IN DEVELOPMENT. DO NOT USE! == # -DKDDockWidgets_WERROR=[true|false]
# Build for QtQuick instead of QtWidgets # Compile with the -Werror gcc/clang option (always true for developer-mode)
# Default=false # Default=false
# #
# -DKDDockWidgets_PYTHON_BINDINGS=[true|false] # -DKDDockWidgets_LINTER=[true|false]
# Build/Generate python bindings. Always false for Debug builds # Build the layout linter.
# Default=false # Ignored unless KDDockWidgets_DEVELOPER_MODE=True
#
# -DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=[path]
# Set an alternative install path for Python bindings
# Default=CMAKE_INSTALL_PREFIX
#
# -DKDDockWidgets_UNITY_BUILD=[true|false]
# Build with CMake's UNITY_BUILD (requires CMake version 3.16 or higher)
# Default=true # Default=true
# #
# -DKDDockWidgets_FUZZER=[true|false]
# Build the fuzzer.
# Ignored unless KDDockWidgets_DEVELOPER_MODE=True
# Default=true
cmake_minimum_required(VERSION 3.7) cmake_minimum_required(VERSION 3.7)
if(POLICY CMP0020) if(POLICY CMP0020)
@@ -63,8 +83,26 @@ if(POLICY CMP0042)
cmake_policy(SET CMP0042 NEW) cmake_policy(SET CMP0042 NEW)
endif() endif()
# Just to fix warnings with --warn-uninitialized
if(NOT DEFINED USE_DEFAULT_INSTALL_LOCATION)
set(USE_DEFAULT_INSTALL_LOCATION FALSE)
endif()
if(NOT DEFINED CMAKE_INSTALL_PREFIX)
set(CMAKE_INSTALL_PREFIX "")
endif()
if(NOT DEFINED SHIBOKEN_CUSTOM_PREFIX) #look for shiboken in a custom location
set(SHIBOKEN_CUSTOM_PREFIX "")
endif()
if(NOT DEFINED PYSIDE2_CUSTOM_PREFIX) #look for pyside in a custom location
set(PYSIDE2_CUSTOM_PREFIX "")
endif()
if(NOT DEFINED PYSIDE6_CUSTOM_PREFIX) #look for pyside in a custom location
set(PYSIDE6_CUSTOM_PREFIX "")
endif()
# Allow using a non-KDAB install location
set(KDAB_INSTALL True) set(KDAB_INSTALL True)
if((NOT DEFINED ${USE_DEFAULT_INSTALL_LOCATION}) OR (NOT ${USE_DEFAULT_INSTALL_LOCATION})) if(NOT ${USE_DEFAULT_INSTALL_LOCATION})
if(NOT "${CMAKE_INSTALL_PREFIX}" STREQUAL "") if(NOT "${CMAKE_INSTALL_PREFIX}" STREQUAL "")
set(KDAB_INSTALL False) set(KDAB_INSTALL False)
endif() endif()
@@ -81,60 +119,81 @@ else()
endif() endif()
set(${PROJECT_NAME}_VERSION_MAJOR 1) set(${PROJECT_NAME}_VERSION_MAJOR 1)
set(${PROJECT_NAME}_VERSION_MINOR 2) set(${PROJECT_NAME}_VERSION_MINOR 4)
set(${PROJECT_NAME}_VERSION_PATCH 1) set(${PROJECT_NAME}_VERSION_PATCH 0)
set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH}) set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH})
set(${PROJECT_NAME}_SOVERSION "1.3") set(PROJECT_VERSION ${${PROJECT_NAME}_VERSION}) #PROJECT_VERSION is needed by some ECM modules
set(${PROJECT_NAME}_SOVERSION "1.4")
include(FeatureSummary) include(FeatureSummary)
option(${PROJECT_NAME}_QT6 "Build against Qt 6" OFF) option(${PROJECT_NAME}_QT6 "Build against Qt 6" OFF)
option(${PROJECT_NAME}_DEVELOPER_MODE "Developer Mode" OFF) option(${PROJECT_NAME}_DEVELOPER_MODE "Developer Mode" OFF)
option(${PROJECT_NAME}_PYTHON_BINDINGS "Build python bindings" OFF) option(${PROJECT_NAME}_PYTHON_BINDINGS "Build python bindings" OFF)
option(${PROJECT_NAME}_UNINSTALL "Enable the uninstall target" ON)
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.16.0") option(${PROJECT_NAME}_STATIC "Build statically" OFF)
option(${PROJECT_NAME}_UNITY_BUILD "Build with CMake's UNITY_BUILD" ON)
endif()
if(${PROJECT_NAME}_PYTHON_BINDINGS AND (CMAKE_BUILD_TYPE MATCHES "^[Dd]eb" OR ${PROJECT_NAME}_STATIC))
message(FATAL_ERROR "** Python Bindings are disabled in debug or static builds.")
endif()
option(${PROJECT_NAME}_TESTS "Build the tests" OFF) option(${PROJECT_NAME}_TESTS "Build the tests" OFF)
option(${PROJECT_NAME}_EXAMPLES "Build the examples" ON) option(${PROJECT_NAME}_EXAMPLES "Build the examples" ON)
option(${PROJECT_NAME}_DOCS "Build the API documentation" OFF) option(${PROJECT_NAME}_DOCS "Build the API documentation" OFF)
option(${PROJECT_NAME}_WERROR "Use -Werror (will be true for developer-mode unconditionally)" OFF) option(${PROJECT_NAME}_WERROR "Use -Werror (will be true for developer-mode unconditionally)" OFF)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/ECM/modules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/KDAB/modules")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake/Python")
#Always build the test harness in developer-mode #Always build the test harness in developer-mode
if(${PROJECT_NAME}_DEVELOPER_MODE) if(${PROJECT_NAME}_DEVELOPER_MODE)
set(${PROJECT_NAME}_TESTS ON) set(${PROJECT_NAME}_TESTS ON)
set(${PROJECT_NAME}_WERROR ON) set(${PROJECT_NAME}_WERROR ON)
include(ECMEnableSanitizers)
endif() endif()
#option(${PROJECT_NAME}_QTQUICK "Build for QtQuick instead of QtWidgets" OFF) option(${PROJECT_NAME}_QTQUICK "Build for QtQuick instead of QtWidgets" OFF)
if (${PROJECT_NAME}_QT6) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(IS_CLANG_BUILD TRUE)
else()
set(IS_CLANG_BUILD FALSE)
endif()
if(${PROJECT_NAME}_QT6)
find_package(Qt6Widgets REQUIRED) find_package(Qt6Widgets REQUIRED)
find_package(Qt6Test REQUIRED) find_package(Qt6Test REQUIRED)
set(QT_MAJOR_VERSION 6) set(QT_MAJOR_VERSION 6)
set(KDDockWidgets_LIBRARY_QTID "-qt6")
else() else()
find_package(Qt5Widgets 5.9 REQUIRED) find_package(Qt5Widgets 5.12 REQUIRED)
find_package(Qt5Test 5.9 REQUIRED) find_package(Qt5Test 5.12 REQUIRED)
set(QT_MAJOR_VERSION 5) set(QT_MAJOR_VERSION 5)
set(KDDockWidgets_LIBRARY_QTID "")
endif()
if(${PROJECT_NAME}_QTQUICK)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
endif() endif()
set(CMAKE_AUTOMOC ON) set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON) set(CMAKE_AUTORCC ON)
set(ECM_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ECM/modules/")
set(PYTHON_MODULE_DIR "${CMAKE_CURRENT_LIST_DIR}/cmake/Python")
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/cmake" ${ECM_MODULE_DIR} ${PYTHON_MODULE_DIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
# Set a default build type if none was specified
set(default_build_type "Release")
if(EXISTS "${CMAKE_SOURCE_DIR}/.git" OR ${PROJECT_NAME}_DEVELOPER_MODE)
set(default_build_type "Debug")
endif()
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
message(STATUS "Setting build type to ${default_build_type} as none was specified.")
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE STRING "Choose the type of build." FORCE)
# Set the possible values of build type for cmake-gui
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release" "MinSizeRel" "RelWithDebInfo")
endif()
# setup default install locations # setup default install locations
include(InstallLocation) include(InstallLocation)
include(QtInstallPaths) #to set QT_INSTALL_FOO variables include(KDQtInstallPaths) #to set QT_INSTALL_FOO variables
macro(set_compiler_flags targetName) macro(set_compiler_flags targetName)
if(${PROJECT_NAME}_DEVELOPER_MODE) if(${PROJECT_NAME}_DEVELOPER_MODE)
@@ -150,20 +209,27 @@ macro(set_compiler_flags targetName)
endif() endif()
# Enable -Werror # Enable -Werror
if(NOT MSVC AND ${PROJECT_NAME}_WERROR) if(${PROJECT_NAME}_WERROR AND (NOT MSVC OR IS_CLANG_BUILD)) # clang-cl accepts these too
target_compile_options(${targetName} PRIVATE -Werror -Wno-error=deprecated-declarations) target_compile_options(${targetName} PRIVATE -Werror -Wundef -Wno-error=deprecated-declarations)
endif() endif()
endmacro() endmacro()
set(${PROJECT_NAME}_DEPS "widgets")
if(${PROJECT_NAME}_QTQUICK) if(${PROJECT_NAME}_QTQUICK)
find_package(Qt${QT_MAJOR_VERSION}Quick) find_package(Qt${QT_MAJOR_VERSION}Quick)
find_package(Qt${QT_MAJOR_VERSION}QuickControls2) find_package(Qt${QT_MAJOR_VERSION}QuickControls2)
add_definitions(-DKDDOCKWIDGETS_QTQUICK) add_definitions(-DKDDOCKWIDGETS_QTQUICK)
set(${PROJECT_NAME}_DEPS "${${PROJECT_NAME}_DEPS} quick quickcontrols2")
else() else()
add_definitions(-DKDDOCKWIDGETS_QTWIDGETS) add_definitions(-DKDDOCKWIDGETS_QTWIDGETS)
endif() endif()
if(NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN AND NOT ${PROJECT_NAME}_QT6)
set(${PROJECT_NAME}_DEPS "${${PROJECT_NAME}_DEPS} x11extras")
endif()
if(${PROJECT_NAME}_STATIC) if(${PROJECT_NAME}_STATIC)
set(${PROJECT_NAME}_LIBRARY_MODE "STATIC") set(${PROJECT_NAME}_LIBRARY_MODE "STATIC")
else() else()
@@ -178,69 +244,82 @@ if(USE_DEFAULT_INSTALL_LOCATION)
endif() endif()
endif() endif()
add_subdirectory(src)
if(${PROJECT_NAME}_PYTHON_BINDINGS)
if(CMAKE_BUILD_TYPE MATCHES "^[Dd]eb" OR ${PROJECT_NAME}_STATIC)
message(FATAL_ERROR "** Python Bindings are disabled in debug or static builds.")
endif()
add_subdirectory(python)
endif()
# Generate .pri file for qmake users # Generate .pri file for qmake users
include(ECMGeneratePriFile) if(CMAKE_VERSION VERSION_GREATER "3.11.99" AND NOT CMAKE_CONFIGURATION_TYPES) # Not working with VS generator or older cmake versions
set(PROJECT_VERSION_STRING ${${PROJECT_NAME}_VERSION}) #TODO: ECM does not support Qt6 yet
ecm_generate_pri_file(BASE_NAME KDDockWidgets if(QT_MAJOR_VERSION EQUAL 5)
LIB_NAME kddockwidgets include(ECMGeneratePriFile)
FILENAME_VAR pri_filename set(PROJECT_VERSION_STRING ${${PROJECT_NAME}_VERSION})
) ecm_generate_pri_file(BASE_NAME KDDockWidgets
install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) LIB_NAME kddockwidgets
DEPS ${${PROJECT_NAME}_DEPS}
FILENAME_VAR pri_filename
INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR}
)
install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
endif()
else()
message(WARNING "Unable to generate the pri file for qmake users. Try updating CMake.")
endif()
install(FILES LICENSE.txt README.md DESTINATION ${INSTALL_DOC_DIR}) 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)
if(${PROJECT_NAME}_PYTHON_BINDINGS)
add_subdirectory(python)
endif()
if(${PROJECT_NAME}_EXAMPLES) if(${PROJECT_NAME}_EXAMPLES)
if (${PROJECT_NAME}_QTQUICK) if(${PROJECT_NAME}_QTQUICK)
add_subdirectory(examples/qtquick) add_subdirectory(examples/qtquick)
else() else()
add_subdirectory(examples/dockwidgets) add_subdirectory(examples/dockwidgets)
add_subdirectory(examples/minimal) add_subdirectory(examples/minimal)
set_compiler_flags(kddockwidgets_example) add_subdirectory(examples/minimal-mdi)
set_compiler_flags(kddockwidgets_minimal_example) set_compiler_flags(kddockwidgets_example)
set_compiler_flags(kddockwidgets_minimal_example)
endif() endif()
endif() endif()
if(${PROJECT_NAME}_DEVELOPER_MODE) if(${PROJECT_NAME}_DEVELOPER_MODE)
include(ECMEnableSanitizers)
if(${PROJECT_NAME}_TESTS) if(${PROJECT_NAME}_TESTS)
enable_testing() enable_testing()
add_subdirectory(tests) add_subdirectory(tests)
# Require Qt5.15.1 or higher to run the tests_launcher tests on Mac # Require Qt5.15.1 or higher to run the tests_launcher tests on Mac
if (NOT APPLE OR Qt5Widgets_VERSION VERSION_GREATER 5.15.0) if(NOT APPLE OR Qt5Widgets_VERSION VERSION_GREATER 5.15.0)
# tst_docks.exe is pretty big (160 tests), so split it in more runs so we can use threads. # tst_docks.exe is pretty big (160 tests), so split it in more runs so we can use threads.
add_test(NAME tst_docks0 COMMAND tests_launcher 0 5) add_test(NAME tst_docks0 COMMAND tests_launcher 0 5)
add_test(NAME tst_docks1 COMMAND tests_launcher 1 5) add_test(NAME tst_docks1 COMMAND tests_launcher 1 5)
add_test(NAME tst_docks2 COMMAND tests_launcher 2 5) add_test(NAME tst_docks2 COMMAND tests_launcher 2 5)
add_test(NAME tst_docks3 COMMAND tests_launcher 3 5) add_test(NAME tst_docks3 COMMAND tests_launcher 3 5)
add_test(NAME tst_docks4 COMMAND tests_launcher 4 5) add_test(NAME tst_docks4 COMMAND tests_launcher 4 5)
add_test(NAME tst_docks5 COMMAND tests_launcher 5 5) add_test(NAME tst_docks5 COMMAND tests_launcher 5 5)
add_test(NAME tst_docks6 COMMAND tests_launcher 6 5) add_test(NAME tst_docks6 COMMAND tests_launcher 6 5)
add_test(NAME tst_docks7 COMMAND tests_launcher 7 5) add_test(NAME tst_docks7 COMMAND tests_launcher 7 5)
add_test(NAME tst_docks8 COMMAND tests_launcher 8 5) add_test(NAME tst_docks8 COMMAND tests_launcher 8 5)
add_test(NAME tst_docks9 COMMAND tests_launcher 9 5) add_test(NAME tst_docks9 COMMAND tests_launcher 9 5)
add_test(NAME tst_docks10 COMMAND tests_launcher 10 5) add_test(NAME tst_docks10 COMMAND tests_launcher 10 5)
add_test(NAME tst_docks11 COMMAND tests_launcher 10 5) add_test(NAME tst_docks11 COMMAND tests_launcher 10 5)
add_test(NAME tst_docks12 COMMAND tests_launcher 11 5) add_test(NAME tst_docks12 COMMAND tests_launcher 11 5)
add_test(NAME tst_docks13 COMMAND tests_launcher 12 5) add_test(NAME tst_docks13 COMMAND tests_launcher 12 5)
add_test(NAME tst_docks14 COMMAND tests_launcher 13 5) add_test(NAME tst_docks14 COMMAND tests_launcher 13 5)
add_test(NAME tst_docks15 COMMAND tests_launcher 14 5) add_test(NAME tst_docks15 COMMAND tests_launcher 14 5)
add_test(NAME tst_docks16 COMMAND tests_launcher 15 5) add_test(NAME tst_docks16 COMMAND tests_launcher 15 5)
add_test(NAME tst_docks17 COMMAND tests_launcher 16 5) add_test(NAME tst_docks17 COMMAND tests_launcher 16 5)
add_test(NAME tst_docks18 COMMAND tests_launcher 17 5) add_test(NAME tst_docks18 COMMAND tests_launcher 17 5)
add_test(NAME tst_docks19 COMMAND tests_launcher 18 5) add_test(NAME tst_docks19 COMMAND tests_launcher 18 5)
add_test(NAME tst_docks20 COMMAND tests_launcher 19 5) add_test(NAME tst_docks20 COMMAND tests_launcher 19 5)
add_test(NAME tst_docks21 COMMAND tests_launcher 20 5) # one more for rounding leftovers add_test(NAME tst_docks21 COMMAND tests_launcher 20 5) # one more for rounding leftovers
endif() endif()
if (NOT ${PROJECT_NAME}_QTQUICK) if(NOT ${PROJECT_NAME}_QTQUICK)
# tst_multisplitter depends on QWidget # tst_multisplitter depends on QWidget
add_test(NAME tst_multisplitter COMMAND tst_multisplitter) add_test(NAME tst_multisplitter COMMAND tst_multisplitter)
endif() endif()
endif() endif()
@@ -248,8 +327,16 @@ endif()
if(${PROJECT_NAME}_DOCS) if(${PROJECT_NAME}_DOCS)
add_subdirectory(docs) # needs to go last, in case there are build source files add_subdirectory(docs) # needs to go last, in case there are build source files
#don't create the dummy docs target as it can conflict when used as a submodule
#else()
# add_custom_target(docs
# COMMAND ${CMAKE_COMMAND} -E echo "Sorry, there is no docs target since KDDockWidgets_DOCS=OFF."
# "Re-run cmake with the -DKDDockWidgets_DOCS=True option if you want to generate the documentation.")
endif() endif()
if (${PROJECT_NAME}_UNITY_BUILD) if(${PROJECT_NAME}_UNINSTALL)
set_target_properties(kddockwidgets PROPERTIES UNITY_BUILD ON) # Add uninstall target
include(ECMUninstallTarget)
endif() endif()
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)

View File

@@ -1,47 +1,88 @@
{ {
"version": 1, "version": 2,
"configurePresets": [ "configurePresets": [
{ {
"name": "dev-qtwidgets", "name": "dev",
"displayName": "dev-qtwidgets", "displayName": "dev",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-dev-qtwidgets", "binaryDir": "${sourceDir}/build-dev",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug", "CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_DEVELOPER_MODE": "ON", "KDDockWidgets_DEVELOPER_MODE": "ON",
"ECM_ENABLE_SANITIZERS" : "'address;undefined'" "ECM_ENABLE_SANITIZERS" : "'address;undefined'",
"CMAKE_EXPORT_COMPILE_COMMANDS" : "ON",
"KDDockWidgets_FUZZER" : "OFF"
},
"warnings" : {
"uninitialized" : true
} }
}, },
{ {
"name": "clazy-qtwidgets", "name": "dev-gammaray",
"displayName": "clazy-qtwidgets", "displayName": "dev-gammaray",
"description": "A Gammaray friendly build. (No ASAN)",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-clazy-qtwidgets", "binaryDir": "${sourceDir}/build-dev-gammaray",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug", "CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_WERROR": "ON" "KDDockWidgets_DEVELOPER_MODE": "ON",
"CMAKE_EXPORT_COMPILE_COMMANDS" : "ON",
"KDDockWidgets_FUZZER" : "OFF"
},
"warnings" : {
"uninitialized" : true
}
},
{
"name": "clazy",
"displayName": "clazy",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-clazy",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_WERROR": "ON",
"KDDockWidgets_EXAMPLES" : "OFF"
}, },
"environment": { "environment": {
"CXX": "clazy" "CXX": "clazy",
"CCACHE_DISABLE" : "ON"
} }
}, },
{ {
"name": "qtwidgets", "name": "clazy-qtquick",
"displayName": "qtwidgets", "displayName": "clazy-qtquick",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-qtwidgets", "binaryDir": "${sourceDir}/build-clazy-qtquick",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release" "CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_EXAMPLES" : "OFF",
"KDDockWidgets_WERROR": "ON",
"KDDockWidgets_QTQUICK": "ON"
},
"environment": {
"CXX": "clazy",
"CCACHE_DISABLE" : "ON"
} }
}, },
{ {
"name": "qtquick", "name": "release",
"displayName": "qtquick", "displayName": "release",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-qtquick", "binaryDir": "${sourceDir}/build-release",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release", "CMAKE_BUILD_TYPE": "Release",
"KDDockWidgets_QTQUICK": "ON" "CMAKE_UNITY_BUILD" : "ON"
}
},
{
"name": "release-qtquick",
"displayName": "release-qtquick",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-release-qtquick",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Release",
"KDDockWidgets_QTQUICK": "ON",
"CMAKE_UNITY_BUILD" : "ON"
} }
}, },
{ {
@@ -53,7 +94,9 @@
"CMAKE_BUILD_TYPE": "Debug", "CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_QTQUICK": "ON", "KDDockWidgets_QTQUICK": "ON",
"KDDockWidgets_DEVELOPER_MODE": "ON", "KDDockWidgets_DEVELOPER_MODE": "ON",
"ECM_ENABLE_SANITIZERS" : "'address;undefined'" "ECM_ENABLE_SANITIZERS" : "'address;undefined'",
"CMAKE_EXPORT_COMPILE_COMMANDS" : "ON",
"KDDockWidgets_FUZZER" : "OFF"
} }
}, },
{ {
@@ -63,17 +106,19 @@
"binaryDir": "${sourceDir}/build-python", "binaryDir": "${sourceDir}/build-python",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release", "CMAKE_BUILD_TYPE": "Release",
"KDDockWidgets_PYTHON_BINDINGS": "ON" "KDDockWidgets_PYTHON_BINDINGS": "ON",
"CMAKE_UNITY_BUILD" : "ON"
} }
}, },
{ {
"name": "static-qtwidgets", "name": "static",
"displayName": "static-qtwidgets", "displayName": "static",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-static-qtwidgets", "binaryDir": "${sourceDir}/build-static",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release", "CMAKE_BUILD_TYPE": "Release",
"KDDockWidgets_STATIC": "ON" "KDDockWidgets_STATIC": "ON",
"CMAKE_UNITY_BUILD" : "ON"
} }
}, },
{ {
@@ -84,49 +129,178 @@
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release", "CMAKE_BUILD_TYPE": "Release",
"KDDockWidgets_STATIC": "ON", "KDDockWidgets_STATIC": "ON",
"KDDockWidgets_QTQUICK": "ON" "KDDockWidgets_QTQUICK": "ON",
"CMAKE_UNITY_BUILD" : "ON"
} }
}, },
{ {
"name": "qtwidgets6", "name": "release6",
"displayName": "qtwidgets6", "displayName": "release6",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-qtwidgets6", "binaryDir": "${sourceDir}/build-release6",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release", "CMAKE_BUILD_TYPE": "Release",
"KDDockWidgets_QT6": "ON" "KDDockWidgets_QT6": "ON",
"CMAKE_UNITY_BUILD" : "ON",
"CMAKE_PREFIX_PATH" : "$env{QT6_DIR}"
}, },
"environment": { "environment": {
"PATH": "$env{HOME}/Qt/6.0.0/gcc_64/bin:$penv{PATH}" "PATH": "$env{QT6_DIR}/bin:$penv{PATH}"
} }
}, },
{ {
"name": "dev-qtwidgets6", "name": "dev6",
"displayName": "dev-qtwidgets6", "displayName": "dev6",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-dev-qtwidgets6", "binaryDir": "${sourceDir}/build-dev6",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug", "CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_QT6": "ON", "KDDockWidgets_QT6": "ON",
"KDDockWidgets_DEVELOPER_MODE": "ON", "KDDockWidgets_DEVELOPER_MODE": "ON",
"ECM_ENABLE_SANITIZERS" : "'address;undefined'" "CMAKE_EXPORT_COMPILE_COMMANDS" : "ON",
"ECM_ENABLE_SANITIZERS" : "'address;undefined'",
"KDDockWidgets_FUZZER" : "OFF",
"CMAKE_PREFIX_PATH" : "$env{QT6_DIR}"
}, },
"environment": { "environment": {
"PATH": "$env{HOME}/Qt/6.0.0/gcc_64/bin:$penv{PATH}" "PATH": "$env{QT6_DIR}/bin:$penv{PATH}"
} }
}, },
{ {
"name": "qtquick6", "name": "release-qtquick6",
"displayName": "qtquick6", "displayName": "release-qtquick6",
"generator": "Ninja", "generator": "Ninja",
"binaryDir": "${sourceDir}/build-qtquick6", "binaryDir": "${sourceDir}/build-release-qtquick6",
"cacheVariables": { "cacheVariables": {
"CMAKE_BUILD_TYPE": "Release", "CMAKE_BUILD_TYPE": "Release",
"KDDockWidgets_QTQUICK": "ON", "KDDockWidgets_QTQUICK": "ON",
"KDDockWidgets_QT6": "ON" "KDDockWidgets_QT6": "ON",
"CMAKE_UNITY_BUILD" : "ON",
"CMAKE_PREFIX_PATH" : "$env{QT6_DIR}"
}, },
"environment": { "environment": {
"PATH": "$env{HOME}/Qt/6.0.0/gcc_64/bin:$penv{PATH}" "PATH": "$env{QT6_DIR}/bin:$penv{PATH}"
}
},
{
"name": "dev-qtquick6",
"displayName": "dev-qtquick6",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-dev-qtquick6",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_QTQUICK": "ON",
"CMAKE_EXPORT_COMPILE_COMMANDS" : "ON",
"KDDockWidgets_DEVELOPER_MODE": "ON",
"ECM_ENABLE_SANITIZERS" : "'address;undefined'",
"KDDockWidgets_QT6": "ON",
"CMAKE_PREFIX_PATH" : "$env{QT6_DIR}"
},
"environment": {
"PATH": "$env{QT6_DIR}/bin:$penv{PATH}",
"QML2_IMPORT_PATH" : "$env{QT6_DIR}/imports:$env{QT6_DIR}/qml",
"LD_LIBRARY_PATH" : "$env{QT6_DIR}/lib"
}
},
{
"name": "dev-clangcl",
"displayName": "dev-clangcl",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-dev-clangcl",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_DEVELOPER_MODE": "ON",
"CMAKE_EXPORT_COMPILE_COMMANDS" : "ON",
"KDDockWidgets_FUZZER" : "ON"
},
"warnings" : {
"uninitialized" : true
},
"environment": {
"CC": "clang-cl",
"CXX": "clang-cl"
}
},
{
"name": "dev-qtquick-clangcl",
"displayName": "dev-qtquick-clangcl",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-dev-qtquick-clangcl",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_DEVELOPER_MODE": "ON",
"KDDockWidgets_FUZZER" : "OFF",
"KDDockWidgets_QTQUICK": "ON"
},
"warnings" : {
"uninitialized" : true
},
"environment": {
"CC": "clang-cl",
"CXX": "clang-cl"
}
},
{
"name": "dev-clangcl6",
"displayName": "dev-clangcl6",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-dev-clangcl6",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_DEVELOPER_MODE": "ON",
"KDDockWidgets_FUZZER" : "ON",
"KDDockWidgets_QT6": "ON",
"CMAKE_PREFIX_PATH" : "$env{QT6_DIR}"
},
"warnings" : {
"uninitialized" : true
},
"environment": {
"CC": "clang-cl",
"CXX": "clang-cl",
"PATH": "$env{QT6_DIR}/bin:$penv{PATH}"
}
},
{
"name": "dev-qtquick-clangcl6",
"displayName": "dev-qtquick-clangcl6",
"generator": "Ninja",
"binaryDir": "${sourceDir}/build-dev-qtquick-clangcl6",
"cacheVariables": {
"CMAKE_BUILD_TYPE": "Debug",
"KDDockWidgets_DEVELOPER_MODE": "ON",
"KDDockWidgets_FUZZER" : "OFF",
"KDDockWidgets_QTQUICK": "ON",
"KDDockWidgets_QT6": "ON",
"CMAKE_PREFIX_PATH" : "$env{QT6_DIR}"
},
"warnings" : {
"uninitialized" : true
},
"environment": {
"CC": "clang-cl",
"CXX": "clang-cl",
"PATH": "$env{QT6_DIR}/bin:$penv{PATH}",
"QML2_IMPORT_PATH" : "$env{QT6_DIR}/imports:$env{QT6_DIR}/qml",
"LD_LIBRARY_PATH" : "$env{QT6_DIR}/lib"
}
}
],
"buildPresets": [
{
"name": "clazy",
"configurePreset": "clazy",
"environment": {
"CLAZY_CHECKS" : "level2,detaching-member,heap-allocated-small-trivial-type,isempty-vs-count,qstring-varargs,qvariant-template-instantiation,raw-environment-function,reserve-candidates,signal-with-return-value,thread-with-slots,no-ctor-missing-parent-argument,no-missing-typeinfo",
"CCACHE_DISABLE" : "ON"
}
},
{
"name": "clazy-qtquick",
"configurePreset": "clazy-qtquick",
"environment": {
"CLAZY_CHECKS" : "level2,detaching-member,heap-allocated-small-trivial-type,isempty-vs-count,qstring-varargs,qvariant-template-instantiation,raw-environment-function,reserve-candidates,signal-with-return-value,thread-with-slots,no-ctor-missing-parent-argument,no-missing-typeinfo",
"CCACHE_DISABLE" : "ON"
} }
} }
] ]

7
CONTRIBUTORS.txt Normal file
View File

@@ -0,0 +1,7 @@
People who have signed the CLA:
Christian Riggenbach <criggenbach@magahugu.ch>
Jacob Young <amazingjacob@gmail.com>
Matthew Waltz <matthewwaltzis@gmail.com>
Roman Pudashkin <r.pudashkin@gmail.com>
Elnur Ismailzada <eismailzada@gmail.com>

View File

@@ -1,12 +1,69 @@
* v1.3.0 (unreleased) * v1.4.0 (16 July 2021)
- [TODO] QtQuick support - No longer supports Qt versions less than 5.12
- Experimental MDI support. By using MainWindowMDI you can now have "docked" dock widgets
which are free to be arbitrarily positioned and even overlapped inside the main window.
- TitleBar's height is now controlled by sizeHint() instead of hardcoded.
If you haven't overridden TitleBar or just inheriting from TitleBarWidget then there's nothing to do,
as TitleBarWidget already reimplements sizeHint. If you're inheriting directly from TitleBar then make
sure to provide a sizeHint.
- Added MainWindow::closeDockWidgets()
- Fixed crash in MainWindow::layoutEqually()
- QtQuick: Added more declarative API
- FloatingWindow now honours the dockwidget's max-size, if there's a single
dock widget docked. Tabbed cases are more difficult since QStackedLayout doesn't
propagate size constraints.
- Added MainWindowBase::frameCountChanged()
- Introduced Config::setDropIndicatorsInhibited(), which allows you to disable support
for drop indicators while dragging.
- Fixed embedding the main window into a non-kddw main window (#204, #168)
- Fixed crash with an MFC application
- Allows to disable translucency via the KDDW_NO_TRANSLUCENCY env var, useful
in case running on weird Window Managers.
- Added Flag_ShowButtonsOnTabBarIfTitleBarHidden, which can be used when using Flag_HideTitleBarWhenTabsVisible.
The close and float buttons will be shown directly in the tab-bar.
- Fixes persistent central frame being invisible after closing all tabs (#220)
- Added python bindings for the InitialOption struct (#198)
- Generate and install camelcase forwarding headers (public, exported classes)
- Build in Release mode by default (in non-developer situations)
* v1.3.1 (7 June 2021)
- Improve restoring layout when RestoreOption_RelativeToMainWindow is used (#171)
- Improved dragging windows across screens in mixed hdpi setups
- Fixed Flag_NativeTitleBar not hiding the client title bars when restoring (#170)
- Double clicking a native title bar of a Qt::Tool window will now redock the window (#173)
- Size of FloatingWindow now accounts for the fact that it's using Flag_NativeTitleBar and
resizes its content accordingly (#174)
- Fixed popups on overlayed dock widgets not working
- Don't restore maximized state when using RestoreOption_RelativeToMainWindow (#184)
* v1.3.0 (8 February 2021)
- Experimental QtQuick support (#49)
- Added static DockWidgetBase::byName() (#126) - Added static DockWidgetBase::byName() (#126)
- The enum KDDockWidgets::AddingOption has been deprecated, use - The enum KDDockWidgets::AddingOption has been deprecated, use
KDDockWidgets::InitialVisibilityOption instead KDDockWidgets::InitialVisibilityOption instead
- You can now pass a preferred initial size to MainWindow::addDockWidget() (#95) - You can now pass a preferred initial size to MainWindow::addDockWidget() (#95)
- Added DockWidgetBase::Option_DeleteOnClose
- Added Config::Flag_CloseOnlyCurrentTab
- PySide6 support
- Layout restorer now restores maximzied/minimized state too (#81)
- Fixed dock indicators sometimes not appearing on Windows (#103)
- Fixed Flag_NativeTitleBar not working
- Fixed drag offset when dragging too fast with mouse
- Fixed bug where last tab index position wouldn't be remembered in case user
had manually reordered tabs (#154)
- Fixed crash when hosting a QQuickWidget (#150)
- Fixed CMake Visual Studio generator not working
- Sidebar overlays now maintain their size when toggled (#155)
- Added DockWidget::setFloatingGeometry() (#144)
* v1.2.1 (unreleased) * v1.2.1 (6 February 2021)
- Support for resizing dock widgets when they are in overlay/popup mode (autohide/sidebar feature) - Support for resizing dock widgets when they are in overlay/popup mode (autohide/sidebar feature)
- Fixed title bar close button enabled state not being restored with Layout saver (#137)
- Installs a version header (kddockwidgets_version.h) that defines a version string and other useful versioning macros (#138)
- DockWidgetBase::eventFilter() is protected instead of private (regression vs v1.1) (#148)
It's recommended that you rebuild your application when updating KDDW, as MSVC encodes private/protected in the name mangling.
- Fixed WASM build on Windows (#163)
- Fixed sidebar overlay not getting hidden when clicking on the main window docking area (#157)
* v1.2.0 (17 December 2020) * v1.2.0 (17 December 2020)
- Wayland support - Wayland support

28
LICENSES/BSD-3-Clause.txt Normal file
View File

@@ -0,0 +1,28 @@
Copyright (c) <year> <owner>. All rights reserved.
This license applies to the CMake ECM modules only.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software without
specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

18
README-QtQuick.md Normal file
View File

@@ -0,0 +1,18 @@
Supported Qt versions and toolchains
=====================================
KDDockWidgets for QtQuick requires a C++17 capable compiler and either
Qt >= 5.15.0 or Qt >= 6.2.
TROUBLESHOOTING
===============
- QtGraphicalEffects is not supported, as it's buggy when moving between different QWindows.
See for example QTBUG-94943, KDDockWidgets issue #213. Also search the Qt bug tracker
for "QQuickItem: Cannot use same item on different windows at the same time"
- Very rarely, in some Nvidia/X11 setups, floating/docking has noticeable lag (like 1 second)
This could be solved by going to Nvidia's settings and making sure all monitors have
the same refresh rate and disabling "Allow Flipping". It's not known why this solves it. Might also
be a bug in Qt.

74
README-bindings.md Normal file
View File

@@ -0,0 +1,74 @@
These are the instructions for building the Python bindings for KDDockWidgets.
Make sure you have PySide2, shiboken2 and shiboken2-generator installed.
As this time, you cannot get shiboken2-generator because the wheels are not on PyPi.
To use the wheels do this:
```
% pip3 install \
--index-url=http://download.qt.io/official_releases/QtForPython/ \
--trusted-host download.qt.io \
shiboken2 pyside2 shiboken2_generator
```
For more info visit https://doc.qt.io/qtforpython/shiboken2/gettingstarted.html
afterwards run 'pip3 list | grep PySide2'
Note the version *must* match the same Qt you intend to use when building KDDockWidgets.
Not supported:
- Debug builds
- static builds
- python2 bindings
- only some 32-bit platforms are supported. see https://wiki.qt.io/Qt_for_Python
Tell CMake to build the bindings by passing the `-DKDDockWidgets_PYTHON_BINDINGS=True' option,
followed by the make command.
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
running applications. Alternatively, configure the bindings install location
by passing `-DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=/usr/lib/python3.8/site-packages`
to CMake (adjust to the python path on your system).
To run the KDDW python example
```
$ export PYTHONPATH=/kddw/install/path # Only if needed
$ cd python/examples/
$ rcc -g python -o rc_assets.py ../../examples/dockwidgets/resources_example.qrc
$ python3 main.py
```
Build Issues
* If you see errors like "Unable to locate Clang's built-in include directory"
then first make sure you have llvm installed. If you still have problems try
setting the environment variable `LLVM_INSTALL_DIR` to point to your llvm installation.
Examples:
```
export LLVM_INSTALL_DIR=/usr/local/opt/llvm-11
set "LLVM_INSTALL_DIR=C:\Program Files\LLVM" #Windows
```
* When building the examples you may encounter errors loading shared libraries from shiboken2_generator.
Try:
```
export LD_LIBRARY_PATH=/usr/local/lib/python/dist-packages/PySide2/Qt/lib #linux
export DYLD_LIBRARY_PATH=/usr/local/lib/python/dist-packages/PySide2/Qt/lib #Mac
#adjust to wherever your PySide is installed
```
* On Windows the `libclang.dll` that ship with QtForPython is not compatible with MSVC2019.
To fix this, copy the `libclang.dll` that comes with llvm into shiboken2, like so:
```
cd C:\Python37\Lib\site-packages\shiboken2_generator
copy libclang.dll libclang.dll.save
copy "C:\Program Files\llvm\bin\libclang.dll" libclang.dll
#Python3 installation in C:\Python37 and llvm in c:\Program Files\llvm. adjust as needed
```

View File

@@ -1,3 +1,5 @@
[![Build Status](https://travis-ci.com/KDAB/KDDockWidgets.svg?branch=master)](https://travis-ci.com/KDAB/KDDockWidgets)
KDDockWidgets KDDockWidgets
============= =============
`KDDockWidgets` is a Qt dock widget library written by KDAB, suitable for replacing `KDDockWidgets` is a Qt dock widget library written by KDAB, suitable for replacing
@@ -29,7 +31,7 @@ however that this demo isn't fully featured, as it's running on Qt for WebAssemb
Features Features
======== ========
- Provide advanced docking that QDockWidgets doesn't support - Provide advanced docking that QDockWidget doesn't support
- Native window resize on Windows (allowing for Aero-snap even with custom title bar decorations) - Native window resize on Windows (allowing for Aero-snap even with custom title bar decorations)
- Arrow drop indicators for great drop precision - Arrow drop indicators for great drop precision
- Allow for totally different, user provided, drop indicator types - Allow for totally different, user provided, drop indicator types
@@ -46,13 +48,13 @@ Features
- Customize title bars - Customize title bars
- Customize window frames - Customize window frames
- Custom widget separators - Custom widget separators
- Crossplatform (macOS, Linux, Windows, WebAssembly, Wayland, X11/XCB, EGLFS are working) - Cross-platform (macOS, Linux, Windows, WebAssembly, Wayland, X11/XCB, EGLFS are working)
See README-Wayland.md and README-WASM.md for platform specific information. See README-Wayland.md and README-WASM.md for platform specific information.
- Layouting engine honouring min/max size constraints and some size policies - Layouting engine honouring min/max size constraints and some size policies
- PySide2 bindings - PySide2 bindings
- Clean codebase - Clean codebase
- Not mixing GUI with state with logic with animations - Not mixing GUI with state with logic with animations
- Great test coverage, even the gui and DnD operations are tested. 200 tests currently. - Great test coverage, even the GUI and DnD operations are tested. 200 tests currently.
- Fuzzer for doing random testing and finding bugs - Fuzzer for doing random testing and finding bugs
- Lazy separator resize - Lazy separator resize
- Reordering tabs with mouse - Reordering tabs with mouse
@@ -69,16 +71,12 @@ Screen capture
![Screen capture](./screencap.gif?raw=true "The docking system in action") ![Screen capture](./screencap.gif?raw=true "The docking system in action")
Roadmap
========
- QtQuick support
Trying out the examples Trying out the examples
======================= =======================
A full demo lives in `examples/dockwidgets/`, it showcasts most of the features. A full demo that showcases most of the features lives in [examples/dockwidgets](examples/dockwidgets).
A simpler example lives in `examples/minimal/`, which might be more indicated
to learn the API, as it's less overwelming than the full demo.
A simpler example can be found in [examples/minimal](examples/minimal),
which might be more indicated to learn the API, as it's less overwhelming than the full demo.
Open a terminal capable of building Qt5 applications. Open a terminal capable of building Qt5 applications.
Make sure you have cmake, ninja, compiler, Qt, etc in PATH. Make sure you have cmake, ninja, compiler, Qt, etc in PATH.
@@ -93,72 +91,58 @@ $ 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 -G Ninja -DCMAKE_PREFIX_PATH=/path/where/to/install $ cmake -G Ninja -DCMAKE_PREFIX_PATH=/path/where/to/install
$ cmake --build . $ cmake --build .
$ ./kddockwidgets_example $ ./kddockwidgets_example
``` ```
The installation directory defaults to `c:\KDAB\KDDockWidgets-<version>` on Windows The installation directory defaults to `c:\KDAB\KDDockWidgets-<version>` on Windows
and `/usr/local/KDAB/KDDockWidgets-<version>` on non-Windows. You can change this and `/usr/local/KDAB/KDDockWidgets-<version>` on non-Windows.
location by passing the option `-DCMAKE_INSTALL_PREFIX=/install/path` to cmake.
You can change the installation location by passing the option `-DCMAKE_INSTALL_PREFIX=/install/path` to cmake.
Using Using
===== =====
From your CMake project, add From your CMake project, add
```
find_package(KDDockWidgets CONFIG) find_package(KDDockWidgets CONFIG)
```
and link to the imported target `KDAB::kddockwidgets`. and link to the imported target `KDAB::kddockwidgets`.
That's all you need to do (the imported target also brings in the include directories) That's all you need to do (the imported target also brings in the include directories)
You may also need to modify the `CMAKE_MODULE_PATH` environment variable depending You may also need to modify the `CMAKE_PREFIX_PATH` environment variable depending
on where you installed KDDockWidgets. on where you installed KDDockWidgets.
Python Bindings Python Bindings
================ ================
Make sure you have pyside2, shiboken2 and shiboken2-generator installed. Please refer to [README-bindings.md](README-bindings.md).
As this time, you cannot get shiboken2-generator because the wheels are not on PyPi.
To use the wheels do this:
``` Versioning
% pip3 install \ ==========
--index-url=http://download.qt.io/official_releases/QtForPython/ \
--trusted-host download.qt.io \
shiboken2 pyside2 shiboken2_generator
```
For more info visit https://doc.qt.io/qtforpython/shiboken2/gettingstarted.html New features go to master while the stable branch only accepts non-intrusive bug fixes.
Once QtForPython is installed you are ready to generate the PySide bindings We'll try to remain source-compatible across versions. API will get a deprecation
for KDDockwWidgets. notice before being removed in the next version. Note that this source-compatibility
effort is only for the public API. Private API (headers ending in _p.h) might change so you
shouldn't depend on them. Private API is only exposed so more advanced users can
override, for example `paintEvent()`, and not so they can change internal business logic.
Next pass `-DKDDockWidgets_PYTHON_BINDINGS=ON` to CMake, followed by the We don't promise or test binary compatibility. It's advised that you recompile
make command. your application whenever updating KDDW.
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
running applications. Alternatively, configure the bindings install location
by passing `-DKDDockWidgets_PYTHON_BINDINGS_INSTALL_PREFIX=/usr/lib/python3.8/site-packages`
to CMake (adjust to the python path on your system).
To run the KDDW python example
```
$ export PYTHONPATH=/kddw/install/path # Only if needed
$ cd python/examples/
$ rcc -g python -o rc_assets.py ../../examples/dockwidgets/resources_example.qrc
$ python3 main.py
```
Supported Qt versions and toolchains Supported Qt versions and toolchains
===================================== =====================================
KDDockWidgets requires Qt >= 5.9 (or >=5.12 if Python bindings are enabled). KDDockWidgets requires Qt5 >= 5.12 or Qt6 >= 6.1.
The QtQuick support will require Qt >= 5.15. The QtQuick support requires Qt5 >= 5.15 or Qt6 >= 6.1.
Qt 6 is supported.
Regarding compilers, whatever toolchain is able to build Qt 5.9 should also be Regarding compilers, whatever toolchain is able to build Qt 5.9 should also be
fine. Note however that MSVC 2013 isn't supported anymore due to compiler crashes. fine. Note however that MSVC 2013 isn't supported anymore due to compiler crashes.
@@ -166,7 +150,7 @@ fine. Note however that MSVC 2013 isn't supported anymore due to compiler crashe
Licensing Licensing
========= =========
KDDockWidgets is (C) 2018-2021, Klarälvdalens Datakonsult AB, and is licensed according to KDDockWidgets is (C) 2019-2021, Klarälvdalens Datakonsult AB, and is licensed according to
the terms of the [GPL 2.0](LICENSES/GPL-2.0-only.txt) or [GPL 3.0](LICENSES/GPL-3.0-only.txt). the terms of the [GPL 2.0](LICENSES/GPL-2.0-only.txt) or [GPL 3.0](LICENSES/GPL-3.0-only.txt).
Contact KDAB at <info@kdab.com> to inquire about commercial licensing. Contact KDAB at <info@kdab.com> to inquire about commercial licensing.
@@ -174,14 +158,26 @@ Contact KDAB at <info@kdab.com> to inquire about commercial licensing.
Get Involved Get Involved
============ ============
Please submit your issue reports to our GitHub space at
https://github.com/KDAB/KDDockWidgets
When reporting bugs please make it easy for the maintainer to reproduce it. Use `examples/minimal/` or
`examples/dockwidgets/` for reproducing the problem. If you did modifications to the example in order to
reproduce then please attach the *patch* and not a picture of your changes. You can get a patch by doing
`git diff > repro.diff` at the repo root.
Also state which KDDW sha1, branch or version you're using, and which operating system.
KDAB will happily accept external contributions; however, **all** contributions require a KDAB will happily accept external contributions; however, **all** contributions require a
signed [Copyright Assignment Agreement](docs/KDDockWidgets-CopyrightAssignmentForm.docx). signed [Copyright Assignment Agreement](docs/KDDockWidgets-CopyrightAssignmentForm.pdf).
This is needed so we can continue to dual-license it.
Contact info@kdab.com for more information. Contact info@kdab.com for more information.
Please submit your contributions or issue reports from our GitHub space at Thanks to our [contributors](CONTRIBUTORS.txt).
https://github.com/KDAB/KDDockWidgets
About KDAB About KDAB
========== ==========

80
appveyor.yml Normal file
View File

@@ -0,0 +1,80 @@
#---------------------------------#
# general configuration #
#---------------------------------#
# version format
version: 1.0.{build}-{branch}
# branches to build
branches:
except:
- gh-pages
# Do not build on tags (GitHub and BitBucket)
skip_tags: false
#---------------------------------#
# environment configuration #
#---------------------------------#
# Build worker image
image:
- Visual Studio 2019
# scripts that are called at very beginning, before repo cloning
init:
- git config --global core.autocrlf input
#---------------------------------#
# build configuration #
#---------------------------------#
# build platform, i.e. x86, x64, Any CPU. This setting is optional.
platform:
- x64
# build Configuration, i.e. Debug, Release, etc.
configuration:
- Release
install:
- call "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars64.bat"
- set QTDIR=C:\Qt\5.15\msvc2019_64
- set PATH=%QTDIR%\bin;%PATH%
build_script:
- mkdir build
- cd build
- cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=%CONFIGURATION% -DKDDockWidgets_TESTS=True -DKDDockWidgets_EXAMPLES=True -DKDDockWidgets_DEVELOPER_MODE=True ..
- nmake
# to disable automatic builds
#build: off
#---------------------------------#
# tests configuration #
#---------------------------------#
test_script:
- nmake test
# to disable automatic tests
#test: off
#---------------------------------#
# deployment configuration #
#---------------------------------#
deploy: off
#---------------------------------#
# notifications #
#---------------------------------#
notifications:
# Email
- provider: Email
to:
- allen.winter@kdab.com
- sergio.martins@kdab.com
on_build_success: false
on_build_failure: true

View File

@@ -40,6 +40,7 @@
# - thread # - thread
# - leak # - leak
# - undefined # - undefined
# - fuzzer-no-link
# - fuzzer # - fuzzer
# #
# The sanitizers "address", "memory" and "thread" are mutually exclusive. You # The sanitizers "address", "memory" and "thread" are mutually exclusive. You
@@ -102,30 +103,47 @@ endmacro ()
# MACRO check_compiler_support # MACRO check_compiler_support
#------------------------------ #------------------------------
macro (enable_sanitizer_flags sanitize_option) macro (enable_sanitizer_flags sanitize_option)
if (${sanitize_option} MATCHES "address") if (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
check_compiler_version("4.8" "3.1") if (${sanitize_option} MATCHES "address")
set(XSAN_COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls") set(msvc_asan_required_version "19.28")
set(XSAN_LINKER_FLAGS "asan") if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS ${msvc_asan_required_version})
elseif (${sanitize_option} MATCHES "thread") message(WARNING "Address sanitizer requires at least MSVC ${msvc_asan_required_version}")
check_compiler_version("4.8" "3.1") else()
set(XSAN_COMPILE_FLAGS "-fsanitize=thread") set(XSAN_COMPILE_FLAGS "-fsanitize=address")
set(XSAN_LINKER_FLAGS "tsan") endif()
elseif (${sanitize_option} MATCHES "memory") else()
check_compiler_version("99.99" "3.1") message(WARNING "Compiler sanitizer option \"${sanitize_option}\" not supported on MSVC yet")
set(XSAN_COMPILE_FLAGS "-fsanitize=memory") endif()
elseif (${sanitize_option} MATCHES "leak") else()
check_compiler_version("4.9" "3.4") if (${sanitize_option} MATCHES "address")
set(XSAN_COMPILE_FLAGS "-fsanitize=leak") check_compiler_version("4.8" "3.1")
set(XSAN_LINKER_FLAGS "lsan") set(XSAN_COMPILE_FLAGS "-fsanitize=address -fno-omit-frame-pointer -fno-optimize-sibling-calls")
elseif (${sanitize_option} MATCHES "undefined") set(XSAN_LINKER_FLAGS "asan")
check_compiler_version("4.9" "3.1") elseif (${sanitize_option} MATCHES "thread")
set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls") check_compiler_version("4.8" "3.1")
elseif (${sanitize_option} MATCHES "fuzzer") set(XSAN_COMPILE_FLAGS "-fsanitize=thread")
check_compiler_version("99.99" "6.0") set(XSAN_LINKER_FLAGS "tsan")
set(XSAN_COMPILE_FLAGS "-fsanitize=fuzzer") elseif (${sanitize_option} MATCHES "memory")
else () check_compiler_version("99.99" "3.1")
message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.") set(XSAN_COMPILE_FLAGS "-fsanitize=memory")
endif () elseif (${sanitize_option} MATCHES "leak")
check_compiler_version("4.9" "3.4")
set(XSAN_COMPILE_FLAGS "-fsanitize=leak")
set(XSAN_LINKER_FLAGS "lsan")
elseif (${sanitize_option} MATCHES "undefined")
check_compiler_version("4.9" "3.1")
set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fsanitize=float-divide-by-zero -fno-omit-frame-pointer -fno-optimize-sibling-calls")
elseif (${sanitize_option} MATCHES "fuzzer-no-link")
check_compiler_version("99.99" "6.0")
set(XSAN_COMPILE_FLAGS "-fsanitize=fuzzer-no-link")
set(XSAN_LINKER_FLAGS "-fsanitize=fuzzer-no-link")
elseif (${sanitize_option} MATCHES "fuzzer")
check_compiler_version("99.99" "6.0")
set(XSAN_COMPILE_FLAGS "-fsanitize=fuzzer")
else ()
message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.")
endif ()
endif()
endmacro () endmacro ()
if (ECM_ENABLE_SANITIZERS) if (ECM_ENABLE_SANITIZERS)
@@ -149,6 +167,11 @@ if (ECM_ENABLE_SANITIZERS)
string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}") string(REPLACE "-Wl,--no-undefined" "" CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS}")
endif () endif ()
endforeach() endforeach()
elseif (CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
foreach (CUR_SANITIZER ${ECM_ENABLE_SANITIZERS})
enable_sanitizer_flags(${CUR_SANITIZER})
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${XSAN_COMPILE_FLAGS}")
endforeach()
else() else()
message(STATUS "Tried to enable sanitizers (-DECM_ENABLE_SANITIZERS=${ECM_ENABLE_SANITIZERS}), \ message(STATUS "Tried to enable sanitizers (-DECM_ENABLE_SANITIZERS=${ECM_ENABLE_SANITIZERS}), \
but compiler (${CMAKE_CXX_COMPILER_ID}) does not have sanitizer support") but compiler (${CMAKE_CXX_COMPILER_ID}) does not have sanitizer support")

View File

@@ -0,0 +1,223 @@
# SPDX-FileCopyrightText: 2013 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kdemail.net>
# SPDX-FileCopyrightText: 2015 Patrick Spendrin <patrick.spendrin@kdab.com>
#
# SPDX-License-Identifier: BSD-3-Clause
#[=======================================================================[.rst:
ECMGenerateHeaders
------------------
Generate C/C++ CamelCase forwarding headers.
::
ecm_generate_headers(<camelcase_forwarding_headers_var>
HEADER_NAMES <CamelCaseName> [<CamelCaseName> [...]]
[ORIGINAL <CAMELCASE|LOWERCASE>]
[HEADER_EXTENSION <header_extension>]
[OUTPUT_DIR <output_dir>]
[PREFIX <prefix>]
[REQUIRED_HEADERS <variable>]
[COMMON_HEADER <HeaderName>]
[RELATIVE <relative_path>])
For each CamelCase header name passed to HEADER_NAMES, a file of that name
will be generated that will include a version with ``.h`` or, if set,
``.<header_extension>`` appended.
For example, the generated header ``ClassA`` will include ``classa.h`` (or
``ClassA.h``, see ORIGINAL).
If a CamelCaseName consists of multiple comma-separated files, e.g.
``ClassA,ClassB,ClassC``, then multiple camelcase header files will be
generated which are redirects to the first header file.
The file locations of these generated headers will be stored in
<camelcase_forwarding_headers_var>.
ORIGINAL specifies how the name of the original header is written: lowercased
or also camelcased. The default is LOWERCASE. Since 1.8.0.
HEADER_EXTENSION specifies what file name extension is used for the header
files. The default is "h". Since 5.48.0.
PREFIX places the generated headers in subdirectories. This should be a
CamelCase name like ``KParts``, which will cause the CamelCase forwarding
headers to be placed in the ``KParts`` directory (e.g. ``KParts/Part``). It
will also, for the convenience of code in the source distribution, generate
forwarding headers based on the original names (e.g. ``kparts/part.h``). This
allows includes like ``"#include <kparts/part.h>"`` to be used before
installation, as long as the include_directories are set appropriately.
OUTPUT_DIR specifies where the files will be generated; this should be within
the build directory. By default, ``${CMAKE_CURRENT_BINARY_DIR}`` will be used.
This option can be used to avoid file conflicts.
REQUIRED_HEADERS specifies an output variable name where all the required
headers will be appended so that they can be installed together with the
generated ones. This is mostly intended as a convenience so that adding a new
header to a project only requires specifying the CamelCase variant in the
CMakeLists.txt file; the original variant will then be added to this
variable.
COMMON_HEADER generates an additional convenience header which includes all
other header files.
The RELATIVE argument indicates where the original headers can be found
relative to CMAKE_CURRENT_SOURCE_DIR. It does not affect the generated
CamelCase forwarding files, but ecm_generate_headers() uses it when checking
that the original header exists, and to generate originally named forwarding
headers when PREFIX is set.
To allow other parts of the source distribution (eg: tests) to use the
generated headers before installation, it may be desirable to set the
INCLUDE_DIRECTORIES property for the library target to output_dir. For
example, if OUTPUT_DIR is CMAKE_CURRENT_BINARY_DIR (the default), you could do
.. code-block:: cmake
target_include_directories(MyLib PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}>")
Example usage (without PREFIX):
.. code-block:: cmake
ecm_generate_headers(
MyLib_FORWARDING_HEADERS
HEADERS
MLFoo
MLBar
# etc
REQUIRED_HEADERS MyLib_HEADERS
COMMON_HEADER MLGeneral
)
install(FILES ${MyLib_FORWARDING_HEADERS} ${MyLib_HEADERS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/include
COMPONENT Devel)
Example usage (with PREFIX):
.. code-block:: cmake
ecm_generate_headers(
MyLib_FORWARDING_HEADERS
HEADERS
Foo
# several classes are contained in bar.h, so generate
# additional files
Bar,BarList
# etc
PREFIX MyLib
REQUIRED_HEADERS MyLib_HEADERS
)
install(FILES ${MyLib_FORWARDING_HEADERS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/MyLib
COMPONENT Devel)
install(FILES ${MyLib_HEADERS}
DESTINATION ${CMAKE_INSTALL_PREFIX}/include/mylib
COMPONENT Devel)
Since pre-1.0.0.
#]=======================================================================]
include(CMakeParseArguments)
function(ECM_GENERATE_HEADERS camelcase_forwarding_headers_var)
set(options)
set(oneValueArgs ORIGINAL HEADER_EXTENSION OUTPUT_DIR PREFIX REQUIRED_HEADERS COMMON_HEADER RELATIVE)
set(multiValueArgs HEADER_NAMES)
cmake_parse_arguments(EGH "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if (EGH_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unexpected arguments to ECM_GENERATE_HEADERS: ${EGH_UNPARSED_ARGUMENTS}")
endif()
if(NOT EGH_HEADER_NAMES)
message(FATAL_ERROR "Missing header_names argument to ECM_GENERATE_HEADERS")
endif()
if(NOT EGH_ORIGINAL)
# default
set(EGH_ORIGINAL "LOWERCASE")
endif()
if(NOT EGH_ORIGINAL STREQUAL "LOWERCASE" AND NOT EGH_ORIGINAL STREQUAL "CAMELCASE")
message(FATAL_ERROR "Unexpected value for original argument to ECM_GENERATE_HEADERS: ${EGH_ORIGINAL}")
endif()
if(NOT EGH_HEADER_EXTENSION)
set(EGH_HEADER_EXTENSION "h")
endif()
if(NOT EGH_OUTPUT_DIR)
set(EGH_OUTPUT_DIR "${CMAKE_CURRENT_BINARY_DIR}")
endif()
# Make sure EGH_RELATIVE is /-terminated when it's not empty
if (EGH_RELATIVE AND NOT "${EGH_RELATIVE}" MATCHES "^.*/$")
set(EGH_RELATIVE "${EGH_RELATIVE}/")
endif()
set(originalprefix)
if (EGH_PREFIX)
if (NOT "${EGH_PREFIX}" MATCHES "^.*/$")
set(EGH_PREFIX "${EGH_PREFIX}/")
endif()
if (EGH_ORIGINAL STREQUAL "CAMELCASE")
set(originalprefix "${EGH_PREFIX}")
else()
string(TOLOWER "${EGH_PREFIX}" originalprefix)
endif()
endif()
foreach(_classnameentry ${EGH_HEADER_NAMES})
string(REPLACE "," ";" _classnames ${_classnameentry})
list(GET _classnames 0 _baseclass)
if (EGH_ORIGINAL STREQUAL "CAMELCASE")
set(originalbasename "${_baseclass}")
else()
string(TOLOWER "${_baseclass}" originalbasename)
endif()
set(_actualheader "${CMAKE_CURRENT_SOURCE_DIR}/${EGH_RELATIVE}${originalbasename}.${EGH_HEADER_EXTENSION}")
if (NOT EXISTS ${_actualheader})
message(FATAL_ERROR "Could not find \"${_actualheader}\"")
endif()
foreach(_CLASSNAME ${_classnames})
set(FANCY_HEADER_FILE "${EGH_OUTPUT_DIR}/${EGH_PREFIX}${_CLASSNAME}")
if (NOT EXISTS ${FANCY_HEADER_FILE})
file(WRITE ${FANCY_HEADER_FILE} "#include \"${originalprefix}${originalbasename}.${EGH_HEADER_EXTENSION}\"\n")
endif()
list(APPEND ${camelcase_forwarding_headers_var} "${FANCY_HEADER_FILE}")
if (EGH_PREFIX)
# Local forwarding header, for namespaced headers, e.g. kparts/part.h
if(EGH_ORIGINAL STREQUAL "CAMELCASE")
set(originalclassname "${_CLASSNAME}")
else()
string(TOLOWER "${_CLASSNAME}" originalclassname)
endif()
set(REGULAR_HEADER_NAME ${EGH_OUTPUT_DIR}/${originalprefix}${originalclassname}.${EGH_HEADER_EXTENSION})
if (NOT EXISTS ${REGULAR_HEADER_NAME})
file(WRITE ${REGULAR_HEADER_NAME} "#include \"${_actualheader}\"\n")
endif()
endif()
endforeach()
list(APPEND _REQUIRED_HEADERS "${_actualheader}")
endforeach()
if(EGH_COMMON_HEADER)
#combine required headers into 1 big convenience header
set(COMMON_HEADER ${EGH_OUTPUT_DIR}/${EGH_PREFIX}${EGH_COMMON_HEADER})
file(WRITE ${COMMON_HEADER} "// convenience header\n")
foreach(_header ${_REQUIRED_HEADERS})
get_filename_component(_base ${_header} NAME)
file(APPEND ${COMMON_HEADER} "#include \"${_base}\"\n")
endforeach()
list(APPEND ${camelcase_forwarding_headers_var} "${COMMON_HEADER}")
endif()
set(${camelcase_forwarding_headers_var} ${${camelcase_forwarding_headers_var}} PARENT_SCOPE)
if (EGH_REQUIRED_HEADERS)
set(${EGH_REQUIRED_HEADERS} ${${EGH_REQUIRED_HEADERS}} ${_REQUIRED_HEADERS} PARENT_SCOPE)
endif ()
endfunction()

View File

@@ -1,81 +1,88 @@
#.rst:
# ECMGeneratePriFile
# ------------------
#
# Generate a ``.pri`` file for the benefit of qmake-based projects.
#
# As well as the function below, this module creates the cache variable
# ``ECM_MKSPECS_INSTALL_DIR`` and sets the default value to ``mkspecs/modules``.
# This assumes Qt and the current project are both installed to the same
# non-system prefix. Packagers who use ``-DCMAKE_INSTALL_PREFIX=/usr`` will
# certainly want to set ``ECM_MKSPECS_INSTALL_DIR`` to something like
# ``share/qt5/mkspecs/modules``.
#
# The main thing is that this should be the ``modules`` subdirectory of either
# the default qmake ``mkspecs`` directory or of a directory that will be in the
# ``$QMAKEPATH`` environment variable when qmake is run.
#
# ::
#
# ecm_generate_pri_file(BASE_NAME <baseName>
# LIB_NAME <libName>
# [DEPS "<dep> [<dep> [...]]"]
# [FILENAME_VAR <filename_variable>]
# [INCLUDE_INSTALL_DIR <dir>]
# [LIB_INSTALL_DIR <dir>])
#
# If your CMake project produces a Qt-based library, you may expect there to be
# applications that wish to use it that use a qmake-based build system, rather
# than a CMake-based one. Creating a ``.pri`` file will make use of your
# library convenient for them, in much the same way that CMake config files make
# things convenient for CMake-based applications.
#
# ecm_generate_pri_file() generates just such a file. It requires the
# ``PROJECT_VERSION_STRING`` variable to be set. This is typically set by
# :module:`ECMSetupVersion`, although the project() command in CMake 3.0.0 and
# later can also set this.
#
# BASE_NAME specifies the name qmake project (.pro) files should use to refer to
# the library (eg: KArchive). LIB_NAME is the name of the actual library to
# link to (ie: the first argument to add_library()). DEPS is a space-separated
# list of the base names of other libraries (for Qt libraries, use the same
# names you use with the ``QT`` variable in a qmake project file, such as "core"
# for QtCore). FILENAME_VAR specifies the name of a variable to store the path
# to the generated file in.
#
# INCLUDE_INSTALL_DIR is the path (relative to ``CMAKE_INSTALL_PREFIX``) that
# include files will be installed to. It defaults to
# ``${INCLUDE_INSTALL_DIR}/<baseName>`` if the ``INCLUDE_INSTALL_DIR`` variable
# is set. If that variable is not set, the ``CMAKE_INSTALL_INCLUDEDIR`` variable
# is used instead, and if neither are set ``include`` is used. LIB_INSTALL_DIR
# operates similarly for the installation location for libraries; it defaults to
# ``${LIB_INSTALL_DIR}``, ``${CMAKE_INSTALL_LIBDIR}`` or ``lib``, in that order.
#
# Example usage:
#
# .. code-block:: cmake
#
# ecm_generate_pri_file(
# BASE_NAME KArchive
# LIB_NAME KF5KArchive
# DEPS "core"
# FILENAME_VAR pri_filename
# )
# install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
#
# A qmake-based project that wished to use this would then do::
#
# QT += KArchive
#
# in their ``.pro`` file.
#
# Since pre-1.0.0.
#=============================================================================
# SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org> # SPDX-FileCopyrightText: 2014 David Faure <faure@kde.org>
# #
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
#[=======================================================================[.rst:
ECMGeneratePriFile
------------------
Generate a ``.pri`` file for the benefit of qmake-based projects.
As well as the function below, this module creates the cache variable
``ECM_MKSPECS_INSTALL_DIR`` and sets the default value to ``mkspecs/modules``.
This assumes Qt and the current project are both installed to the same
non-system prefix. Packagers who use ``-DCMAKE_INSTALL_PREFIX=/usr`` will
certainly want to set ``ECM_MKSPECS_INSTALL_DIR`` to something like
``share/qt5/mkspecs/modules``.
The main thing is that this should be the ``modules`` subdirectory of either
the default qmake ``mkspecs`` directory or of a directory that will be in the
``$QMAKEPATH`` environment variable when qmake is run.
::
ecm_generate_pri_file(BASE_NAME <baseName>
LIB_NAME <libName>
[VERSION <version>] # since 5.83
[DEPS "<dep> [<dep> [...]]"]
[FILENAME_VAR <filename_variable>]
[INCLUDE_INSTALL_DIR <dir>]
[LIB_INSTALL_DIR <dir>])
If your CMake project produces a Qt-based library, you may expect there to be
applications that wish to use it that use a qmake-based build system, rather
than a CMake-based one. Creating a ``.pri`` file will make use of your
library convenient for them, in much the same way that CMake config files make
things convenient for CMake-based applications. ``ecm_generate_pri_file()``
generates just such a file.
VERSION specifies the version of the library the ``.pri`` file describes. If
not set, the value is taken from the context variable ``PROJECT_VERSION``.
This variable is usually set by the ``project(... VERSION ...)`` command or,
if CMake policy CMP0048 is not NEW, by :module:`ECMSetupVersion`.
For backward-compatibility with older ECM versions the
``PROJECT_VERSION_STRING`` variable as set by :module:`ECMSetupVersion`
will be preferred over ``PROJECT_VERSION`` if set, unless the minimum
required version of ECM is 5.83 and newer. Since 5.83.
BASE_NAME specifies the name qmake project (.pro) files should use to refer to
the library (eg: KArchive). LIB_NAME is the name of the actual library to
link to (ie: the first argument to add_library()). DEPS is a space-separated
list of the base names of other libraries (for Qt libraries, use the same
names you use with the ``QT`` variable in a qmake project file, such as "core"
for QtCore). FILENAME_VAR specifies the name of a variable to store the path
to the generated file in.
INCLUDE_INSTALL_DIR is the path (relative to ``CMAKE_INSTALL_PREFIX``) that
include files will be installed to. It defaults to
``${INCLUDE_INSTALL_DIR}/<baseName>`` if the ``INCLUDE_INSTALL_DIR`` variable
is set. If that variable is not set, the ``CMAKE_INSTALL_INCLUDEDIR`` variable
is used instead, and if neither are set ``include`` is used. LIB_INSTALL_DIR
operates similarly for the installation location for libraries; it defaults to
``${LIB_INSTALL_DIR}``, ``${CMAKE_INSTALL_LIBDIR}`` or ``lib``, in that order.
Example usage:
.. code-block:: cmake
ecm_generate_pri_file(
BASE_NAME KArchive
LIB_NAME KF5KArchive
DEPS "core"
FILENAME_VAR pri_filename
VERSION 4.2.0
)
install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
A qmake-based project that wished to use this would then do::
QT += KArchive
in their ``.pro`` file.
Since pre-1.0.0.
#]=======================================================================]
# Replicate the logic from KDEInstallDirs.cmake as we can't depend on it # Replicate the logic from KDEInstallDirs.cmake as we can't depend on it
# Ask qmake if we're using the same prefix as Qt # Ask qmake if we're using the same prefix as Qt
set(_askqmake OFF) set(_askqmake OFF)
@@ -89,15 +96,24 @@ endif()
if(KDE_INSTALL_USE_QT_SYS_PATHS OR _askqmake) if(KDE_INSTALL_USE_QT_SYS_PATHS OR _askqmake)
include(ECMQueryQmake) include(ECMQueryQmake)
query_qmake(qt_install_prefix_dir QT_INSTALL_PREFIX)
query_qmake(qt_host_data_dir QT_HOST_DATA) query_qmake(qt_host_data_dir QT_HOST_DATA)
set(ECM_MKSPECS_INSTALL_DIR ${qt_host_data_dir}/mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.") if(qt_install_prefix_dir STREQUAL "${CMAKE_INSTALL_PREFIX}")
file(RELATIVE_PATH qt_host_data_dir ${qt_install_prefix_dir} ${qt_host_data_dir})
endif()
if(qt_host_data_dir STREQUAL "")
set(mkspecs_install_dir mkspecs/modules)
else()
set(mkspecs_install_dir ${qt_host_data_dir}/mkspecs/modules)
endif()
set(ECM_MKSPECS_INSTALL_DIR ${mkspecs_install_dir} CACHE PATH "The directory where mkspecs will be installed to.")
else() else()
set(ECM_MKSPECS_INSTALL_DIR mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.") set(ECM_MKSPECS_INSTALL_DIR mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.")
endif() endif()
function(ECM_GENERATE_PRI_FILE) function(ECM_GENERATE_PRI_FILE)
set(options ) set(options )
set(oneValueArgs BASE_NAME LIB_NAME DEPS FILENAME_VAR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR) set(oneValueArgs BASE_NAME LIB_NAME DEPS FILENAME_VAR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR VERSION)
set(multiValueArgs ) set(multiValueArgs )
cmake_parse_arguments(EGPF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN}) cmake_parse_arguments(EGPF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
@@ -106,14 +122,28 @@ function(ECM_GENERATE_PRI_FILE)
message(FATAL_ERROR "Unknown keywords given to ECM_GENERATE_PRI_FILE(): \"${EGPF_UNPARSED_ARGUMENTS}\"") message(FATAL_ERROR "Unknown keywords given to ECM_GENERATE_PRI_FILE(): \"${EGPF_UNPARSED_ARGUMENTS}\"")
endif() endif()
if(ECM_GLOBAL_FIND_VERSION VERSION_LESS 5.83.0)
set(_support_backward_compat_version_string_var TRUE)
else()
set(_support_backward_compat_version_string_var FALSE)
endif()
if(NOT EGPF_BASE_NAME) if(NOT EGPF_BASE_NAME)
message(FATAL_ERROR "Required argument BASE_NAME missing in ECM_GENERATE_PRI_FILE() call") message(FATAL_ERROR "Required argument BASE_NAME missing in ECM_GENERATE_PRI_FILE() call")
endif() endif()
if(NOT EGPF_LIB_NAME) if(NOT EGPF_LIB_NAME)
message(FATAL_ERROR "Required argument LIB_NAME missing in ECM_GENERATE_PRI_FILE() call") message(FATAL_ERROR "Required argument LIB_NAME missing in ECM_GENERATE_PRI_FILE() call")
endif() endif()
if(NOT PROJECT_VERSION_STRING) if(NOT EGPF_VERSION)
message(FATAL_ERROR "Required variable PROJECT_VERSION_STRING not set before ECM_GENERATE_PRI_FILE() call. Did you call ecm_setup_version?") if(_support_backward_compat_version_string_var)
if(NOT PROJECT_VERSION_STRING AND NOT PROJECT_VERSION)
message(FATAL_ERROR "Required variable PROJECT_VERSION_STRING or PROJECT_VERSION not set before ECM_GENERATE_PRI_FILE() call. Missing call of ecm_setup_version() or project(VERSION)?")
endif()
else()
if(NOT PROJECT_VERSION)
message(FATAL_ERROR "Required variable PROJECT_VERSION not set before ECM_GENERATE_PRI_FILE() call. Missing call of ecm_setup_version() or project(VERSION)?")
endif()
endif()
endif() endif()
if(NOT EGPF_INCLUDE_INSTALL_DIR) if(NOT EGPF_INCLUDE_INSTALL_DIR)
if(INCLUDE_INSTALL_DIR) if(INCLUDE_INSTALL_DIR)
@@ -134,9 +164,22 @@ function(ECM_GENERATE_PRI_FILE)
endif() endif()
endif() endif()
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" PROJECT_VERSION_MAJOR "${PROJECT_VERSION_STRING}") if(EGPF_VERSION)
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" PROJECT_VERSION_MINOR "${PROJECT_VERSION_STRING}") set(PRI_VERSION "${EGPF_VERSION}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PROJECT_VERSION_PATCH "${PROJECT_VERSION_STRING}") else()
if(_support_backward_compat_version_string_var AND PROJECT_VERSION_STRING)
set(PRI_VERSION "${PROJECT_VERSION_STRING}")
if(NOT PROJECT_VERSION_STRING STREQUAL PROJECT_VERSION)
message(DEPRECATION "ECM_GENERATE_PRI_FILE() will no longer support PROJECT_VERSION_STRING when the required minimum version of ECM is 5.83 or newer. Set VERSION parameter or use PROJECT_VERSION instead.")
endif()
else()
set(PRI_VERSION "${PROJECT_VERSION}")
endif()
endif()
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" PRI_VERSION_MAJOR "${PRI_VERSION}")
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" PRI_VERSION_MINOR "${PRI_VERSION}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PRI_VERSION_PATCH "${PRI_VERSION}")
# Prepare the right number of "../.." to go from ECM_MKSPECS_INSTALL_DIR to the install prefix # Prepare the right number of "../.." to go from ECM_MKSPECS_INSTALL_DIR to the install prefix
# This allows to make the generated pri files relocatable (no absolute paths) # This allows to make the generated pri files relocatable (no absolute paths)
@@ -182,10 +225,10 @@ function(ECM_GENERATE_PRI_FILE)
file(GENERATE file(GENERATE
OUTPUT ${PRI_FILENAME} OUTPUT ${PRI_FILENAME}
CONTENT CONTENT
"QT.${PRI_TARGET_BASENAME}.VERSION = ${PROJECT_VERSION_STRING} "QT.${PRI_TARGET_BASENAME}.VERSION = ${PRI_VERSION}
QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PROJECT_VERSION_MAJOR} QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PRI_VERSION_MAJOR}
QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PROJECT_VERSION_MINOR} QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PRI_VERSION_MINOR}
QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PROJECT_VERSION_PATCH} QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PRI_VERSION_PATCH}
QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME} QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME}
QT.${PRI_TARGET_BASENAME}.module = ${PRI_TARGET_LIBNAME} QT.${PRI_TARGET_BASENAME}.module = ${PRI_TARGET_LIBNAME}
QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES} QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES}

View File

@@ -0,0 +1,212 @@
# SPDX-FileCopyrightText: 2014 Alex Merry <alex.merry@kde.org>
# SPDX-FileCopyrightText: 2012 Alexander Neundorf <neundorf@kde.org>
#
# SPDX-License-Identifier: BSD-3-Clause
#[=======================================================================[.rst:
ECMSetupVersion
---------------
Handle library version information.
::
ecm_setup_version(<version>
VARIABLE_PREFIX <prefix>
[SOVERSION <soversion>]
[VERSION_HEADER <filename>]
[PACKAGE_VERSION_FILE <filename> [COMPATIBILITY <compat>]] )
This parses a version string and sets up a standard set of version variables.
It can optionally also create a C version header file and a CMake package
version file to install along with the library.
If the ``<version>`` argument is of the form ``<major>.<minor>.<patch>``
(or ``<major>.<minor>.<patch>.<tweak>``), The following CMake variables are
set::
<prefix>_VERSION_MAJOR - <major>
<prefix>_VERSION_MINOR - <minor>
<prefix>_VERSION_PATCH - <patch>
<prefix>_VERSION - <version>
<prefix>_SOVERSION - <soversion>, or <major> if SOVERSION was not given
For backward-compatibility also this variable is set (only if the minimum required
version of ECM is < 5.83)::
<prefix>_VERSION_STRING - <version> (use <prefix>_VERSION instead)
If CMake policy CMP0048 is not NEW, the following CMake variables will also
be set::
PROJECT_VERSION_MAJOR - <major>
PROJECT_VERSION_MINOR - <minor>
PROJECT_VERSION_PATCH - <patch>
PROJECT_VERSION - <version>
For backward-compatibility, if CMake policy CMP0048 is not NEW, also this variable is set
(only if the minimum required version of ECM is < 5.83)::
PROJECT_VERSION_STRING - <version> (use PROJECT_VERSION instead)
If the VERSION_HEADER option is used, a simple C header is generated with the
given filename. If filename is a relative path, it is interpreted as relative
to CMAKE_CURRENT_BINARY_DIR. The generated header contains the following
macros::
<prefix>_VERSION_MAJOR - <major> as an integer
<prefix>_VERSION_MINOR - <minor> as an integer
<prefix>_VERSION_PATCH - <patch> as an integer
<prefix>_VERSION_STRING - <version> as a C string
<prefix>_VERSION - the version as an integer
``<prefix>_VERSION`` has ``<patch>`` in the bottom 8 bits, ``<minor>`` in the
next 8 bits and ``<major>`` in the remaining bits. Note that ``<patch>`` and
``<minor>`` must be less than 256.
If the PACKAGE_VERSION_FILE option is used, a simple CMake package version
file is created using the write_basic_package_version_file() macro provided by
CMake. It should be installed in the same location as the Config.cmake file of
the library so that it can be found by find_package(). If the filename is a
relative path, it is interpreted as relative to CMAKE_CURRENT_BINARY_DIR. The
optional COMPATIBILITY option is forwarded to
write_basic_package_version_file(), and defaults to AnyNewerVersion.
If CMake policy CMP0048 is NEW, an alternative form of the command is
available::
ecm_setup_version(PROJECT
[VARIABLE_PREFIX <prefix>]
[SOVERSION <soversion>]
[VERSION_HEADER <filename>]
[PACKAGE_VERSION_FILE <filename>] )
This will use the version information set by the project() command.
VARIABLE_PREFIX defaults to the project name. Note that PROJECT must be the
first argument. In all other respects, it behaves like the other form of the
command.
Since pre-1.0.0.
COMPATIBILITY option available since 1.6.0.
#]=======================================================================]
include(CMakePackageConfigHelpers)
# save the location of the header template while CMAKE_CURRENT_LIST_DIR
# has the value we want
set(_ECM_SETUP_VERSION_HEADER_TEMPLATE "${CMAKE_CURRENT_LIST_DIR}/ECMVersionHeader.h.in")
function(ecm_setup_version _version)
set(options )
set(oneValueArgs VARIABLE_PREFIX SOVERSION VERSION_HEADER PACKAGE_VERSION_FILE COMPATIBILITY)
set(multiValueArgs )
cmake_parse_arguments(ESV "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
if(ESV_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown keywords given to ECM_SETUP_VERSION(): \"${ESV_UNPARSED_ARGUMENTS}\"")
endif()
set(project_manages_version FALSE)
set(use_project_version FALSE)
cmake_policy(GET CMP0048 project_version_policy)
if(project_version_policy STREQUAL "NEW")
set(project_manages_version TRUE)
if(_version STREQUAL "PROJECT")
set(use_project_version TRUE)
endif()
elseif(_version STREQUAL "PROJECT")
message(FATAL_ERROR "ecm_setup_version given PROJECT argument, but CMP0048 is not NEW")
endif()
set(should_set_prefixed_vars TRUE)
if(NOT ESV_VARIABLE_PREFIX)
if(use_project_version)
set(ESV_VARIABLE_PREFIX "${PROJECT_NAME}")
set(should_set_prefixed_vars FALSE)
else()
message(FATAL_ERROR "Required argument PREFIX missing in ECM_SETUP_VERSION() call")
endif()
endif()
if(use_project_version)
set(_version "${PROJECT_VERSION}")
set(_major "${PROJECT_VERSION_MAJOR}")
set(_minor "${PROJECT_VERSION_MINOR}")
set(_patch "${PROJECT_VERSION_PATCH}")
else()
string(REGEX REPLACE "^0*([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" _major "${_version}")
string(REGEX REPLACE "^[0-9]+\\.0*([0-9]+)\\.[0-9]+.*" "\\1" _minor "${_version}")
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.0*([0-9]+).*" "\\1" _patch "${_version}")
endif()
if(NOT ESV_SOVERSION)
set(ESV_SOVERSION ${_major})
endif()
if(ECM_GLOBAL_FIND_VERSION VERSION_LESS 5.83.0)
set(_set_backward_compat_version_string_vars TRUE)
else()
set(_set_backward_compat_version_string_vars FALSE)
endif()
if(should_set_prefixed_vars)
set(${ESV_VARIABLE_PREFIX}_VERSION "${_version}")
set(${ESV_VARIABLE_PREFIX}_VERSION_MAJOR ${_major})
set(${ESV_VARIABLE_PREFIX}_VERSION_MINOR ${_minor})
set(${ESV_VARIABLE_PREFIX}_VERSION_PATCH ${_patch})
endif()
set(${ESV_VARIABLE_PREFIX}_SOVERSION ${ESV_SOVERSION})
if(NOT project_manages_version)
set(PROJECT_VERSION "${_version}")
set(PROJECT_VERSION_MAJOR "${_major}")
set(PROJECT_VERSION_MINOR "${_minor}")
set(PROJECT_VERSION_PATCH "${_patch}")
endif()
if(_set_backward_compat_version_string_vars)
set(PROJECT_VERSION_STRING "${PROJECT_VERSION}")
set(${ESV_VARIABLE_PREFIX}_VERSION_STRING "${${ESV_VARIABLE_PREFIX}_VERSION}")
endif()
if(ESV_VERSION_HEADER)
set(HEADER_PREFIX "${ESV_VARIABLE_PREFIX}")
set(HEADER_VERSION "${_version}")
set(HEADER_VERSION_MAJOR "${_major}")
set(HEADER_VERSION_MINOR "${_minor}")
set(HEADER_VERSION_PATCH "${_patch}")
configure_file("${_ECM_SETUP_VERSION_HEADER_TEMPLATE}" "${ESV_VERSION_HEADER}")
endif()
if(ESV_PACKAGE_VERSION_FILE)
if(NOT ESV_COMPATIBILITY)
set(ESV_COMPATIBILITY AnyNewerVersion)
endif()
write_basic_package_version_file("${ESV_PACKAGE_VERSION_FILE}" VERSION ${_version} COMPATIBILITY ${ESV_COMPATIBILITY})
endif()
if(should_set_prefixed_vars)
set(${ESV_VARIABLE_PREFIX}_VERSION_MAJOR "${${ESV_VARIABLE_PREFIX}_VERSION_MAJOR}" PARENT_SCOPE)
set(${ESV_VARIABLE_PREFIX}_VERSION_MINOR "${${ESV_VARIABLE_PREFIX}_VERSION_MINOR}" PARENT_SCOPE)
set(${ESV_VARIABLE_PREFIX}_VERSION_PATCH "${${ESV_VARIABLE_PREFIX}_VERSION_PATCH}" PARENT_SCOPE)
set(${ESV_VARIABLE_PREFIX}_VERSION "${${ESV_VARIABLE_PREFIX}_VERSION}" PARENT_SCOPE)
endif()
# always set the soversion
set(${ESV_VARIABLE_PREFIX}_SOVERSION "${${ESV_VARIABLE_PREFIX}_SOVERSION}" PARENT_SCOPE)
if(NOT project_manages_version)
set(PROJECT_VERSION "${PROJECT_VERSION}" PARENT_SCOPE)
set(PROJECT_VERSION_MAJOR "${PROJECT_VERSION_MAJOR}" PARENT_SCOPE)
set(PROJECT_VERSION_MINOR "${PROJECT_VERSION_MINOR}" PARENT_SCOPE)
set(PROJECT_VERSION_PATCH "${PROJECT_VERSION_PATCH}" PARENT_SCOPE)
endif()
if(_set_backward_compat_version_string_vars)
set(PROJECT_VERSION_STRING "${PROJECT_VERSION_STRING}" PARENT_SCOPE)
set(${ESV_VARIABLE_PREFIX}_VERSION_STRING "${${ESV_VARIABLE_PREFIX}_VERSION}" PARENT_SCOPE)
endif()
endfunction()

View File

@@ -0,0 +1,50 @@
# SPDX-FileCopyrightText: 2015 Alex Merry <alex.merry@kde.org>
#
# SPDX-License-Identifier: BSD-3-Clause
#[=======================================================================[.rst:
ECMUninstallTarget
------------------
Add an ``uninstall`` target.
By including this module, an ``uninstall`` target will be added to your CMake
project. This will remove all files installed (or updated) by a previous
invocation of the ``install`` target. It will not remove files created or
modified by an ``install(SCRIPT)`` or ``install(CODE)`` command; you should
create a custom uninstallation target for these and use ``add_dependency`` to
make the ``uninstall`` target depend on it:
.. code-block:: cmake
include(ECMUninstallTarget)
install(SCRIPT install-foo.cmake)
add_custom_target(uninstall_foo COMMAND ${CMAKE_COMMAND} -P uninstall-foo.cmake)
add_dependency(uninstall uninstall_foo)
The target will fail if the ``install`` target has not yet been run (so it is
not possible to run CMake on the project and then immediately run the
``uninstall`` target).
.. warning::
CMake deliberately does not provide an ``uninstall`` target by default on
the basis that such a target has the potential to remove important files
from a user's computer. Use with caution.
Since 1.7.0.
#]=======================================================================]
if (NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_LIST_DIR}/ecm_uninstall.cmake.in"
"${CMAKE_BINARY_DIR}/ecm_uninstall.cmake"
IMMEDIATE
@ONLY
)
add_custom_target(uninstall
COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_BINARY_DIR}/ecm_uninstall.cmake"
WORKING_DIRECTORY "${CMAKE_BINARY_DIR}"
)
endif()

View File

@@ -0,0 +1,17 @@
// This file was generated by ecm_setup_version(): DO NOT EDIT!
#ifndef @HEADER_PREFIX@_VERSION_H
#define @HEADER_PREFIX@_VERSION_H
#define @HEADER_PREFIX@_VERSION_STRING "@HEADER_VERSION@"
#define @HEADER_PREFIX@_VERSION_MAJOR @HEADER_VERSION_MAJOR@
#define @HEADER_PREFIX@_VERSION_MINOR @HEADER_VERSION_MINOR@
#define @HEADER_PREFIX@_VERSION_PATCH @HEADER_VERSION_PATCH@
#define @HEADER_PREFIX@_VERSION @HEADER_PREFIX@_VERSION_CHECK(@HEADER_PREFIX@_VERSION_MAJOR, @HEADER_PREFIX@_VERSION_MINOR, @HEADER_PREFIX@_VERSION_PATCH)
/*
for example: @HEADER_PREFIX@_VERSION >= @HEADER_PREFIX@_VERSION_CHECK(1, 2, 2))
*/
#define @HEADER_PREFIX@_VERSION_CHECK(major, minor, patch) ((major<<16)|(minor<<8)|(patch))
#endif

View File

@@ -0,0 +1,21 @@
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif()
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else()
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach()

View File

@@ -12,10 +12,10 @@ if(NOT INSTALL_RUNTIME_DIR)
set(INSTALL_RUNTIME_DIR ${CMAKE_INSTALL_BINDIR}) set(INSTALL_RUNTIME_DIR ${CMAKE_INSTALL_BINDIR})
endif() endif()
if(NOT INSTALL_LIBRARY_DIR) if(NOT INSTALL_LIBRARY_DIR)
set(INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR}) set(INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR})
endif() endif()
if(NOT INSTALL_ARCHIVE_DIR) if(NOT INSTALL_ARCHIVE_DIR)
set(INSTALL_ARCHIVE_DIR ${CMAKE_INSTALL_LIBDIR}) set(INSTALL_ARCHIVE_DIR ${CMAKE_INSTALL_LIBDIR})
endif() endif()
if(NOT INSTALL_INCLUDE_DIR) if(NOT INSTALL_INCLUDE_DIR)
set(INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR}) set(INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
@@ -28,7 +28,7 @@ if(NOT INSTALL_DOC_DIR)
endif() endif()
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE) set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
if (APPLE) if(APPLE)
set(CMAKE_MACOSX_RPATH ON) set(CMAKE_MACOSX_RPATH ON)
else() else()
set(CMAKE_INSTALL_RPATH "$ORIGIN/../${INSTALL_LIBRARY_DIR}") set(CMAKE_INSTALL_RPATH "$ORIGIN/../${INSTALL_LIBRARY_DIR}")

View File

@@ -4,29 +4,6 @@
# #
# SPDX-License-Identifier: BSD-3-Clause # SPDX-License-Identifier: BSD-3-Clause
# #
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# #
# Create variables for all the various install paths for the Qt version in use # Create variables for all the various install paths for the Qt version in use
@@ -63,7 +40,7 @@ foreach(QVAL ${VARS_LIST})
else() else()
list(GET QVAL_LIST 1 path) list(GET QVAL_LIST 1 path)
endif() endif()
if(NOT ${var}) #if set aleady on the command line for example if(NOT ${var}) #if set already on the command line for example
set(${var} ${path} CACHE PATH "Qt install path for ${var}") set(${var} ${path} CACHE PATH "Qt install path for ${var}")
endif() endif()
endif() endif()

View File

@@ -80,12 +80,12 @@ else()
message(STATUS "ShibokenGenerator base dir: ${SHIBOKEN_GENERATOR_BASEDIR}") message(STATUS "ShibokenGenerator base dir: ${SHIBOKEN_GENERATOR_BASEDIR}")
message(STATUS "Shiboken base dir: ${SHIBOKEN_BASEDIR}") message(STATUS "Shiboken base dir: ${SHIBOKEN_BASEDIR}")
message(STATUS "Shiboken custom path: ${SHIBOKEN_CUSTOM_PATH}") message(STATUS "Shiboken custom path: ${SHIBOKEN_CUSTOM_PREFIX}")
if(SHIBOKEN_BASEDIR) if(SHIBOKEN_BASEDIR)
find_path(SHIBOKEN_INCLUDE_DIR find_path(SHIBOKEN_INCLUDE_DIR
shiboken.h shiboken.h
PATHS ${SHIBOKEN_CUSTOM_PATH} ${SHIBOKEN_GENERATOR_BASEDIR}/include PATHS ${SHIBOKEN_CUSTOM_PREFIX} ${SHIBOKEN_GENERATOR_BASEDIR}/include
NO_DEFAULT_PATH) NO_DEFAULT_PATH)
if(MSVC) if(MSVC)
SET(SHIBOKEN_LIBRARY_BASENAMES "shiboken2.abi3.lib") SET(SHIBOKEN_LIBRARY_BASENAMES "shiboken2.abi3.lib")
@@ -112,7 +112,7 @@ else()
if (NOT SHIBOKEN_INCLUDE_DIR) if (NOT SHIBOKEN_INCLUDE_DIR)
return() return()
endif() endif()
set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PATH}) set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PREFIX})
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})
find_file(SHIBOKEN_LIBRARY find_file(SHIBOKEN_LIBRARY

View File

@@ -58,12 +58,12 @@ string(REPLACE ";" "." SHIBOKEN_VERSION "${SHIBOKEN_VERSION}")
message(STATUS "ShibokenGenerator base dir: ${SHIBOKEN_GENERATOR_BASEDIR}") message(STATUS "ShibokenGenerator base dir: ${SHIBOKEN_GENERATOR_BASEDIR}")
message(STATUS "Shiboken base dir: ${SHIBOKEN_BASEDIR}") message(STATUS "Shiboken base dir: ${SHIBOKEN_BASEDIR}")
message(STATUS "Shiboken custom path: ${SHIBOKEN_CUSTOM_PATH}") message(STATUS "Shiboken custom path: ${SHIBOKEN_CUSTOM_PREFIX}")
if(SHIBOKEN_BASEDIR) if(SHIBOKEN_BASEDIR)
find_path(SHIBOKEN_INCLUDE_DIR find_path(SHIBOKEN_INCLUDE_DIR
shiboken.h shiboken.h
PATHS ${SHIBOKEN_CUSTOM_PATH} ${SHIBOKEN_GENERATOR_BASEDIR}/include PATHS ${SHIBOKEN_CUSTOM_PREFIX} ${SHIBOKEN_GENERATOR_BASEDIR}/include
NO_DEFAULT_PATH) NO_DEFAULT_PATH)
if(MSVC) if(MSVC)
SET(SHIBOKEN_LIBRARY_BASENAMES "shiboken6.abi3.lib") SET(SHIBOKEN_LIBRARY_BASENAMES "shiboken6.abi3.lib")
@@ -90,7 +90,7 @@ if(SHIBOKEN_BASEDIR)
if (NOT SHIBOKEN_INCLUDE_DIR) if (NOT SHIBOKEN_INCLUDE_DIR)
return() return()
endif() endif()
set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PATH}) set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PREFIX})
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})
find_file(SHIBOKEN_LIBRARY find_file(SHIBOKEN_LIBRARY

View File

@@ -74,11 +74,11 @@ endmacro()
# Args: # Args:
# LIBRARY_NAME - The name of the output module # LIBRARY_NAME - The name of the output module
# TYPESYSTEM_PATHS - A list of paths where shiboken should look for typesystem files # TYPESYSTEM_PATHS - A list of paths where shiboken should look for typesystem files
# INCLUDE_PATHS - Include pahts necessary to parse your class. *This is not the same as build* # INCLUDE_PATHS - Include paths necessary to parse your class. *This is not the same as build*
# OUTPUT_SOURCES - The files that will be generated by shiboken # OUTPUT_SOURCES - The files that will be generated by shiboken
# TARGET_INCLUDE_DIRS - This will be passed to target_include_directories # TARGET_INCLUDE_DIRS - This will be passed to target_include_directories
# TARGET_LINK_LIBRARIES - This will be passed to target_link_libraries # TARGET_LINK_LIBRARIES - This will be passed to target_link_libraries
# GLOBAL_INCLUDE - A header-file that contains alls classes that will be generated # GLOBAL_INCLUDE - A header-file that contains all classes that will be generated
# TYPESYSTEM_XML - The target binding typesystem (that should be the full path) # TYPESYSTEM_XML - The target binding typesystem (that should be the full path)
# DEPENDS - This var will be passed to add_custom_command(DEPENDS) so a new generation will be # DEPENDS - This var will be passed to add_custom_command(DEPENDS) so a new generation will be
# trigger if one of these files changes # trigger if one of these files changes
@@ -137,7 +137,6 @@ macro(CREATE_PYTHON_BINDINGS
target_include_directories(${TARGET_NAME} PUBLIC target_include_directories(${TARGET_NAME} PUBLIC
${TARGET_INCLUDE_DIRS} ${TARGET_INCLUDE_DIRS}
${PYSIDE_EXTRA_INCLUDES}
) )
target_link_libraries(${TARGET_NAME} target_link_libraries(${TARGET_NAME}

View File

@@ -74,11 +74,11 @@ endmacro()
# Args: # Args:
# LIBRARY_NAME - The name of the output module # LIBRARY_NAME - The name of the output module
# TYPESYSTEM_PATHS - A list of paths where shiboken should look for typesystem files # TYPESYSTEM_PATHS - A list of paths where shiboken should look for typesystem files
# INCLUDE_PATHS - Include pahts necessary to parse your class. *This is not the same as build* # INCLUDE_PATHS - Include paths necessary to parse your class. *This is not the same as build*
# OUTPUT_SOURCES - The files that will be generated by shiboken # OUTPUT_SOURCES - The files that will be generated by shiboken
# TARGET_INCLUDE_DIRS - This will be passed to target_include_directories # TARGET_INCLUDE_DIRS - This will be passed to target_include_directories
# TARGET_LINK_LIBRARIES - This will be passed to target_link_libraries # TARGET_LINK_LIBRARIES - This will be passed to target_link_libraries
# GLOBAL_INCLUDE - A header-file that contains alls classes that will be generated # GLOBAL_INCLUDE - A header-file that contains all classes that will be generated
# TYPESYSTEM_XML - The target binding typesystem (that should be the full path) # TYPESYSTEM_XML - The target binding typesystem (that should be the full path)
# DEPENDS - This var will be passed to add_custom_command(DEPENDS) so a new generation will be # DEPENDS - This var will be passed to add_custom_command(DEPENDS) so a new generation will be
# trigger if one of these files changes # trigger if one of these files changes
@@ -137,7 +137,6 @@ macro(CREATE_PYTHON_BINDINGS
target_include_directories(${TARGET_NAME} PUBLIC target_include_directories(${TARGET_NAME} PUBLIC
${TARGET_INCLUDE_DIRS} ${TARGET_INCLUDE_DIRS}
${PYSIDE_EXTRA_INCLUDES}
) )
target_link_libraries(${TARGET_NAME} target_link_libraries(${TARGET_NAME}

View File

@@ -0,0 +1,147 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"C_Cpp.default.compileCommands": "${workspaceFolder}/build-dev-qtquick/compile_commands.json",
"C_Cpp.default.cStandard": "c17",
"files.trimTrailingWhitespace": true,
"editor.formatOnType": true,
"C_Cpp.autocompleteAddParentheses": true
},
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "gdb-kddockwidgets_customtitlebar_quick",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_customtitlebar_quick",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-kddockwidgets_example_mdi_quick",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_example_mdi_quick",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-kddockwidgets_example_quick",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_example_quick",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-tst_docks",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_customtitlebar_quick",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_customtitlebar_quick",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_example_mdi_quick",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_example_mdi_quick",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_example_quick",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_example_quick",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-tst_docks",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_customtitlebar_quick",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_customtitlebar_quick",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_example_mdi_quick",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_example_mdi_quick",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_example_quick",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/kddockwidgets_example_quick",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-tst_docks",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev-qtquick/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
}
]
}
}

View File

@@ -0,0 +1,147 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"C_Cpp.default.compileCommands": "${workspaceFolder}/build-dev/compile_commands.json",
"C_Cpp.default.cStandard": "c17",
"files.trimTrailingWhitespace": true,
"editor.formatOnType": true,
"C_Cpp.autocompleteAddParentheses": true
},
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "gdb-kddockwidgets_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-kddockwidgets_minimal_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_minimal_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-kddockwidgets_minimal_mdi_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_minimal_mdi_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-tst_docks",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_minimal_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_minimal_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_minimal_mdi_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_minimal_mdi_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-tst_docks",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_example",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_example",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_minimal_example",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_minimal_example",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_minimal_mdi_example",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/kddockwidgets_minimal_mdi_example",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-tst_docks",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
}
]
}
}

View File

@@ -0,0 +1,147 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"C_Cpp.default.compileCommands": "${workspaceFolder}/build-dev6/compile_commands.json",
"C_Cpp.default.cStandard": "c17",
"files.trimTrailingWhitespace": true,
"editor.formatOnType": true,
"C_Cpp.autocompleteAddParentheses": true
},
"launch": {
"version": "0.2.0",
"configurations": [
{
"name": "gdb-kddockwidgets_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-kddockwidgets_minimal_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_minimal_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-kddockwidgets_minimal_mdi_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_minimal_mdi_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "gdb-tst_docks",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_minimal_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_minimal_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-kddockwidgets_minimal_mdi_example",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_minimal_mdi_example",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "lldb-tst_docks",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "lldb",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_example",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_example",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_minimal_example",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_minimal_example",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-kddockwidgets_minimal_mdi_example",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/kddockwidgets_minimal_mdi_example",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
},
{
"name": "msvc-tst_docks",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build-dev6/bin/tst_docks",
"args": [],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"externalConsole": false
}
]
}
}

View File

@@ -13,6 +13,9 @@ Configuration options:
* build_examples * build_examples
Build the examples. Default=True Build the examples. Default=True
* builde_python_bindings * build_python_bindings
Build/Generate python bindings (always false for Debug or static builds). Default=False Build/Generate python bindings (always false for Debug or static builds). Default=False
* build_for_qt6
Build against Qt6 rather than Qt5. Default=false (Qt5 will be used even if Qt6 is available)
(Make sure the Qt6 bin directory is found in your execute PATH)

View File

@@ -11,7 +11,7 @@ from conans import ConanFile, CMake, tools
class KDDockWidgetsConan(ConanFile): class KDDockWidgetsConan(ConanFile):
name = "kddockwidgets" name = "kddockwidgets"
version = "1.2.0" version = "1.4.0"
default_user = "kdab" default_user = "kdab"
default_channel = "stable" default_channel = "stable"
license = ("https://raw.githubusercontent.com/KDAB/KDDockWidgets/master/LICENSES/GPL-2.0-only.txt", license = ("https://raw.githubusercontent.com/KDAB/KDDockWidgets/master/LICENSES/GPL-2.0-only.txt",
@@ -28,6 +28,7 @@ class KDDockWidgetsConan(ConanFile):
"build_examples": [True, False], "build_examples": [True, False],
"build_tests": [True, False], "build_tests": [True, False],
"build_python_bindings": [True, False], "build_python_bindings": [True, False],
"build_for_qt6": [True, False],
} }
default_options = { default_options = {
@@ -36,6 +37,7 @@ class KDDockWidgetsConan(ConanFile):
"build_examples": True, "build_examples": True,
"build_tests": False, "build_tests": False,
"build_python_bindings": False, "build_python_bindings": False,
"build_for_qt6": False,
} }
def requirements(self): def requirements(self):
@@ -52,6 +54,7 @@ class KDDockWidgetsConan(ConanFile):
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["KDDockWidgets_PYTHON_BINDINGS"] = self.options.build_python_bindings self.cmake.definitions["KDDockWidgets_PYTHON_BINDINGS"] = self.options.build_python_bindings
self.cmake.definitions["KDDockWidgets_QT6"] = self.options.build_for_qt6
self.cmake.configure() self.cmake.configure()
self.cmake.build() self.cmake.build()

View File

@@ -1,157 +0,0 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 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.
*/
/**
* This is an helper script which simply reads CMakePresets.json and builds those
* presets. It's just for quickly checking that every supported setup builds
* without having to wait for CI (or in case you don't have access to KDAB CI)
*
* Usage:
* $ dart build-all.dart <kddw-source-directory> [--unity] [--tests]
*/
import 'dart:io';
import 'dart:convert';
String s_sourceDirectory = "";
bool s_testUnityVariations = false;
bool s_runTests = true;
class Preset {
final String name;
final String buildDir;
Preset.fromJson(var jsonData)
: name = jsonData['name'],
buildDir = jsonData['binaryDir'] {
}
String buildDirectory() {
return buildDir.replaceAll("\${sourceDir}", s_sourceDirectory);
}
List<String> cmakeConfigArguments(bool isUnityBuild) {
return [
"-G",
"Ninja",
"-B",
buildDirectory(),
"-S",
s_sourceDirectory,
"--preset=" + name,
'-DKDDockWidgets_UNITY_BUILD=${isUnityBuild ? "ON" : "OFF"}'
];
}
List<String> cmakeBuildArguments() {
return ["--build", buildDirectory()];
}
// Builds twice. One with unity build and one without.
Future<bool> build() async {
if (!await buildSingle(true)) return false;
if (s_testUnityVariations) if (!await buildSingle(false)) return false;
if (s_runTests && !await runTests()) {
return false;
}
return true;
}
Future<bool> buildSingle(bool isUnityBuild) async {
if (!await runCMake(cmakeConfigArguments(isUnityBuild))) {
return false;
}
if (!await runCMake(cmakeBuildArguments())) {
return false;
}
return true;
}
Future<bool> runTests() async {
print("Running: ctest");
final savedCwd = Directory.current;
Directory.current = buildDirectory();
ProcessResult result = await Process.run('ctest', ["-j8"]);
Directory.current = savedCwd;
if (result.exitCode != 0) {
print(result.stdout);
print(result.stderr);
return false;
}
return true;
}
}
/// Returns the contents of the CMakePresets.json file
String cmakePresetsJson(presetsFile) {
var file = File(presetsFile);
if (!file.existsSync()) {
throw Exception('Not existent file');
}
return file.readAsStringSync();
}
List<Preset> readPresets(var presetsFile) {
var presets = List<Preset>();
final jsonData = jsonDecode(cmakePresetsJson(presetsFile));
for (var presetData in jsonData['configurePresets']) {
presets.add(Preset.fromJson(presetData));
}
return presets;
}
Future<bool> runCMake(var cmd) async {
print("Running: cmake " + cmd.join(' '));
ProcessResult result = await Process.run('cmake', cmd);
if (result.exitCode != 0) {
print(result.stdout);
print(result.stderr);
return false;
}
return true;
}
Future<int> main(List<String> arguments) async {
if (arguments.length == 0) {
print("Usage: build-all.dart <src-directory> [--unity] [--tests]");
return 1;
}
s_sourceDirectory = arguments[0];
s_testUnityVariations = arguments.contains("--unity");
s_runTests = arguments.contains("--tests");
final presetsFile = s_sourceDirectory + '/CMakePresets.json';
if (FileSystemEntity.typeSync(presetsFile) == FileSystemEntityType.notFound) {
print('ERROR: CMakePresets.json file not found in the source directory');
return 1;
}
var presets = readPresets(presetsFile);
for (var preset in presets) {
if (preset.name == 'python')
continue; // TODO: blacklisted as it's not building on my setup yet
if (!await preset.build()) {
return 1;
}
}
print("Success!!");
return 0;
}

View File

@@ -1,3 +1,21 @@
kddockwidgets (1.4.0) release candidate; urgency=high
* 1.4.0 final
-- Allen Winter <allen.winter@kdab.com> Fri, 16 Jul 2021 10:30:00 -0500
kddockwidgets (1.3.1) release candidate; urgency=high
* 1.3.1 final
-- Allen Winter <allen.winter@kdab.com> Mon, 07 Jun 2021 16:00:00 -0500
kddockwidgets (1.3.0) release candidate; urgency=high
* 1.3.0 final
-- Allen Winter <allen.winter@kdab.com> Mon, 08 Feb 2021 15:00:00 -0500
kddockwidgets (1.2.0) release candidate; urgency=high kddockwidgets (1.2.0) release candidate; urgency=high
* 1.2.0 final * 1.2.0 final

View File

@@ -0,0 +1,10 @@
Format: 1.0
Source: kddockwidgets
Version: 1.4.0-1
Binary: kddockwidgets
Maintainer: Allen Winter <allen.winter@kdab.com>
Architecture: any
Build-Depends: debhelper (>=9), cdbs, cmake, qtbase5-dev, libqt5x11extras5-dev
Files:
00000000000000000000000000000000 00000 qt5-kddockwidgets-1.4.0.tar.gz

View File

@@ -1,7 +1,7 @@
Name: kddockwidgets Name: qt5-kddockwidgets
Version: 1.2.0 Version: 1.4.0
Release: 1 Release: 1
Summary: KDAB's Dock Widget Framework for Qt Summary: KDAB's Dock Widget Framework for Qt5
Source0: %{name}-%{version}.tar.gz Source0: %{name}-%{version}.tar.gz
Source1: %{name}-%{version}.tar.gz.asc Source1: %{name}-%{version}.tar.gz.asc
Source2: %{name}-rpmlintrc Source2: %{name}-rpmlintrc
@@ -79,7 +79,18 @@ cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
%files devel %files devel
%defattr(-,root,root,-) %defattr(-,root,root,-)
%if 0%{?sle_version} >= 150200 && 0%{?is_opensuse}
%{_libdir}/qt5/mkspecs/modules/* %{_libdir}/qt5/mkspecs/modules/*
%endif
%if 0%{?suse_version} > 1500
%{_libdir}/qt5/mkspecs/modules/*
%endif
%if 0%{?fedora} > 28
%{_libdir}/qt5/mkspecs/modules/*
%endif
%if %{defined rhel}
%{_libdir}/qt5/mkspecs/modules/*
%endif
%dir %{_includedir}/kddockwidgets %dir %{_includedir}/kddockwidgets
%{_includedir}/kddockwidgets/* %{_includedir}/kddockwidgets/*
%dir %{_libdir}/cmake/KDDockWidgets %dir %{_libdir}/cmake/KDDockWidgets
@@ -87,6 +98,12 @@ cmake . -DCMAKE_INSTALL_PREFIX=/usr -DCMAKE_BUILD_TYPE=Release
%{_libdir}/libkddockwidgets.so %{_libdir}/libkddockwidgets.so
%changelog %changelog
* Fri Jul 16 2021 Allen Winter <allen.winter@kdab.com> 1.4.0
1.4.0 final
* Mon Jun 07 2021 Allen Winter <allen.winter@kdab.com> 1.3.1
1.3.1 final
* Mon Feb 08 2021 Allen Winter <allen.winter@kdab.com> 1.3.0
1.3.0 final
* Thu Dec 17 2020 Allen Winter <allen.winter@kdab.com> 1.2.0 * Thu Dec 17 2020 Allen Winter <allen.winter@kdab.com> 1.2.0
1.2.0 final 1.2.0 final
* Fri Dec 11 2020 Allen Winter <allen.winter@kdab.com> 1.1.1 * Fri Dec 11 2020 Allen Winter <allen.winter@kdab.com> 1.1.1

4
distro/qt6-debian.rules Normal file
View File

@@ -0,0 +1,4 @@
#!/usr/bin/make -f
DEB_CMAKE_EXTRA_FLAGS = -DKDDockWidgets_QT6=True -DCMAKE_BUILD_TYPE=Release
include /usr/share/cdbs/1/rules/debhelper.mk
include /usr/share/cdbs/1/class/cmake.mk

View File

@@ -0,0 +1 @@
addFilter("E: shlib-policy-name-error")

View File

@@ -0,0 +1,10 @@
Format: 1.0
Source: kddockwidgets
Version: 1.4.0-1
Binary: kddockwidgets
Maintainer: Allen Winter <allen.winter@kdab.com>
Architecture: any
Build-Depends: debhelper (>=9), cdbs, cmake, qtbase6-dev, libqt6x11extras5-dev
Files:
00000000000000000000000000000000 00000 qt6-kddockwidgets-1.4.0.tar.gz

View File

@@ -0,0 +1,105 @@
Name: qt6-kddockwidgets
Version: 1.4.0
Release: 1
Summary: KDAB's Dock Widget Framework for Qt6
Source0: %{name}-%{version}.tar.gz
Source1: %{name}-%{version}.tar.gz.asc
Source2: %{name}-rpmlintrc
URL: https://github.com/KDAB/KDDockWidgets
Group: System/Libraries
License: GPL-2.0-only OR GPL-3.0-only
BuildRoot: %{_tmppath}/%{name}-%{version}-build
Vendor: Klaralvdalens Datakonsult AB (KDAB)
Packager: Klaralvdalens Datakonsult AB (KDAB) <info@kdab.com>
BuildRequires: cmake
%if %{defined suse_version}
BuildRequires: libqt6-qtbase-devel libqt6-qtx11extras-devel
%endif
%if %{defined fedora}
BuildRequires: gcc-c++ qt6-qtbase-devel desktop-file-utils
%endif
%if %{defined rhel}
BuildRequires: gcc-c++ qt6-qtbase-devel qt6-qtx11extras-devel desktop-file-utils
%endif
%description
KDDockWidgets is a Qt dock widget library written by KDAB, suitable for replacing
QDockWidget and implementing advanced functionalities missing in Qt, including:
- Nesting dock widgets in a floating window and docking that group back to main window
- Docking to any main window, not only to the parent main window
- Docking to center of main window, or simply removing the concept of "central widget"
- Main window supporting detachable tabs in center widget
- Detaching arbitrary tabs from a tab bar into a dock area
- Exposing inner helper widgets so the user can customize them or provide his own
- Customize tab widgets
- Customize title bars
- Customize window frames
- Custom widget separators
...and much more
Authors:
--------
Klaralvdalens Datakonsult AB (KDAB) <info@kdab.com>
%define debug_package %{nil}
%global __debug_install_post %{nil}
%package devel
Summary: Development files for %{name}
Group: Development/Libraries/C and C++
Requires: %{name} = %{version}
%description devel
This package contains header files and associated tools and libraries to
develop programs using kddockwidgets.
%prep
%autosetup
%build
cmake . -DCMAKE_INSTALL_PREFIX=/usr -DKDDockWidgets_QT6=True -DCMAKE_BUILD_TYPE=Release
%__make %{?_smp_mflags}
%post -p /sbin/ldconfig
%postun -p /sbin/ldconfig
%install
%make_install
%clean
%__rm -rf "%{buildroot}"
%files
%defattr(-,root,root)
%{_prefix}/share/doc/KDDockWidgets
%{_libdir}/libkddockwidgets-qt6.so.*
%files devel
%defattr(-,root,root,-)
%dir %{_includedir}/kddockwidgets
%{_includedir}/kddockwidgets/*
%dir %{_libdir}/cmake/KDDockWidgets
%{_libdir}/cmake/KDDockWidgets/*
%{_libdir}/libkddockwidgets-qt6.so
#%{_prefix}/mkspecs/modules/* ECMGeneratePriFile isn't ported to Qt6 yet
%changelog
* Fri Jul 16 2021 Allen Winter <allen.winter@kdab.com> 1.4.0
1.4.0 final
* Mon Jun 07 2021 Allen Winter <allen.winter@kdab.com> 1.3.1
1.3.1 final
* Mon Feb 08 2021 Allen Winter <allen.winter@kdab.com> 1.3.0
1.3.0 final
* Thu Dec 17 2020 Allen Winter <allen.winter@kdab.com> 1.2.0
1.2.0 final
* Fri Dec 11 2020 Allen Winter <allen.winter@kdab.com> 1.1.1
1.1.1 final
* Mon Oct 26 2020 Allen Winter <allen.winter@kdab.com> 1.1.0
1.1.0 final
* Wed Sep 02 2020 Allen Winter <allen.winter@kdab.com> 1.0.0
1.0.0 final
* Thu Aug 06 2020 Allen Winter <allen.winter@kdab.com> 0.99.9
1.0.0 release candidate

Binary file not shown.

View File

@@ -13,6 +13,7 @@ find_file(QDOC_QTCORE_TAG qtcore.tags
HINTS ${QT_INSTALL_DOCS}/qtcore HINTS ${QT_INSTALL_DOCS}/qtcore
HINTS ${QT_INSTALL_DATA}/doc/qtcore HINTS ${QT_INSTALL_DATA}/doc/qtcore
) )
set(QDOC_TAG_DIR "<QDOC_TAG_DIR_not_found>")
if(QDOC_QTCORE_TAG) if(QDOC_QTCORE_TAG)
get_filename_component(QDOC_TAG_DIR ${QDOC_QTCORE_TAG} DIRECTORY) get_filename_component(QDOC_TAG_DIR ${QDOC_QTCORE_TAG} DIRECTORY)
get_filename_component(QDOC_TAG_DIR ${QDOC_TAG_DIR} DIRECTORY) get_filename_component(QDOC_TAG_DIR ${QDOC_TAG_DIR} DIRECTORY)
@@ -32,9 +33,18 @@ add_custom_command(
COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile COMMAND ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
#handle a bug in doxygen where image files referred to in markdown are not copied the output #handle a bug in doxygen where image files referred to in markdown are not copied the output
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../../screencap.gif ${DOXYGEN_OUTPUT_DIR}/html COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_CURRENT_SOURCE_DIR}/../../screencap.gif ${DOXYGEN_OUTPUT_DIR}/html
#copy some files by-hand that are referred to by the markdown README
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/README-bindings.md ${DOXYGEN_OUTPUT_DIR}/html
COMMAND ${CMAKE_COMMAND} -E make_directory ${DOXYGEN_OUTPUT_DIR}/html/LICENSES
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/LICENSES/GPL-2.0-only.txt ${DOXYGEN_OUTPUT_DIR}/html/LICENSES
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/LICENSES/GPL-3.0-only.txt ${DOXYGEN_OUTPUT_DIR}/html/LICENSES
COMMAND ${CMAKE_COMMAND} -E make_directory ${DOXYGEN_OUTPUT_DIR}/html/docs
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/docs/KDDockWidgets-CopyrightAssignmentForm.pdf ${DOXYGEN_OUTPUT_DIR}/html/docs
COMMAND ${CMAKE_COMMAND} -E copy_directory ${CMAKE_SOURCE_DIR}/examples ${DOXYGEN_OUTPUT_DIR}/html/examples
DEPENDS ${_dox_deps} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile DEPENDS ${_dox_deps} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
WORKING_DIRECTORY ${CMAKE_BINARY_DIR} WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
) )
add_custom_target(kddockwidgets-api.qch ALL DEPENDS ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch) add_custom_target(kddockwidgets-api.qch ALL DEPENDS ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch)
add_custom_target(docs DEPENDS kddockwidgets-api.qch)
install(FILES ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch DESTINATION ${INSTALL_DOC_DIR}) install(FILES ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch DESTINATION ${INSTALL_DOC_DIR})

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = "KDDockWidgets API Documentation"
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = @KDDockWidgets_VERSION@ PROJECT_NUMBER = @KDDockWidgets_VERSION_MAJOR@.@KDDockWidgets_VERSION_MINOR@
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
@@ -261,7 +261,7 @@ TAB_SIZE = 8
# commands \{ and \} for these it is advised to use the version @{ and @} or use # commands \{ and \} for these it is advised to use the version @{ and @} or use
# a double escape (\\{ and \\}) # a double escape (\\{ and \\})
ALIASES = ALIASES = "reimp=Reimplemented for internal purposes.\n"
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For # only. Doxygen will then generate output that is more tailored for C. For

View File

@@ -1,7 +1,7 @@
<hr> <hr>
<div style="float: left;"> <div style="float: left;">
<img src="kdab-logo-16x16.png"> <img src="kdab-logo-16x16.png">
<font style="font-weight: bold;">Klar&auml;lvdalens Datakonsult AB (KDAB)</font> <font style="font-weight: bold;">&copy; 2019-2021 Klar&auml;lvdalens Datakonsult AB (KDAB)</font>
<br> <br>
"The Qt, C++ and OpenGL 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>
@@ -12,7 +12,8 @@
<font style="font-weight: bold;">KDDockWidgets</font> <font style="font-weight: bold;">KDDockWidgets</font>
<br> <br>
Advanced Dock Widget Framework for Qt<br> Advanced Dock Widget Framework for Qt<br>
<a href="https://www.kdab.com/development-resources/qt-tools/kddockwidgets/">https://www.kdab.com/development-resources/qt-tools/kddockwidgets/</a> <a href="https://www.kdab.com/development-resources/qt-tools/kddockwidgets/">https://www.kdab.com/development-resources/qt-tools/kddockwidgets/</a><br>
$generatedby doxygen $doxygenversion<br>
</div> </div>
</body> </body>

View File

@@ -12,6 +12,11 @@
#include "MyFrameworkWidgetFactory.h" #include "MyFrameworkWidgetFactory.h"
#include <kddockwidgets/FrameworkWidgetFactory.h> #include <kddockwidgets/FrameworkWidgetFactory.h>
#include <kddockwidgets/private/TabWidget_p.h>
#include <kddockwidgets/private/widgets/FrameWidget_p.h>
#include <kddockwidgets/private/widgets/TabBarWidget_p.h>
#include <kddockwidgets/private/widgets/TabWidgetWidget_p.h>
#include <kddockwidgets/private/widgets/TitleBarWidget_p.h> #include <kddockwidgets/private/widgets/TitleBarWidget_p.h>
#include <kddockwidgets/private/multisplitter/Separator_qwidget.h> #include <kddockwidgets/private/multisplitter/Separator_qwidget.h>

View File

@@ -12,6 +12,7 @@
#include "MyMainWindow.h" #include "MyMainWindow.h"
#include "MyWidget.h" #include "MyWidget.h"
#include <kddockwidgets/Config.h>
#include <kddockwidgets/LayoutSaver.h> #include <kddockwidgets/LayoutSaver.h>
#include <QMenu> #include <QMenu>
@@ -20,9 +21,7 @@
#include <QDebug> #include <QDebug>
#include <QString> #include <QString>
#include <QTextEdit> #include <QTextEdit>
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
#include <QRandomGenerator> #include <QRandomGenerator>
#endif
#include <QApplication> #include <QApplication>
@@ -33,12 +32,7 @@
static MyWidget *newMyWidget() static MyWidget *newMyWidget()
{ {
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
const int randomNumber = qrand() % 100 + 1;
#else
const int randomNumber = QRandomGenerator::global()->bounded(0, 100) + 1; const int randomNumber = QRandomGenerator::global()->bounded(0, 100) + 1;
#endif
if (randomNumber < 50) { if (randomNumber < 50) {
if (randomNumber < 33) { if (randomNumber < 33) {
return new MyWidget1(); return new MyWidget1();
@@ -52,24 +46,23 @@ static MyWidget *newMyWidget()
MyMainWindow::MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options, MyMainWindow::MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
bool dockWidget0IsNonClosable, bool nonDockableDockWidget9, bool restoreIsRelative, bool dockWidget0IsNonClosable, bool nonDockableDockWidget9, bool restoreIsRelative,
bool maxSizeForDockWidget8, bool maxSizeForDockWidget8, bool dockwidget5DoesntCloseBeforeRestore,
const QString &affinityName, QWidget *parent) const QString &affinityName, QWidget *parent)
: MainWindow(uniqueName, options, parent) : MainWindow(uniqueName, options, parent)
, m_dockWidget0IsNonClosable(dockWidget0IsNonClosable) , m_dockWidget0IsNonClosable(dockWidget0IsNonClosable)
, m_dockWidget9IsNonDockable(nonDockableDockWidget9) , m_dockWidget9IsNonDockable(nonDockableDockWidget9)
, m_restoreIsRelative(restoreIsRelative) , m_restoreIsRelative(restoreIsRelative)
, m_maxSizeForDockWidget8(maxSizeForDockWidget8) , m_maxSizeForDockWidget8(maxSizeForDockWidget8)
, m_dockwidget5DoesntCloseBeforeRestore(dockwidget5DoesntCloseBeforeRestore)
{ {
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
qsrand(time(nullptr));
#endif
// qApp->installEventFilter(this);
auto menubar = menuBar(); auto menubar = menuBar();
auto fileMenu = new QMenu(QStringLiteral("File")); auto fileMenu = new QMenu(QStringLiteral("File"));
m_toggleMenu = new QMenu(QStringLiteral("Toggle")); m_toggleMenu = new QMenu(QStringLiteral("Toggle"));
auto miscMenu = new QMenu(QStringLiteral("Misc"));
menubar->addMenu(fileMenu); menubar->addMenu(fileMenu);
menubar->addMenu(m_toggleMenu); menubar->addMenu(m_toggleMenu);
menubar->addMenu(miscMenu);
QAction *newAction = fileMenu->addAction(QStringLiteral("New DockWidget")); QAction *newAction = fileMenu->addAction(QStringLiteral("New DockWidget"));
@@ -113,6 +106,13 @@ MyMainWindow::MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowO
auto quitAction = fileMenu->addAction(QStringLiteral("Quit")); auto quitAction = fileMenu->addAction(QStringLiteral("Quit"));
connect(quitAction, &QAction::triggered, qApp, &QApplication::quit); connect(quitAction, &QAction::triggered, qApp, &QApplication::quit);
QAction *toggleDropIndicatorSupport = miscMenu->addAction(QStringLiteral("Toggle Drop Indicator Support"));
toggleDropIndicatorSupport->setCheckable(true);
toggleDropIndicatorSupport->setChecked(true);
connect(toggleDropIndicatorSupport, &QAction::toggled, this, [](bool checked) {
KDDockWidgets::Config::self().setDropIndicatorsInhibited(!checked);
});
setAffinities({ affinityName }); setAffinities({ affinityName });
createDockWidgets(); createDockWidgets();
} }
@@ -133,7 +133,6 @@ void MyMainWindow::createDockWidgets()
for (int i = 0; i < numDockWidgets; i++) for (int i = 0; i < numDockWidgets; i++)
m_dockwidgets << newDockWidget(); m_dockwidgets << newDockWidget();
// MainWindow::addDockWidget() attaches a dock widget to the main window: // MainWindow::addDockWidget() attaches a dock widget to the main window:
addDockWidget(m_dockwidgets.at(0), KDDockWidgets::Location_OnTop); addDockWidget(m_dockwidgets.at(0), KDDockWidgets::Location_OnTop);
@@ -164,13 +163,18 @@ KDDockWidgets::DockWidgetBase *MyMainWindow::newDockWidget()
// Passing options is optional, we just want to illustrate Option_NotClosable here // Passing options is optional, we just want to illustrate Option_NotClosable here
KDDockWidgets::DockWidget::Options options = KDDockWidgets::DockWidget::Option_None; KDDockWidgets::DockWidget::Options options = KDDockWidgets::DockWidget::Option_None;
KDDockWidgets::DockWidget::LayoutSaverOptions layoutSaverOptions = KDDockWidgets::DockWidget::LayoutSaverOption::None;
if (count == 0 && m_dockWidget0IsNonClosable) if (count == 0 && m_dockWidget0IsNonClosable)
options |= KDDockWidgets::DockWidget::Option_NotClosable; options |= KDDockWidgets::DockWidget::Option_NotClosable;
if (count == 9 && m_dockWidget9IsNonDockable) if (count == 9 && m_dockWidget9IsNonDockable)
options |= KDDockWidgets::DockWidget::Option_NotDockable; options |= KDDockWidgets::DockWidget::Option_NotDockable;
auto dock = new KDDockWidgets::DockWidget(QStringLiteral("DockWidget #%1").arg(count), options); if (count == 5 && m_dockwidget5DoesntCloseBeforeRestore)
layoutSaverOptions |= KDDockWidgets::DockWidget::LayoutSaverOption::Skip;
auto dock = new KDDockWidgets::DockWidget(QStringLiteral("DockWidget #%1").arg(count), options, layoutSaverOptions);
dock->setAffinities(affinities()); // optional, just to show the feature. Pass -mi to the example to see incompatible dock widgets dock->setAffinities(affinities()); // optional, just to show the feature. Pass -mi to the example to see incompatible dock widgets
if (count == 1) if (count == 1)
@@ -192,6 +196,7 @@ KDDockWidgets::DockWidgetBase *MyMainWindow::newDockWidget()
dock->resize(600, 600); dock->resize(600, 600);
m_toggleMenu->addAction(dock->toggleAction()); m_toggleMenu->addAction(dock->toggleAction());
dock->toggleAction()->setShortcut(QStringLiteral("ctrl+%1").arg(count));
count++; count++;
return dock; return dock;

View File

@@ -20,7 +20,7 @@ class MyMainWindow : public KDDockWidgets::MainWindow
public: public:
explicit MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options, explicit MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
bool dockWidget0IsNonClosable, bool nonDockableDockWidget9, bool restoreIsRelative, bool dockWidget0IsNonClosable, bool nonDockableDockWidget9, bool restoreIsRelative,
bool maxSizeForDockWidget8, bool maxSizeForDockWidget8, bool dockwidget5DoesntCloseBeforeRestore,
const QString &affinityName = {}, // Usually not needed. Just here to show the feature. const QString &affinityName = {}, // Usually not needed. Just here to show the feature.
QWidget *parent = nullptr); QWidget *parent = nullptr);
~MyMainWindow() override; ~MyMainWindow() override;
@@ -33,5 +33,6 @@ private:
const bool m_dockWidget9IsNonDockable; const bool m_dockWidget9IsNonDockable;
const bool m_restoreIsRelative; const bool m_restoreIsRelative;
const bool m_maxSizeForDockWidget8; const bool m_maxSizeForDockWidget8;
const bool m_dockwidget5DoesntCloseBeforeRestore;
KDDockWidgets::DockWidget::List m_dockwidgets; KDDockWidgets::DockWidget::List m_dockwidgets;
}; };

View File

@@ -111,6 +111,18 @@ int main(int argc, char **argv)
QCommandLineOption autoHideSupport("w", QCoreApplication::translate("main", "Enables auto-hide/minimization to side-bar support")); QCommandLineOption autoHideSupport("w", QCoreApplication::translate("main", "Enables auto-hide/minimization to side-bar support"));
parser.addOption(autoHideSupport); parser.addOption(autoHideSupport);
QCommandLineOption closeOnlyCurrentTab("close-only-current-tab",
QCoreApplication::translate("main", "The title bar's close button will only close the current tab instead of all. Illustrates using Config::Flag_CloseOnlyCurrentTab"));
parser.addOption(closeOnlyCurrentTab);
QCommandLineOption dontCloseBeforeRestore("dont-close-widget-before-restore", //krazy:exclude=spelling
QCoreApplication::translate("main", "DockWidget #5 won't be closed before a restore. Illustrates LayoutSaverOption::DontCloseBeforeRestore"));
parser.addOption(dontCloseBeforeRestore);
QCommandLineOption showButtonsInTabBarIfTitleBarHidden("show-buttons-in-tabbar-if-titlebar-hidden",
QCoreApplication::translate("main", "If we're not using title bars we'll still show the close and float button in the tab bar"));
parser.addOption(showButtonsInTabBarIfTitleBarHidden);
#if defined(DOCKS_DEVELOPER_MODE) #if defined(DOCKS_DEVELOPER_MODE)
parser.addOption(centralFrame); parser.addOption(centralFrame);
@@ -177,6 +189,12 @@ int main(int argc, char **argv)
if (parser.isSet(autoHideSupport)) if (parser.isSet(autoHideSupport))
flags |= Config::Flag_AutoHideSupport; flags |= Config::Flag_AutoHideSupport;
if (parser.isSet(closeOnlyCurrentTab))
flags |= Config::Flag_CloseOnlyCurrentTab;
if (parser.isSet(showButtonsInTabBarIfTitleBarHidden))
flags |= Config::Flag_ShowButtonsOnTabBarIfTitleBarHidden;
if (parser.isSet(noTitleBars)) if (parser.isSet(noTitleBars))
flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible; flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible;
@@ -227,6 +245,7 @@ int main(int argc, char **argv)
const bool restoreIsRelative = parser.isSet(relativeRestore); const bool restoreIsRelative = parser.isSet(relativeRestore);
const bool nonDockableDockWidget9 = parser.isSet(nonDockable); const bool nonDockableDockWidget9 = parser.isSet(nonDockable);
const bool maxSizeForDockWidget8 = parser.isSet(maxSizeOption); const bool maxSizeForDockWidget8 = parser.isSet(maxSizeOption);
const bool dontCloseDockWidget5BeforeRestore = parser.isSet(dontCloseBeforeRestore);
const bool usesMainWindowsWithAffinity = parser.isSet(multipleMainWindows); const bool usesMainWindowsWithAffinity = parser.isSet(multipleMainWindows);
#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS #ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
@@ -236,7 +255,8 @@ int main(int argc, char **argv)
#endif #endif
MyMainWindow mainWindow(QStringLiteral("MyMainWindow"), options, nonClosableDockWidget0, MyMainWindow mainWindow(QStringLiteral("MyMainWindow"), options, nonClosableDockWidget0,
nonDockableDockWidget9, restoreIsRelative, maxSizeForDockWidget8); nonDockableDockWidget9, restoreIsRelative, maxSizeForDockWidget8,
dontCloseDockWidget5BeforeRestore);
mainWindow.setWindowTitle("Main Window 1"); mainWindow.setWindowTitle("Main Window 1");
mainWindow.resize(1200, 1200); mainWindow.resize(1200, 1200);
mainWindow.show(); mainWindow.show();
@@ -254,7 +274,8 @@ int main(int argc, char **argv)
auto mainWindow2 = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options, auto mainWindow2 = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options,
nonClosableDockWidget0, nonDockableDockWidget9, nonClosableDockWidget0, nonDockableDockWidget9,
restoreIsRelative, maxSizeForDockWidget8, affinity); restoreIsRelative, maxSizeForDockWidget8,
dontCloseDockWidget5BeforeRestore, affinity);
if (affinity.isEmpty()) if (affinity.isEmpty())
mainWindow2->setWindowTitle("Main Window 2"); mainWindow2->setWindowTitle("Main Window 2");
else else
@@ -267,7 +288,8 @@ int main(int argc, char **argv)
const QString affinity = QStringLiteral("Inner-DockWidgets-2"); const QString affinity = QStringLiteral("Inner-DockWidgets-2");
auto dockableMainWindow = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options, auto dockableMainWindow = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options,
false, false, restoreIsRelative, false, affinity); false, false, restoreIsRelative, false,
false, affinity);
dockableMainWindow->setAffinities({ affinity }); dockableMainWindow->setAffinities({ affinity });

View File

@@ -0,0 +1,37 @@
#
# This file is part of KDDockWidgets.
#
# SPDX-FileCopyrightText: 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
# Author: Sergio Martins <sergio.martins@kdab.com>
#
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
#
# Contact KDAB at <info@kdab.com> for commercial licensing options.
#
cmake_minimum_required(VERSION 3.7)
project(kddockwidgets_minimal_mdi_example)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
if(NOT TARGET kddockwidgets)
# This will look for Qt, do find_package yourself manually before
# if you want to look for a specific Qt version for instance.
find_package(KDDockWidgets REQUIRED)
endif()
set(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../dockwidgets/resources_example.qrc)
add_executable(kddockwidgets_minimal_mdi_example
main.cpp
../dockwidgets/MyWidget.cpp
${RESOURCES_EXAMPLE_SRC}
)
target_link_libraries(kddockwidgets_minimal_mdi_example
PRIVATE
KDAB::kddockwidgets
)

View File

@@ -0,0 +1,116 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2019-2021 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 "MyWidget.h"
#include <QPainter>
#include <QDebug>
#include <QFile>
#include <QLineEdit>
static QHash<QString, QImage> s_images; /// clazy:exclude=non-pod-global-static
MyWidget::MyWidget(const QString &backgroundFile, const QString &logoFile, QWidget *parent)
: QWidget(parent)
{
if (!backgroundFile.isEmpty()) {
auto it = s_images.find(backgroundFile);
if (it == s_images.end())
it = s_images.insert(backgroundFile, QImage(backgroundFile));
m_background = it.value();
}
if (!logoFile.isEmpty()) {
auto it = s_images.find(logoFile);
if (it == s_images.end())
it = s_images.insert(logoFile, QImage(logoFile));
m_logo = it.value();
}
setFocusPolicy(Qt::StrongFocus);
#if 0
// Uncomment to show focus propagation working
new QLineEdit(this);
auto l2 = new QLineEdit(this);
l2->move(0, 100);
setFocusProxy(l2);
#endif
}
MyWidget::~MyWidget()
{
}
void MyWidget::drawLogo(QPainter &p)
{
if (m_logo.isNull())
return;
const qreal ratio = m_logo.height() / (m_logo.width() * 1.0);
const int maxWidth = int(0.80 * size().width());
const int maxHeight = int(0.80 * size().height());
const int proposedHeight = int(maxWidth * ratio);
const int width = proposedHeight <= maxHeight ? maxWidth
: int(maxHeight / ratio);
const int height = int(width * ratio);
QRect targetLogoRect(0,0, width, height);
targetLogoRect.moveCenter(rect().center() + QPoint(0, -int(size().height() * 0.00)));
p.drawImage(targetLogoRect, m_logo, m_logo.rect());
}
MyWidget1::MyWidget1(MyWidget::QWidget *parent)
: MyWidget(QStringLiteral(":/assets/triangles.png"), QStringLiteral(":/assets/KDAB_bubble_white.png"), parent)
{
}
void MyWidget1::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.fillRect(rect(), QColor(0xCC, 0xCC, 0xCC));
p.drawImage(m_background.rect(), m_background, m_background.rect());
drawLogo(p);
}
MyWidget2::MyWidget2(MyWidget::QWidget *parent)
: MyWidget(QString(), QStringLiteral(":/assets/KDAB_bubble_blue.png"), parent)
{
}
void MyWidget2::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.fillRect(rect(), Qt::white);
drawLogo(p);
}
MyWidget3::MyWidget3(MyWidget::QWidget *parent)
: MyWidget(QStringLiteral(":/assets/base.png"), QStringLiteral(":/assets/KDAB_bubble_fulcolor.png"), parent)
, m_triangle(QImage(QStringLiteral(":/assets/tri.png")))
{
}
void MyWidget3::paintEvent(QPaintEvent *)
{
QPainter p(this);
p.fillRect(rect(), QColor(0xD5, 0xD5, 0xD5));
p.drawImage(m_background.rect(), m_background, m_background.rect());
const QRect targetRect = QRect({ width() - m_triangle.width(), height() - m_triangle.height() }, m_triangle.size());
p.drawImage(targetRect, m_triangle, m_triangle.rect());
drawLogo(p);
}

View File

@@ -0,0 +1,65 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2019-2021 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 EXAMPLEDOCKABLEWIDGET_H
#define EXAMPLEDOCKABLEWIDGET_H
#pragma once
#include <QWidget>
QT_BEGIN_NAMESPACE
class QPainter;
QT_END_NAMESPACE
class MyWidget : public QWidget
{
Q_OBJECT
public:
MyWidget() = default;
explicit MyWidget(const QString &backgroundFile, const QString &logoFile, QWidget *parent = nullptr);
~MyWidget();
protected:
void drawLogo(QPainter &);
QImage m_background;
QImage m_logo;
};
class MyWidget1 : public MyWidget
{
Q_OBJECT
public:
explicit MyWidget1(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent*) override;
};
class MyWidget2 : public MyWidget
{
Q_OBJECT
public:
explicit MyWidget2(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent*) override;
};
class MyWidget3 : public MyWidget
{
Q_OBJECT
public:
explicit MyWidget3(QWidget *parent = nullptr);
protected:
void paintEvent(QPaintEvent*) override;
QImage m_triangle;
};
#endif

View File

@@ -0,0 +1,62 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2019-2021 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 "MyWidget.h"
#include <kddockwidgets/DockWidget.h>
#include <kddockwidgets/MainWindowMDI.h>
#include <QStyleFactory>
#include <QApplication>
// clazy:excludeall=qstring-allocations
int main(int argc, char **argv)
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif
QApplication app(argc, argv);
app.setOrganizationName(QStringLiteral("KDAB"));
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
KDDockWidgets::MainWindowMDI mainWindow(QStringLiteral("MyMainWindow"));
mainWindow.setWindowTitle("Main Window");
mainWindow.resize(1200, 1200);
mainWindow.show();
// # 2. Create a dock widget, it needs a unique name
auto dock1 = new KDDockWidgets::DockWidget(QStringLiteral("MyDock1"));
auto widget1 = new MyWidget1();
dock1->setWidget(widget1);
auto dock2 = new KDDockWidgets::DockWidget(QStringLiteral("MyDock2"));
auto widget2 = new MyWidget2();
dock2->setWidget(widget2);
auto dock3 = new KDDockWidgets::DockWidget(QStringLiteral("MyDock3"));
auto widget3 = new MyWidget3();
dock3->setWidget(widget3);
// # 3. Dock them
mainWindow.addDockWidget(dock1, QPoint(10, 10));
mainWindow.addDockWidget(dock2, QPoint(50, 50));
mainWindow.addDockWidget(dock3, QPoint(90, 90));
return app.exec();
}

View File

@@ -10,6 +10,8 @@
add_subdirectory(customtitlebar) add_subdirectory(customtitlebar)
add_subdirectory(dockwidgets) add_subdirectory(dockwidgets)
add_subdirectory(mdi)
set_compiler_flags(kddockwidgets_example_quick) set_compiler_flags(kddockwidgets_example_quick)
set_compiler_flags(kddockwidgets_example_mdi_quick)
set_compiler_flags(kddockwidgets_customtitlebar_quick) set_compiler_flags(kddockwidgets_customtitlebar_quick)

View File

@@ -17,6 +17,7 @@
#include <QQuickView> #include <QQuickView>
#include <QGuiApplication> #include <QGuiApplication>
#include <QQmlApplicationEngine>
class CustomFrameworkWidgetFactory : public KDDockWidgets::DefaultWidgetFactory class CustomFrameworkWidgetFactory : public KDDockWidgets::DefaultWidgetFactory
{ {
@@ -45,15 +46,11 @@ int main(int argc, char *argv[])
config.setFlags(flags); config.setFlags(flags);
config.setFrameworkWidgetFactory(new CustomFrameworkWidgetFactory()); config.setFrameworkWidgetFactory(new CustomFrameworkWidgetFactory());
QQuickView view; QQmlApplicationEngine appEngine;
view.setObjectName("MainWindow QQuickView"); KDDockWidgets::Config::self().setQmlEngine(&appEngine);
KDDockWidgets::Config::self().setQmlEngine(view.engine()); appEngine.load((QUrl("qrc:/main.qml")));
view.resize(1000, 800);
view.show();
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));

View File

@@ -10,14 +10,18 @@
*/ */
import QtQuick 2.6 import QtQuick 2.6
import QtQuick.Controls 2.12
import com.kdab.dockwidgets 1.0 as KDDW import com.kdab.dockwidgets 1.0 as KDDW
KDDW.MainWindow { ApplicationWindow {
id: root visible: true
width: 1000
height: 800
KDDW.MainWindowLayout {
id: dockWidgetArea
anchors.fill: parent
Component.onCompleted: { uniqueName: "MyMainLayout"
root.init("MyWindowName-1");
} }
} }

View File

@@ -10,38 +10,10 @@
*/ */
import QtQuick 2.9 import QtQuick 2.9
import QtQuick.Controls 2.12
import com.kdab.dockwidgets 1.0 as KDDW import com.kdab.dockwidgets 1.0 as KDDW
Guest { Guest {
anchors.fill: parent anchors.fill: parent
background: "qrc:/assets/triangles.png" background: "qrc:/assets/triangles.png"
logo: "qrc:/assets/KDAB_bubble_white.png" logo: "qrc:/assets/KDAB_bubble_white.png"
KDDW.DockWidget {
id: another
uniqueName: "another1"
source: ":/Another.qml"
}
Button {
text: "Toggle Another"
anchors {
bottom: parent.bottom
left: parent.left
margins: 5
}
onClicked: {
if (another.dockWidget.visible) {
another.dockWidget.close();
} else {
another.dockWidget.show();
}
}
}
} }

View File

@@ -15,7 +15,7 @@
#include <kddockwidgets/private/DockRegistry_p.h> #include <kddockwidgets/private/DockRegistry_p.h>
#include <kddockwidgets/FrameworkWidgetFactory.h> #include <kddockwidgets/FrameworkWidgetFactory.h>
#include <QQuickView> #include <QQmlApplicationEngine>
#include <QGuiApplication> #include <QGuiApplication>
#include <QCommandLineParser> #include <QCommandLineParser>
@@ -23,6 +23,10 @@ int main(int argc, char *argv[])
{ {
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES); QGuiApplication::setAttribute(Qt::AA_UseOpenGLES);
#endif
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
#endif #endif
QGuiApplication app(argc, argv); QGuiApplication app(argc, argv);
QCommandLineParser parser; QCommandLineParser parser;
@@ -69,20 +73,22 @@ int main(int argc, char *argv[])
internalFlags |= KDDockWidgets::Config::InternalFlag_NoAeroSnap; internalFlags |= KDDockWidgets::Config::InternalFlag_NoAeroSnap;
# endif # endif
// These are debug-only/development flags, which you can ignore.
KDDockWidgets::Config::self().setInternalFlags(internalFlags); KDDockWidgets::Config::self().setInternalFlags(internalFlags);
#endif #endif
// Set any required flags. The defaults are usually fine.
KDDockWidgets::Config::self().setFlags(flags); KDDockWidgets::Config::self().setFlags(flags);
QQuickView view; // Create your engine which loads main.qml. A simple QQuickView would work too.
view.setObjectName("MainWindow QQuickView"); QQmlApplicationEngine appEngine;
KDDockWidgets::Config::self().setQmlEngine(view.engine()); KDDockWidgets::Config::self().setQmlEngine(&appEngine);
view.resize(1000, 800); appEngine.load((QUrl("qrc:/main.qml")));
view.show();
view.setResizeMode(QQuickView::SizeRootObjectToView); // Below we illustrate usage of our C++ API. Alternative you can use declarative API.
// See main.qml for examples of dockwidgets created directly in QML
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));

View File

@@ -10,14 +10,130 @@
*/ */
import QtQuick 2.6 import QtQuick 2.6
import QtQuick.Controls 2.12
import com.kdab.dockwidgets 1.0 as KDDW import com.kdab.dockwidgets 1.0 as KDDW
KDDW.MainWindow { ApplicationWindow {
id: root visible: true
width: 1000
height: 800
menuBar: MenuBar {
Menu {
title: qsTr("&File")
Component.onCompleted: { Action {
root.init("MyWindowName-1"); text: qsTr("Save layout")
onTriggered: {
layoutSaver.saveToFile("mySavedLayout.json");
}
}
Action {
text: qsTr("Restore layout")
onTriggered: {
layoutSaver.restoreFromFile("mySavedLayout.json");
}
}
Action {
text: qsTr("Toggle widget #4")
onTriggered: {
toggleDockWidget(dock4);
}
}
Action {
text: qsTr("Toggle widget #5")
onTriggered: {
toggleDockWidget(dock5);
}
}
Action {
text: qsTr("Toggle widget #6")
onTriggered: {
toggleDockWidget(dock6);
}
}
Action {
text: qsTr("Close All")
onTriggered: {
_kddwDockRegistry.clear();
}
}
MenuSeparator { }
Action { text: qsTr("&Quit")
onTriggered: {
Qt.quit();
}
}
}
}
KDDW.MainWindowLayout {
anchors.fill: parent
// Each main layout needs a unique id
uniqueName: "MainLayout-1"
Repeater {
model: 3
KDDW.DockWidget {
uniqueName: "fromRepeater-" + index
source: ":/Another.qml"
}
}
KDDW.DockWidget {
id: dock4
uniqueName: "dock4" // Each dock widget needs a unique id
source: ":/Another.qml"
}
KDDW.DockWidget {
id: dock5
uniqueName: "dock5"
Rectangle {
id: guest
color: "pink"
}
}
KDDW.DockWidget {
id: dock6
uniqueName: "dock6"
Rectangle {
color: "black"
}
}
Component.onCompleted: {
// Add dock4 to the Bottom location
addDockWidget(dock4, KDDW.KDDockWidgets.Location_OnBottom);
// Add dock5 to the left of dock4
addDockWidget(dock5, KDDW.KDDockWidgets.Location_OnRight, dock4);
// Adds dock6 but specifies a preferred initial size and it starts hidden
// When toggled it will be shown on the desired dock location.
// See MainWindowInstantiator_p.h for the API
addDockWidget(dock6, KDDW.KDDockWidgets.Location_OnLeft, null,
Qt.size(500, 100), KDDW.KDDockWidgets.StartHidden);
}
}
KDDW.LayoutSaver {
id: layoutSaver
}
function toggleDockWidget(dw) {
if (dw.dockWidget.isOpen()) {
dw.dockWidget.close();
} else {
dw.dockWidget.show();
}
} }
} }

View File

@@ -0,0 +1,18 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sergio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
import QtQuick 2.9
Rectangle {
id: root
color: "green"
anchors.fill: parent
}

View File

@@ -0,0 +1,37 @@
#
# This file is part of KDDockWidgets.
#
# SPDX-FileCopyrightText: 2019-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
# Author: Sergio Martins <sergio.martins@kdab.com>
#
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
#
# Contact KDAB at <info@kdab.com> for commercial licensing options.
#
cmake_minimum_required(VERSION 3.7)
project(kddockwidgets_example_mdi_quick)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
if(NOT TARGET kddockwidgets)
# This will look for Qt, do find_package yourself manually before
# if you want to look for a specific Qt version for instance.
find_package(KDDockWidgets REQUIRED)
endif()
set(RESOURCES_EXAMPLE_SRC
${CMAKE_CURRENT_SOURCE_DIR}/resources_qtquick_mdi_example.qrc
${CMAKE_CURRENT_SOURCE_DIR}/../../dockwidgets/resources_example.qrc)
add_executable(kddockwidgets_example_mdi_quick
main.cpp
${RESOURCES_EXAMPLE_SRC}
)
target_link_libraries(kddockwidgets_example_mdi_quick
PRIVATE
KDAB::kddockwidgets
)

View File

@@ -0,0 +1,37 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sergio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
import QtQuick 2.9
Rectangle {
color: "white"
anchors.fill: parent
property alias background: background.source
property alias logo: logo.source
Image {
id: background
anchors.fill: parent
fillMode: Image.PreserveAspectCrop
Image {
id: logo
fillMode: Image.PreserveAspectFit
anchors {
fill: parent
margins: 50
}
}
}
}

View File

@@ -0,0 +1,44 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sergio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
import QtQuick 2.9
import QtQuick.Controls 2.12
import com.kdab.dockwidgets 1.0 as KDDW
Guest {
anchors.fill: parent
background: "qrc:/assets/triangles.png"
logo: "qrc:/assets/KDAB_bubble_white.png"
KDDW.DockWidget {
id: another
uniqueName: "another1"
source: ":/Another.qml"
}
Button {
text: "Toggle Another"
anchors {
bottom: parent.bottom
left: parent.left
margins: 5
}
onClicked: {
if (another.dockWidget.visible) {
another.dockWidget.close();
} else {
another.dockWidget.show();
}
}
}
}

View File

@@ -0,0 +1,17 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sergio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
import QtQuick 2.9
Guest {
anchors.fill: parent
logo: "qrc:/assets/KDAB_bubble_blue.png"
}

View File

@@ -0,0 +1,18 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sergio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
import QtQuick 2.9
Guest {
anchors.fill: parent
background: "qrc:/assets/base.png"
logo: "qrc:/assets/KDAB_bubble_fulcolor.png"
}

View File

@@ -0,0 +1,59 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sergio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
#include <kddockwidgets/Config.h>
#include <kddockwidgets/DockWidgetQuick.h>
#include <kddockwidgets/private/DockRegistry_p.h>
#include <kddockwidgets/FrameworkWidgetFactory.h>
#include <kddockwidgets/MainWindowMDI.h>
#include <QQmlApplicationEngine>
#include <QGuiApplication>
#include <QCommandLineParser>
// Foro my own debugging, until we have better API
#include "../../src/private/MDILayoutWidget_p.h"
int main(int argc, char *argv[])
{
#ifdef Q_OS_WIN
QGuiApplication::setAttribute(Qt::AA_UseOpenGLES);
#endif
QGuiApplication app(argc, argv);
QCommandLineParser parser;
parser.setApplicationDescription("KDDockWidgets example application");
parser.addHelpOption();
QQmlApplicationEngine appEngine;
KDDockWidgets::Config::self().setQmlEngine(&appEngine);
appEngine.load((QUrl("qrc:/main.qml")));
auto dw1 = new KDDockWidgets::DockWidgetQuick("Dock #1");
dw1->setWidget(QStringLiteral("qrc:/Guest1.qml"));
dw1->resize(QSize(400, 400));
auto dw2 = new KDDockWidgets::DockWidgetQuick("Dock #2");
dw2->setWidget(QStringLiteral("qrc:/Guest2.qml"));
dw2->resize(QSize(400, 400));
auto dw3 = new KDDockWidgets::DockWidgetQuick("Dock #3");
dw3->setWidget(QStringLiteral("qrc:/Guest3.qml"));
auto mainWindow = static_cast<KDDockWidgets::MainWindowMDI*>(KDDockWidgets::DockRegistry::self()->mainwindows().constFirst());
mainWindow->addDockWidget(dw1, QPoint(10, 10));
mainWindow->addDockWidget(dw2, QPoint(50, 50));
mainWindow->addDockWidget(dw3, QPoint(90, 90));
return app.exec();
}

View File

@@ -0,0 +1,26 @@
/*
This file is part of KDDockWidgets.
SPDX-FileCopyrightText: 2020-2021 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
Author: Sergio Martins <sergio.martins@kdab.com>
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
Contact KDAB at <info@kdab.com> for commercial licensing options.
*/
import QtQuick 2.6
import QtQuick.Controls 2.12
import com.kdab.dockwidgets 1.0 as KDDW
ApplicationWindow {
visible: true
width: 1000
height: 1200
KDDW.MainWindowLayout {
anchors.fill: parent
uniqueName: "MyMainLayout"
options: KDDW.KDDockWidgets.MainWindowOption_MDI
}
}

View File

@@ -0,0 +1,10 @@
<RCC>
<qresource prefix="/">
<file>main.qml</file>
<file>Guest1.qml</file>
<file>Guest2.qml</file>
<file>Guest3.qml</file>
<file>Guest.qml</file>
<file>Another.qml</file>
</qresource>
</RCC>

View File

@@ -1,10 +0,0 @@
Format: 1.0
Source: kddockwidgets
Version: 1.2.0-1
Binary: kddockwidgets
Maintainer: Allen Winter <allen.winter@kdab.com>
Architecture: any
Build-Depends: debhelper (>=9), cdbs, cmake, qt5-default, qtbase5-dev, libqt5x11extras5-dev
Files:
00000000000000000000000000000000 00000 kddockwidgets-1.2.0.tar.gz

View File

@@ -12,16 +12,16 @@
set(PYTHON_VERSION "3.7" CACHE STRING "Use specific python version to build the project.") set(PYTHON_VERSION "3.7" CACHE STRING "Use specific python version to build the project.")
find_package(Python3 ${PYTHON_VERSION} REQUIRED COMPONENTS Interpreter Development) find_package(Python3 ${PYTHON_VERSION} REQUIRED COMPONENTS Interpreter Development)
if (${PROJECT_NAME}_QT6) if(${PROJECT_NAME}_QT6)
find_package(Shiboken6 REQUIRED) find_package(Shiboken6 REQUIRED)
find_package(PySide6 ${Qt5Widgets_VERSION} EXACT REQUIRED) find_package(PySide6 ${Qt6Widgets_VERSION} EXACT REQUIRED)
include(PySide6ModuleBuild) include(PySide6ModuleBuild)
set(PYSIDE_MAJOR_VERSION "6") set(PYSIDE_MAJOR_VERSION "6")
else() else()
find_package(Shiboken2 REQUIRED) find_package(Shiboken2 REQUIRED)
find_package(PySide2 ${Qt5Widgets_VERSION} EXACT REQUIRED) find_package(PySide2 ${Qt5Widgets_VERSION} EXACT REQUIRED)
include(PySide2ModuleBuild) include(PySide2ModuleBuild)
set(PYSIDE_MAJOR_VERSION "2") set(PYSIDE_MAJOR_VERSION "2")
endif() endif()
add_subdirectory(PyKDDockWidgets) add_subdirectory(PyKDDockWidgets)

View File

@@ -16,10 +16,14 @@ set(PyKDDockWidgets_SRC
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_dockwidgetbase_wrapper.h ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_dockwidgetbase_wrapper.h
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_dockwidget_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_dockwidget_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_dockwidget_wrapper.h ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_dockwidget_wrapper.h
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_initialoption_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_initialoption_wrapper.h
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindowbase_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindowbase_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindowbase_wrapper.h ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindowbase_wrapper.h
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindow_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindow_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindow_wrapper.h ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindow_wrapper.h
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_layoutsaver_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_layoutsaver_wrapper.h
# global module wrapper # global module wrapper
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_module_wrapper.cpp ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_module_wrapper.cpp
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_python.h ${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_python.h
@@ -56,6 +60,7 @@ set(PyKDDockWidgets_DEPENDS
${CMAKE_SOURCE_DIR}/src/DockWidget.h ${CMAKE_SOURCE_DIR}/src/DockWidget.h
${CMAKE_SOURCE_DIR}/src/MainWindowBase.h ${CMAKE_SOURCE_DIR}/src/MainWindowBase.h
${CMAKE_SOURCE_DIR}/src/MainWindow.h ${CMAKE_SOURCE_DIR}/src/MainWindow.h
${CMAKE_SOURCE_DIR}/src/LayoutSaver.h
) )
create_python_bindings( create_python_bindings(
@@ -75,4 +80,4 @@ create_python_bindings(
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.cmake ${CMAKE_CURRENT_BINARY_DIR}/__init__.py @ONLY) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py.cmake ${CMAKE_CURRENT_BINARY_DIR}/__init__.py @ONLY)
# install # install
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py DESTINATION ${${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/PyKDDockWidgets) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/__init__.py DESTINATION ${${PROJECT_NAME}_PYTHON_BINDINGS_INSTALL_PREFIX}/PyKDDockWidgets)

View File

@@ -25,3 +25,4 @@
#include <kddockwidgets/MainWindow.h> #include <kddockwidgets/MainWindow.h>
#include <kddockwidgets/DockWidgetBase.h> #include <kddockwidgets/DockWidgetBase.h>
#include <kddockwidgets/DockWidget.h> #include <kddockwidgets/DockWidget.h>
#include <kddockwidgets/LayoutSaver.h>

View File

@@ -16,7 +16,6 @@
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"/> <primitive-type name="SideBar"/>
<primitive-type name="InitialOption"/>
<!-- Some plublic enum and flags --> <!-- Some plublic enum and flags -->
<enum-type name="Location"/> <enum-type name="Location"/>
@@ -28,6 +27,9 @@
<enum-type name="DropIndicatorType"/> <enum-type name="DropIndicatorType"/>
<enum-type name="SideBarLocation"/> <enum-type name="SideBarLocation"/>
<enum-type name="TitleBarButtonType"/> <enum-type name="TitleBarButtonType"/>
<enum-type name="SuggestedGeometryHint" flags="SuggestedGeometryHints" />
<enum-type name="CursorPosition" flags="CursorPositions" />
<enum-type name="AddingOption" />
<!-- our classes <!-- our classes
For class we can use two types: For class we can use two types:
@@ -35,6 +37,7 @@
value-type: class that can be passed as value for functions value-type: class that can be passed as value for functions
Here we only use 'object-type' since all our classes are derived from QWidget Here we only use 'object-type' since all our classes are derived from QWidget
--> -->
<value-type name="InitialOption"/>
<object-type name="MainWindowBase" /> <object-type name="MainWindowBase" />
<object-type name="MainWindow" /> <object-type name="MainWindow" />
<object-type name="DockWidgetBase" > <object-type name="DockWidgetBase" >
@@ -42,8 +45,10 @@
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" /> <enum-type name="IconPlace" flags="IconPlaces" />
<enum-type name="LayoutSaverOption" flags="LayoutSaverOptions" />
</object-type> </object-type>
<object-type name="DockWidget" /> <object-type name="DockWidget" />
<object-type name="LayoutSaver" />
</namespace-type> </namespace-type>
</typesystem> </typesystem>

View File

@@ -106,7 +106,8 @@ class MyMainWindow(KDDockWidgets.MainWindow):
self.m_dockwidgets.append(self.newDockWidget()) self.m_dockwidgets.append(self.newDockWidget())
# MainWindow::addDockWidget() attaches a dock widget to the main window: # MainWindow::addDockWidget() attaches a dock widget to the main window:
self.addDockWidget(self.m_dockwidgets[0], KDDockWidgets.Location_OnTop) initialOpts = KDDockWidgets.InitialOption(KDDockWidgets.InitialVisibilityOption.StartHidden, QtCore.QSize(500, 500))
self.addDockWidget(self.m_dockwidgets[0], KDDockWidgets.Location_OnBottom, None, initialOpts)
# Here, for finer granularity we specify right of dockwidgets[0]: # Here, for finer granularity we specify right of dockwidgets[0]:
self.addDockWidget(self.m_dockwidgets[1], KDDockWidgets.Location_OnRight, self.m_dockwidgets[0]) self.addDockWidget(self.m_dockwidgets[1], KDDockWidgets.Location_OnRight, self.m_dockwidgets[0])

View File

@@ -33,9 +33,15 @@ set(DOCKSLIBS_SRCS
DockWidgetBase.h DockWidgetBase.h
MainWindowBase.cpp MainWindowBase.cpp
MainWindowBase.h MainWindowBase.h
MainWindowMDI.cpp
MainWindowMDI.h
LayoutSaver.cpp LayoutSaver.cpp
LayoutSaver.h LayoutSaver.h
LayoutSaver_p.h private/LayoutSaver_p.h
private/LayoutWidget.cpp
private/LayoutWidget_p.h
private/MDILayoutWidget.cpp
private/MDILayoutWidget_p.h
private/MultiSplitter.cpp private/MultiSplitter.cpp
private/MultiSplitter_p.h private/MultiSplitter_p.h
private/Position.cpp private/Position.cpp
@@ -77,6 +83,8 @@ set(DOCKSLIBS_SRCS
private/multisplitter/Item.cpp private/multisplitter/Item.cpp
private/multisplitter/Item_p.h private/multisplitter/Item_p.h
private/multisplitter/ItemFreeContainer.cpp
private/multisplitter/ItemFreeContainer_p.h
private/multisplitter/Logging.cpp private/multisplitter/Logging.cpp
private/multisplitter/Logging_p.h private/multisplitter/Logging_p.h
private/multisplitter/MultiSplitterConfig.cpp private/multisplitter/MultiSplitterConfig.cpp
@@ -97,18 +105,24 @@ set(DOCKS_INSTALLABLE_INCLUDES
FocusScope.h FocusScope.h
QWidgetAdapter.h QWidgetAdapter.h
LayoutSaver.h LayoutSaver.h
LayoutSaver_p.h MainWindowMDI.h
MainWindowBase.h
) )
set(DOCKS_INSTALLABLE_PRIVATE_INCLUDES set(DOCKS_INSTALLABLE_PRIVATE_INCLUDES
private/DragController_p.h private/DragController_p.h
private/Draggable_p.h private/Draggable_p.h
private/DropArea_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/LayoutSaver_p.h
private/MultiSplitter_p.h
private/LayoutWidget_p.h
private/SideBar_p.h private/SideBar_p.h
private/TitleBar_p.h private/TitleBar_p.h
private/WindowBeingDragged_p.h private/WindowBeingDragged_p.h
private/WidgetResizeHandler_p.h
private/DockRegistry_p.h private/DockRegistry_p.h
private/TabWidget_p.h private/TabWidget_p.h
) )
@@ -141,14 +155,18 @@ if(${PROJECT_NAME}_QTQUICK)
private/quick/TitleBarQuick_p.h private/quick/TitleBarQuick_p.h
private/quick/QmlTypes.cpp private/quick/QmlTypes.cpp
private/quick/QmlTypes.h private/quick/QmlTypes.h
private/quick/Helpers.cpp
private/quick/Helpers_p.h
private/quick/FrameQuick.cpp private/quick/FrameQuick.cpp
private/quick/FrameQuick_p.h private/quick/FrameQuick_p.h
private/quick/LayoutSaverInstantiator.cpp
private/quick/LayoutSaverInstantiator_p.h
private/quick/RubberBandQuick.cpp private/quick/RubberBandQuick.cpp
private/quick/RubberBandQuick.h private/quick/RubberBandQuick.h
private/quick/MainWindowQuick.cpp private/quick/MainWindowQuick.cpp
private/quick/MainWindowQuick_p.h private/quick/MainWindowQuick_p.h
private/quick/MainWindowWrapper.cpp private/quick/MainWindowInstantiator.cpp
private/quick/MainWindowWrapper_p.h private/quick/MainWindowInstantiator_p.h
private/multisplitter/Widget_quick.cpp private/multisplitter/Widget_quick.cpp
private/multisplitter/Widget_quick.h private/multisplitter/Widget_quick.h
private/multisplitter/Separator_quick.cpp private/multisplitter/Separator_quick.cpp
@@ -156,6 +174,9 @@ if(${PROJECT_NAME}_QTQUICK)
private/multisplitter/Rubberband_quick.cpp private/multisplitter/Rubberband_quick.cpp
private/multisplitter/Rubberband_quick.h private/multisplitter/Rubberband_quick.h
kddockwidgets_qtquick.qrc) kddockwidgets_qtquick.qrc)
set(DOCKS_INSTALLABLE_INCLUDES ${DOCKS_INSTALLABLE_INCLUDES} DockWidgetQuick.h)
else() else()
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS} set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
private/DebugWindow.cpp private/DebugWindow.cpp
@@ -187,26 +208,37 @@ else()
private/indicators/SegmentedIndicators.cpp private/indicators/SegmentedIndicators.cpp
private/indicators/SegmentedIndicators_p.h private/indicators/SegmentedIndicators_p.h
# private/indicators/AnimatedIndicators.cpp # private/indicators/AnimatedIndicators.cpp
) )
set(DOCKS_INSTALLABLE_INCLUDES set(DOCKS_INSTALLABLE_INCLUDES
${DOCKS_INSTALLABLE_INCLUDES} ${DOCKS_INSTALLABLE_INCLUDES}
MainWindow.h MainWindow.h
MainWindowBase.h
DockWidget.h DockWidget.h
) )
endif() endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") #Generate C/C++ CamelCase forwarding headers (only public includes)
set(IS_CLANG_BUILD TRUE) include(ECMGenerateHeaders)
else() ecm_generate_headers(camelcase_HEADERS
set(IS_CLANG_BUILD FALSE) ORIGINAL
endif() CAMELCASE
HEADER_NAMES
Config
DockWidget
DockWidgetBase
FocusScope
FrameworkWidgetFactory,DefaultWidgetFactory
LayoutSaver
MainWindow
MainWindowBase
MainWindowMDI
)
set(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/kddockwidgets_resources.qrc) set(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/kddockwidgets_resources.qrc)
add_library(kddockwidgets ${KDDockWidgets_LIBRARY_MODE} ${DOCKSLIBS_SRCS} ${DOCKS_INSTALLABLE_INCLUDES} ${RESOURCES} ${RESOURCES_QUICK}) add_library(kddockwidgets ${KDDockWidgets_LIBRARY_MODE} ${DOCKSLIBS_SRCS} ${DOCKS_INSTALLABLE_INCLUDES} ${RESOURCES})
add_library(KDAB::kddockwidgets ALIAS kddockwidgets) add_library(KDAB::kddockwidgets ALIAS kddockwidgets)
set_target_properties(kddockwidgets PROPERTIES OUTPUT_NAME "kddockwidgets${KDDockWidgets_LIBRARY_QTID}")
set_compiler_flags(kddockwidgets) set_compiler_flags(kddockwidgets)
target_include_directories(kddockwidgets target_include_directories(kddockwidgets
@@ -215,8 +247,6 @@ target_include_directories(kddockwidgets
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fwd_headers> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/fwd_headers>
PRIVATE PRIVATE
${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/private
${CMAKE_CURRENT_SOURCE_DIR}/private/multisplitter/
) )
target_compile_definitions(kddockwidgets target_compile_definitions(kddockwidgets
@@ -232,11 +262,18 @@ else()
target_compile_definitions(kddockwidgets PRIVATE BUILDING_DOCKS_LIBRARY) target_compile_definitions(kddockwidgets PRIVATE BUILDING_DOCKS_LIBRARY)
endif() endif()
if(KDDockWidgets_QTQUICK)
target_compile_definitions(kddockwidgets PUBLIC KDDOCKWIDGETS_QTQUICK)
endif()
if(CMAKE_COMPILER_IS_GNUCXX OR IS_CLANG_BUILD) if(CMAKE_COMPILER_IS_GNUCXX OR IS_CLANG_BUILD)
target_compile_options(kddockwidgets PRIVATE -Wshadow -fvisibility=hidden) target_compile_options(kddockwidgets PRIVATE -Wshadow)
if(NOT MSVC)
target_compile_options(kddockwidgets PRIVATE -fvisibility=hidden)
endif()
# Disable -Wconversion for Qt6. The qsizetype to int conversions are harmless # Disable -Wconversion for Qt6. The qsizetype to int conversions are harmless
if (NOT ${PROJECT_NAME}_QT6) if(NOT ${PROJECT_NAME}_QT6)
target_compile_options(kddockwidgets PRIVATE -Wconversion) target_compile_options(kddockwidgets PRIVATE -Wconversion)
endif() endif()
@@ -251,11 +288,11 @@ else()
target_link_libraries(kddockwidgets PUBLIC Qt${QT_MAJOR_VERSION}::Widgets) target_link_libraries(kddockwidgets PUBLIC Qt${QT_MAJOR_VERSION}::Widgets)
endif() endif()
if (WIN32) if(WIN32)
target_link_libraries(kddockwidgets PRIVATE Qt${QT_MAJOR_VERSION}::GuiPrivate dwmapi) target_link_libraries(kddockwidgets PRIVATE Qt${QT_MAJOR_VERSION}::GuiPrivate dwmapi)
elseif(NOT APPLE AND NOT EMSCRIPTEN AND NOT ${PROJECT_NAME}_QT6) elseif(NOT APPLE AND NOT EMSCRIPTEN AND NOT ${PROJECT_NAME}_QT6)
find_package(Qt${QT_MAJOR_VERSION}X11Extras) find_package(Qt${QT_MAJOR_VERSION}X11Extras)
target_link_libraries(kddockwidgets PUBLIC Qt${QT_MAJOR_VERSION}::X11Extras) target_link_libraries(kddockwidgets PUBLIC Qt${QT_MAJOR_VERSION}::X11Extras)
endif() endif()
set_target_properties(kddockwidgets PROPERTIES set_target_properties(kddockwidgets PROPERTIES
@@ -265,13 +302,19 @@ set_target_properties(kddockwidgets PROPERTIES
#version libraries on Windows #version libraries on Windows
if(WIN32) if(WIN32)
set(postfix ${${PROJECT_NAME}_VERSION_MAJOR}) if(CMAKE_BUILD_TYPE)
set(CMAKE_RELEASE_POSTFIX ${postfix}) set(postfix ${${PROJECT_NAME}_VERSION_MAJOR})
set_target_properties(kddockwidgets PROPERTIES RELEASE_POSTFIX ${CMAKE_RELEASE_POSTFIX}) string(TOUPPER ${CMAKE_BUILD_TYPE} UPPER_BUILD_TYPE)
#append 'd' to debug libraries if(${UPPER_BUILD_TYPE} MATCHES "^DEBUG")
string(CONCAT postfix ${postfix} "d") string(CONCAT postfix ${postfix} "d")
set(CMAKE_DEBUG_POSTFIX ${postfix}) set_target_properties(kddockwidgets PROPERTIES DEBUG_POSTFIX ${postfix})
set_target_properties(kddockwidgets PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX}) else()
set_target_properties(kddockwidgets PROPERTIES ${UPPER_BUILD_TYPE}_POSTFIX ${postfix})
endif()
elseif(CMAKE_CONFIGURATION_TYPES)
# Visual Studio generator
set_target_properties(kddockwidgets PROPERTIES DEBUG_POSTFIX d)
endif()
endif() endif()
install(TARGETS kddockwidgets install(TARGETS kddockwidgets
@@ -283,24 +326,36 @@ install(TARGETS kddockwidgets
if(MSVC AND NOT ${PROJECT_NAME}_STATIC) if(MSVC AND NOT ${PROJECT_NAME}_STATIC)
install(FILES "$<TARGET_PDB_FILE_DIR:kddockwidgets>/$<TARGET_PDB_FILE_NAME:kddockwidgets>" DESTINATION ${INSTALL_LIBRARY_DIR} CONFIGURATIONS Debug RelWithDebInfo) install(FILES "$<TARGET_PDB_FILE_DIR:kddockwidgets>/$<TARGET_PDB_FILE_NAME:kddockwidgets>" DESTINATION ${INSTALL_LIBRARY_DIR} CONFIGURATIONS Debug RelWithDebInfo)
endif() endif()
install(FILES ${camelcase_HEADERS} DESTINATION include/kddockwidgets)
install(FILES ${DOCKS_INSTALLABLE_INCLUDES} DESTINATION include/kddockwidgets) install(FILES ${DOCKS_INSTALLABLE_INCLUDES} DESTINATION include/kddockwidgets)
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_INCLUDES} DESTINATION include/kddockwidgets/private) install(FILES ${DOCKS_INSTALLABLE_PRIVATE_INCLUDES} DESTINATION include/kddockwidgets/private)
install(FILES private/multisplitter/Item_p.h DESTINATION include/kddockwidgets/private/multisplitter) install(FILES private/multisplitter/Item_p.h DESTINATION include/kddockwidgets/private/multisplitter)
install(FILES private/multisplitter/Widget.h DESTINATION include/kddockwidgets/private/multisplitter) install(FILES private/multisplitter/Widget.h DESTINATION include/kddockwidgets/private/multisplitter)
install(FILES private/multisplitter/Widget_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
install(FILES private/multisplitter/Separator_p.h DESTINATION include/kddockwidgets/private/multisplitter) install(FILES private/multisplitter/Separator_p.h DESTINATION include/kddockwidgets/private/multisplitter)
install(FILES private/multisplitter/Separator_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
install(FILES private/indicators/ClassicIndicators_p.h DESTINATION include/kddockwidgets/private/indicators) install(FILES private/indicators/ClassicIndicators_p.h DESTINATION include/kddockwidgets/private/indicators)
install(FILES private/indicators/SegmentedIndicators_p.h DESTINATION include/kddockwidgets/private/indicators) install(FILES private/indicators/SegmentedIndicators_p.h DESTINATION include/kddockwidgets/private/indicators)
include(CMakePackageConfigHelpers) if(KDDockWidgets_QTQUICK)
write_basic_package_version_file( install(FILES private/multisplitter/Separator_quick.h DESTINATION include/kddockwidgets/private/multisplitter)
KDDockWidgetsConfigVersion.cmake install(FILES private/multisplitter/Widget_quick.h DESTINATION include/kddockwidgets/private/multisplitter)
VERSION ${${PROJECT_NAME}_VERSION} else()
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
install(FILES private/multisplitter/Separator_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
install(FILES private/multisplitter/Widget_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
endif()
# Generate library version files
include(ECMSetupVersion)
ecm_setup_version(
${${PROJECT_NAME}_VERSION}
VARIABLE_PREFIX KDDOCKWIDGETS
VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kddockwidgets_version.h"
PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgetsConfigVersion.cmake"
SOVERSION ${${PROJECT_NAME}_SOVERSION}
COMPATIBILITY AnyNewerVersion COMPATIBILITY AnyNewerVersion
) )
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/kddockwidgets_version.h" DESTINATION include/kddockwidgets)
install(EXPORT kddockwidgetsTargets install(EXPORT kddockwidgetsTargets
FILE KDDockWidgetsTargets.cmake FILE KDDockWidgetsTargets.cmake
@@ -319,7 +374,7 @@ if(${PROJECT_NAME}_DEVELOPER_MODE)
option(KDDockWidgets_LINTER "Build the layout linter" ON) option(KDDockWidgets_LINTER "Build the layout linter" ON)
if (NOT ${PROJECT_NAME}_QTQUICK AND KDDockWidgets_LINTER) # TODO: We can support it if(NOT ${PROJECT_NAME}_QTQUICK AND KDDockWidgets_LINTER) # 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 Qt${QT_MAJOR_VERSION}::Widgets) target_link_libraries(kddockwidgets_linter kddockwidgets Qt${QT_MAJOR_VERSION}::Widgets)
endif() endif()

View File

@@ -17,22 +17,23 @@
*/ */
#include "Config.h" #include "Config.h"
#include "multisplitter/MultiSplitterConfig.h" #include "private/multisplitter/MultiSplitterConfig.h"
#include "multisplitter/Widget.h" #include "private/multisplitter/Widget.h"
#include "DockRegistry_p.h" #include "private/DockRegistry_p.h"
#include "private/Utils_p.h"
#include "private/DragController_p.h"
#include "FrameworkWidgetFactory.h" #include "FrameworkWidgetFactory.h"
#include "Utils_p.h"
#include <QDebug> #include <QDebug>
#include <QOperatingSystemVersion> #include <QOperatingSystemVersion>
#ifdef KDDOCKWIDGETS_QTQUICK #ifdef KDDOCKWIDGETS_QTQUICK
# include <QQmlEngine> #include "private/quick/Helpers_p.h"
# include <QQmlContext> #include <QQmlEngine>
#include <QQmlContext>
#endif #endif
namespace KDDockWidgets namespace KDDockWidgets {
{
class Config::Private class Config::Private
{ {
@@ -56,7 +57,13 @@ public:
FrameworkWidgetFactory *m_frameworkWidgetFactory = nullptr; FrameworkWidgetFactory *m_frameworkWidgetFactory = nullptr;
Flags m_flags = Flag_Default; Flags m_flags = Flag_Default;
InternalFlags m_internalFlags = InternalFlag_None; InternalFlags m_internalFlags = InternalFlag_None;
CustomizableWidgets m_disabledPaintEvents = CustomizableWidget_None;
qreal m_draggedWindowOpacity = Q_QNAN; qreal m_draggedWindowOpacity = Q_QNAN;
int m_mdiPopupThreshold = 250;
bool m_dropIndicatorsInhibited = false;
#ifdef KDDOCKWIDGETS_QTQUICK
QtQuickHelpers m_qquickHelpers;
#endif
}; };
Config::Config() Config::Config()
@@ -72,7 +79,7 @@ Config::Config()
Layouting::Config::self().setSeparatorFactoryFunc(separatorCreator); Layouting::Config::self().setSeparatorFactoryFunc(separatorCreator);
} }
Config& Config::self() Config &Config::self()
{ {
static Config config; static Config config;
return config; return config;
@@ -91,7 +98,7 @@ Config::Flags Config::flags() const
void Config::setFlags(Flags f) void Config::setFlags(Flags f)
{ {
auto dr = DockRegistry::self(); auto dr = DockRegistry::self();
if (!dr->isEmpty(/*excludeBeingDeleted=*/ true)) { if (!dr->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"
<< "; These are already created: " << dr->mainWindowsNames() << "; These are already created: " << dr->mainWindowsNames()
<< dr->dockWidgetNames() << dr->floatingWindows(); << dr->dockWidgetNames() << dr->floatingWindows();
@@ -145,7 +152,7 @@ int Config::separatorThickness() const
void Config::setSeparatorThickness(int value) void Config::setSeparatorThickness(int value)
{ {
if (!DockRegistry::self()->isEmpty(/*excludeBeingDeleted=*/ true)) { 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;
} }
@@ -175,7 +182,7 @@ TabbingAllowedFunc Config::tabbingAllowedFunc() const
void Config::setAbsoluteWidgetMinSize(QSize size) void Config::setAbsoluteWidgetMinSize(QSize size)
{ {
if (!DockRegistry::self()->isEmpty(/*excludeBeingDeleted=*/ false)) { if (!DockRegistry::self()->isEmpty(/*excludeBeingDeleted=*/false)) {
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;
} }
@@ -190,7 +197,7 @@ QSize Config::absoluteWidgetMinSize() const
void Config::setAbsoluteWidgetMaxSize(QSize size) void Config::setAbsoluteWidgetMaxSize(QSize size)
{ {
if (!DockRegistry::self()->isEmpty(/*excludeBeingDeleted=*/ false)) { if (!DockRegistry::self()->isEmpty(/*excludeBeingDeleted=*/false)) {
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;
} }
@@ -226,14 +233,21 @@ void Config::setQmlEngine(QQmlEngine *qmlEngine)
return; return;
} }
d->m_qmlEngine = qmlEngine; auto dr = DockRegistry::self(); // make sure our QML types are registered
QQmlContext *context = qmlEngine->rootContext(); QQmlContext *context = qmlEngine->rootContext();
context->setContextProperty(QStringLiteral("_kddwHelpers"), &d->m_qquickHelpers);
context->setContextProperty(QStringLiteral("_kddwDockRegistry"), dr);
context->setContextProperty(QStringLiteral("_kddwDragController"), DragController::instance());
context->setContextProperty(QStringLiteral("_kddw_widgetFactory"), d->m_frameworkWidgetFactory); context->setContextProperty(QStringLiteral("_kddw_widgetFactory"), d->m_frameworkWidgetFactory);
d->m_qmlEngine = qmlEngine;
} }
QQmlEngine *Config::qmlEngine() const QQmlEngine *Config::qmlEngine() const
{ {
if (!d->m_qmlEngine)
qWarning() << "Please call KDDockWidgets::Config::self()->setQmlEngine(engine)";
return d->m_qmlEngine; return d->m_qmlEngine;
} }
#endif #endif
@@ -290,6 +304,44 @@ void Config::Private::fixFlags()
m_internalFlags |= InternalFlag_DontUseParentForFloatingWindows; m_internalFlags |= InternalFlag_DontUseParentForFloatingWindows;
m_internalFlags |= InternalFlag_DontUseQtToolWindowsForFloatingWindows; m_internalFlags |= InternalFlag_DontUseQtToolWindowsForFloatingWindows;
} }
if (m_flags & Flag_ShowButtonsOnTabBarIfTitleBarHidden) {
// Flag_ShowButtonsOnTabBarIfTitleBarHidden doesn't make sense if used alone
m_flags |= Flag_HideTitleBarWhenTabsVisible;
}
}
void Config::setDisabledPaintEvents(CustomizableWidgets widgets)
{
d->m_disabledPaintEvents = widgets;
}
Config::CustomizableWidgets Config::disabledPaintEvents() const
{
return d->m_disabledPaintEvents;
}
void Config::setMDIPopupThreshold(int threshold)
{
d->m_mdiPopupThreshold = threshold;
}
int Config::mdiPopupThreshold() const
{
return d->m_mdiPopupThreshold;
}
void Config::setDropIndicatorsInhibited(bool inhibit) const
{
if (d->m_dropIndicatorsInhibited != inhibit) {
d->m_dropIndicatorsInhibited = inhibit;
Q_EMIT DockRegistry::self()->dropIndicatorsInhibitedChanged(inhibit);
}
}
bool Config::dropIndicatorsInhibited() const
{
return d->m_dropIndicatorsInhibited;
} }
} }

View File

@@ -21,28 +21,29 @@
#include "docks_export.h" #include "docks_export.h"
#include <qglobal.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QQmlEngine; class QQmlEngine;
class QSize; class QSize;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace KDDockWidgets namespace KDDockWidgets {
{
class DockWidgetBase; class DockWidgetBase;
class MainWindowBase; class MainWindowBase;
class FrameworkWidgetFactory; class FrameworkWidgetFactory;
typedef KDDockWidgets::DockWidgetBase* (*DockWidgetFactoryFunc)(const QString &name); typedef KDDockWidgets::DockWidgetBase *(*DockWidgetFactoryFunc)(const QString &name);
typedef KDDockWidgets::MainWindowBase* (*MainWindowFactoryFunc)(const QString &name); typedef KDDockWidgets::MainWindowBase *(*MainWindowFactoryFunc)(const QString &name);
/// @brief Function to allow the user more granularity to disallow dock widgets to tab together /// @brief Function to allow the user more granularity to disallow dock widgets to tab together
/// @param source The dock widgets being dragged /// @param source The dock widgets being dragged
/// @param target The dock widgets within an existing docked tab group /// @param target The dock widgets within an existing docked tab group
/// @return true if the docking is allowed. /// @return true if the docking is allowed.
/// @sa setTabbingAllowedFunc /// @sa setTabbingAllowedFunc
typedef bool (*TabbingAllowedFunc)(const QVector<DockWidgetBase*> &source, typedef bool (*TabbingAllowedFunc)(const QVector<DockWidgetBase *> &source,
const QVector<DockWidgetBase*> &target); const QVector<DockWidgetBase *> &target);
/** /**
* @brief Singleton to allow to choose certain behaviours of the framework. * @brief Singleton to allow to choose certain behaviours of the framework.
@@ -53,7 +54,6 @@ typedef bool (*TabbingAllowedFunc)(const QVector<DockWidgetBase*> &source,
class DOCKS_EXPORT Config class DOCKS_EXPORT Config
{ {
public: public:
///@brief returns the singleton Config instance ///@brief returns the singleton Config instance
static Config &self(); static Config &self();
@@ -61,9 +61,10 @@ public:
~Config(); ~Config();
///@brief Flag enum to tune certain behaviours, the defaults are Flag_Default ///@brief Flag enum to tune certain behaviours, the defaults are Flag_Default
enum Flag { enum Flag
{
Flag_None = 0, ///< No option set Flag_None = 0, ///< No option set
Flag_NativeTitleBar = 1, ///< Enables the Native OS title bar on OSes that support it (Windows 10, macOS), ignored otherwise. This is mutually exclusive with Flag_AeroSnap Flag_NativeTitleBar = 1, ///< Enables the Native OS title bar on OSes that support it (Windows 10, macOS), ignored otherwise.
Flag_AeroSnapWithClientDecos = 2, ///< Deprecated. This is now default and cannot be turned off. Moving a window on Windows 10 uses native moving, as that works well across screens with different HDPI settings. There's no reason to use manual client/Qt window moving. Flag_AeroSnapWithClientDecos = 2, ///< Deprecated. This is now default and cannot be turned off. Moving a window on Windows 10 uses native moving, as that works well across screens with different HDPI settings. There's no reason to use manual client/Qt window moving.
Flag_AlwaysTitleBarWhenFloating = 4, ///< Floating windows will have a title bar even if Flag_HideTitleBarWhenTabsVisible is specified. Unneeded if Flag_HideTitleBarWhenTabsVisible isn't specified, as that's the default already. Flag_AlwaysTitleBarWhenFloating = 4, ///< Floating windows will have a title bar even if Flag_HideTitleBarWhenTabsVisible is specified. Unneeded if Flag_HideTitleBarWhenTabsVisible isn't specified, as that's the default already.
Flag_HideTitleBarWhenTabsVisible = 8, ///< Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable. Flag_HideTitleBarWhenTabsVisible = 8, ///< Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
@@ -75,24 +76,44 @@ public:
Flag_TitleBarIsFocusable = 512, ///< You can click the title bar and it will focus the last focused widget in the focus scope. If no previously focused widget then it focuses the user's dock widget guest, which should accept focus or use a focus proxy. Flag_TitleBarIsFocusable = 512, ///< You can click the title bar and it will focus the last focused widget in the focus scope. If no previously focused widget then it focuses the user's dock widget guest, which should accept focus or use a focus proxy.
Flag_LazyResize = 1024, ///< The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button. Flag_LazyResize = 1024, ///< The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button.
Flag_DontUseUtilityFloatingWindows = 0x1000, Flag_DontUseUtilityFloatingWindows = 0x1000,
Flag_TitleBarHasMinimizeButton = 0x2000 | Flag_DontUseUtilityFloatingWindows, ///< The title bar will have a minimize button when floating. This implies Flag_DontUseUtilityFloatingWindows too, otherwise they wouldn't appear in the task bar. Flag_TitleBarHasMinimizeButton = 0x2000 | Flag_DontUseUtilityFloatingWindows, ///< The title bar will have a minimize button when floating. This implies Flag_DontUseUtilityFloatingWindows too, otherwise they wouldn't appear in the task bar.
Flag_TitleBarNoFloatButton = 0x4000, ///< The TitleBar won't show the float button Flag_TitleBarNoFloatButton = 0x4000, ///< The TitleBar won't show the float button
Flag_AutoHideSupport = 0x8000 | Flag_TitleBarNoFloatButton, ///< Supports minimizing dock widgets to the side-bar. Flag_AutoHideSupport = 0x8000 | Flag_TitleBarNoFloatButton, ///< Supports minimizing dock widgets to the side-bar.
///< By default it also turns off the float button, but you can remove Flag_TitleBarNoFloatButton to have both. ///< By default it also turns off the float button, but you can remove Flag_TitleBarNoFloatButton to have both.
Flag_KeepAboveIfNotUtilityWindow = 0x10000, ///< Only meaningful if Flag_DontUseUtilityFloatingWindows is set. If floating windows are normal windows, you might still want them to keep above and not minimize when you focus the main window. Flag_KeepAboveIfNotUtilityWindow = 0x10000, ///< Only meaningful if Flag_DontUseUtilityFloatingWindows is set. If floating windows are normal windows, you might still want them to keep above and not minimize when you focus the main window.
Flag_CloseOnlyCurrentTab = 0x20000, ///< The TitleBar's close button will only close the current tab, instead of all of them
Flag_ShowButtonsOnTabBarIfTitleBarHidden = 0x40000, ///< When using Flag_HideTitleBarWhenTabsVisible the close/float buttons disappear with the title bar. With Flag_ShowButtonsOnTabBarIfHidden they'll be shown in the tab bar.
Flag_Default = Flag_AeroSnapWithClientDecos ///< The defaults Flag_Default = Flag_AeroSnapWithClientDecos ///< The defaults
}; };
Q_DECLARE_FLAGS(Flags, Flag) Q_DECLARE_FLAGS(Flags, Flag)
///@brief List of customizable widgets
enum CustomizableWidget
{
CustomizableWidget_None = 0, ///< None
CustomizableWidget_TitleBar, ///< The title bar
CustomizableWidget_DockWidget, ///< The dock widget
CustomizableWidget_Frame, ///< The container for a group of 1 or more dockwidgets which are tabbed together
CustomizableWidget_TabBar, ///< The tab bar, child of Frame, which contains 1 or more dock widgets
CustomizableWidget_TabWidget, ///< The tab widget which relates to the tab bar
CustomizableWidget_FloatingWindow, ///< A top-level window. The container for 1 or more Frame nested side by side
CustomizableWidget_Separator ///< The draggable separator between dock widgets in a layout
};
Q_DECLARE_FLAGS(CustomizableWidgets, CustomizableWidget)
///@internal ///@internal
///Internal flags for addtional tunning. ///Internal flags for additional tuning.
///@warning Not for public consumption, support will be limited. ///@warning Not for public consumption, support will be limited.
enum InternalFlag { enum InternalFlag
{
InternalFlag_None = 0, ///< The default InternalFlag_None = 0, ///< The default
InternalFlag_NoAeroSnap = 1, ///< Only for development. Disables Aero-snap. InternalFlag_NoAeroSnap = 1, ///< Only for development. Disables Aero-snap.
InternalFlag_DontUseParentForFloatingWindows = 2, ///< FloatingWindows won't have a parent top-level. InternalFlag_DontUseParentForFloatingWindows = 2, ///< FloatingWindows won't have a parent top-level.
InternalFlag_DontUseQtToolWindowsForFloatingWindows = 4, ///< FloatingWindows will use Qt::Window instead of Qt::Tool. InternalFlag_DontUseQtToolWindowsForFloatingWindows = 4, ///< FloatingWindows will use Qt::Window instead of Qt::Tool.
InternalFlag_DontShowWhenUnfloatingHiddenWindow = 8 ///< DockWidget::setFloating(false) won't do anything if the window is hidden. InternalFlag_DontShowWhenUnfloatingHiddenWindow = 8, ///< DockWidget::setFloating(false) won't do anything if the window is hidden.
InternalFlag_UseTransparentFloatingWindow = 16, ///< For QtQuick only. Allows to have round-corners. It's flaky when used with native Windows drop-shadow.
InternalFlag_DisableTranslucency = 32 ///< KDDW tries to detect if your Window Manager doesn't support transparent windows, but the detection might fail
/// with more exotic setups. This flag can be used to override.
}; };
Q_DECLARE_FLAGS(InternalFlags, InternalFlag) Q_DECLARE_FLAGS(InternalFlags, InternalFlag)
@@ -167,6 +188,15 @@ public:
///By default it's 1.0, fully opaque ///By default it's 1.0, fully opaque
qreal draggedWindowOpacity() const; qreal draggedWindowOpacity() const;
/// @brief Allows to disable support for drop indicators while dragging
/// By default drop indicators will be shown when dragging dock widgets.
/// This functionality can be toggled whenever you need it (it's not a startup-only setting).
void setDropIndicatorsInhibited(bool inhibit) const;
/// @brief Returns whether drop indicators are inhibited.
/// by default this is false unless you call setDropIndicatorsInhibited(true)
bool dropIndicatorsInhibited() const;
/** /**
* @brief Allows the user to intercept a docking attempt to center (tabbed) and disallow it. * @brief Allows the user to intercept a docking attempt to center (tabbed) and disallow it.
* *
@@ -206,6 +236,13 @@ public:
void setAbsoluteWidgetMaxSize(QSize size); void setAbsoluteWidgetMaxSize(QSize size);
QSize absoluteWidgetMaxSize() const; QSize absoluteWidgetMaxSize() const;
///@brief Disables our internal widget's paint events
/// By default, KDDockWidget's internal widgets reimplement paintEvent(). Disabling them
/// (which makes the base-class, QWidget::paintEvent() be called instead) can be useful if you want to style
// via CSS stylesheets.
void setDisabledPaintEvents(CustomizableWidgets);
Config::CustomizableWidgets disabledPaintEvents() const;
///@internal ///@internal
///@brief returns the internal flags. ///@brief returns the internal flags.
///@warning Not for public consumption, support will be limited. ///@warning Not for public consumption, support will be limited.
@@ -216,10 +253,16 @@ public:
///@warning Not for public consumption, support will be limited. ///@warning Not for public consumption, support will be limited.
void setInternalFlags(InternalFlags flags); void setInternalFlags(InternalFlags flags);
/// @brief Sets the MDI popup threshold. When the layout is MDI and you drag a dock widget
/// X pixels behond the window's edge, it will float the dock widget.
/// by default this value is 250px. Use -1 to disable
void setMDIPopupThreshold(int);
int mdiPopupThreshold() const;
#ifdef KDDOCKWIDGETS_QTQUICK #ifdef KDDOCKWIDGETS_QTQUICK
///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick. ///@brief Sets the QQmlEngine to use. Applicable only when using QtQuick.
void setQmlEngine(QQmlEngine *); void setQmlEngine(QQmlEngine *);
QQmlEngine* qmlEngine() const; QQmlEngine *qmlEngine() const;
#endif #endif
private: private:

View File

@@ -49,7 +49,8 @@ public:
* when visible, or stays without a parent when hidden. This allows to support docking * when visible, or stays without a parent when hidden. This allows to support docking
* to different main windows. * to different main windows.
*/ */
explicit DockWidget(const QString &uniqueName, Options options = DockWidgetBase::Options()); explicit DockWidget(const QString &uniqueName, Options options = KDDockWidgets::DockWidgetBase::Options(),
LayoutSaverOptions layoutSaverOptions = KDDockWidgets::DockWidgetBase::LayoutSaverOptions());
///@brief destructor ///@brief destructor
~DockWidget() override; ~DockWidget() override;

View File

@@ -10,18 +10,21 @@
*/ */
#include "DockWidgetBase.h" #include "DockWidgetBase.h"
#include "Frame_p.h" #include "private/DockWidgetBase_p.h"
#include "FloatingWindow_p.h" #include "private/DockRegistry_p.h"
#include "Logging_p.h" #include "private/FloatingWindow_p.h"
#include "Utils_p.h" #include "private/Frame_p.h"
#include "DockRegistry_p.h" #include "private/LayoutSaver_p.h"
#include "DropArea_p.h" #include "private/Logging_p.h"
#include "Config.h" #include "private/MDILayoutWidget_p.h"
#include "TitleBar_p.h" #include "private/SideBar_p.h"
#include "FrameworkWidgetFactory.h" #include "private/TitleBar_p.h"
#include "private/Utils_p.h"
#include "private/WindowBeingDragged_p.h"
#include "private/Position_p.h" #include "private/Position_p.h"
#include "WindowBeingDragged_p.h"
#include "SideBar_p.h" #include "Config.h"
#include "FrameworkWidgetFactory.h"
#include <QEvent> #include <QEvent>
#include <QCloseEvent> #include <QCloseEvent>
@@ -37,107 +40,10 @@
using namespace KDDockWidgets; using namespace KDDockWidgets;
class DockWidgetBase::Private DockWidgetBase::DockWidgetBase(const QString &name, Options options,
{ LayoutSaverOptions layoutSaverOptions)
public:
Private(const QString &dockName, DockWidgetBase::Options options_, DockWidgetBase *qq)
: name(dockName)
, title(dockName)
, q(qq)
, options(options_)
, toggleAction(new QAction(q))
, floatAction(new QAction(q))
{
q->connect(toggleAction, &QAction::toggled, q, [this] (bool enabled) {
if (!m_updatingToggleAction) { // guard against recursiveness
toggleAction->blockSignals(true); // and don't emit spurious toggle. Like when a dock widget is inserted into a tab widget it might get hide events, ignore those. The Dock Widget is open.
toggle(enabled);
toggleAction->blockSignals(false);
}
});
q->connect(floatAction, &QAction::toggled, q, [this] (bool checked) {
if (!m_updatingFloatAction) { // guard against recursiveness
q->setFloating(checked);
}
Q_EMIT q->isFloatingChanged(checked);
});
toggleAction->setCheckable(true);
floatAction->setCheckable(true);
}
void init()
{
updateTitle();
}
FloatingWindow *floatingWindow() const
{
return qobject_cast<FloatingWindow*>(q->window());
}
MainWindowBase *mainWindow() const
{
if (q->isWindow())
return nullptr;
// Note: Don't simply use window(), as the MainWindow might be embedded into something else
QWidgetOrQuick *p = q->parentWidget();
while (p) {
if (auto window = qobject_cast<MainWindowBase*>(p))
return window;
if (p->isWindow())
return nullptr;
p = p->parentWidget();
}
return nullptr;
}
QPoint defaultCenterPosForFloating();
void updateTitle();
void toggle(bool enabled);
void updateToggleAction();
void updateFloatAction();
void onDockWidgetShown();
void onDockWidgetHidden();
void show();
void close();
bool restoreToPreviousPosition();
void maybeRestoreToPreviousPosition();
int currentTabIndex() const;
/**
* Before floating a dock widget we save its position. So it can be restored when calling
* DockWidget::setFloating(false)
*/
void saveTabIndex();
const QString name;
QStringList affinities;
QString title;
QIcon titleBarIcon;
QIcon tabBarIcon;
QWidgetOrQuick *widget = nullptr;
DockWidgetBase *const q;
DockWidgetBase::Options options;
QAction *const toggleAction;
QAction *const floatAction;
LastPositions m_lastPositions;
bool m_updatingToggleAction = false;
bool m_updatingFloatAction = false;
bool m_isForceClosing = false;
QSize m_lastOverlayedSize = QSize(0, 0);
};
DockWidgetBase::DockWidgetBase(const QString &name, Options options)
: QWidgetAdapter(nullptr, Qt::Tool) : QWidgetAdapter(nullptr, Qt::Tool)
, d(new Private(name, options, this)) , d(new Private(name, options, layoutSaverOptions, this))
{ {
d->init(); d->init();
DockRegistry::self()->registerDockWidget(this); DockRegistry::self()->registerDockWidget(this);
@@ -146,7 +52,6 @@ DockWidgetBase::DockWidgetBase(const QString &name, Options options)
qWarning() << Q_FUNC_INFO << "Name can't be null"; qWarning() << Q_FUNC_INFO << "Name can't be null";
setAttribute(Qt::WA_PendingMoveEvent, false); setAttribute(Qt::WA_PendingMoveEvent, false);
qApp->installEventFilter(this);
} }
DockWidgetBase::~DockWidgetBase() DockWidgetBase::~DockWidgetBase()
@@ -173,13 +78,12 @@ void DockWidgetBase::addDockWidgetAsTab(DockWidgetBase *other, InitialOption opt
return; return;
} }
if ((other->options() & DockWidgetBase::Option_NotDockable) || if ((other->options() & DockWidgetBase::Option_NotDockable) || (options() & DockWidgetBase::Option_NotDockable)) {
(options() & DockWidgetBase::Option_NotDockable)) {
qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other; qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other;
return; return;
} }
Frame *frame = this->frame(); Frame *frame = d->frame();
if (frame) { if (frame) {
if (frame->containsDockWidget(other)) { if (frame->containsDockWidget(other)) {
@@ -189,8 +93,8 @@ void DockWidgetBase::addDockWidgetAsTab(DockWidgetBase *other, InitialOption opt
} else { } else {
if (isWindow()) { if (isWindow()) {
// Doesn't have a frame yet // Doesn't have a frame yet
morphIntoFloatingWindow(); d->morphIntoFloatingWindow();
frame = this->frame(); frame = d->frame();
} else { } else {
// Doesn't happen // Doesn't happen
qWarning() << Q_FUNC_INFO << "null frame"; qWarning() << Q_FUNC_INFO << "null frame";
@@ -207,7 +111,7 @@ void DockWidgetBase::addDockWidgetToContainingWindow(DockWidgetBase *other,
DockWidgetBase *relativeTo, DockWidgetBase *relativeTo,
InitialOption initialOption) InitialOption initialOption)
{ {
if (auto mainWindow = qobject_cast<MainWindowBase*>(window())) { if (auto mainWindow = qobject_cast<MainWindowBase *>(window())) {
// It's inside a main window. Simply use the main window API. // It's inside a main window. Simply use the main window API.
mainWindow->addDockWidget(other, location, relativeTo, initialOption); mainWindow->addDockWidget(other, location, relativeTo, initialOption);
return; return;
@@ -219,17 +123,16 @@ void DockWidgetBase::addDockWidgetToContainingWindow(DockWidgetBase *other,
return; return;
} }
if ((other->options() & DockWidgetBase::Option_NotDockable) || if ((other->options() & DockWidgetBase::Option_NotDockable) || (options() & DockWidgetBase::Option_NotDockable)) {
(options() & DockWidgetBase::Option_NotDockable)) {
qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other; qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other;
return; return;
} }
if (isWindow()) if (isWindow())
morphIntoFloatingWindow(); d->morphIntoFloatingWindow();
if (auto fw = floatingWindow()) { if (auto fw = floatingWindow()) {
fw->dropArea()->addDockWidget(other, location, relativeTo, initialOption); fw->addDockWidget(other, location, relativeTo, initialOption);
} else { } else {
qWarning() << Q_FUNC_INFO << "Couldn't find floating nested window"; qWarning() << Q_FUNC_INFO << "Couldn't find floating nested window";
} }
@@ -237,7 +140,6 @@ void DockWidgetBase::addDockWidgetToContainingWindow(DockWidgetBase *other,
void DockWidgetBase::setWidget(QWidgetOrQuick *w) void DockWidgetBase::setWidget(QWidgetOrQuick *w)
{ {
Q_ASSERT(w);
if (w == d->widget) if (w == d->widget)
return; return;
@@ -251,7 +153,6 @@ void DockWidgetBase::setWidget(QWidgetOrQuick *w)
setSizePolicy(w->sizePolicy()); setSizePolicy(w->sizePolicy());
Q_EMIT widgetChanged(w); Q_EMIT widgetChanged(w);
setWindowTitle(uniqueName());
} }
QWidgetOrQuick *DockWidgetBase::widget() const QWidgetOrQuick *DockWidgetBase::widget() const
@@ -284,7 +185,7 @@ bool DockWidgetBase::setFloating(bool floats)
if (floats) { if (floats) {
d->saveTabIndex(); d->saveTabIndex();
if (isTabbed()) { if (isTabbed()) {
auto frame = this->frame(); auto frame = d->frame();
if (!frame) { if (!frame) {
qWarning() << "DockWidget::setFloating: Tabbed but no frame exists" qWarning() << "DockWidget::setFloating: Tabbed but no frame exists"
<< this; << this;
@@ -294,17 +195,17 @@ bool DockWidgetBase::setFloating(bool floats)
frame->detachTab(this); frame->detachTab(this);
} else { } else {
frame()->titleBar()->makeWindow(); d->frame()->titleBar()->makeWindow();
} }
auto lastGeo = lastPositions().lastFloatingGeometry(); auto lastGeo = d->lastPositions().lastFloatingGeometry();
if (lastGeo.isValid()) { if (lastGeo.isValid()) {
if (auto fw = floatingWindow()) if (auto fw = floatingWindow())
fw->setSuggestedGeometry(lastGeo, /*preserveCenter=*/true); fw->setSuggestedGeometry(lastGeo, SuggestedGeometryHint_PreserveCenter);
} }
return true; return true;
} else { } else {
saveLastFloatingGeometry(); d->saveLastFloatingGeometry();
return d->restoreToPreviousPosition(); return d->restoreToPreviousPosition();
} }
} }
@@ -338,11 +239,25 @@ void DockWidgetBase::setTitle(const QString &title)
} }
} }
QRect DockWidgetBase::frameGeometry() const
{
if (Frame *f = d->frame())
return f->QWidgetAdapter::geometry();
// Means the dock widget isn't visible. Just fallback to its own geometry
return QWidgetAdapter::geometry();
}
DockWidgetBase::Options DockWidgetBase::options() const DockWidgetBase::Options DockWidgetBase::options() const
{ {
return d->options; return d->options;
} }
DockWidgetBase::LayoutSaverOptions DockWidgetBase::layoutSaverOptions() const
{
return d->layoutSaverOptions;
}
void DockWidgetBase::setOptions(Options options) void DockWidgetBase::setOptions(Options options)
{ {
if ((d->options & Option_NotDockable) != (options & Option_NotDockable)) { if ((d->options & Option_NotDockable) != (options & Option_NotDockable)) {
@@ -354,13 +269,13 @@ void DockWidgetBase::setOptions(Options options)
d->options = options; d->options = options;
Q_EMIT optionsChanged(options); Q_EMIT optionsChanged(options);
if (auto tb = titleBar()) if (auto tb = titleBar())
tb->updateCloseButton(); tb->updateButtons();
} }
} }
bool DockWidgetBase::isTabbed() const bool DockWidgetBase::isTabbed() const
{ {
if (Frame *frame = this->frame()) { if (Frame *frame = d->frame()) {
return frame->alwaysShowsTabs() || frame->dockWidgetCount() > 1; return frame->alwaysShowsTabs() || frame->dockWidgetCount() > 1;
} else { } else {
if (!isFloating()) if (!isFloating())
@@ -371,8 +286,8 @@ bool DockWidgetBase::isTabbed() const
bool DockWidgetBase::isCurrentTab() const bool DockWidgetBase::isCurrentTab() const
{ {
if (Frame *frame = this->frame()) { if (Frame *frame = d->frame()) {
return frame->currentIndex() == frame->indexOfDockWidget(const_cast<DockWidgetBase*>(this)); return frame->currentIndex() == frame->indexOfDockWidget(const_cast<DockWidgetBase *>(this));
} else { } else {
return true; return true;
} }
@@ -380,10 +295,18 @@ bool DockWidgetBase::isCurrentTab() const
void DockWidgetBase::setAsCurrentTab() void DockWidgetBase::setAsCurrentTab()
{ {
if (Frame *frame = this->frame()) if (Frame *frame = d->frame())
frame->setCurrentDockWidget(this); frame->setCurrentDockWidget(this);
} }
int DockWidgetBase::tabIndex() const
{
if (Frame *frame = d->frame())
return frame->indexOfDockWidget(this);
return 0;
}
void DockWidgetBase::setIcon(const QIcon &icon, IconPlaces places) void DockWidgetBase::setIcon(const QIcon &icon, IconPlaces places)
{ {
if (places & IconPlace::TitleBar) if (places & IconPlace::TitleBar)
@@ -414,13 +337,12 @@ QIcon DockWidgetBase::icon(IconPlace place) const
void DockWidgetBase::forceClose() void DockWidgetBase::forceClose()
{ {
QScopedValueRollback<bool> rollback(d->m_isForceClosing, true); d->forceClose();
d->close();
} }
TitleBar *DockWidgetBase::titleBar() const TitleBar *DockWidgetBase::titleBar() const
{ {
if (Frame *f = frame()) if (Frame *f = d->frame())
return f->actualTitleBar(); return f->actualTitleBar();
return nullptr; return nullptr;
@@ -441,7 +363,7 @@ void DockWidgetBase::show()
if (isWindow() && (d->m_lastPositions.wasFloating() || !d->m_lastPositions.isValid())) { if (isWindow() && (d->m_lastPositions.wasFloating() || !d->m_lastPositions.isValid())) {
// Create the FloatingWindow already, instead of waiting for the show event. // Create the FloatingWindow already, instead of waiting for the show event.
// This reduces flickering on some platforms // This reduces flickering on some platforms
morphIntoFloatingWindow(); d->morphIntoFloatingWindow();
} else { } else {
QWidgetOrQuick::show(); QWidgetOrQuick::show();
} }
@@ -457,12 +379,15 @@ void DockWidgetBase::raise()
if (auto fw = floatingWindow()) { if (auto fw = floatingWindow()) {
fw->raise(); fw->raise();
fw->activateWindow(); fw->activateWindow();
} else if (Frame *frame = d->frame()) {
if (frame->isMDI())
frame->raise();
} }
} }
bool DockWidgetBase::isMainWindow() const bool DockWidgetBase::isMainWindow() const
{ {
return qobject_cast<MainWindowBase*>(widget()); return qobject_cast<MainWindowBase *>(widget());
} }
bool DockWidgetBase::isInMainWindow() const bool DockWidgetBase::isInMainWindow() const
@@ -470,14 +395,14 @@ bool DockWidgetBase::isInMainWindow() const
return d->mainWindow() != nullptr; return d->mainWindow() != nullptr;
} }
MainWindowBase* DockWidgetBase::mainWindow() const MainWindowBase *DockWidgetBase::mainWindow() const
{ {
return d->mainWindow(); return d->mainWindow();
} }
bool DockWidgetBase::isFocused() const bool DockWidgetBase::isFocused() const
{ {
auto f = this->frame(); auto f = d->frame();
return f && f->isFocused() && isCurrentTab(); return f && f->isFocused() && isCurrentTab();
} }
@@ -523,6 +448,11 @@ SideBarLocation DockWidgetBase::sideBarLocation() const
return DockRegistry::self()->sideBarLocationForDockWidget(this); return DockRegistry::self()->sideBarLocationForDockWidget(this);
} }
bool DockWidgetBase::isInSideBar() const
{
return sideBarLocation() != SideBarLocation::None;
}
bool DockWidgetBase::hasPreviousDockedLocation() const bool DockWidgetBase::hasPreviousDockedLocation() const
{ {
return d->m_lastPositions.isValid(); return d->m_lastPositions.isValid();
@@ -538,27 +468,43 @@ DockWidgetBase *DockWidgetBase::byName(const QString &uniqueName)
return DockRegistry::self()->dockByName(uniqueName); return DockRegistry::self()->dockByName(uniqueName);
} }
FloatingWindow *DockWidgetBase::morphIntoFloatingWindow() bool DockWidgetBase::skipsRestore() const
{
return d->layoutSaverOptions & LayoutSaverOption::Skip;
}
void DockWidgetBase::setFloatingGeometry(QRect geometry)
{
if (isOpen() && isFloating()) {
window()->setGeometry(geometry);
} else {
d->m_lastPositions.setLastFloatingGeometry(geometry);
}
}
FloatingWindow *DockWidgetBase::Private::morphIntoFloatingWindow()
{ {
if (auto fw = floatingWindow()) if (auto fw = floatingWindow())
return fw; // Nothing to do return fw; // Nothing to do
if (isWindow()) { if (q->isWindow()) {
QRect geo = d->m_lastPositions.lastFloatingGeometry(); QRect geo = m_lastPositions.lastFloatingGeometry();
if (geo.isNull()) { if (geo.isNull()) {
geo = geometry(); geo = q->geometry();
if (!testAttribute(Qt::WA_PendingMoveEvent)) { // If user already moved it, we don't interfere if (!q->testAttribute(Qt::WA_PendingMoveEvent)) { // If user already moved it, we don't
const QPoint center = d->defaultCenterPosForFloating(); // interfere
const QPoint center = defaultCenterPosForFloating();
if (!center.isNull()) if (!center.isNull())
geo.moveCenter(center); geo.moveCenter(center);
} }
} }
auto frame = Config::self().frameworkWidgetFactory()->createFrame(); auto frame = Config::self().frameworkWidgetFactory()->createFrame();
frame->addWidget(this); frame->addWidget(q);
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(frame); geo.setSize(geo.size().boundedTo(frame->maxSizeHint()));
floatingWindow->setSuggestedGeometry(geo); auto floatingWindow =
Config::self().frameworkWidgetFactory()->createFloatingWindow(frame, nullptr, geo);
floatingWindow->show(); floatingWindow->show();
return floatingWindow; return floatingWindow;
@@ -567,60 +513,23 @@ FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
} }
} }
void DockWidgetBase::maybeMorphIntoFloatingWindow() void DockWidgetBase::Private::maybeMorphIntoFloatingWindow()
{ {
if (isWindow() && isVisible()) if (q->isWindow() && q->isVisible())
morphIntoFloatingWindow(); morphIntoFloatingWindow();
} }
Frame *DockWidgetBase::frame() const MDILayoutWidget *DockWidgetBase::Private::mdiLayout() const
{ {
QWidgetOrQuick *p = parentWidget(); if (auto mw = mainWindow())
while (p) { return mw->mdiLayoutWidget();
if (auto frame = qobject_cast<Frame *>(p))
return frame;
p = p->parentWidget();
}
return nullptr; return nullptr;
} }
FloatingWindow *DockWidgetBase::floatingWindow() const DockWidgetBase::Private *DockWidgetBase::dptr() const
{ {
return d->floatingWindow(); return d;
}
void DockWidgetBase::addPlaceholderItem(Layouting::Item *item)
{
Q_ASSERT(item);
d->m_lastPositions.addPosition(item);
}
LastPositions& DockWidgetBase::lastPositions() const
{
return d->m_lastPositions;
}
void DockWidgetBase::saveLastFloatingGeometry()
{
if (isFloating() && isVisible()) {
// It's getting docked, save last floating position
lastPositions().setLastFloatingGeometry(window()->geometry());
}
}
void DockWidgetBase::updateFloatAction()
{
d->updateFloatAction();
}
bool DockWidgetBase::eventFilter(QObject *watched, QEvent *event)
{
const bool isWindowActivate = event->type() == QEvent::WindowActivate;
const bool isWindowDeactivate = event->type() == QEvent::WindowDeactivate;
if ((isWindowActivate || isWindowDeactivate) && watched == window())
Q_EMIT windowActiveAboutToChange(isWindowActivate);
return QWidgetAdapter::eventFilter(watched, event);
} }
QPoint DockWidgetBase::Private::defaultCenterPosForFloating() QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
@@ -634,21 +543,36 @@ QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
return mw->geometry().center(); return mw->geometry().center();
} }
bool DockWidgetBase::Private::eventFilter(QObject *watched, QEvent *event)
{
const bool isWindowActivate = event->type() == QEvent::WindowActivate;
const bool isWindowDeactivate = event->type() == QEvent::WindowDeactivate;
if ((isWindowActivate || isWindowDeactivate) && watched == q->window())
Q_EMIT q->windowActiveAboutToChange(isWindowActivate);
return QObject::eventFilter(watched, event);
}
void DockWidgetBase::Private::updateTitle() void DockWidgetBase::Private::updateTitle()
{ {
if (q->isFloating()) if (q->isFloating())
q->window()->setWindowTitle(title); q->window()->setWindowTitle(title);
toggleAction->setText(title); toggleAction->setText(title);
} }
void DockWidgetBase::Private::toggle(bool enabled) void DockWidgetBase::Private::toggle(bool enabled)
{ {
if (enabled) { if (SideBar *sb = sideBar()) {
show(); // The widget is in the sidebar, let's toggle its overlayed state
sb->toggleOverlay(q);
} else { } else {
q->close(); // The most common case. The dock widget is not in the sidebar. just close or open it.
if (enabled) {
show();
} else {
q->close();
}
} }
} }
@@ -656,9 +580,9 @@ void DockWidgetBase::Private::updateToggleAction()
{ {
QScopedValueRollback<bool> recursionGuard(m_updatingToggleAction, true); // Guard against recursiveness QScopedValueRollback<bool> recursionGuard(m_updatingToggleAction, true); // Guard against recursiveness
m_updatingToggleAction = true; m_updatingToggleAction = true;
if ((q->isVisible() || q->frame()) && !toggleAction->isChecked()) { if ((q->isVisible() || frame()) && !toggleAction->isChecked()) {
toggleAction->setChecked(true); toggleAction->setChecked(true);
} else if ((!q->isVisible() && !q->frame()) && toggleAction->isChecked()) { } else if ((!q->isVisible() && !frame()) && toggleAction->isChecked()) {
toggleAction->setChecked(false); toggleAction->setChecked(false);
} }
} }
@@ -692,22 +616,41 @@ void DockWidgetBase::Private::onDockWidgetHidden()
void DockWidgetBase::Private::close() void DockWidgetBase::Private::close()
{ {
if (!m_isForceClosing && q->isFloating() && q->isVisible()) { // only user-closing is interesting to save the geometry if (!m_processingToggleAction && !q->isOpen()) {
// We check for isVisible so we don't save geometry if you call close() on an already closed dock widget return;
}
// If it's overlayed and we're closing, we need to close the overlay
if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
auto mainWindow = sb->mainWindow();
if (mainWindow->overlayedDockWidget() == q) {
mainWindow->clearSideBarOverlay(/* deleteFrame=*/false);
}
}
if (!m_isForceClosing && q->isFloating()
&& q->isVisible()) { // only user-closing is interesting to save the geometry
// We check for isVisible so we don't save geometry if you call close() on an already closed
// dock widget
m_lastPositions.setLastFloatingGeometry(q->window()->geometry()); m_lastPositions.setLastFloatingGeometry(q->window()->geometry());
} }
saveTabIndex(); saveTabIndex();
// Do some cleaning. Widget is hidden, but we must hide the tab containing it. // Do some cleaning. Widget is hidden, but we must hide the tab containing it.
if (Frame *frame = q->frame()) { if (Frame *frame = this->frame()) {
frame->removeWidget(q);
q->setParent(nullptr); q->setParent(nullptr);
frame->removeWidget(q);
if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) { if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
sb->removeDockWidget(q); sb->removeDockWidget(q);
} }
} }
if (!m_isMovingToSideBar && (options & DockWidgetBase::Option_DeleteOnClose)) {
Q_EMIT q->aboutToDeleteOnClose();
q->deleteLater();
}
} }
bool DockWidgetBase::Private::restoreToPreviousPosition() bool DockWidgetBase::Private::restoreToPreviousPosition()
@@ -717,7 +660,7 @@ bool DockWidgetBase::Private::restoreToPreviousPosition()
Layouting::Item *item = m_lastPositions.lastItem(); Layouting::Item *item = m_lastPositions.lastItem();
MultiSplitter *layout = DockRegistry::self()->layoutForItem(item); LayoutWidget *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; return true;
@@ -737,7 +680,7 @@ void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
if (m_lastPositions.wasFloating()) if (m_lastPositions.wasFloating())
return; // Nothing to do, it was floating before, now it'll just get visible return; // Nothing to do, it was floating before, now it'll just get visible
Frame *frame = q->frame(); Frame *frame = this->frame();
if (frame && frame->QWidgetAdapter::parentWidget() == DockRegistry::self()->layoutForItem(layoutItem)) { if (frame && frame->QWidgetAdapter::parentWidget() == DockRegistry::self()->layoutForItem(layoutItem)) {
// There's a frame already. Means the DockWidget was hidden instead of closed. // There's a frame already. Means the DockWidget was hidden instead of closed.
@@ -758,7 +701,7 @@ void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
int DockWidgetBase::Private::currentTabIndex() const int DockWidgetBase::Private::currentTabIndex() const
{ {
Frame *frame = q->frame(); Frame *frame = this->frame();
return frame ? frame->indexOfDockWidget(q) : 0; return frame ? frame->indexOfDockWidget(q) : 0;
} }
@@ -783,6 +726,8 @@ void DockWidgetBase::onParentChanged()
#endif #endif
d->updateToggleAction(); d->updateToggleAction();
d->updateFloatAction(); d->updateFloatAction();
Q_EMIT actualTitleBarChanged();
} }
void DockWidgetBase::onShown(bool spontaneous) void DockWidgetBase::onShown(bool spontaneous)
@@ -790,7 +735,7 @@ void DockWidgetBase::onShown(bool spontaneous)
d->onDockWidgetShown(); d->onDockWidgetShown();
Q_EMIT shown(); Q_EMIT shown();
if (Frame *f = frame()) { if (Frame *f = d->frame()) {
if (!spontaneous) { if (!spontaneous) {
f->onDockWidgetShown(this); f->onDockWidgetShown(this);
} }
@@ -799,7 +744,7 @@ void DockWidgetBase::onShown(bool spontaneous)
d->maybeRestoreToPreviousPosition(); d->maybeRestoreToPreviousPosition();
// Transform into a FloatingWindow if this will be a regular floating dock widget. // Transform into a FloatingWindow if this will be a regular floating dock widget.
QTimer::singleShot(0, this, &DockWidgetBase::maybeMorphIntoFloatingWindow); QTimer::singleShot(0, d, &DockWidgetBase::Private::maybeMorphIntoFloatingWindow);
} }
void DockWidgetBase::onHidden(bool spontaneous) void DockWidgetBase::onHidden(bool spontaneous)
@@ -807,7 +752,7 @@ void DockWidgetBase::onHidden(bool spontaneous)
d->onDockWidgetHidden(); d->onDockWidgetHidden();
Q_EMIT hidden(); Q_EMIT hidden();
if (Frame *f = frame()) { if (Frame *f = d->frame()) {
if (!spontaneous) { if (!spontaneous) {
f->onDockWidgetHidden(this); f->onDockWidgetHidden(this);
} }
@@ -817,7 +762,7 @@ void DockWidgetBase::onHidden(bool spontaneous)
bool DockWidgetBase::onResize(QSize newSize) bool DockWidgetBase::onResize(QSize newSize)
{ {
if (isOverlayed()) { if (isOverlayed()) {
if (auto frame = this->frame()) { if (auto frame = d->frame()) {
d->m_lastOverlayedSize = frame->QWidgetAdapter::size(); d->m_lastOverlayedSize = frame->QWidgetAdapter::size();
} else { } else {
qWarning() << Q_FUNC_INFO << "Overlayed dock widget without frame shouldn't happen"; qWarning() << Q_FUNC_INFO << "Overlayed dock widget without frame shouldn't happen";
@@ -831,7 +776,7 @@ 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)
qApp->sendEvent(d->widget, e); // Give a chancefor the widget to ignore qApp->sendEvent(d->widget, e); // Give a chance for the widget to ignore
if (e->isAccepted()) if (e->isAccepted())
d->close(); d->close();
@@ -839,14 +784,8 @@ void DockWidgetBase::onCloseEvent(QCloseEvent *e)
DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &saved) DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &saved)
{ {
DockWidgetBase *dw = DockRegistry::self()->dockByName(saved->uniqueName); auto dr = DockRegistry::self();
if (!dw) { DockWidgetBase *dw = dr->dockByName(saved->uniqueName, DockRegistry::DockByNameFlag::CreateIfNotFound);
if (auto factoryFunc = Config::self().dockWidgetFactoryFunc()) {
// DockWidget doesn't exist, ask to create it
dw = factoryFunc(saved->uniqueName);
}
}
if (dw) { if (dw) {
if (QWidgetOrQuick *w = dw->widget()) if (QWidgetOrQuick *w = dw->widget())
w->setVisible(true); w->setVisible(true);
@@ -857,18 +796,132 @@ DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &
<< "; to" << saved->affinities; << "; to" << saved->affinities;
dw->d->affinities = saved->affinities; dw->d->affinities = saved->affinities;
} }
} else {
qWarning() << Q_FUNC_INFO << "Couldn't find dock widget" << saved->uniqueName;
} }
return dw; return dw;
} }
LayoutSaver::DockWidget::Ptr DockWidgetBase::serialize() const void DockWidgetBase::setUserType(int userType)
{ {
auto ptr = LayoutSaver::DockWidget::dockWidgetForName(uniqueName()); d->m_userType = userType;
ptr->affinities = affinities(); }
int DockWidgetBase::userType() const
{
return d->m_userType;
}
void DockWidgetBase::setMDIPosition(QPoint pos)
{
if (MDILayoutWidget *layout = d->mdiLayout())
layout->moveDockWidget(this, pos);
}
void DockWidgetBase::setMDISize(QSize size)
{
if (MDILayoutWidget *layout = d->mdiLayout())
layout->resizeDockWidget(this, size);
}
void DockWidgetBase::setMDIZ(int z)
{
#ifdef KDDOCKWIDGETS_QTQUICK
if (Frame *frame = d->frame()) {
if (!frame->isMDI())
return;
frame->setZ(z);
}
#else
Q_UNUSED(z);
qWarning() << Q_FUNC_INFO << "Not implemented for QtQuick";
#endif
}
LayoutSaver::DockWidget::Ptr DockWidgetBase::Private::serialize() const
{
auto ptr = LayoutSaver::DockWidget::dockWidgetForName(q->uniqueName());
ptr->affinities = q->affinities();
return ptr; return ptr;
} }
void DockWidgetBase::Private::forceClose()
{
QScopedValueRollback<bool> rollback(m_isForceClosing, true);
close();
}
DockWidgetBase::Private::Private(const QString &dockName, DockWidgetBase::Options options_,
LayoutSaverOptions layoutSaverOptions_, DockWidgetBase *qq)
: name(dockName)
, title(dockName)
, q(qq)
, options(options_)
, layoutSaverOptions(layoutSaverOptions_)
, toggleAction(new QAction(q))
, floatAction(new QAction(q))
{
q->connect(toggleAction, &QAction::toggled, q, [this](bool enabled) {
if (!m_updatingToggleAction) { // guard against recursiveness
toggleAction->blockSignals(true); // and don't emit spurious toggle. Like when a dock
// widget is inserted into a tab widget it might get
// hide events, ignore those. The Dock Widget is open.
m_processingToggleAction = true;
toggle(enabled);
toggleAction->blockSignals(false);
m_processingToggleAction = false;
}
});
q->connect(floatAction, &QAction::toggled, q, [this](bool checked) {
if (!m_updatingFloatAction) { // guard against recursiveness
q->setFloating(checked);
}
Q_EMIT q->isFloatingChanged(checked);
// When floating, we remove from the sidebar
if (checked && q->isOpen()) {
if (SideBar *sb = DockRegistry::self()->sideBarForDockWidget(q)) {
sb->mainWindow()->clearSideBarOverlay(/* deleteFrame=*/false);
sb->removeDockWidget(q);
}
}
});
toggleAction->setCheckable(true);
floatAction->setCheckable(true);
qApp->installEventFilter(this);
}
void DockWidgetBase::Private::addPlaceholderItem(Layouting::Item *item)
{
Q_ASSERT(item);
m_lastPositions.addPosition(item);
}
LastPositions &DockWidgetBase::Private::lastPositions()
{
return m_lastPositions;
}
Frame *DockWidgetBase::Private::frame() const
{
QWidgetOrQuick *p = q->parentWidget();
while (p) {
if (auto frame = qobject_cast<Frame *>(p))
return frame;
p = p->parentWidget();
}
return nullptr;
}
void DockWidgetBase::Private::saveLastFloatingGeometry()
{
if (q->isFloating() && q->isVisible()) {
// It's getting docked, save last floating position
lastPositions().setLastFloatingGeometry(q->window()->geometry());
}
}

View File

@@ -22,25 +22,17 @@
#include "docks_export.h" #include "docks_export.h"
#include "KDDockWidgets.h" #include "KDDockWidgets.h"
#include "QWidgetAdapter.h" #include "QWidgetAdapter.h"
#include "LayoutSaver_p.h" #include "LayoutSaver.h"
#include <QVector> #include <QVector>
#include <memory>
// clazy:excludeall=ctor-missing-parent-argument // clazy:excludeall=ctor-missing-parent-argument
QT_BEGIN_NAMESPACE
class QAction;
QT_END_NAMESPACE
class TestDocks; class TestDocks;
namespace Layouting {
class Item;
}
namespace KDDockWidgets { namespace KDDockWidgets {
struct LastPositions;
class Frame; class Frame;
class FloatingWindow; class FloatingWindow;
class DragController; class DragController;
@@ -51,6 +43,8 @@ class TitleBar;
class MainWindowBase; class MainWindowBase;
class StateDragging; class StateDragging;
class FrameQuick; class FrameQuick;
class DockWidgetQuick;
class LayoutWidget;
/** /**
* @brief The DockWidget base-class. DockWidget and DockWidgetBase are only * @brief The DockWidget base-class. DockWidget and DockWidgetBase are only
@@ -68,18 +62,35 @@ class DOCKS_EXPORT DockWidgetBase : public QWidget
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool isFocused READ isFocused NOTIFY isFocusedChanged) Q_PROPERTY(bool isFocused READ isFocused NOTIFY isFocusedChanged)
Q_PROPERTY(bool isFloating READ isFloating WRITE setFloating NOTIFY isFloatingChanged) Q_PROPERTY(bool isFloating READ isFloating WRITE setFloating NOTIFY isFloatingChanged)
Q_PROPERTY(QString uniqueName READ uniqueName CONSTANT)
Q_PROPERTY(QString title READ title WRITE setTitle NOTIFY titleChanged)
Q_PROPERTY(QObject *widget READ widget NOTIFY widgetChanged)
Q_PROPERTY(KDDockWidgets::DockWidgetBase::Options options READ options WRITE setOptions NOTIFY
optionsChanged)
public: public:
typedef QVector<DockWidgetBase *> List; typedef QVector<DockWidgetBase *> List;
///@brief DockWidget options to pass at construction time ///@brief DockWidget options to pass at construction time
enum Option { enum Option
{
Option_None = 0, ///< No option, the default Option_None = 0, ///< No option, the default
Option_NotClosable = 1, ///< The DockWidget can't be closed on the [x], only programatically Option_NotClosable = 1, ///< The DockWidget can't be closed on the [x], only programmatically
Option_NotDockable = 2 ///< The DockWidget can't be docked, it's always floating Option_NotDockable = 2, ///< The DockWidget can't be docked, it's always floating
Option_DeleteOnClose = 4 ///< Deletes the DockWidget when closed
}; };
Q_DECLARE_FLAGS(Options, Option) Q_DECLARE_FLAGS(Options, Option)
Q_ENUM(Options);
enum class IconPlace { /// @brief Options which will affect LayoutSaver save/restore
enum class LayoutSaverOption
{
None = 0, ///< Just use the defaults
Skip = 1, ///< The dock widget won't participate in save/restore. Currently only available for floating windows.
};
Q_DECLARE_FLAGS(LayoutSaverOptions, LayoutSaverOption)
enum class IconPlace
{
TitleBar = 1, TitleBar = 1,
TabBar = 2, TabBar = 2,
ToggleAction = 4, ToggleAction = 4,
@@ -91,12 +102,15 @@ public:
/** /**
* @brief constructs a new DockWidget * @brief constructs a new DockWidget
* @param uniqueName the name of the dockwidget, should be unique. Use title for user visible text. * @param uniqueName the name of the dockwidget, should be unique. Use title for user visible text.
* @param options optional options controlling behaviour * @param options the options controlling certain behaviours
* @param layoutSaverOptions the options to control save/restore
* *
* There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow * There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow
* when visible, or stays without a parent when hidden. * when visible, or stays without a parent when hidden.
*/ */
explicit DockWidgetBase(const QString &uniqueName, Options options = DockWidgetBase::Options()); explicit DockWidgetBase(const QString &uniqueName,
Options options = KDDockWidgets::DockWidgetBase::Options(),
LayoutSaverOptions layoutSaverOptions = KDDockWidgets::DockWidgetBase::LayoutSaverOptions());
///@brief destructor ///@brief destructor
~DockWidgetBase() override; ~DockWidgetBase() override;
@@ -109,7 +123,8 @@ public:
* shown. * shown.
* @sa MainWindow::addDockWidget(), DockWidget::addDockWidgetToContainingWindow() * @sa MainWindow::addDockWidget(), DockWidget::addDockWidgetToContainingWindow()
*/ */
void addDockWidgetAsTab(DockWidgetBase *other, InitialOption initialOption = {}); Q_INVOKABLE void addDockWidgetAsTab(KDDockWidgets::DockWidgetBase *other,
KDDockWidgets::InitialOption initialOption = {});
/** /**
* @brief docks @p other widget into the window that contains this one. * @brief docks @p other widget into the window that contains this one.
@@ -123,9 +138,11 @@ public:
* @param initialOption Allows to specify some extra options that are used while docking. * @param initialOption Allows to specify some extra options that are used while docking.
* @sa MainWindow::addDockWidget(), DockWidget::addDockWidgetAsTab() * @sa MainWindow::addDockWidget(), DockWidget::addDockWidgetAsTab()
*/ */
void addDockWidgetToContainingWindow(DockWidgetBase *other, KDDockWidgets::Location location, Q_INVOKABLE void
DockWidgetBase *relativeTo = nullptr, addDockWidgetToContainingWindow(KDDockWidgets::DockWidgetBase *other,
InitialOption initialOption = {}); KDDockWidgets::Location location,
KDDockWidgets::DockWidgetBase *relativeTo = nullptr,
KDDockWidgets::InitialOption initialOption = {});
/** /**
* @brief sets the widget which this dock widget hosts. * @brief sets the widget which this dock widget hosts.
@@ -164,13 +181,13 @@ public:
* @brief Returns the QAction that allows to hide/show the dock widget * @brief Returns the QAction that allows to hide/show the dock widget
* Useful to put in menus. * Useful to put in menus.
*/ */
QAction *toggleAction() const; Q_INVOKABLE QAction *toggleAction() const;
/** /**
* @brief Returns the QAction that allows to dock/undock the dock widget * @brief Returns the QAction that allows to dock/undock the dock widget
* Useful to put in menus. * Useful to put in menus.
*/ */
QAction *floatAction() const; Q_INVOKABLE QAction *floatAction() const;
/** /**
* @brief the dock widget's unique name. * @brief the dock widget's unique name.
@@ -192,12 +209,28 @@ public:
*/ */
void setTitle(const QString &title); void setTitle(const QString &title);
/**
* @brief Returns the size of the dock widget's parent frame.
*
* This will always be bigger than the DockWidget's size, as there's margins and a title bar.
* Also, a frame can contain more than 1 dock widget (tabbed), meaning the geometry will account
* for the tab bar and title bar.
*
* The position of the rect is in layout coordinates. 0,0 is the top-left of the layout
* holding the widgets.
*/
QRect frameGeometry() const;
/** /**
* @brief Returns the dock widget's options which control behaviour. * @brief Returns the dock widget's options which control behaviour.
* @sa setOptions(), optionsChanged() * @sa setOptions(), optionsChanged()
*/ */
Options options() const; Options options() const;
/// @brief returns the per-dockwidget options which will affect LayoutSaver
/// These are the options which were passed to the constructor
KDDockWidgets::DockWidgetBase::LayoutSaverOptions layoutSaverOptions() const;
/** /**
* @brief Setter for the options. * @brief Setter for the options.
* Only Option_NotClosable is allowed to change after construction. For the other options use * Only Option_NotClosable is allowed to change after construction. For the other options use
@@ -210,7 +243,7 @@ public:
/** /**
* @brief returns if this dock widget is tabbed into another * @brief returns if this dock widget is tabbed into another
* *
* Technically a docked DockWidget always lives in a tab widget, but from the user's prespective * Technically a docked DockWidget always lives in a tab widget, but from the user's perspective
* it's not tabbed when there's only 1 dock widget, as there are no tabs displayed. Unless * it's not tabbed when there's only 1 dock widget, as there are no tabs displayed. Unless
* the frame is using Option_AlwaysShowsTabs, in which case this method will return true regardless * the frame is using Option_AlwaysShowsTabs, in which case this method will return true regardless
* if being the single one. * if being the single one.
@@ -228,7 +261,13 @@ public:
/** /**
* @brief Makes this dock widget current in its tab group. * @brief Makes this dock widget current in its tab group.
*/ */
void setAsCurrentTab(); Q_INVOKABLE void setAsCurrentTab();
/**
* @brief Returns which tab index this dock widget occupies in the tab widget it's contained in
*/
int tabIndex() const;
/** /**
* @brief Sets an icon to show on title bars and tab bars. * @brief Sets an icon to show on title bars and tab bars.
@@ -267,7 +306,7 @@ public:
* @brief Returns whether this dock widget is open. * @brief Returns whether this dock widget is open.
* Equivalent to calling toggleAction().isChecked() or isVisible() * Equivalent to calling toggleAction().isChecked() or isVisible()
*/ */
bool isOpen() const; Q_INVOKABLE bool isOpen() const;
/** /**
* @brief Sets the affinity names. Dock widgets can only dock into dock widgets of the same affinity. * @brief Sets the affinity names. Dock widgets can only dock into dock widgets of the same affinity.
@@ -322,7 +361,7 @@ public:
bool isMainWindow() const; bool isMainWindow() const;
/** /**
* @brief Returns whether this dock widget is docked into a main window. * @brief Returns whether this dock widget is docked into a main window (as opposed to floating)
* *
* Note that isFloating() returning false might either mean the dock widget is docked into a * Note that isFloating() returning false might either mean the dock widget is docked into a
* main window or into a floating window (groupped/nested with other dock widgets. Use this function * main window or into a floating window (groupped/nested with other dock widgets. Use this function
@@ -331,6 +370,7 @@ public:
bool isInMainWindow() const; bool isInMainWindow() const;
/// @brief Returns the main window this dock widget is in. nullptr if it's not inside a main window /// @brief Returns the main window this dock widget is in. nullptr if it's not inside a main window
/// Also returns nullptr if it's minimized to a sidebar
MainWindowBase *mainWindow() const; MainWindowBase *mainWindow() const;
///@brief Returns whether This or any child of this dock widget is focused ///@brief Returns whether This or any child of this dock widget is focused
@@ -348,17 +388,24 @@ public:
* The dockwidget will initially be visible and overlayed on top of the current layout (this is * The dockwidget will initially be visible and overlayed on top of the current layout (this is
* the auto-hide feature). * the auto-hide feature).
*/ */
void moveToSideBar(); Q_INVOKABLE void moveToSideBar();
/// @brief Returns whether this dock widget is overlayed on top of the main window, instead of /// @brief Returns whether this dock widget is overlayed from the side-bar.
/// docked into the layout. This is only relevant when using the auto-hide and side-bar feature. ///
/// This is only relevant when using the auto-hide and side-bar feature.
/// Not to be confused with "floating", which means top-level window.
bool isOverlayed() const; bool isOverlayed() const;
///@brief Returns whether this dock widget is in a side bar, and which. ///@brief Returns whether this dock widget is in a side bar, and which.
/// SideBarLocation::None is returned if it's not in a sidebar. /// SideBarLocation::None is returned if it's not in a sidebar.
/// This is only relevant when using the auto-hide and side-bar feature. /// This is only relevant when using the auto-hide and side-bar feature.
/// @sa isInSideBar
SideBarLocation sideBarLocation() const; SideBarLocation sideBarLocation() const;
/// @brief Returns where this dockwidget is in a sidebar
/// Similar to sideBarLocation(), but returns a bool
bool isInSideBar() const;
/// @brief Returns whether this floating dock widget knows its previous docked location /// @brief Returns whether this floating dock widget knows its previous docked location
/// Result only makes sense if it's floating. /// Result only makes sense if it's floating.
/// ///
@@ -373,7 +420,35 @@ public:
/// @brief Returns a dock widget by its name /// @brief Returns a dock widget by its name
/// This is the same name you passed to DockWidget CTOR. /// This is the same name you passed to DockWidget CTOR.
/// nullptr is returned if the dock widget isn't found. /// nullptr is returned if the dock widget isn't found.
static DockWidgetBase* byName(const QString &uniqueName); static DockWidgetBase *byName(const QString &uniqueName);
/// @brief Returns whether this widget has the LayoutSaverOption::Skip flag
bool skipsRestore() const;
/// @brief If this dock widget is floating, then sets its geometry to @p geo.
///
/// If this dock widget is hidden then it stores the geometry so it can be used the next
/// time it becomes floating.
///
/// This is just convenience, equivalent to calling window()->setGeometry(rect), with the
/// added bonus of remembering the requested geometry in case it's still hidden.
void setFloatingGeometry(QRect geo);
///@brief Allows the user to set a type on this dock widget
///The type is opaque and will not be interpreted by KDDockWidgets.
///This type is passed to FrameWorkWidgetFactory::createTitleBar(), which the user can override
///and return different TitleBar subclasses, depending on the type.
void setUserType(int userType);
int userType() const;
/// @brief Sets this dock widgets position to pos within the MDI layout
/// This only applies if the main window is in MDI mode, which it is not by default
void setMDIPosition(QPoint pos);
/// @brief like setMDIPosition(), but for the size.
void setMDISize(QSize size);
/// @brief like setMDIPosition(), but for the Z
/// only implemented for QtQuick
void setMDIZ(int z);
Q_SIGNALS: Q_SIGNALS:
#ifdef KDDOCKWIDGETS_QTWIDGETS #ifdef KDDOCKWIDGETS_QTWIDGETS
@@ -424,6 +499,12 @@ Q_SIGNALS:
/// have it's 'activeWindow' property updated yet at this point. /// have it's 'activeWindow' property updated yet at this point.
void windowActiveAboutToChange(bool activated); void windowActiveAboutToChange(bool activated);
///@brief Emitted when the title bar that serves this dock widget changes
void actualTitleBarChanged();
/// @brief Emitted when this dock widget is about to be deleted due to Option_DeleteOnClose
void aboutToDeleteOnClose();
protected: protected:
void onParentChanged(); void onParentChanged();
void onShown(bool spontaneous); void onShown(bool spontaneous);
@@ -434,21 +515,6 @@ protected:
bool onResize(QSize newSize) override; bool onResize(QSize newSize) override;
#endif #endif
#if defined(DOCKS_DEVELOPER_MODE)
public Q_SLOTS:
#else
private Q_SLOTS:
#endif
/**
* @brief Creates a FloatingWindow and adds itself into it
* @return the created FloatingWindow
*/
KDDockWidgets::FloatingWindow *morphIntoFloatingWindow();
/// @brief calls morphIntoFloatingWindow() if the dock widget is visible and is a top-level
/// This is called delayed whenever we show a floating dock widget, so we get a FloatingWindow
void maybeMorphIntoFloatingWindow();
#if defined(DOCKS_DEVELOPER_MODE) #if defined(DOCKS_DEVELOPER_MODE)
public: public:
#else #else
@@ -456,6 +522,8 @@ private:
#endif #endif
Q_DISABLE_COPY(DockWidgetBase) Q_DISABLE_COPY(DockWidgetBase)
friend class MultiSplitter; friend class MultiSplitter;
friend class LayoutWidget;
friend class MDILayoutWidget;
friend class Frame; friend class Frame;
friend class DropArea; friend class DropArea;
friend class ::TestDocks; friend class ::TestDocks;
@@ -467,125 +535,22 @@ private:
friend class KDDockWidgets::LayoutSaver; friend class KDDockWidgets::LayoutSaver;
friend class KDDockWidgets::MainWindowBase; friend class KDDockWidgets::MainWindowBase;
friend class KDDockWidgets::FrameQuick; friend class KDDockWidgets::FrameQuick;
friend class KDDockWidgets::DockWidgetQuick;
/** /**
* @brief Constructs a dock widget from its serialized form. * @brief Constructs a dock widget from its serialized form.
* @internal * @internal
*/ */
static DockWidgetBase *deserialize(const LayoutSaver::DockWidget::Ptr &); static DockWidgetBase *deserialize(const std::shared_ptr<LayoutSaver::DockWidget> &);
/**
* @brief Serializes this dock widget into an intermediate form
*/
LayoutSaver::DockWidget::Ptr serialize() const;
/**
* @brief the Frame which contains this dock widgets.
*
* A frame wraps a docked DockWidget, giving it a TabWidget so it can accept other dock widgets.
* Frame is also the actual class that goes into a MultiSplitter.
*
* It's nullptr immediately after creation.
*/
Frame *frame() const;
/**
* @brief returns the FloatingWindow this dock widget is in. If nullptr then it's in a MainWindow.
*
* Note: Being in a FloatingWindow doesn't necessarily mean @ref isFloating() returns true, as
* the dock widget might be in a floating window with other dock widgets side by side.
*/
FloatingWindow *floatingWindow() const;
///@brief adds the current layout item containing this dock widget
void addPlaceholderItem(Layouting::Item*);
///@brief returns the last position, just for tests. TODO Make tests just use the d-pointer.
LastPositions &lastPositions() const;
///@brief If this dock widget is floating, then it saves its geometry
void saveLastFloatingGeometry();
///@brief Updates the floatAction state
void updateFloatAction();
///@reimp
bool eventFilter(QObject *, QEvent *) override;
class Private; class Private;
Private *const d; Private *const d;
Private *dptr() const;
}; };
} }
Q_DECLARE_METATYPE(KDDockWidgets::Location) Q_DECLARE_METATYPE(KDDockWidgets::Location)
#if defined(QT_WIDGETS_LIB)
# include <QAction>
#else
// A QAction for QtQuick. Just so it compiles, for now
class QAction : public QObject
{
Q_OBJECT
public:
using QObject::QObject;
bool isChecked() const {
return m_isChecked ;
}
void setCheckable(bool is) {
m_isCheckable = is;
}
void setText(const QString &text) {
m_text = text;
}
void setToolTip(const QString &text) {
m_toolTip = text;
}
QString toolTip() const {
returm m_toolTip;
}
bool enabled() const {
return m_enabled;
}
void setEnabled(bool enabled) {
m_enabled = enabled;
}
bool checked() const {
return m_checked;
}
void setChecked(bool checked) {
m_checked = checked;
}
bool isEnabled() const {
return m_enabled;
}
void toggle() {
m_enabled = !m_enabled;
Q_EMIT toggled(m_enabled);
}
Q_SIGNALS:
bool toggled(bool);
private:
QString m_text;
QString m_toolTip;
bool m_isChecked = false;
bool m_isCheckable = false;
bool m_enabled = false;
bool m_checked = false;
};
#endif
#endif #endif

View File

@@ -10,6 +10,11 @@
*/ */
#include "DockWidgetQuick.h" #include "DockWidgetQuick.h"
#include "FrameworkWidgetFactory.h"
#include "private/TitleBar_p.h"
#include "private/DockWidgetBase_p.h"
#include "private/quick/FrameQuick_p.h"
#include <Config.h> #include <Config.h>
#include <QQuickItem> #include <QQuickItem>
@@ -27,9 +32,11 @@ using namespace KDDockWidgets;
class DockWidgetQuick::Private class DockWidgetQuick::Private
{ {
public: public:
Private(DockWidgetQuick *dw) Private(DockWidgetQuick *dw, QQmlEngine *qmlengine)
: q(dw) : q(dw)
, m_visualItem(q->createItem(Config::self().qmlEngine(), QStringLiteral("qrc:/kddockwidgets/private/quick/qml/DockWidget.qml"))) , m_visualItem(q->createItem(qmlengine,
Config::self().frameworkWidgetFactory()->dockwidgetFilename().toString()))
, m_qmlEngine(qmlengine)
{ {
Q_ASSERT(m_visualItem); Q_ASSERT(m_visualItem);
m_visualItem->setParent(q); m_visualItem->setParent(q);
@@ -38,11 +45,13 @@ public:
DockWidgetBase *const q; DockWidgetBase *const q;
QQuickItem *const m_visualItem; QQuickItem *const m_visualItem;
QQmlEngine *const m_qmlEngine;
}; };
DockWidgetQuick::DockWidgetQuick(const QString &name, Options options) DockWidgetQuick::DockWidgetQuick(const QString &name, Options options,
: DockWidgetBase(name, options) LayoutSaverOptions layoutSaverOptions, QQmlEngine *engine)
, d(new Private(this)) : DockWidgetBase(name, options, layoutSaverOptions)
, d(new Private(this, engine ? engine : Config::self().qmlEngine()))
{ {
// To mimic what QtWidgets does when creating a new QWidget. // To mimic what QtWidgets does when creating a new QWidget.
setVisible(false); setVisible(false);
@@ -55,15 +64,11 @@ DockWidgetQuick::~DockWidgetQuick()
void DockWidgetQuick::setWidget(const QString &qmlFilename) void DockWidgetQuick::setWidget(const QString &qmlFilename)
{ {
QQuickItem *guest = createItem(Config::self().qmlEngine(), qmlFilename); QQuickItem *guest = createItem(d->m_qmlEngine, qmlFilename);
if (!guest) if (!guest)
return; return;
auto adapter = new QWidgetAdapter(this); setWidget(guest);
guest->setParentItem(adapter);
guest->setParent(adapter);
setWidget(adapter);
} }
void DockWidgetQuick::setWidget(QWidgetAdapter *widget) void DockWidgetQuick::setWidget(QWidgetAdapter *widget)
@@ -73,16 +78,33 @@ void DockWidgetQuick::setWidget(QWidgetAdapter *widget)
DockWidgetBase::setWidget(widget); DockWidgetBase::setWidget(widget);
} }
void DockWidgetQuick::setWidget(QQuickItem *guest)
{
auto adapter = new QWidgetAdapter(this);
adapter->setIsWrapper();
// In case the user app needs to use them:
adapter->setProperty("originalParent", QVariant::fromValue(guest->parent()));
adapter->setProperty("originalParentItem", QVariant::fromValue(guest->parentItem()));
guest->setParentItem(adapter);
guest->setParent(adapter);
QWidgetAdapter::makeItemFillParent(guest);
setWidget(adapter);
}
bool DockWidgetQuick::event(QEvent *e) bool DockWidgetQuick::event(QEvent *e)
{ {
if (e->type() == QEvent::ParentChange) { if (e->type() == QEvent::ParentChange) {
onParentChanged(); onParentChanged();
Q_EMIT actualTitleBarChanged();
} else if (e->type() == QEvent::Show) { } else if (e->type() == QEvent::Show) {
onShown(e->spontaneous()); onShown(e->spontaneous());
} 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) {
onCloseEvent(static_cast<QCloseEvent*>(e)); onCloseEvent(static_cast<QCloseEvent *>(e));
} }
return DockWidgetBase::event(e); return DockWidgetBase::event(e);
@@ -107,3 +129,36 @@ QSize DockWidgetQuick::maximumSize() const
return DockWidgetBase::maximumSize(); return DockWidgetBase::maximumSize();
} }
TitleBar *DockWidgetQuick::actualTitleBar() const
{
if (Frame *frame = DockWidgetBase::d->frame())
return frame->actualTitleBar();
return nullptr;
}
QObject *DockWidgetQuick::actualTitleBarObj() const
{
return actualTitleBar();
}
QQuickItem *DockWidgetQuick::frameVisualItem() const
{
if (auto frame = qobject_cast<FrameQuick *>(DockWidgetBase::d->frame()))
return frame->visualItem();
return nullptr;
}
void DockWidgetQuick::onGeometryUpdated()
{
if (auto frame = qobject_cast<FrameQuick *>(DockWidgetBase::d->frame())) {
frame->updateConstriants();
frame->updateGeometry();
}
}
Frame *DockWidgetQuick::frame() const
{
return qobject_cast<FrameQuick *>(DockWidgetBase::d->frame());
}

View File

@@ -23,10 +23,14 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QCloseEvent; class QCloseEvent;
class QQmlEngine;
QT_END_NAMESPACE QT_END_NAMESPACE
namespace KDDockWidgets { namespace KDDockWidgets {
class Frame;
class TitleBar;
/** /**
* @brief Represents a dock widget. * @brief Represents a dock widget.
* *
@@ -35,17 +39,22 @@ namespace KDDockWidgets {
class DOCKS_EXPORT DockWidgetQuick : public DockWidgetBase class DOCKS_EXPORT DockWidgetQuick : public DockWidgetBase
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(QObject *actualTitleBar READ actualTitleBarObj NOTIFY actualTitleBarChanged)
public: public:
/** /**
* @brief constructs a new DockWidget * @brief constructs a new DockWidget
* @param name the name of the dockwidget, should be unique. Use title for user visible text. * @param uniqueName the name of the dockwidget, should be unique. Use title for user visible text.
* @param options optional options controlling behaviour * @param options optional options controlling behaviour
* @param parent optional QWidget parent, for ownership purposes * @param layoutSaverOptions options regarding LayoutSaver behaviour
* @param engine the QML engine this dock widget will be created on. If not specified then
* Config::self().qmlEngine() will be used
* *
* There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow * There's no parent argument. The DockWidget is either parented to FloatingWindow or MainWindow
* when visible, or stays without a parent when hidden. * when visible, or stays without a parent when hidden.
*/ */
explicit DockWidgetQuick(const QString &uniqueName, Options options = {}); explicit DockWidgetQuick(const QString &uniqueName, Options options = {},
LayoutSaverOptions layoutSaverOptions = LayoutSaverOptions(),
QQmlEngine *engine = nullptr);
///@brief destructor ///@brief destructor
~DockWidgetQuick() override; ~DockWidgetQuick() override;
@@ -57,12 +66,38 @@ public:
/// @reimp /// @reimp
void setWidget(QWidgetAdapter *widget) override; void setWidget(QWidgetAdapter *widget) override;
/// @reimp
Q_INVOKABLE void setWidget(QQuickItem *widget);
/// @reimp /// @reimp
QSize minimumSize() const override; QSize minimumSize() const override;
/// @reimp /// @reimp
QSize maximumSize() const override; QSize maximumSize() const override;
/// @brief Returns the title bar
TitleBar *actualTitleBar() const;
/// @brief Returns the title bar
/// Qt6 requires us to include TitleBar_p.h, so instead the Q_PROPERTY uses
/// QObject so we don't include private headers in public headers
QObject *actualTitleBarObj() const;
/// @brief Returns the visual item which represents Frame in the screen
/// Equivalent to Frame::visualItem().
QQuickItem *frameVisualItem() const;
///@internal
Q_INVOKABLE KDDockWidgets::Frame *frame() const;
/// @brief Called by QtQuick when min-size changes
Q_INVOKABLE void onGeometryUpdated();
Q_SIGNALS:
/// @brief The geometry of the frame container this dock widget is in changed
/// For example, when dragging a dockwidget
void frameGeometryChanged(QRect);
protected: protected:
bool event(QEvent *e) override; bool event(QEvent *e) override;

View File

@@ -17,10 +17,11 @@
*/ */
#include "FocusScope.h" #include "FocusScope.h"
#include "TitleBar_p.h"
#include "Frame_p.h"
#include "DockWidgetBase.h" #include "DockWidgetBase.h"
#include "DockRegistry_p.h"
#include "private/TitleBar_p.h"
#include "private/Frame_p.h"
#include "private/DockRegistry_p.h"
#include <QObject> #include <QObject>
#include <QGuiApplication> #include <QGuiApplication>
@@ -43,12 +44,27 @@ public:
m_inCtor = false; m_inCtor = false;
} }
/// @brief Returns whether the last focused widget is the tab widget itself
bool lastFocusedIsTabWidget() const
{
if (!m_lastFocusedInScope)
return false;
if (auto metaObj = m_lastFocusedInScope->metaObject()) {
const auto className = QLatin1String(metaObj->className());
return className == QLatin1String("KDDockWidgets::TabBarWidget")
|| className == QLatin1String("KDDockWidgets::TabBarQuick");
}
return false;
}
~Private() override; ~Private() override;
void setIsFocused(bool); void setIsFocused(bool);
void onFocusObjectChanged(QObject *); void onFocusObjectChanged(QObject *);
bool isInFocusScope(WidgetType *) const; bool isInFocusScope(WidgetType *) const;
void emitDockWidgetFocusChanged();
FocusScope *const q; FocusScope *const q;
QWidgetAdapter *const m_thisWidget; QWidgetAdapter *const m_thisWidget;
@@ -83,10 +99,13 @@ WidgetType *FocusScope::focusedWidget() const
void FocusScope::focus(Qt::FocusReason reason) void FocusScope::focus(Qt::FocusReason reason)
{ {
if (d->m_lastFocusedInScope) { if (d->m_lastFocusedInScope && !d->lastFocusedIsTabWidget()) {
// When we focus the FocusScope, we give focus to the last focused widget, but let's
// do better than focusing a tab widget. The tab widget itself being focused isn't
// very useful.
d->m_lastFocusedInScope->setFocus(reason); d->m_lastFocusedInScope->setFocus(reason);
} else { } else {
if (auto frame = qobject_cast<Frame*>(d->m_thisWidget)) { if (auto frame = qobject_cast<Frame *>(d->m_thisWidget)) {
if (DockWidgetBase *dw = frame->currentDockWidget()) { if (DockWidgetBase *dw = frame->currentDockWidget()) {
if (auto guest = dw->widget()) { if (auto guest = dw->widget()) {
if (guest->focusPolicy() != Qt::NoFocus) if (guest->focusPolicy() != Qt::NoFocus)
@@ -105,9 +124,6 @@ void FocusScope::Private::setIsFocused(bool is)
if (is != m_isFocused) { if (is != m_isFocused) {
m_isFocused = is; m_isFocused = is;
if (is)
emitDockWidgetFocusChanged();
if (!m_inCtor) // Hack so we don't call pure-virtual if (!m_inCtor) // Hack so we don't call pure-virtual
/* Q_EMIT */ q->isFocusedChangedCallback(); /* Q_EMIT */ q->isFocusedChangedCallback();
} }
@@ -115,14 +131,14 @@ void FocusScope::Private::setIsFocused(bool is)
void FocusScope::Private::onFocusObjectChanged(QObject *obj) void FocusScope::Private::onFocusObjectChanged(QObject *obj)
{ {
auto widget = qobject_cast<WidgetType*>(obj); auto widget = qobject_cast<WidgetType *>(obj);
if (!widget) { if (!widget) {
setIsFocused(false); setIsFocused(false);
return; return;
} }
const bool is = isInFocusScope(widget); const bool is = isInFocusScope(widget);
if (is && m_lastFocusedInScope != widget && !qobject_cast<TitleBar*>(obj)) { if (is && m_lastFocusedInScope != widget && !qobject_cast<TitleBar *>(obj)) {
m_lastFocusedInScope = widget; m_lastFocusedInScope = widget;
setIsFocused(is); setIsFocused(is);
/* Q_EMIT */ q->focusedWidgetChangedCallback(); /* Q_EMIT */ q->focusedWidgetChangedCallback();
@@ -143,33 +159,3 @@ bool FocusScope::Private::isInFocusScope(WidgetType *widget) const
return false; return false;
} }
void FocusScope::Private::emitDockWidgetFocusChanged()
{
auto p = qobject_cast<WidgetType*>(qApp->focusObject());
if (!p) return;
// Find the nearest DockWidget and send the focusChangedSignal
while (p) {
if (auto frame = qobject_cast<Frame*>(p)) {
// Special case: The focused widget is inside the frame but not inside the dockwidget.
// For example, it's a line edit in the QTabBar. We still need to send the signal for
// the current dw in the tab group
if (auto dw = frame->currentDockWidget()) {
DockRegistry::self()->setFocusedDockWidget(dw);
}
break;
}
if (p == m_thisWidget)
break;
if (auto dw = qobject_cast<DockWidgetBase*>(p)) {
DockRegistry::self()->setFocusedDockWidget(dw);
break;
}
p = KDDockWidgets::Private::parentWidget(p);
}
}

View File

@@ -22,8 +22,7 @@
#include "docks_export.h" #include "docks_export.h"
#include "QWidgetAdapter.h" #include "QWidgetAdapter.h"
namespace KDDockWidgets namespace KDDockWidgets {
{
///@brief Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets ///@brief Allows to implement a similar functionality to QtQuick's FocusScope item, in QtWidgets
class DOCKS_EXPORT FocusScope class DOCKS_EXPORT FocusScope
{ {
@@ -41,14 +40,14 @@ public:
///@brief Returns the widget that's focused in this scope ///@brief Returns the widget that's focused in this scope
///The widget itself might not have focus as in QWidget::hasFocus(), but will get actual focus ///The widget itself might not have focus as in QWidget::hasFocus(), but will get actual focus
///as soon as this scope is focused. ///as soon as this scope is focused.
WidgetType* focusedWidget() const; WidgetType *focusedWidget() const;
///@brief Sets focus on this scope. ///@brief Sets focus on this scope.
/// ///
/// This will call QWidget::focus() on the last QWidget that was focused in this scope. /// This will call QWidget::focus() on the last QWidget that was focused in this scope.
void focus(Qt::FocusReason = Qt::OtherFocusReason); void focus(Qt::FocusReason = Qt::OtherFocusReason);
/*Q_SIGNALS:*/ /*Q_SIGNALS:*/
protected: protected:
///@brief reimplement in the 1st QObject derived class ///@brief reimplement in the 1st QObject derived class
virtual void isFocusedChangedCallback() = 0; virtual void isFocusedChangedCallback() = 0;

View File

@@ -10,37 +10,38 @@
*/ */
#include "FrameworkWidgetFactory.h" #include "FrameworkWidgetFactory.h"
#include "Frame_p.h"
#include "TitleBar_p.h"
#include "multisplitter/Separator_p.h"
#include "FloatingWindow_p.h"
#include "Config.h" #include "Config.h"
#include "indicators/ClassicIndicators_p.h"
#include "indicators/NullIndicators_p.h" #include "private/Frame_p.h"
#include "Utils_p.h" #include "private/TitleBar_p.h"
#include "TabWidget_p.h" #include "private/multisplitter/Separator_p.h"
#include "private/FloatingWindow_p.h"
#include "private/indicators/ClassicIndicators_p.h"
#include "private/indicators/NullIndicators_p.h"
#include "private/Utils_p.h"
#include "private/TabWidget_p.h"
#ifdef KDDOCKWIDGETS_QTWIDGETS #ifdef KDDOCKWIDGETS_QTWIDGETS
# include "widgets/FrameWidget_p.h" #include "private/widgets/FrameWidget_p.h"
# include "widgets/TitleBarWidget_p.h" #include "private/widgets/TitleBarWidget_p.h"
# include "widgets/TabBarWidget_p.h" #include "private/widgets/TabBarWidget_p.h"
# include "widgets/SideBarWidget_p.h" #include "private/widgets/SideBarWidget_p.h"
# include "widgets/TabWidgetWidget_p.h" #include "private/widgets/TabWidgetWidget_p.h"
# include "multisplitter/Separator_qwidget.h" #include "private/multisplitter/Separator_qwidget.h"
# include "widgets/FloatingWindowWidget_p.h" #include "private/widgets/FloatingWindowWidget_p.h"
# include "indicators/SegmentedIndicators_p.h" #include "private/indicators/SegmentedIndicators_p.h"
# include <QRubberBand> #include <QRubberBand>
# include <QToolButton> #include <QToolButton>
#else #else
# include "DockWidgetQuick.h" #include "DockWidgetQuick.h"
# include "quick/FrameQuick_p.h" #include "private/quick/FrameQuick_p.h"
# include "quick/TitleBarQuick_p.h" #include "private/quick/TitleBarQuick_p.h"
# include "quick/TabWidgetQuick_p.h" #include "private/quick/TabWidgetQuick_p.h"
# include "quick/TabBarQuick_p.h" #include "private/quick/TabBarQuick_p.h"
# include "quick/FloatingWindowQuick_p.h" #include "private/quick/FloatingWindowQuick_p.h"
# include "quick/RubberBandQuick.h" #include "private/quick/RubberBandQuick.h"
# include "multisplitter/Separator_quick.h" #include "private/multisplitter/Separator_quick.h"
#endif #endif
// clazy:excludeall=ctor-missing-parent-argument // clazy:excludeall=ctor-missing-parent-argument
@@ -86,12 +87,12 @@ Layouting::Separator *DefaultWidgetFactory::createSeparator(Layouting::Widget *p
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(MainWindowBase *parent) const FloatingWindow *DefaultWidgetFactory::createFloatingWindow(MainWindowBase *parent) const
{ {
return new FloatingWindowWidget(parent); return new FloatingWindowWidget(QRect(), parent);
} }
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWindowBase *parent) const FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWindowBase *parent, QRect suggestedGeometry) const
{ {
return new FloatingWindowWidget(frame, parent); return new FloatingWindowWidget(frame, suggestedGeometry, parent);
} }
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
@@ -123,7 +124,7 @@ SideBar *DefaultWidgetFactory::createSideBar(SideBarLocation loc, MainWindowBase
return new SideBarWidget(loc, parent); return new SideBarWidget(loc, parent);
} }
QAbstractButton* DefaultWidgetFactory::createTitleBarButton(QWidget *parent, TitleBarButtonType type) const QAbstractButton *DefaultWidgetFactory::createTitleBarButton(QWidget *parent, TitleBarButtonType type) const
{ {
if (!parent) { if (!parent) {
qWarning() << Q_FUNC_INFO << "Parent not provided"; qWarning() << Q_FUNC_INFO << "Parent not provided";
@@ -163,9 +164,9 @@ FloatingWindow *DefaultWidgetFactory::createFloatingWindow(MainWindowBase *paren
return new FloatingWindowQuick(parent); return new FloatingWindowQuick(parent);
} }
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWindowBase *parent) const FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWindowBase *parent, QRect suggestedGeometry) const
{ {
return new FloatingWindowQuick(frame, parent); return new FloatingWindowQuick(frame, suggestedGeometry, parent);
} }
DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(DropArea *dropArea) const
@@ -217,6 +218,21 @@ QUrl DefaultWidgetFactory::titleBarFilename() const
return QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/TitleBar.qml")); return QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/TitleBar.qml"));
} }
QUrl DefaultWidgetFactory::dockwidgetFilename() const
{
return QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/DockWidget.qml"));
}
QUrl DefaultWidgetFactory::frameFilename() const
{
return QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/Frame.qml"));
}
QUrl DefaultWidgetFactory::floatingWindowFilename() const
{
return QUrl(QStringLiteral("qrc:/kddockwidgets/private/quick/qml/FloatingWindow.qml"));
}
#endif // QtQuick #endif // QtQuick
// iconForButtonType impl is the same for QtQuick and QtWidgets // iconForButtonType impl is the same for QtQuick and QtWidgets
@@ -252,25 +268,15 @@ QIcon DefaultWidgetFactory::iconForButtonType(TitleBarButtonType type, qreal dpr
return {}; return {};
QIcon icon(QStringLiteral(":/img/%1.png").arg(iconName)); QIcon icon(QStringLiteral(":/img/%1.png").arg(iconName));
if (!scalingFactorIsSupported(dpr))
#if QT_VERSION < QT_VERSION_CHECK(5, 15, 2)
const bool isFractional = int(dpr) != dpr;
if (isFractional) {
// We don't support 1.5x yet.
// 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
// Mostly affects Linux. Unless you're using Qt::HighDpiScaleFactorRoundingPolicy::PassThrough, in which case it will
// affect other OSes too.
return icon; return icon;
}
#else
// Not using Qt's sugar syntax, which doesn't support 1.5x anyway when we need it. // 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 // Simply add the high-res files and Qt will pick them when needed
icon.addFile(QStringLiteral(":/img/%1-1.5x.png").arg(iconName)); if (scalingFactorIsSupported(1.5))
Q_UNUSED(dpr); icon.addFile(QStringLiteral(":/img/%1-1.5x.png").arg(iconName));
#endif
icon.addFile(QStringLiteral(":/img/%1-2x.png").arg(iconName)); icon.addFile(QStringLiteral(":/img/%1-2x.png").arg(iconName));
return icon; return icon;

View File

@@ -66,9 +66,6 @@ class TabWidgetQuick;
*/ */
class DOCKS_EXPORT FrameworkWidgetFactory : public QObject class DOCKS_EXPORT FrameworkWidgetFactory : public QObject
{ {
#ifdef KDDOCKWIDGETS_QTQUICK
Q_PROPERTY(QUrl titleBarFilename READ titleBarFilename CONSTANT)
#endif
Q_OBJECT Q_OBJECT
public: public:
FrameworkWidgetFactory() = default; FrameworkWidgetFactory() = default;
@@ -83,35 +80,35 @@ public:
/// DockWidgets. /// DockWidgets.
///@param parent just forward to Frame's constructor ///@param parent just forward to Frame's constructor
///@param options just forward to Frame's constructor ///@param options just forward to Frame's constructor
virtual Frame* createFrame(QWidgetOrQuick *parent = nullptr, FrameOptions options = FrameOption_None) const = 0; virtual Frame *createFrame(QWidgetOrQuick *parent = nullptr, FrameOptions options = FrameOption_None) const = 0;
///@brief Called internally by the framework to create a TitleBar ///@brief Called internally by the framework to create a TitleBar
/// Override to provide your own TitleBar sub-class. If overridden then /// Override to provide your own TitleBar sub-class. If overridden then
/// you also need to override the overload below. /// you also need to override the overload below.
///@param frame Just forward to TitleBar's constructor. ///@param frame Just forward to TitleBar's constructor.
virtual TitleBar* createTitleBar(Frame *frame) const = 0; virtual TitleBar *createTitleBar(Frame *frame) const = 0;
///@brief Called internally by the framework to create a TitleBar ///@brief Called internally by the framework to create a TitleBar
/// Override to provide your own TitleBar sub-class. If overridden then /// Override to provide your own TitleBar sub-class. If overridden then
/// you also need to override the overload above. /// you also need to override the overload above.
///@param floatingWindow Just forward to TitleBar's constructor. ///@param floatingWindow Just forward to TitleBar's constructor.
virtual TitleBar* createTitleBar(FloatingWindow *floatingWindow) const = 0; virtual TitleBar *createTitleBar(FloatingWindow *floatingWindow) const = 0;
///@brief Called internally by the framework to create a TabWidget ///@brief Called internally by the framework to create a TabWidget
/// Override to provide your own TabWidget sub-class. /// Override to provide your own TabWidget sub-class.
///@param parent Just forward to TabWidget's constructor. ///@param parent Just forward to TabWidget's constructor.
virtual TabWidget* createTabWidget(Frame *parent) const = 0; virtual TabWidget *createTabWidget(Frame *parent) const = 0;
///@brief Called internally by the framework to create a TabBar ///@brief Called internally by the framework to create a TabBar
/// Override to provide your own TabBar sub-class. /// Override to provide your own TabBar sub-class.
///@param parent Just forward to TabBar's's constructor. ///@param parent Just forward to TabBar's's constructor.
virtual TabBar* createTabBar(TabWidget *parent = nullptr) const = 0; virtual TabBar *createTabBar(TabWidget *parent = nullptr) const = 0;
///@brief Called internally by the framework to create a Separator ///@brief Called internally by the framework to create a Separator
/// Override to provide your own Separator sub-class. The Separator allows /// Override to provide your own Separator sub-class. The Separator allows
/// the user to resize nested dock widgets. /// the user to resize nested dock widgets.
///@param parent Just forward to Separator's constructor. ///@param parent Just forward to Separator's constructor.
virtual Layouting::Separator* createSeparator(Layouting::Widget *parent = nullptr) const = 0; virtual Layouting::Separator *createSeparator(Layouting::Widget *parent = nullptr) const = 0;
///@brief Called internally by the framework to create a FloatingWindow ///@brief Called internally by the framework to create a FloatingWindow
/// Override to provide your own FloatingWindow sub-class. If overridden then /// Override to provide your own FloatingWindow sub-class. If overridden then
@@ -124,7 +121,7 @@ public:
/// you also need to override the overloads above. /// you also need to override the overloads above.
///@param frame Just forward to FloatingWindow's constructor. ///@param frame Just forward to FloatingWindow's constructor.
///@param parent Just forward to FloatingWindow's constructor. ///@param parent Just forward to FloatingWindow's constructor.
virtual FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr) const = 0; virtual FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr, QRect suggestedGeometry = {}) const = 0;
///@brief Called internally by the framework to create a DropIndicatorOverlayInterface ///@brief Called internally by the framework to create a DropIndicatorOverlayInterface
/// Override to provide your own DropIndicatorOverlayInterface sub-class. /// Override to provide your own DropIndicatorOverlayInterface sub-class.
@@ -143,14 +140,18 @@ public:
#ifdef KDDOCKWIDGETS_QTWIDGETS #ifdef KDDOCKWIDGETS_QTWIDGETS
///@brief Called internally by the framework to create a title bar button ///@brief Called internally by the framework to create a title bar button
///@p parent the button's parent ///@p parent the button's parent
virtual QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const = 0; virtual QAbstractButton *createTitleBarButton(QWidget *parent, TitleBarButtonType) const = 0;
#else #else
virtual QUrl titleBarFilename() const = 0; virtual QUrl titleBarFilename() const = 0;
virtual QUrl dockwidgetFilename() const = 0;
virtual QUrl frameFilename() const = 0;
virtual QUrl floatingWindowFilename() const = 0;
#endif #endif
/// @brief Returns the icon to be used with the specified @p type /// @brief Returns the icon to be used with the specified @p type
/// @param dpr the device pixel ratio of the button /// @param dpr the device pixel ratio of the button
virtual QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const = 0; virtual QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const = 0;
private: private:
Q_DISABLE_COPY(FrameworkWidgetFactory) Q_DISABLE_COPY(FrameworkWidgetFactory)
}; };
@@ -170,20 +171,24 @@ public:
TabBar *createTabBar(TabWidget *parent) const override; TabBar *createTabBar(TabWidget *parent) const override;
Layouting::Separator *createSeparator(Layouting::Widget *parent = nullptr) const override; Layouting::Separator *createSeparator(Layouting::Widget *parent = nullptr) const override;
FloatingWindow *createFloatingWindow(MainWindowBase *parent = nullptr) const override; FloatingWindow *createFloatingWindow(MainWindowBase *parent = nullptr) const override;
FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr) const override; FloatingWindow *createFloatingWindow(Frame *frame, MainWindowBase *parent = nullptr, QRect suggestedGeometry = {}) 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; SideBar *createSideBar(SideBarLocation loc, MainWindowBase *parent) const override;
#ifdef KDDOCKWIDGETS_QTWIDGETS #ifdef KDDOCKWIDGETS_QTWIDGETS
QAbstractButton* createTitleBarButton(QWidget *parent, TitleBarButtonType) const override; QAbstractButton *createTitleBarButton(QWidget *parent, TitleBarButtonType) const override;
#else #else
QUrl titleBarFilename() const override; Q_INVOKABLE QUrl titleBarFilename() const override;
QUrl dockwidgetFilename() const override;
QUrl frameFilename() const override;
QUrl floatingWindowFilename() const override;
#endif #endif
QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const override; QIcon iconForButtonType(TitleBarButtonType type, qreal dpr) const override;
static DropIndicatorType s_dropIndicatorType; static DropIndicatorType s_dropIndicatorType;
private: private:
Q_DISABLE_COPY(DefaultWidgetFactory) Q_DISABLE_COPY(DefaultWidgetFactory)
}; };

View File

@@ -19,6 +19,7 @@
#ifndef KD_KDDOCKWIDGETS_H #ifndef KD_KDDOCKWIDGETS_H
#define KD_KDDOCKWIDGETS_H #define KD_KDDOCKWIDGETS_H
#include "docks_export.h"
#include "Qt5Qt6Compat_p.h" #include "Qt5Qt6Compat_p.h"
#include <QObject> #include <QObject>
@@ -26,7 +27,7 @@
#ifdef Q_OS_WIN #ifdef Q_OS_WIN
// Only on Windows, where this is popular. On linux the Qt::Tool windows need reparenting. Untested on macOS. // Only on Windows, where this is popular. On linux the Qt::Tool windows need reparenting. Untested on macOS.
# define KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS #define KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
#endif #endif
namespace Layouting { namespace Layouting {
@@ -34,104 +35,124 @@ class Item;
class ItemBoxContainer; class ItemBoxContainer;
} }
namespace KDDockWidgets namespace KDDockWidgets {
DOCKS_EXPORT
Q_NAMESPACE
class MultiSplitter;
class DropArea;
enum Location
{ {
class MultiSplitter; Location_None,
class DropArea; Location_OnLeft, ///> Left docking location
Location_OnTop, ///> Top docking location
Location_OnRight, ///> Right docking location
Location_OnBottom ///> Bottom docking location
};
Q_ENUM_NS(Location)
enum Location { enum MainWindowOption
Location_None, {
Location_OnLeft, ///> Left docking location MainWindowOption_None = 0, ///> No option set
Location_OnTop, ///> Top docking location MainWindowOption_HasCentralFrame = 1, ///> Makes the MainWindow always have a central frame, for tabbing documents
Location_OnRight, ///> Right docking location MainWindowOption_MDI = 2 ///> EXPERIMENTAL!!1 The layout will be MDI. DockWidgets can have arbitrary positions, not restricted by any layout
Location_OnBottom ///> Bottom docking location };
}; Q_DECLARE_FLAGS(MainWindowOptions, MainWindowOption)
Q_ENUM_NS(MainWindowOptions)
enum MainWindowOption { ///@internal
MainWindowOption_None = 0, ///> No option set ///@brief Describes some sizing strategies for the layouting engine.
MainWindowOption_HasCentralFrame = 1 ///> Makes the MainWindow always have a central frame, for tabbing documents ///This is internal. The public API for dealing with sizing is InitialOption.
}; ///@sa InitialOption
Q_DECLARE_FLAGS(MainWindowOptions, MainWindowOption) enum class DefaultSizeMode
{
ItemSize, ///< Simply uses the Item::size() of the item being added. Actual used size might be smaller if our window isn't big enough.
Fair, ///< Gives an equal relative size as the items that are already in the layout
FairButFloor, ///< Equal to fair, but if the item we're adding is smaller than the fair suggestion, then that small size is used.
NoDefaultSizeMode, ///< Don't do any sizing
};
Q_ENUM_NS(DefaultSizeMode)
///@internal ///@brief Only here for source-compat with v1.2. Do not use.
///@brief Describes some sizing strategies for the layouting engine. ///Use InitialVisibilityOption instead.
///This is internal. The public API for dealing with sizing is InitialOption. enum AddingOption
///@sa InitialOption {
enum class DefaultSizeMode { AddingOption_None = 0,
ItemSize, ///< Simply uses the Item::size() of the item being added. Actual used size might be smaller if our window isn't big enough. AddingOption_StartHidden
Fair, ///< Gives an equal relative size as the items that are already in the layout };
FairButFloor, ///< Equal to fair, but if the item we're adding is smaller than the fair suggestion, then that small size is used. Q_ENUM_NS(AddingOption)
None, ///< Don't do any sizing
};
///@brief Only here for source-compat with v1.2. Do not use. enum class InitialVisibilityOption
///Use InitialVisibilityOption instead. {
enum AddingOption { StartVisible = 0, ///< The dock widget is made visible when docked
AddingOption_None = 0, StartHidden ///< Don't show the dock widget when adding it
AddingOption_StartHidden };
}; Q_ENUM_NS(InitialVisibilityOption)
enum class InitialVisibilityOption { /**
StartVisible = 0, ///< The dock widget is made visible when docked
StartHidden ///< Don't show the dock widget when adding it
};
/**
* @brief Struct describing the preferred dock widget size and visibility when adding it to a layout * @brief Struct describing the preferred dock widget size and visibility when adding it to a layout
* *
* You can pass this to MainWindowBase::addDockWidget() to give an hint of your preferred size * You can pass this to MainWindowBase::addDockWidget() to give an hint of your preferred size
* and visibility. * and visibility.
* *
* See bellow the documentation for InitialOption::visibility and InitialOption::preferredSize. * See below the documentation for InitialOption::visibility and InitialOption::preferredSize.
* *
* @sa MainWindowBase::addDockWidget() * @sa MainWindowBase::addDockWidget()
*/ */
struct InitialOption struct InitialOption
{
// Implicit ctors for convenience:
InitialOption() = default;
InitialOption(InitialVisibilityOption v)
: visibility(v)
{ {
// Implicit ctors for convenience: }
InitialOption() = default; InitialOption(QSize size)
: preferredSize(size)
{
}
InitialOption(InitialVisibilityOption v) InitialOption(InitialVisibilityOption v, QSize size)
: visibility(v) {} : visibility(v)
, preferredSize(size)
{
}
InitialOption(QSize size) QT_DEPRECATED_X("AddingOption is deprecated and will be removed in v1.5. Use InitialVisibilityOption instead.")
: preferredSize(size) {} InitialOption(AddingOption opt)
: visibility(opt == AddingOption_StartHidden ? InitialVisibilityOption::StartHidden
: InitialVisibilityOption::StartVisible)
{
}
InitialOption(InitialVisibilityOption v, QSize size) bool startsHidden() const
: visibility(v) {
, preferredSize(size) return visibility == InitialVisibilityOption::StartHidden;
{} }
QT_DEPRECATED_X("AddingOption is deprecated and will be removed in v1.5. Use InitialVisibilityOption instead.") int preferredLength(Qt::Orientation o) const
InitialOption(AddingOption opt) {
: visibility(opt == AddingOption_StartHidden ? InitialVisibilityOption::StartHidden return o == Qt::Horizontal ? preferredSize.width()
: InitialVisibilityOption::StartVisible) : preferredSize.height();
{ }
}
bool startsHidden() const { bool hasPreferredLength(Qt::Orientation o) const
return visibility == InitialVisibilityOption::StartHidden; {
} return preferredLength(o) > 0;
}
int preferredLength(Qt::Orientation o) const { /**
return o == Qt::Horizontal ? preferredSize.width()
: preferredSize.height();
}
bool hasPreferredLength(Qt::Orientation o) const {
return preferredLength(o) > 0;
}
/**
* @brief Allows a dock widget to be docked as hidden. * @brief Allows a dock widget to be docked as hidden.
* *
* Next time you call DockWidget::show() it will be shown at that place. This avoids * Next time you call DockWidget::show() it will be shown at that place. This avoids
* flickering, as no show()/hide() workarounds are needed. * flickering, as no show()/hide() workarounds are needed.
*/ */
const InitialVisibilityOption visibility = InitialVisibilityOption::StartVisible; InitialVisibilityOption visibility = InitialVisibilityOption::StartVisible;
/** /**
* @brief Allows to control the size a dock widget should get when docked. * @brief Allows to control the size a dock widget should get when docked.
* *
* If an invalid or empty size is passed then KDDW's default heuristics are applied. * If an invalid or empty size is passed then KDDW's default heuristics are applied.
@@ -140,86 +161,126 @@ namespace KDDockWidgets
* dock widget to the left then only the preferred width will be taken into account, as the * dock widget to the left then only the preferred width will be taken into account, as the
* height will simply fill the whole layout. * height will simply fill the whole layout.
*/ */
const QSize preferredSize; QSize preferredSize;
private: private:
friend class Layouting::Item; friend class Layouting::Item;
friend class Layouting::ItemBoxContainer; friend class Layouting::ItemBoxContainer;
friend class KDDockWidgets::MultiSplitter; friend class KDDockWidgets::MultiSplitter;
friend class KDDockWidgets::DropArea; friend class KDDockWidgets::DropArea;
InitialOption(DefaultSizeMode mode) InitialOption(DefaultSizeMode mode)
: sizeMode(mode) {} : sizeMode(mode)
const DefaultSizeMode sizeMode = DefaultSizeMode::Fair;
};
///@internal
enum FrameOption {
FrameOption_None = 0,
FrameOption_AlwaysShowsTabs = 1,
FrameOption_IsCentralFrame = 2,
FrameOption_IsOverlayed = 4
};
Q_DECLARE_FLAGS(FrameOptions, FrameOption)
enum RestoreOption {
RestoreOption_None = 0,
RestoreOption_RelativeToMainWindow = 1, ///< Skips restoring the main window geometry and the restored dock widgets will use relative sizing.
///< Loading layouts won't change the main window geometry and just use whatever the user has at the moment.
};
Q_DECLARE_FLAGS(RestoreOptions, RestoreOption)
enum class DropIndicatorType {
Classic, ///< The default
Segmented, ///< Segmented indicators
None ///< Don't show any drop indicators while dragging
};
///@internal
inline QString locationStr(Location loc)
{ {
switch (loc) {
case KDDockWidgets::Location_None:
return QStringLiteral("none");
case KDDockWidgets::Location_OnLeft:
return QStringLiteral("left");
case KDDockWidgets::Location_OnTop:
return QStringLiteral("top");
case KDDockWidgets::Location_OnRight:
return QStringLiteral("right");
case KDDockWidgets::Location_OnBottom:
return QStringLiteral("bottom");
}
return QString();
} }
/// @brief Each main window supports 4 sidebars DefaultSizeMode sizeMode = DefaultSizeMode::Fair;
enum class SideBarLocation { };
None,
North,
East,
West,
South
};
///@brief describes a type of button you can have in the title bar enum RestoreOption
enum class TitleBarButtonType { {
Close, RestoreOption_None = 0,
Float, RestoreOption_RelativeToMainWindow = 1, ///< Skips restoring the main window geometry and the restored dock widgets will use relative sizing.
Minimize, ///< Loading layouts won't change the main window geometry and just use whatever the user has at the moment.
Maximize, };
Normal, // Restore from maximized state Q_DECLARE_FLAGS(RestoreOptions, RestoreOption)
AutoHide, Q_ENUM_NS(RestoreOptions)
UnautoHide
};
///@internal enum class DropIndicatorType
inline Qt5Qt6Compat::qhashtype qHash(SideBarLocation loc, Qt5Qt6Compat::qhashtype seed) {
{ Classic, ///< The default
return ::qHash(static_cast<uint>(loc), seed); Segmented, ///< Segmented indicators
None ///< Don't show any drop indicators while dragging
};
Q_ENUM_NS(DropIndicatorType)
///@internal
enum SuggestedGeometryHint
{
SuggestedGeometryHint_None,
SuggestedGeometryHint_PreserveCenter = 1,
SuggestedGeometryHint_GeometryIsFromDocked = 2
};
Q_DECLARE_FLAGS(SuggestedGeometryHints, SuggestedGeometryHint)
Q_ENUM_NS(SuggestedGeometryHint)
/// @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
};
Q_ENUM_NS(TitleBarButtonType)
///@internal
inline Qt5Qt6Compat::qhashtype qHash(SideBarLocation loc, Qt5Qt6Compat::qhashtype seed)
{
return ::qHash(static_cast<uint>(loc), seed);
}
///@internal
enum CursorPosition
{
CursorPosition_Undefined = 0,
CursorPosition_Left = 1,
CursorPosition_Right = 2,
CursorPosition_Top = 4,
CursorPosition_Bottom = 8,
CursorPosition_TopLeft = CursorPosition_Top | CursorPosition_Left,
CursorPosition_TopRight = CursorPosition_Top | CursorPosition_Right,
CursorPosition_BottomRight = CursorPosition_Bottom | CursorPosition_Right,
CursorPosition_BottomLeft = CursorPosition_Bottom | CursorPosition_Left,
CursorPosition_Horizontal = CursorPosition_Right | CursorPosition_Left,
CursorPosition_Vertical = CursorPosition_Top | CursorPosition_Bottom,
CursorPosition_All = CursorPosition_Left | CursorPosition_Right | CursorPosition_Top | CursorPosition_Bottom
};
Q_DECLARE_FLAGS(CursorPositions, CursorPosition)
Q_ENUM_NS(CursorPosition)
///@internal
enum FrameOption
{
FrameOption_None = 0,
FrameOption_AlwaysShowsTabs = 1,
FrameOption_IsCentralFrame = 2,
FrameOption_IsOverlayed = 4
};
Q_DECLARE_FLAGS(FrameOptions, FrameOption)
Q_ENUM_NS(FrameOptions)
///@internal
inline QString locationStr(Location loc)
{
switch (loc) {
case KDDockWidgets::Location_None:
return QStringLiteral("none");
case KDDockWidgets::Location_OnLeft:
return QStringLiteral("left");
case KDDockWidgets::Location_OnTop:
return QStringLiteral("top");
case KDDockWidgets::Location_OnRight:
return QStringLiteral("right");
case KDDockWidgets::Location_OnBottom:
return QStringLiteral("bottom");
} }
return QString();
}
} }
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@@ -16,7 +16,7 @@ if (@KDDockWidgets_QTQUICK@)
find_dependency(Qt5Quick REQUIRED) find_dependency(Qt5Quick REQUIRED)
endif() endif()
if (NOT WIN32 AND NOT APPLE) if (NOT WIN32 AND NOT APPLE AND NOT EMSCRIPTEN)
find_dependency(Qt5X11Extras REQUIRED) find_dependency(Qt5X11Extras REQUIRED)
endif() endif()

View File

@@ -17,74 +17,65 @@
*/ */
#include "LayoutSaver.h" #include "LayoutSaver.h"
#include "LayoutSaver_p.h"
#include "Config.h" #include "Config.h"
#include "DockRegistry_p.h"
#include "DockWidgetBase.h"
#include "DropArea_p.h"
#include "Logging_p.h"
#include "Frame_p.h"
#include "Position_p.h"
#include "FrameworkWidgetFactory.h"
#include "MainWindowBase.h" #include "MainWindowBase.h"
#include "FloatingWindow_p.h" #include "DockWidgetBase.h"
#include "FrameworkWidgetFactory.h"
#include "private/LayoutSaver_p.h"
#include "private/DockRegistry_p.h"
#include "private/DockWidgetBase_p.h"
#include "private/FloatingWindow_p.h"
#include "private/Frame_p.h"
#include "private/LayoutWidget_p.h"
#include "private/Logging_p.h"
#include "private/Position_p.h"
#include <qmath.h> #include <qmath.h>
#include <QDebug> #include <QDebug>
#include <QSettings>
#include <QFile> #include <QFile>
#include <memory> /**
* Some implementation details:
*
* Restoring is done in two phases. From the JSON, we construct an intermediate representation,
* which doesn't have any GUI types. Finally we then construct the GUI from the intermediate
* representation.
*
* JSON <-> Intermediate rep (bunch non-gui structs) <-> GUI classes
*
* This is in contrast to many other dock widget frameworks which just do:
* serialized <-> GUI
*
* The advantage of having the intermediate structs is that we can do validations on them and if
* we find some corruption we don't even start messing with the GUI.
*
* See the LayoutSaver::* structs in LayoutSaver_p.h, those are the intermediate structs.
* They have methods to convert to/from JSON.
* All other gui classes have methods to convert to/from these structs. For example
* FloatingWindow::serialize()/deserialize()
*/
using namespace KDDockWidgets; using namespace KDDockWidgets;
QHash<QString, LayoutSaver::DockWidget::Ptr> LayoutSaver::DockWidget::s_dockWidgets; QHash<QString, LayoutSaver::DockWidget::Ptr> LayoutSaver::DockWidget::s_dockWidgets;
LayoutSaver::Layout* LayoutSaver::Layout::s_currentLayoutBeingRestored = nullptr; LayoutSaver::Layout *LayoutSaver::Layout::s_currentLayoutBeingRestored = nullptr;
class KDDockWidgets::LayoutSaver::Private
inline InternalRestoreOptions internalRestoreOptions(RestoreOptions options)
{ {
public: if (options == RestoreOption_None) {
return InternalRestoreOption::None;
struct RAIIIsRestoring } else if (options == RestoreOption_RelativeToMainWindow) {
{ return InternalRestoreOptions(InternalRestoreOption::SkipMainWindowGeometry)
RAIIIsRestoring() | InternalRestoreOption::RelativeFloatingWindowGeometry;
{ } else {
LayoutSaver::Private::s_restoreInProgress = true; qWarning() << Q_FUNC_INFO << "Unknown options" << options;
} return {};
~RAIIIsRestoring()
{
LayoutSaver::Private::s_restoreInProgress = false;
}
Q_DISABLE_COPY(RAIIIsRestoring)
};
Private(RestoreOptions options)
: m_dockRegistry(DockRegistry::self())
, m_restoreOptions(options)
{
} }
}
bool matchesAffinity(const QStringList &affinities) const {
return m_affinityNames.isEmpty() || affinities.isEmpty() || DockRegistry::self()->affinitiesMatch(m_affinityNames, affinities);
}
template <typename T>
void deserializeWindowGeometry(const T &saved, QWidgetOrQuick *topLevel);
void deleteEmptyFrames();
void clearRestoredProperty();
std::unique_ptr<QSettings> settings() const;
DockRegistry *const m_dockRegistry;
const RestoreOptions m_restoreOptions;
QStringList m_affinityNames;
static bool s_restoreInProgress;
};
bool LayoutSaver::Private::s_restoreInProgress = false; bool LayoutSaver::Private::s_restoreInProgress = false;
static QVariantList stringListToVariant(const QStringList &strs) static QVariantList stringListToVariant(const QStringList &strs)
{ {
QVariantList variantList; QVariantList variantList;
@@ -162,7 +153,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->floatingWindows(); 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()))
@@ -174,7 +165,7 @@ QByteArray LayoutSaver::serializeLayout() const
layout.closedDockWidgets.reserve(closedDockWidgets.size()); layout.closedDockWidgets.reserve(closedDockWidgets.size());
for (DockWidgetBase *dockWidget : closedDockWidgets) { for (DockWidgetBase *dockWidget : closedDockWidgets) {
if (d->matchesAffinity(dockWidget->affinities())) if (d->matchesAffinity(dockWidget->affinities()))
layout.closedDockWidgets.push_back(dockWidget->serialize()); layout.closedDockWidgets.push_back(dockWidget->d->serialize());
} }
// Save the placeholder info. We do it last, as we also restore it last, since we need all items to be created // Save the placeholder info. We do it last, as we also restore it last, since we need all items to be created
@@ -184,8 +175,8 @@ QByteArray LayoutSaver::serializeLayout() const
layout.allDockWidgets.reserve(dockWidgets.size()); layout.allDockWidgets.reserve(dockWidgets.size());
for (DockWidgetBase *dockWidget : dockWidgets) { for (DockWidgetBase *dockWidget : dockWidgets) {
if (d->matchesAffinity(dockWidget->affinities())) { if (d->matchesAffinity(dockWidget->affinities())) {
auto dw = dockWidget->serialize(); auto dw = dockWidget->d->serialize();
dw->lastPosition = dockWidget->lastPositions().serialize(); dw->lastPosition = dockWidget->d->lastPositions().serialize();
layout.allDockWidgets.push_back(dw); layout.allDockWidgets.push_back(dw);
} }
} }
@@ -199,9 +190,8 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
if (data.isEmpty()) if (data.isEmpty())
return true; return true;
Private::RAIIIsRestoring isRestoring; struct FrameCleanup
{
struct FrameCleanup {
FrameCleanup(LayoutSaver *saver) FrameCleanup(LayoutSaver *saver)
: m_saver(saver) : m_saver(saver)
{ {
@@ -226,19 +216,23 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
return false; return false;
} }
if (d->m_restoreOptions & RestoreOption_RelativeToMainWindow) layout.scaleSizes(d->m_restoreOptions);
layout.scaleSizes();
d->floatWidgetsWhichSkipRestore(layout.mainWindowNames());
Private::RAIIIsRestoring isRestoring;
// Hide all dockwidgets and unparent them from any layout before starting restore // Hide all dockwidgets and unparent them from any layout before starting restore
// We only close the stuff that the loaded JSON knows about. Unknown widgets might be newer. // We only close the stuff that the loaded JSON knows about. Unknown widgets might be newer.
d->m_dockRegistry->clear(d->m_dockRegistry->dockWidgets(layout.dockWidgetNames()),
d->m_dockRegistry->clear(d->m_dockRegistry->dockWidgets(layout.dockWidgetsToClose()),
d->m_dockRegistry->mainWindows(layout.mainWindowNames()), d->m_dockRegistry->mainWindows(layout.mainWindowNames()),
d->m_affinityNames); d->m_affinityNames);
// 1. Restore main windows // 1. Restore main windows
for (const LayoutSaver::MainWindow &mw : qAsConst(layout.mainWindows)) { for (const LayoutSaver::MainWindow &mw : qAsConst(layout.mainWindows)) {
MainWindowBase *mainWindow = d->m_dockRegistry->mainWindowByName(mw.uniqueName); MainWindowBase *mainWindow = d->m_dockRegistry->mainWindowByName(mw.uniqueName);
if (!mainWindow ) { if (!mainWindow) {
if (auto mwFunc = Config::self().mainWindowFactoryFunc()) { if (auto mwFunc = Config::self().mainWindowFactoryFunc()) {
mainWindow = mwFunc(mw.uniqueName); mainWindow = mwFunc(mw.uniqueName);
} else { } else {
@@ -250,22 +244,29 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
if (!d->matchesAffinity(mainWindow->affinities())) if (!d->matchesAffinity(mainWindow->affinities()))
continue; continue;
if (!(d->m_restoreOptions & RestoreOption_RelativeToMainWindow)) if (!(d->m_restoreOptions & InternalRestoreOption::SkipMainWindowGeometry)) {
d->deserializeWindowGeometry(mw, mainWindow->window()); // window(), as the MainWindow can be embedded d->deserializeWindowGeometry(mw, mainWindow->window()); // window(), as the MainWindow can be embedded
if (mw.windowState != Qt::WindowNoState) {
if (auto w = mainWindow->windowHandle()) {
w->setWindowState(mw.windowState);
}
}
}
if (!mainWindow->deserialize(mw)) if (!mainWindow->deserialize(mw))
return false; return false;
} }
// 2. Restore FloatingWindows // 2. Restore FloatingWindows
for (const LayoutSaver::FloatingWindow &fw : qAsConst(layout.floatingWindows)) { for (LayoutSaver::FloatingWindow &fw : layout.floatingWindows) {
if (!d->matchesAffinity(fw.affinities)) if (!d->matchesAffinity(fw.affinities) || fw.skipsRestore())
continue; continue;
MainWindowBase *parent = fw.parentIndex == -1 ? nullptr MainWindowBase *parent = fw.parentIndex == -1 ? nullptr
: DockRegistry::self()->mainwindows().at(fw.parentIndex); : DockRegistry::self()->mainwindows().at(fw.parentIndex);
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(parent); auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(parent);
fw.floatingWindowInstance = floatingWindow;
d->deserializeWindowGeometry(fw, floatingWindow); d->deserializeWindowGeometry(fw, floatingWindow);
if (!floatingWindow->deserialize(fw)) { if (!floatingWindow->deserialize(fw)) {
qWarning() << Q_FUNC_INFO << "Failed to deserialize floating window"; qWarning() << Q_FUNC_INFO << "Failed to deserialize floating window";
@@ -285,8 +286,9 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
if (!d->matchesAffinity(dw->affinities)) if (!d->matchesAffinity(dw->affinities))
continue; continue;
if (DockWidgetBase *dockWidget = d->m_dockRegistry->dockByName(dw->uniqueName)) { if (DockWidgetBase *dockWidget =
dockWidget->lastPositions().deserialize(dw->lastPosition); d->m_dockRegistry->dockByName(dw->uniqueName, DockRegistry::DockByNameFlag::ConsultRemapping)) {
dockWidget->d->lastPositions().deserialize(dw->lastPosition);
} else { } else {
qWarning() << Q_FUNC_INFO << "Couldn't find dock widget" << dw->uniqueName; qWarning() << Q_FUNC_INFO << "Couldn't find dock widget" << dw->uniqueName;
} }
@@ -304,6 +306,11 @@ void LayoutSaver::setAffinityNames(const QStringList &affinityNames)
} }
} }
LayoutSaver::Private *LayoutSaver::dptr() const
{
return d;
}
DockWidgetBase::List LayoutSaver::restoredDockWidgets() const DockWidgetBase::List LayoutSaver::restoredDockWidgets() const
{ {
const DockWidgetBase::List &allDockWidgets = DockRegistry::self()->dockwidgets(); const DockWidgetBase::List &allDockWidgets = DockRegistry::self()->dockwidgets();
@@ -325,13 +332,50 @@ void LayoutSaver::Private::clearRestoredProperty()
} }
} }
template <typename T> template<typename T>
void LayoutSaver::Private::deserializeWindowGeometry(const T &saved, QWidgetOrQuick *topLevel) void LayoutSaver::Private::deserializeWindowGeometry(const T &saved, QWidgetOrQuick *topLevel)
{ {
topLevel->setGeometry(saved.geometry); // Not simply calling QWidget::setGeometry() here.
// For QtQuick we need to modify the QWindow's geometry.
if (topLevel->isWindow()) {
topLevel->setGeometry(saved.geometry);
} else {
KDDockWidgets::Private::setTopLevelGeometry(saved.geometry, topLevel);
}
topLevel->setVisible(saved.isVisible); topLevel->setVisible(saved.isVisible);
} }
LayoutSaver::Private::Private(RestoreOptions options)
: m_dockRegistry(DockRegistry::self())
, m_restoreOptions(internalRestoreOptions(options))
{
}
bool LayoutSaver::Private::matchesAffinity(const QStringList &affinities) const
{
return m_affinityNames.isEmpty() || affinities.isEmpty()
|| DockRegistry::self()->affinitiesMatch(m_affinityNames, affinities);
}
void LayoutSaver::Private::floatWidgetsWhichSkipRestore(const QStringList &mainWindowNames)
{
// Widgets with the DockWidget::LayoutSaverOption::Skip flag skip restore completely.
// If they were visible before they need to remain visible now.
// If they were previously docked we need to float them, as the main window they were on will
// be loading a new layout.
for (MainWindowBase *mw : DockRegistry::self()->mainWindows(mainWindowNames)) {
const KDDockWidgets::DockWidgetBase::List docks = mw->layoutWidget()->dockWidgets();
for (auto dw : docks) {
if (dw->skipsRestore()) {
dw->setFloating(true);
}
}
}
}
void LayoutSaver::Private::deleteEmptyFrames() void LayoutSaver::Private::deleteEmptyFrames()
{ {
// After a restore it can happen that some DockWidgets didn't exist, so weren't restored. // After a restore it can happen that some DockWidgets didn't exist, so weren't restored.
@@ -393,7 +437,7 @@ bool LayoutSaver::Layout::fromJson(const QByteArray &jsonData)
{ {
QJsonParseError error; QJsonParseError error;
QJsonDocument doc = QJsonDocument::fromJson(jsonData, &error); QJsonDocument doc = QJsonDocument::fromJson(jsonData, &error);
if (error.error == QJsonParseError::NoError) { if (error.error == QJsonParseError::NoError) {
fromVariantMap(doc.toVariant().toMap()); fromVariantMap(doc.toVariant().toMap());
return true; return true;
} }
@@ -439,25 +483,44 @@ void LayoutSaver::Layout::fromVariantMap(const QVariantMap &map)
screenInfo = fromVariantList<LayoutSaver::ScreenInfo>(map.value(QStringLiteral("screenInfo")).toList()); screenInfo = fromVariantList<LayoutSaver::ScreenInfo>(map.value(QStringLiteral("screenInfo")).toList());
} }
void LayoutSaver::Layout::scaleSizes() void LayoutSaver::Layout::scaleSizes(InternalRestoreOptions options)
{ {
if (mainWindows.isEmpty()) if (mainWindows.isEmpty())
return; return;
const bool skipsMainWindowGeometry = options & InternalRestoreOption::SkipMainWindowGeometry;
if (!skipsMainWindowGeometry) {
// No scaling to do. All windows will be restored with the exact size specified in the
// saved JSON layouts.
return;
}
// We won't restore MainWindow's geometry, we use whatever the user has now, meaning
// we need to scale all dock widgets inside the layout, as the layout might not have
// the same size as specified in the saved JSON layout
for (auto &mw : mainWindows) for (auto &mw : mainWindows)
mw.scaleSizes(); mw.scaleSizes();
for (auto &fw : floatingWindows) {
LayoutSaver::MainWindow mw = mainWindowForIndex(fw.parentIndex); // MainWindow has a different size than the one in JSON, so we also restore FloatingWindows
if (mw.scalingInfo.isValid()) // relatively to the user set new MainWindow size
fw.scaleSizes(mw.scalingInfo); const bool useRelativeSizesForFloatingWidgets =
options & InternalRestoreOption::RelativeFloatingWindowGeometry;
if (useRelativeSizesForFloatingWidgets) {
for (auto &fw : floatingWindows) {
LayoutSaver::MainWindow mw = mainWindowForIndex(fw.parentIndex);
if (mw.scalingInfo.isValid())
fw.scaleSizes(mw.scalingInfo);
}
} }
const ScalingInfo firstScalingInfo = mainWindows.constFirst().scalingInfo; const ScalingInfo firstScalingInfo = mainWindows.constFirst().scalingInfo;
if (firstScalingInfo.isValid()) { if (firstScalingInfo.isValid()) {
for (auto &dw : allDockWidgets) { for (auto &dw : allDockWidgets) {
// TODO: Determine the best main window. This only interesting for closed dock widget geometry // TODO: Determine the best main window. This only interesting for closed dock
// which was previously floating. But they still have some other main window as parent. // widget geometry which was previously floating. But they still have some other
// main window as parent.
dw->scaleSizes(firstScalingInfo); dw->scaleSizes(firstScalingInfo);
} }
} }
@@ -471,6 +534,14 @@ LayoutSaver::MainWindow LayoutSaver::Layout::mainWindowForIndex(int index) const
return mainWindows.at(index); return mainWindows.at(index);
} }
LayoutSaver::FloatingWindow LayoutSaver::Layout::floatingWindowForIndex(int index) const
{
if (index < 0 || index >= floatingWindows.size())
return {};
return floatingWindows.at(index);
}
QStringList LayoutSaver::Layout::mainWindowNames() const QStringList LayoutSaver::Layout::mainWindowNames() const
{ {
QStringList names; QStringList names;
@@ -493,6 +564,35 @@ QStringList LayoutSaver::Layout::dockWidgetNames() const
return names; return names;
} }
QStringList LayoutSaver::Layout::dockWidgetsToClose() const
{
// Before restoring a layout we close all dock widgets, unless they're a floating window with the DontCloseBeforeRestore flag
QStringList names;
names.reserve(allDockWidgets.size());
auto registry = DockRegistry::self();
for (const auto &dw : allDockWidgets) {
if (DockWidgetBase *dockWidget = registry->dockByName(dw->uniqueName)) {
bool doClose = true;
if (dockWidget->skipsRestore()) {
if (auto fw = dockWidget->floatingWindow()) {
if (fw->allDockWidgetsHave(DockWidgetBase::LayoutSaverOption::Skip)) {
// All dock widgets in this floating window skips float, so we can honour it for all.
doClose = false;
}
}
}
if (doClose)
names << dw->uniqueName;
}
}
return names;
}
bool LayoutSaver::Frame::isValid() const bool LayoutSaver::Frame::isValid() const
{ {
if (isNull) if (isNull)
@@ -528,9 +628,24 @@ bool LayoutSaver::Frame::isValid() const
return true; return true;
} }
void LayoutSaver::Frame::scaleSizes(const ScalingInfo &scalingInfo) bool LayoutSaver::Frame::hasSingleDockWidget() const
{ {
scalingInfo.applyFactorsTo(geometry); return dockWidgets.size() == 1;
}
bool LayoutSaver::Frame::skipsRestore() const
{
return std::all_of(dockWidgets.cbegin(), dockWidgets.cend(), [](LayoutSaver::DockWidget::Ptr dw) {
return dw->skipsRestore();
});
}
LayoutSaver::DockWidget::Ptr LayoutSaver::Frame::singleDockWidget() const
{
if (!hasSingleDockWidget())
return {};
return dockWidgets.first();
} }
QVariantMap LayoutSaver::Frame::toVariantMap() const QVariantMap LayoutSaver::Frame::toVariantMap() const
@@ -560,7 +675,7 @@ void LayoutSaver::Frame::fromVariantMap(const QVariantMap &map)
isNull = map.value(QStringLiteral("isNull")).toBool(); isNull = map.value(QStringLiteral("isNull")).toBool();
objectName = map.value(QStringLiteral("objectName")).toString(); objectName = map.value(QStringLiteral("objectName")).toString();
geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap()); geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap());
options = map.value(QStringLiteral("options")).toUInt(); options = static_cast<QFlags<FrameOption>::Int>(map.value(QStringLiteral("options")).toUInt());
currentTabIndex = map.value(QStringLiteral("currentTabIndex")).toInt(); currentTabIndex = map.value(QStringLiteral("currentTabIndex")).toInt();
const QVariantList dockWidgetsV = map.value(QStringLiteral("dockWidgets")).toList(); const QVariantList dockWidgetsV = map.value(QStringLiteral("dockWidgets")).toList();
@@ -583,6 +698,14 @@ void LayoutSaver::DockWidget::scaleSizes(const ScalingInfo &scalingInfo)
lastPosition.scaleSizes(scalingInfo); lastPosition.scaleSizes(scalingInfo);
} }
bool LayoutSaver::DockWidget::skipsRestore() const
{
if (DockWidgetBase *dw = DockRegistry::self()->dockByName(uniqueName))
return dw->skipsRestore();
return false;
}
QVariantMap LayoutSaver::DockWidget::toVariantMap() const QVariantMap LayoutSaver::DockWidget::toVariantMap() const
{ {
QVariantMap map; QVariantMap map;
@@ -621,10 +744,24 @@ bool LayoutSaver::FloatingWindow::isValid() const
return true; return true;
} }
bool LayoutSaver::FloatingWindow::hasSingleDockWidget() const
{
return multiSplitterLayout.hasSingleDockWidget();
}
LayoutSaver::DockWidget::Ptr LayoutSaver::FloatingWindow::singleDockWidget() const
{
return multiSplitterLayout.singleDockWidget();
}
bool LayoutSaver::FloatingWindow::skipsRestore() const
{
return multiSplitterLayout.skipsRestore();
}
void LayoutSaver::FloatingWindow::scaleSizes(const ScalingInfo &scalingInfo) void LayoutSaver::FloatingWindow::scaleSizes(const ScalingInfo &scalingInfo)
{ {
scalingInfo.applyFactorsTo(/*by-ref*/geometry); scalingInfo.applyFactorsTo(/*by-ref*/ geometry);
multiSplitterLayout.scaleSizes(scalingInfo);
} }
QVariantMap LayoutSaver::FloatingWindow::toVariantMap() const QVariantMap LayoutSaver::FloatingWindow::toVariantMap() const
@@ -682,9 +819,6 @@ void LayoutSaver::MainWindow::scaleSizes()
} }
scalingInfo = ScalingInfo(uniqueName, geometry); scalingInfo = ScalingInfo(uniqueName, geometry);
if (scalingInfo.isValid())
multiSplitterLayout.scaleSizes(scalingInfo);
} }
QVariantMap LayoutSaver::MainWindow::toVariantMap() const QVariantMap LayoutSaver::MainWindow::toVariantMap() const
@@ -698,6 +832,7 @@ QVariantMap LayoutSaver::MainWindow::toVariantMap() const
map.insert(QStringLiteral("screenSize"), Layouting::sizeToMap(screenSize)); map.insert(QStringLiteral("screenSize"), Layouting::sizeToMap(screenSize));
map.insert(QStringLiteral("isVisible"), isVisible); map.insert(QStringLiteral("isVisible"), isVisible);
map.insert(QStringLiteral("affinities"), stringListToVariant(affinities)); map.insert(QStringLiteral("affinities"), stringListToVariant(affinities));
map.insert(QStringLiteral("windowState"), windowState);
for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) { for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) {
const QStringList dockWidgets = dockWidgetsPerSideBar.value(loc); const QStringList dockWidgets = dockWidgetsPerSideBar.value(loc);
@@ -718,6 +853,7 @@ void LayoutSaver::MainWindow::fromVariantMap(const QVariantMap &map)
screenSize = Layouting::mapToSize(map.value(QStringLiteral("screenSize")).toMap()); screenSize = Layouting::mapToSize(map.value(QStringLiteral("screenSize")).toMap());
isVisible = map.value(QStringLiteral("isVisible")).toBool(); isVisible = map.value(QStringLiteral("isVisible")).toBool();
affinities = variantToStringList(map.value(QStringLiteral("affinities")).toList()); affinities = variantToStringList(map.value(QStringLiteral("affinities")).toList());
windowState = Qt::WindowState(map.value(QStringLiteral("windowState"), Qt::WindowNoState).toInt());
// Compatibility hack. Old json format had a single "affinityName" instead of an "affinities" list: // Compatibility hack. Old json format had a single "affinityName" instead of an "affinities" list:
const QString affinityName = map.value(QStringLiteral("affinityName")).toString(); const QString affinityName = map.value(QStringLiteral("affinityName")).toString();
@@ -747,11 +883,24 @@ bool LayoutSaver::MultiSplitter::isValid() const
return true; return true;
} }
void LayoutSaver::MultiSplitter::scaleSizes(const ScalingInfo &) bool LayoutSaver::MultiSplitter::hasSingleDockWidget() const
{ {
// scalingInfo.applyFactorsTo(/*by-ref*/size); return frames.size() == 1 && frames.cbegin()->hasSingleDockWidget();
//for (LayoutSaver::Item &item : items) TODO }
// item.scaleSizes(scalingInfo);
LayoutSaver::DockWidget::Ptr LayoutSaver::MultiSplitter::singleDockWidget() const
{
if (!hasSingleDockWidget())
return {};
return frames.cbegin()->singleDockWidget();
}
bool LayoutSaver::MultiSplitter::skipsRestore() const
{
return std::all_of(frames.cbegin(), frames.cend(), [](const LayoutSaver::Frame &frame) {
return frame.skipsRestore();
});
} }
QVariantMap LayoutSaver::MultiSplitter::toVariantMap() const QVariantMap LayoutSaver::MultiSplitter::toVariantMap() const
@@ -781,7 +930,7 @@ void LayoutSaver::MultiSplitter::fromVariantMap(const QVariantMap &map)
void LayoutSaver::Position::scaleSizes(const ScalingInfo &scalingInfo) void LayoutSaver::Position::scaleSizes(const ScalingInfo &scalingInfo)
{ {
scalingInfo.applyFactorsTo(/*by-ref*/lastFloatingGeometry); scalingInfo.applyFactorsTo(/*by-ref*/ lastFloatingGeometry);
} }
QVariantMap LayoutSaver::Position::toVariantMap() const QVariantMap LayoutSaver::Position::toVariantMap() const
@@ -883,8 +1032,7 @@ void LayoutSaver::ScalingInfo::translatePos(QPoint &pt) const
void LayoutSaver::ScalingInfo::applyFactorsTo(QPoint &pt) const void LayoutSaver::ScalingInfo::applyFactorsTo(QPoint &pt) const
{ {
pt.setX(qCeil(pt.x() * widthFactor)); translatePos(pt);
pt.setY(qCeil(pt.y() * heightFactor));
} }
void LayoutSaver::ScalingInfo::applyFactorsTo(QSize &sz) const void LayoutSaver::ScalingInfo::applyFactorsTo(QSize &sz) const
@@ -901,9 +1049,19 @@ void LayoutSaver::ScalingInfo::applyFactorsTo(QRect &rect) const
QPoint pos = rect.topLeft(); QPoint pos = rect.topLeft();
QSize size = rect.size(); QSize size = rect.size();
applyFactorsTo(/*by-ref*/size); applyFactorsTo(/*by-ref*/ size);
applyFactorsTo(/*by-ref*/pos); applyFactorsTo(/*by-ref*/ pos);
rect.moveTopLeft(pos); rect.moveTopLeft(pos);
rect.setSize(size); rect.setSize(size);
} }
LayoutSaver::Private::RAIIIsRestoring::RAIIIsRestoring()
{
LayoutSaver::Private::s_restoreInProgress = true;
}
LayoutSaver::Private::RAIIIsRestoring::~RAIIIsRestoring()
{
LayoutSaver::Private::s_restoreInProgress = false;
}

View File

@@ -33,6 +33,24 @@ namespace KDDockWidgets {
class DockWidgetBase; class DockWidgetBase;
/**
* @brief LayoutSaver allows to save or restore layouts.
*
* You can save a layout to a file or to a byte array.
* JSON is used as the serialized format.
*
* Example:
* LayoutSaver saver;
*
* // Save to a file:
* saver.saveToFile(filename);
*
* The counterpart of saveToFile() is restoreFromFile().
*
* You can also save to a QByteArray instead, with serializeLayout().
* The counterpart of serializeLayout() is restoreLayout();
*/
class DOCKS_EXPORT LayoutSaver class DOCKS_EXPORT LayoutSaver
{ {
public: public:
@@ -86,7 +104,6 @@ public:
*/ */
QVector<DockWidgetBase *> restoredDockWidgets() const; QVector<DockWidgetBase *> restoredDockWidgets() const;
/** /**
* @brief Sets the list of affinity names for which restore and save will be applied on. * @brief Sets the list of affinity names for which restore and save will be applied on.
* Allows to save/restore only a subset of the windows. * Allows to save/restore only a subset of the windows.
@@ -95,6 +112,10 @@ public:
*/ */
void setAffinityNames(const QStringList &affinityNames); void setAffinityNames(const QStringList &affinityNames);
/// @internal Returns the private-impl. Not intended for public use.
class Private;
Private *dptr() const;
struct Layout; struct Layout;
struct MainWindow; struct MainWindow;
struct FloatingWindow; struct FloatingWindow;
@@ -105,11 +126,11 @@ public:
struct Placeholder; struct Placeholder;
struct ScalingInfo; struct ScalingInfo;
struct ScreenInfo; struct ScreenInfo;
private: private:
Q_DISABLE_COPY(LayoutSaver) Q_DISABLE_COPY(LayoutSaver)
friend class ::TestDocks; friend class ::TestDocks;
class Private;
Private *const d; Private *const d;
}; };
} }

View File

@@ -18,61 +18,73 @@
#include "MainWindow.h" #include "MainWindow.h"
#include "Config.h" #include "Config.h"
#include "DropArea_p.h"
#include "Frame_p.h"
#include "Logging_p.h"
#include "SideBar_p.h"
#include "DropAreaWithCentralFrame_p.h"
#include "FrameworkWidgetFactory.h" #include "FrameworkWidgetFactory.h"
#include <QVBoxLayout> #include "private/DockRegistry_p.h"
#include "private/DropAreaWithCentralFrame_p.h"
#include "private/DropArea_p.h"
#include "private/Frame_p.h"
#include "private/Logging_p.h"
#include "private/SideBar_p.h"
#include <QPainter> #include <QPainter>
#include <QScreen>
#include <QVBoxLayout>
#include <QWindow>
// clazy:excludeall=ctor-missing-parent-argument,missing-qobject-macro // clazy:excludeall=ctor-missing-parent-argument,missing-qobject-macro
using namespace KDDockWidgets; using namespace KDDockWidgets;
class MainWindow::Private
{
public:
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
{ {
public: public:
explicit MyCentralWidget(QWidget *parent = nullptr) : QWidget(parent) explicit MyCentralWidget(QWidget *parent = nullptr)
: QWidget(parent)
{ {
setObjectName(QStringLiteral("MyCentralWidget")); setObjectName(QStringLiteral("MyCentralWidget"));
} }
~MyCentralWidget() override; ~MyCentralWidget() override;
void paintEvent(QPaintEvent *) override
{
QPainter p(this);
QPen pen(QColor(184, 184, 184, 184));
p.setPen(pen);
p.drawLine(0, 0, width(), 0);
}
}; };
} }
MyCentralWidget::~MyCentralWidget() {} class MainWindow::Private
{
public:
explicit Private(MainWindowOptions, MainWindow *mainWindow)
: q(mainWindow)
, m_supportsAutoHide(Config::self().flags() & Config::Flag_AutoHideSupport)
, m_centralWidget(new MyCentralWidget(mainWindow))
, m_layout(new QHBoxLayout(m_centralWidget)) // 1 level of indirection so we can add some margins
{
if (m_supportsAutoHide) {
for (auto location : { SideBarLocation::North, SideBarLocation::East,
SideBarLocation::West, SideBarLocation::South }) {
m_sideBars.insert(location, Config::self().frameworkWidgetFactory()->createSideBar(location, mainWindow));
}
}
m_layout->setSpacing(0);
updateMargins();
}
void updateMargins()
{
m_layout->setContentsMargins(q->centerWidgetMargins());
}
MainWindow *const q;
const bool m_supportsAutoHide;
QHash<SideBarLocation, SideBar *> m_sideBars;
MyCentralWidget *const m_centralWidget;
QHBoxLayout *const m_layout;
};
MyCentralWidget::~MyCentralWidget()
{
}
MainWindow::MainWindow(const QString &name, MainWindowOptions options, MainWindow::MainWindow(const QString &name, MainWindowOptions options,
@@ -80,26 +92,28 @@ MainWindow::MainWindow(const QString &name, MainWindowOptions options,
: MainWindowBase(name, options, parent, flags) : MainWindowBase(name, options, parent, flags)
, d(new Private(options, this)) , d(new Private(options, this))
{ {
auto centralWidget = new MyCentralWidget(this);
auto layout = new QHBoxLayout(centralWidget); // 1 level of indirection so we can add some margins
layout->setSpacing(0);
layout->setContentsMargins(centerWidgetMargins());
if (d->m_supportsAutoHide) { if (d->m_supportsAutoHide) {
layout->addWidget(sideBar(SideBarLocation::West)); d->m_layout->addWidget(sideBar(SideBarLocation::West));
auto innerVLayout = new QVBoxLayout(); auto innerVLayout = new QVBoxLayout();
innerVLayout->setSpacing(0); innerVLayout->setSpacing(0);
innerVLayout->setContentsMargins(0, 0, 0, 0); innerVLayout->setContentsMargins(0, 0, 0, 0);
innerVLayout->addWidget(sideBar(SideBarLocation::North)); innerVLayout->addWidget(sideBar(SideBarLocation::North));
innerVLayout->addWidget(dropArea()); innerVLayout->addWidget(layoutWidget());
innerVLayout->addWidget(sideBar(SideBarLocation::South)); innerVLayout->addWidget(sideBar(SideBarLocation::South));
layout->addLayout(innerVLayout); d->m_layout->addLayout(innerVLayout);
layout->addWidget(sideBar(SideBarLocation::East)); d->m_layout->addWidget(sideBar(SideBarLocation::East));
} else { } else {
layout->addWidget(dropArea()); d->m_layout->addWidget(layoutWidget());
} }
setCentralWidget(centralWidget); setCentralWidget(d->m_centralWidget);
create();
connect(windowHandle(), &QWindow::screenChanged, DockRegistry::self(),
[this] {
d->updateMargins(); // logical dpi might have changed
Q_EMIT DockRegistry::self()->windowChangedScreen(windowHandle());
});
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
@@ -125,7 +139,8 @@ void MainWindow::resizeEvent(QResizeEvent *ev)
QMargins MainWindow::centerWidgetMargins() const QMargins MainWindow::centerWidgetMargins() const
{ {
return { 1, 5, 1, 1}; const QMargins margins = { 1, 5, 1, 1 };
return margins * logicalDpiFactor(this);
} }
QRect MainWindow::centralAreaGeometry() const QRect MainWindow::centralAreaGeometry() const

View File

@@ -33,7 +33,7 @@ class DOCKS_EXPORT MainWindow : public MainWindowBase
{ {
Q_OBJECT Q_OBJECT
public: public:
typedef QVector<MainWindow*> List; typedef QVector<MainWindow *> List;
///@brief Constructor. Use it as you would use QMainWindow. ///@brief Constructor. Use it as you would use QMainWindow.
///@param uniqueName Mandatory name that should be unique between all MainWindow instances. ///@param uniqueName Mandatory name that should be unique between all MainWindow instances.
@@ -54,6 +54,7 @@ protected:
void resizeEvent(QResizeEvent *) override; void resizeEvent(QResizeEvent *) override;
QMargins centerWidgetMargins() const override; QMargins centerWidgetMargins() const override;
QRect centralAreaGeometry() 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

View File

@@ -18,25 +18,36 @@
*/ */
#include "MainWindowBase.h" #include "MainWindowBase.h"
#include "DockRegistry_p.h" #include "private/DockRegistry_p.h"
#include "DropArea_p.h" #include "private/MDILayoutWidget_p.h"
#include "Frame_p.h" #include "private/DropArea_p.h"
#include "Utils_p.h" #include "private/Frame_p.h"
#include "SideBar_p.h" #include "private/Utils_p.h"
#include "Logging_p.h" #include "private/SideBar_p.h"
#include "WidgetResizeHandler_p.h" #include "private/Logging_p.h"
#include "private/WidgetResizeHandler_p.h"
#include "FrameworkWidgetFactory.h" #include "FrameworkWidgetFactory.h"
#include "DropAreaWithCentralFrame_p.h" #include "private/DropAreaWithCentralFrame_p.h"
#include "private/LayoutSaver_p.h"
#include "private/DockWidgetBase_p.h"
using namespace KDDockWidgets; using namespace KDDockWidgets;
static LayoutWidget *createLayoutWidget(MainWindowBase *mainWindow, MainWindowOptions options)
{
if (options & MainWindowOption_MDI)
return new MDILayoutWidget(mainWindow);
return new DropAreaWithCentralFrame(mainWindow, options);
}
class MainWindowBase::Private class MainWindowBase::Private
{ {
public: public:
explicit Private(MainWindowBase *mainWindow, MainWindowOptions options) explicit Private(MainWindowBase *mainWindow, MainWindowOptions options)
: m_options(options) : m_options(options)
, q(mainWindow) , q(mainWindow)
, m_dropArea(new DropAreaWithCentralFrame(mainWindow, options)) , m_layoutWidget(createLayoutWidget(mainWindow, options))
{ {
} }
@@ -45,11 +56,11 @@ public:
return m_options & MainWindowOption_HasCentralFrame; return m_options & MainWindowOption_HasCentralFrame;
} }
WidgetResizeHandler::CursorPositions allowedResizeSides(SideBarLocation loc) const; CursorPositions allowedResizeSides(SideBarLocation loc) const;
QRect rectForOverlay(Frame *, SideBarLocation) const; QRect rectForOverlay(Frame *, SideBarLocation) const;
SideBarLocation preferredSideBar(DockWidgetBase *) const; SideBarLocation preferredSideBar(DockWidgetBase *) const;
void updateOverlayGeometry(bool reusePreviousSize = false); void updateOverlayGeometry(QSize suggestedSize);
void clearSideBars(); void clearSideBars();
QString name; QString name;
@@ -57,7 +68,7 @@ public:
const MainWindowOptions m_options; const MainWindowOptions m_options;
MainWindowBase *const q; MainWindowBase *const q;
QPointer<DockWidgetBase> m_overlayedDockWidget; QPointer<DockWidgetBase> m_overlayedDockWidget;
DropAreaWithCentralFrame *const m_dropArea; LayoutWidget *const m_layoutWidget;
}; };
MainWindowBase::MainWindowBase(const QString &uniqueName, KDDockWidgets::MainWindowOptions options, MainWindowBase::MainWindowBase(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
@@ -66,6 +77,9 @@ MainWindowBase::MainWindowBase(const QString &uniqueName, KDDockWidgets::MainWin
, d(new Private(this, options)) , d(new Private(this, options))
{ {
setUniqueName(uniqueName); setUniqueName(uniqueName);
connect(d->m_layoutWidget, &LayoutWidget::visibleWidgetCountChanged, this,
&MainWindowBase::frameCountChanged);
} }
MainWindowBase::~MainWindowBase() MainWindowBase::~MainWindowBase()
@@ -90,6 +104,11 @@ void MainWindowBase::addDockWidgetAsTab(DockWidgetBase *widget)
return; return;
} }
if (isMDI()) {
// Not applicable to MDI
return;
}
if (d->supportsCentralFrame()) { if (d->supportsCentralFrame()) {
dropArea()->m_centralFrame->addWidget(widget); dropArea()->m_centralFrame->addWidget(widget);
} else { } else {
@@ -105,6 +124,11 @@ void MainWindowBase::addDockWidget(DockWidgetBase *dw, Location location,
return; return;
} }
if (isMDI()) {
// Not applicable to MDI
return;
}
dropArea()->addDockWidget(dw, location, relativeTo, option); dropArea()->addDockWidget(dw, location, relativeTo, option);
} }
@@ -120,7 +144,7 @@ MainWindowOptions MainWindowBase::options() const
DropAreaWithCentralFrame *MainWindowBase::dropArea() const DropAreaWithCentralFrame *MainWindowBase::dropArea() const
{ {
return d->m_dropArea; return qobject_cast<DropAreaWithCentralFrame *>(d->m_layoutWidget);
} }
MultiSplitter *MainWindowBase::multiSplitter() const MultiSplitter *MainWindowBase::multiSplitter() const
@@ -128,6 +152,16 @@ MultiSplitter *MainWindowBase::multiSplitter() const
return dropArea(); return dropArea();
} }
LayoutWidget *MainWindowBase::layoutWidget() const
{
return d->m_layoutWidget;
}
MDILayoutWidget *MainWindowBase::mdiLayoutWidget() const
{
return qobject_cast<MDILayoutWidget *>(layoutWidget());
}
void MainWindowBase::setAffinities(const QStringList &affinityNames) void MainWindowBase::setAffinities(const QStringList &affinityNames)
{ {
QStringList affinities = affinityNames; QStringList affinities = affinityNames;
@@ -161,25 +195,25 @@ void MainWindowBase::layoutParentContainerEqually(DockWidgetBase *dockWidget)
dropArea()->layoutParentContainerEqually(dockWidget); dropArea()->layoutParentContainerEqually(dockWidget);
} }
WidgetResizeHandler::CursorPositions MainWindowBase::Private::allowedResizeSides(SideBarLocation loc) const CursorPositions MainWindowBase::Private::allowedResizeSides(SideBarLocation loc) const
{ {
// When a sidebar is on top, you can only resize its bottom. // When a sidebar is on top, you can only resize its bottom.
// and so forth... // and so forth...
switch (loc) { switch (loc) {
case SideBarLocation::North: case SideBarLocation::North:
return WidgetResizeHandler::CursorPosition_Bottom; return CursorPosition_Bottom;
case SideBarLocation::East: case SideBarLocation::East:
return WidgetResizeHandler::CursorPosition_Left; return CursorPosition_Left;
case SideBarLocation::West: case SideBarLocation::West:
return WidgetResizeHandler::CursorPosition_Right; return CursorPosition_Right;
case SideBarLocation::South: case SideBarLocation::South:
return WidgetResizeHandler::CursorPosition_Top; return CursorPosition_Top;
case SideBarLocation::None: case SideBarLocation::None:
return WidgetResizeHandler::CursorPosition_Undefined; return CursorPosition_Undefined;
} }
return WidgetResizeHandler::CursorPosition_Undefined; return CursorPosition_Undefined;
} }
QRect MainWindowBase::Private::rectForOverlay(Frame *frame, SideBarLocation location) const QRect MainWindowBase::Private::rectForOverlay(Frame *frame, SideBarLocation location) const
@@ -286,7 +320,7 @@ SideBarLocation MainWindowBase::Private::preferredSideBar(DockWidgetBase *dw) co
{ {
// TODO: Algorithm can still be made smarter // TODO: Algorithm can still be made smarter
Layouting::Item *item = q->multiSplitter()->itemForFrame(dw->frame()); Layouting::Item *item = q->layoutWidget()->itemForFrame(dw->d->frame());
if (!item) { if (!item) {
qWarning() << Q_FUNC_INFO << "No item for dock widget"; qWarning() << Q_FUNC_INFO << "No item for dock widget";
return SideBarLocation::None; return SideBarLocation::None;
@@ -348,7 +382,7 @@ SideBarLocation MainWindowBase::Private::preferredSideBar(DockWidgetBase *dw) co
: SideBarLocation::West; : SideBarLocation::West;
} }
void MainWindowBase::Private::updateOverlayGeometry(bool reusePreviousSize) void MainWindowBase::Private::updateOverlayGeometry(QSize suggestedSize)
{ {
if (!m_overlayedDockWidget) if (!m_overlayedDockWidget)
return; return;
@@ -359,46 +393,45 @@ void MainWindowBase::Private::updateOverlayGeometry(bool reusePreviousSize)
return; return;
} }
const QRect defaultGeometry = rectForOverlay(m_overlayedDockWidget->frame(), sb->location()); const QRect defaultGeometry = rectForOverlay(m_overlayedDockWidget->d->frame(), sb->location());
QRect newGeometry = defaultGeometry; QRect newGeometry = defaultGeometry;
Frame *frame = m_overlayedDockWidget->frame(); Frame *frame = m_overlayedDockWidget->d->frame();
if (reusePreviousSize) { if (suggestedSize.isValid() && !suggestedSize.isEmpty()) {
// Let's try to honour the previous overlay size // Let's try to honour the suggested overlay size
switch (sb->location()) { switch (sb->location()) {
case SideBarLocation::North: { case SideBarLocation::North: {
const int maxHeight = q->height() - frame->pos().y() - 10; // gap const int maxHeight = q->height() - frame->pos().y() - 10; // gap
newGeometry.setHeight(qMin(frame->height(), maxHeight)); newGeometry.setHeight(qMin(suggestedSize.height(), maxHeight));
break; break;
} }
case SideBarLocation::South: { case SideBarLocation::South: {
const int maxHeight = sb->pos().y() - m_dropArea->pos().y() - 10; // gap const int maxHeight = sb->pos().y() - m_layoutWidget->pos().y() - 10; // gap
const int bottom = newGeometry.bottom(); const int bottom = newGeometry.bottom();
newGeometry.setHeight(qMin(frame->height(), maxHeight)); newGeometry.setHeight(qMin(suggestedSize.height(), maxHeight));
newGeometry.moveBottom(bottom); newGeometry.moveBottom(bottom);
break; break;
} }
case SideBarLocation::East: { case SideBarLocation::East: {
const int maxWidth = sb->pos().x() - m_dropArea->pos().x() - 10; // gap const int maxWidth = sb->pos().x() - m_layoutWidget->pos().x() - 10; // gap
const int right = newGeometry.right(); const int right = newGeometry.right();
newGeometry.setWidth(qMin(frame->width(), maxWidth)); newGeometry.setWidth(qMin(suggestedSize.width(), maxWidth));
newGeometry.moveRight(right); newGeometry.moveRight(right);
break; break;
} }
case SideBarLocation::West: { case SideBarLocation::West: {
const int maxWidth = q->width() - frame->pos().x() - 10; // gap const int maxWidth = q->width() - frame->pos().x() - 10; // gap
newGeometry.setWidth(qMin(frame->height(), maxWidth)); newGeometry.setWidth(qMin(suggestedSize.width(), maxWidth));
break; break;
} }
case SideBarLocation::None: case SideBarLocation::None:
qWarning() << Q_FUNC_INFO << "Unexpected sidebar value"; qWarning() << Q_FUNC_INFO << "Unexpected sidebar value";
break; break;
} }
} }
m_overlayedDockWidget->frame()->QWidgetAdapter::setGeometry(newGeometry); m_overlayedDockWidget->d->frame()->QWidgetAdapter::setGeometry(newGeometry);
} }
void MainWindowBase::Private::clearSideBars() void MainWindowBase::Private::clearSideBars()
@@ -418,6 +451,7 @@ void MainWindowBase::moveToSideBar(DockWidgetBase *dw)
void MainWindowBase::moveToSideBar(DockWidgetBase *dw, SideBarLocation location) void MainWindowBase::moveToSideBar(DockWidgetBase *dw, SideBarLocation location)
{ {
if (SideBar *sb = sideBar(location)) { if (SideBar *sb = sideBar(location)) {
QScopedValueRollback<bool> rollback(dw->d->m_isMovingToSideBar, true);
dw->forceClose(); dw->forceClose();
sb->addDockWidget(dw); sb->addDockWidget(dw);
} else { } else {
@@ -465,12 +499,9 @@ void MainWindowBase::overlayOnSideBar(DockWidgetBase *dw)
auto frame = Config::self().frameworkWidgetFactory()->createFrame(this, FrameOption_IsOverlayed); auto frame = Config::self().frameworkWidgetFactory()->createFrame(this, FrameOption_IsOverlayed);
d->m_overlayedDockWidget = dw; d->m_overlayedDockWidget = dw;
frame->addWidget(dw); frame->addWidget(dw);
d->updateOverlayGeometry(/*reusePreviousSize=*/ false); d->updateOverlayGeometry(dw->d->lastPositions().lastOverlayedGeometry(sb->location()).size());
// Uncomment once I'm happy with the resizing
auto resizeHandler = new WidgetResizeHandler(true, frame);
resizeHandler->setAllowedResizeSides(d->allowedResizeSides(sb->location()));
frame->setAllowedResizeSides(d->allowedResizeSides(sb->location()));
frame->QWidgetAdapter::show(); frame->QWidgetAdapter::show();
Q_EMIT dw->isOverlayedChanged(true); Q_EMIT dw->isOverlayedChanged(true);
@@ -485,16 +516,34 @@ void MainWindowBase::toggleOverlayOnSideBar(DockWidgetBase *dw)
} }
} }
void MainWindowBase::clearSideBarOverlay() void MainWindowBase::clearSideBarOverlay(bool deleteFrame)
{ {
if (!d->m_overlayedDockWidget) if (!d->m_overlayedDockWidget)
return; return;
Frame *frame = d->m_overlayedDockWidget->frame(); Frame *frame = d->m_overlayedDockWidget->d->frame();
d->m_overlayedDockWidget->setParent(nullptr); if (!frame) { // prophylactic check
Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false); d->m_overlayedDockWidget = nullptr;
d->m_overlayedDockWidget = nullptr; return;
delete frame; }
const SideBarLocation loc = d->m_overlayedDockWidget->sideBarLocation();
d->m_overlayedDockWidget->d->lastPositions().setLastOverlayedGeometry(
loc, frame->QWidgetAdapter::geometry());
frame->unoverlay();
if (deleteFrame) {
d->m_overlayedDockWidget->setParent(nullptr);
Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false);
d->m_overlayedDockWidget = nullptr;
delete frame;
} else {
// No cleanup, just unset. When we drag the overlay it becomes a normal floating window
// meaning we reuse Frame. Don't delete it.
Q_EMIT d->m_overlayedDockWidget->isOverlayedChanged(false);
d->m_overlayedDockWidget = nullptr;
}
} }
SideBar *MainWindowBase::sideBarForDockWidget(const DockWidgetBase *dw) const SideBar *MainWindowBase::sideBarForDockWidget(const DockWidgetBase *dw) const
@@ -536,6 +585,41 @@ bool MainWindowBase::anySideBarIsVisible() const
return false; return false;
} }
bool MainWindowBase::isMDI() const
{
return d->m_options & MainWindowOption_MDI;
}
bool MainWindowBase::closeDockWidgets(bool force)
{
bool allClosed = true;
const auto dockWidgets = d->m_layoutWidget->dockWidgets();
for (DockWidgetBase *dw : dockWidgets) {
Frame *frame = dw->d->frame();
if (force) {
dw->forceClose();
} else {
const bool closed = dw->close();
allClosed = allClosed && closed;
}
if (frame->beingDeletedLater()) {
// The dock widget was closed and this frame is empty, delete immediately instead of
// waiting. I'm not a big fan of deleting stuff later, as state becomes inconsistent
// Empty frames are historically deleted later since they are triggered by mouse click
// on the title bar, and the title bar is inside the frame.
// When doing it programmatically we can delete immediately.
delete frame;
}
}
return allClosed;
}
void MainWindowBase::setUniqueName(const QString &uniqueName) void MainWindowBase::setUniqueName(const QString &uniqueName)
{ {
if (uniqueName.isEmpty()) if (uniqueName.isEmpty())
@@ -553,7 +637,7 @@ void MainWindowBase::setUniqueName(const QString &uniqueName)
void MainWindowBase::onResized(QResizeEvent *) void MainWindowBase::onResized(QResizeEvent *)
{ {
if (d->m_overlayedDockWidget) if (d->m_overlayedDockWidget)
d->updateOverlayGeometry(/*reusePreviousSize=*/ true); d->updateOverlayGeometry(d->m_overlayedDockWidget->d->frame()->QWidgetAdapter::size());
} }
bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw) bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
@@ -571,7 +655,7 @@ bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
d->affinities = mw.affinities; d->affinities = mw.affinities;
} }
const bool success = dropArea()->deserialize(mw.multiSplitterLayout); const bool success = layoutWidget()->deserialize(mw.multiSplitterLayout);
// Restore the SideBars // Restore the SideBars
d->clearSideBars(); d->clearSideBars();
@@ -583,7 +667,7 @@ bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
const QStringList dockWidgets = mw.dockWidgetsPerSideBar.value(loc); const QStringList dockWidgets = mw.dockWidgetsPerSideBar.value(loc);
for (const QString &uniqueName : dockWidgets) { for (const QString &uniqueName : dockWidgets) {
DockWidgetBase *dw = DockRegistry::self()->dockByName(uniqueName); DockWidgetBase *dw = DockRegistry::self()->dockByName(uniqueName, DockRegistry::DockByNameFlag::CreateIfNotFound);
if (!dw) { if (!dw) {
qWarning() << Q_FUNC_INFO << "Could not find dock widget" << uniqueName qWarning() << Q_FUNC_INFO << "Could not find dock widget" << uniqueName
<< ". Won't restore it to sidebar"; << ". Won't restore it to sidebar";
@@ -594,7 +678,7 @@ bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
} }
} }
// Commented-out for now, we dont' want to restore the popup/overlay. popups are perishable // Commented-out for now, we don't want to restore the popup/overlay. popups are perishable
//if (!mw.overlayedDockWidget.isEmpty()) //if (!mw.overlayedDockWidget.isEmpty())
// overlayOnSideBar(DockRegistry::self()->dockByName(mw.overlayedDockWidget)); // overlayOnSideBar(DockRegistry::self()->dockByName(mw.overlayedDockWidget));
@@ -606,13 +690,15 @@ LayoutSaver::MainWindow MainWindowBase::serialize() const
LayoutSaver::MainWindow m; LayoutSaver::MainWindow m;
m.options = options(); m.options = options();
m.geometry = window()->geometry(); // window() as the MainWindow can be embedded m.geometry = windowGeometry();
m.isVisible = isVisible(); m.isVisible = isVisible();
m.uniqueName = uniqueName(); m.uniqueName = uniqueName();
m.screenIndex = screenNumberForWidget(this); m.screenIndex = screenNumberForWidget(this);
m.screenSize = screenSizeForWidget(this); m.screenSize = screenSizeForWidget(this);
m.multiSplitterLayout = dropArea()->serialize(); m.multiSplitterLayout = layoutWidget()->serialize();
m.affinities = d->affinities; m.affinities = d->affinities;
m.windowState = windowHandle() ? windowHandle()->windowState()
: Qt::WindowNoState;
for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) { for (SideBarLocation loc : { SideBarLocation::North, SideBarLocation::East, SideBarLocation::West, SideBarLocation::South }) {
if (SideBar *sb = sideBar(loc)) { if (SideBar *sb = sideBar(loc)) {
@@ -624,3 +710,11 @@ LayoutSaver::MainWindow MainWindowBase::serialize() const
return m; return m;
} }
QRect MainWindowBase::windowGeometry() const
{
if (QWindow *window = windowHandle())
return window->geometry();
return window()->geometry();
}

Some files were not shown because too many files have changed in this diff Show More