Compare commits
542 Commits
backup/lay
...
fix-python
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2b3ead1f01 | ||
|
|
4ebf60a9c8 | ||
|
|
d738f6f43f | ||
|
|
ae000e75bc | ||
|
|
e017438605 | ||
|
|
bcd29f1dcc | ||
|
|
9903780792 | ||
|
|
5a66d09266 | ||
|
|
e3f89b6c17 | ||
|
|
9d8587aa40 | ||
|
|
4b4d839074 | ||
|
|
1c65b3e453 | ||
|
|
70a4ca6533 | ||
|
|
073647cf79 | ||
|
|
90da74b211 | ||
|
|
fbe88f7b99 | ||
|
|
05276999ad | ||
|
|
a1c473fb0e | ||
|
|
721b4de55e | ||
|
|
f1b9ce714b | ||
|
|
2b0a426135 | ||
|
|
369a020d81 | ||
|
|
b1b5cd169a | ||
|
|
5061620f46 | ||
|
|
23ee5d538c | ||
|
|
fa0576362d | ||
|
|
40d868581b | ||
|
|
f8a6bd7ad4 | ||
|
|
635a63deba | ||
|
|
8731450cda | ||
|
|
1eb5392aef | ||
|
|
f58a76426a | ||
|
|
2e6623c9e7 | ||
|
|
2fdb85f3fb | ||
|
|
0a6f760100 | ||
|
|
8db40d368c | ||
|
|
96a3eea108 | ||
|
|
47b20f03f9 | ||
|
|
bdcd8c1e20 | ||
|
|
eaff83251c | ||
|
|
1cdd1a1b74 | ||
|
|
21938e4b3f | ||
|
|
95710d9e5e | ||
|
|
8a3252473f | ||
|
|
c52c8922dc | ||
|
|
80dcd57d91 | ||
|
|
37590b44d7 | ||
|
|
051f8ab3a6 | ||
|
|
78dcb0f7f3 | ||
|
|
6bb0d7ab08 | ||
|
|
c7afbf0803 | ||
|
|
bbea17b81b | ||
|
|
769d34d746 | ||
|
|
64020568d6 | ||
|
|
b7df2fb5f5 | ||
|
|
ddc6da5894 | ||
|
|
6502ee5071 | ||
|
|
22a13c7c9c | ||
|
|
a29f80f90b | ||
|
|
0ccd4b8afa | ||
|
|
48433a05fb | ||
|
|
c6a455a059 | ||
|
|
3e3df799e6 | ||
|
|
912f2de1ee | ||
|
|
1ad8a67caf | ||
|
|
a0588cd312 | ||
|
|
40f0c0f322 | ||
|
|
52626b1874 | ||
|
|
1cfceb4d07 | ||
|
|
fd56ab7932 | ||
|
|
4fd28f9577 | ||
|
|
fd6d9654bc | ||
|
|
31f391294c | ||
|
|
9dd4e733eb | ||
|
|
e4f6893324 | ||
|
|
3c841aa2a9 | ||
|
|
85b4fc3751 | ||
|
|
197a0abb7e | ||
|
|
1df0e6d6dd | ||
|
|
36407d2abe | ||
|
|
2ffdfcad24 | ||
|
|
0e1dc4bd45 | ||
|
|
2853f54ac7 | ||
|
|
76efd45e2d | ||
|
|
7c5e0826c6 | ||
|
|
7c77c9597e | ||
|
|
312d95a376 | ||
|
|
dc1b4f79e4 | ||
|
|
44da2dca65 | ||
|
|
9657bc50a3 | ||
|
|
affd7dfb87 | ||
|
|
dc59ecb4eb | ||
|
|
f95e3d10e7 | ||
|
|
a664a05201 | ||
|
|
7b3e858aa3 | ||
|
|
1d032abb72 | ||
|
|
61a5fec3cb | ||
|
|
4e6022e529 | ||
|
|
9216964b02 | ||
|
|
a87a694e3c | ||
|
|
8736d2cdb6 | ||
|
|
fc633f2547 | ||
|
|
82abc90133 | ||
|
|
f8f596ad30 | ||
|
|
c13f9c00aa | ||
|
|
0ff9b95577 | ||
|
|
ab28c63273 | ||
|
|
cbe6e47233 | ||
|
|
dc3a598594 | ||
|
|
6738bb0ae1 | ||
|
|
1286fc28ca | ||
|
|
6104fdf2e0 | ||
|
|
f42f3804a1 | ||
|
|
10226fc61a | ||
|
|
ba2ce8b8db | ||
|
|
dccdeda18a | ||
|
|
a23c76f6fb | ||
|
|
0245b6e81b | ||
|
|
35728f54cd | ||
|
|
fc7af85c83 | ||
|
|
c87f5ba6eb | ||
|
|
a574364100 | ||
|
|
88e10ffb31 | ||
|
|
2895de3ef5 | ||
|
|
5346f808f9 | ||
|
|
36e6613f6a | ||
|
|
0090799f7f | ||
|
|
c64b938e40 | ||
|
|
08721ea458 | ||
|
|
fa7e8af014 | ||
|
|
7d01b7649a | ||
|
|
9275432aea | ||
|
|
df5738dd34 | ||
|
|
119cadae30 | ||
|
|
f6837ee4e5 | ||
|
|
ed752d953a | ||
|
|
34ea666007 | ||
|
|
0659f1e52b | ||
|
|
1f09bfa9d5 | ||
|
|
ebda537a11 | ||
|
|
ac115bc078 | ||
|
|
a84fea36fe | ||
|
|
e4c87f60e9 | ||
|
|
a21abef6bd | ||
|
|
6fe8d7aea0 | ||
|
|
2a34ecd563 | ||
|
|
2e2288cc0f | ||
|
|
1a44d36838 | ||
|
|
c53d71e2de | ||
|
|
e2674d2a68 | ||
|
|
e66cbae09f | ||
|
|
08dc55ea06 | ||
|
|
5c0c204859 | ||
|
|
85c32abdf0 | ||
|
|
b7353d2bba | ||
|
|
e9131897e4 | ||
|
|
fab0c5f8f8 | ||
|
|
77307a1664 | ||
|
|
40e944ee9d | ||
|
|
a9402d1073 | ||
|
|
9a15ac4bfa | ||
|
|
6a13085e77 | ||
|
|
14e862f1fb | ||
|
|
b4f49895c2 | ||
|
|
2d0dcb9dbe | ||
|
|
9b2b8bbc02 | ||
|
|
1ae66eb8c2 | ||
|
|
478c6e3bbc | ||
|
|
41b48bd41c | ||
|
|
709728e456 | ||
|
|
e1bf1cd786 | ||
|
|
8474f246ae | ||
|
|
beaa45d16d | ||
|
|
ffe13f4bea | ||
|
|
2559b29b30 | ||
|
|
7dfcdd1981 | ||
|
|
341f682274 | ||
|
|
5349ff3832 | ||
|
|
259a78ebaf | ||
|
|
090392a02e | ||
|
|
563d569ec4 | ||
|
|
0899a4e0c8 | ||
|
|
29e625b85f | ||
|
|
380c3eee81 | ||
|
|
21ef8017e8 | ||
|
|
eee8cb8341 | ||
|
|
9630f0f48a | ||
|
|
0f71b30096 | ||
|
|
2ec226c432 | ||
|
|
fa2cd1bc74 | ||
|
|
730af05aa1 | ||
|
|
4788f41593 | ||
|
|
84b0b8f6ad | ||
|
|
cf1514f8a4 | ||
|
|
47f0dfd3ae | ||
|
|
183c48696e | ||
|
|
2462f991be | ||
|
|
d373585e0c | ||
|
|
7f324dda91 | ||
|
|
c5739e8626 | ||
|
|
5362200d21 | ||
|
|
d7f9bf7adc | ||
|
|
52c37f28d0 | ||
|
|
bcfb57f89d | ||
|
|
16fac61a9d | ||
|
|
5203718f93 | ||
|
|
d3aee0dabb | ||
|
|
b6e8703038 | ||
|
|
153aa65b40 | ||
|
|
0701e8aa97 | ||
|
|
baed168458 | ||
|
|
6b45f97215 | ||
|
|
1fc1e3abb2 | ||
|
|
b825e0b9ea | ||
|
|
7aa45ebed9 | ||
|
|
c50fe5fa88 | ||
|
|
ba2fdfc46c | ||
|
|
815b496599 | ||
|
|
b2e79d4285 | ||
|
|
4c630f6c6a | ||
|
|
bf4ef05d00 | ||
|
|
e35fcb02df | ||
|
|
4fa2be3263 | ||
|
|
7c04cd96c6 | ||
|
|
a8bd46155c | ||
|
|
5f4d8b515f | ||
|
|
da4b90e373 | ||
|
|
7ec2f31a46 | ||
|
|
3217c61713 | ||
|
|
2a33599bde | ||
|
|
2994046c7b | ||
|
|
842e72c4c3 | ||
|
|
3b5ca4dafb | ||
|
|
b76ec9e611 | ||
|
|
7a1a2f2c43 | ||
|
|
4ffe5e72d8 | ||
|
|
0275fe441e | ||
|
|
44bf882a2a | ||
|
|
f9196203e7 | ||
|
|
275e334120 | ||
|
|
f97f920ffb | ||
|
|
7773c3fe27 | ||
|
|
19d5467f4d | ||
|
|
4c0e418bc1 | ||
|
|
fab4d39f92 | ||
|
|
91b291a1a9 | ||
|
|
be4a71685a | ||
|
|
8b862b7843 | ||
|
|
b0503cfeb4 | ||
|
|
ecb01ff9c3 | ||
|
|
40c816e0c5 | ||
|
|
6bbba2bff7 | ||
|
|
36fba5db3d | ||
|
|
744f351c4e | ||
|
|
b8664c44c7 | ||
|
|
e3276411f9 | ||
|
|
84989745b4 | ||
|
|
3121b4cf28 | ||
|
|
da6df47706 | ||
|
|
e5c0316ebb | ||
|
|
c0d8f22049 | ||
|
|
c2d8991283 | ||
|
|
a599736c1b | ||
|
|
5526022a57 | ||
|
|
25dd149475 | ||
|
|
e6b67101fa | ||
|
|
16c32cea4b | ||
|
|
9f44eb3154 | ||
|
|
c7b6a1a654 | ||
|
|
6bbcb8f8f2 | ||
|
|
163b194398 | ||
|
|
86e58dd8a7 | ||
|
|
e54ef787ed | ||
|
|
d5957a0dc5 | ||
|
|
bb79bd12a7 | ||
|
|
47795d0751 | ||
|
|
e234ad65ab | ||
|
|
1c3dd93ee3 | ||
|
|
ccf161e139 | ||
|
|
9636054ccc | ||
|
|
6e77dce573 | ||
|
|
e6a335a3f7 | ||
|
|
a442419db2 | ||
|
|
479e1acece | ||
|
|
a7878122ac | ||
|
|
fa32054085 | ||
|
|
f3de1ad63d | ||
|
|
8baac15d24 | ||
|
|
4cf1159019 | ||
|
|
ee065795b9 | ||
|
|
7f9d160658 | ||
|
|
daa220d513 | ||
|
|
d5797a3aea | ||
|
|
ab8545e2c2 | ||
|
|
5fc16954f5 | ||
|
|
6610e48cb3 | ||
|
|
dabfeeaf3b | ||
|
|
9601f57050 | ||
|
|
7c442dce85 | ||
|
|
07ea3ff1a6 | ||
|
|
874fd7d69f | ||
|
|
69a737e286 | ||
|
|
ddc49c9358 | ||
|
|
2b3c3b75bf | ||
|
|
296889cace | ||
|
|
4ebe8ed631 | ||
|
|
ecfa43f801 | ||
|
|
f5f39a37a1 | ||
|
|
0a75d89848 | ||
|
|
e418725c13 | ||
|
|
180fb96ecc | ||
|
|
83af55a592 | ||
|
|
fe6d80ae89 | ||
|
|
103a0e514a | ||
|
|
7cc302c977 | ||
|
|
c2d51bddc8 | ||
|
|
443f80cdab | ||
|
|
9af3740d86 | ||
|
|
567b61c9ec | ||
|
|
df8511b3dc | ||
|
|
1dad16bb63 | ||
|
|
4e88b3742d | ||
|
|
a086713bb6 | ||
|
|
0c0a232e07 | ||
|
|
a66e750f7d | ||
|
|
3697814141 | ||
|
|
d8af06a7ee | ||
|
|
6797d291b6 | ||
|
|
798c808790 | ||
|
|
4e3197388e | ||
|
|
6cd5254779 | ||
|
|
f770e768b8 | ||
|
|
d07f715ed7 | ||
|
|
87c7a8ad65 | ||
|
|
05f93a98f0 | ||
|
|
bab10c8d65 | ||
|
|
5e3a305a7c | ||
|
|
c9fa637ae7 | ||
|
|
79064b539a | ||
|
|
aa7107bde2 | ||
|
|
704e6d0182 | ||
|
|
7634438f6c | ||
|
|
314cd6649d | ||
|
|
e08a7a6725 | ||
|
|
45d5d7b519 | ||
|
|
63c90875aa | ||
|
|
ee4ad02722 | ||
|
|
cd1f52a4bb | ||
|
|
66a0959ac0 | ||
|
|
39d70c8186 | ||
|
|
d541a41536 | ||
|
|
9761759fee | ||
|
|
d4d83111ff | ||
|
|
de09d5532f | ||
|
|
944138273f | ||
|
|
d2ca14bf99 | ||
|
|
84391c693c | ||
|
|
d94263fce5 | ||
|
|
2fd9d45525 | ||
|
|
8461f1f79e | ||
|
|
d9badf3ffd | ||
|
|
1ece0f0fef | ||
|
|
4af582a21f | ||
|
|
ab90da3b19 | ||
|
|
45f4d9f6a8 | ||
|
|
ba49e1cbe2 | ||
|
|
c67f1c28f6 | ||
|
|
de0bcf9ce3 | ||
|
|
3bbc33d8c4 | ||
|
|
e8abc23f59 | ||
|
|
c63c713bea | ||
|
|
c33c7ab450 | ||
|
|
c31edd0cd8 | ||
|
|
b395b96234 | ||
|
|
16aac70510 | ||
|
|
7c9ee4f497 | ||
|
|
7f49f6e6a4 | ||
|
|
c477fce1d9 | ||
|
|
e28f82dcad | ||
|
|
7016656264 | ||
|
|
7f981a1d1d | ||
|
|
94b4051e31 | ||
|
|
86a2b14921 | ||
|
|
4fab2cf360 | ||
|
|
0a2fb6ed73 | ||
|
|
3d95263b40 | ||
|
|
e75b47737c | ||
|
|
9ad6eefa7a | ||
|
|
2527b39368 | ||
|
|
71c7a7c9a9 | ||
|
|
72c2586e20 | ||
|
|
7c5ed8bf84 | ||
|
|
70f0c49709 | ||
|
|
986a25971e | ||
|
|
0c776b6595 | ||
|
|
7a852f700f | ||
|
|
bd848d8040 | ||
|
|
a7013b4cf7 | ||
|
|
8e39ce2dea | ||
|
|
4917da9e7c | ||
|
|
6d44362991 | ||
|
|
b3b25ba047 | ||
|
|
76ba261f62 | ||
|
|
d9184e2396 | ||
|
|
ce7c913f8c | ||
|
|
b4526b007c | ||
|
|
618ec9fd41 | ||
|
|
e1c18de48e | ||
|
|
9779b8edc3 | ||
|
|
50934ae56d | ||
|
|
2da37180b9 | ||
|
|
7ab1500651 | ||
|
|
f260a76f8b | ||
|
|
ba740a4934 | ||
|
|
e0f16ae57e | ||
|
|
8a3e784ae2 | ||
|
|
01112779b0 | ||
|
|
6de5860e9a | ||
|
|
1061edb3b0 | ||
|
|
88b830d297 | ||
|
|
283d2a80c7 | ||
|
|
215e8cfd24 | ||
|
|
235018bfae | ||
|
|
dc87c05f04 | ||
|
|
4a17b04310 | ||
|
|
6001e655fd | ||
|
|
af22e3e12d | ||
|
|
0d3ae48fed | ||
|
|
9e198917f0 | ||
|
|
d2531d48d3 | ||
|
|
dc0dab6a83 | ||
|
|
8b81cd12f8 | ||
|
|
044c590b92 | ||
|
|
6c2a29968a | ||
|
|
90fe9be6f6 | ||
|
|
2350f847d7 | ||
|
|
8f7df69fa1 | ||
|
|
b687224801 | ||
|
|
209005478e | ||
|
|
af25af1259 | ||
|
|
8b0be3b2ba | ||
|
|
43fafa1f33 | ||
|
|
ea56d20959 | ||
|
|
8477fdc7e1 | ||
|
|
d613d25ef5 | ||
|
|
c5d9b38fc2 | ||
|
|
36061fc6dc | ||
|
|
2b6b6e2ba5 | ||
|
|
adedcfd6db | ||
|
|
a9e02ccd41 | ||
|
|
4647814aae | ||
|
|
5b1b029b80 | ||
|
|
6fe998d9df | ||
|
|
131b43a833 | ||
|
|
a87ab40aad | ||
|
|
2fb66c681b | ||
|
|
0bd2f8f23a | ||
|
|
0f796da901 | ||
|
|
cc5578f8f4 | ||
|
|
f89aa59371 | ||
|
|
3f242a8b59 | ||
|
|
c4b94f0f21 | ||
|
|
582ce6ef31 | ||
|
|
10b47a8f9c | ||
|
|
d2716cf1c5 | ||
|
|
2984b62ca0 | ||
|
|
1f6c49d5ba | ||
|
|
d0b36cf932 | ||
|
|
d1d1c983f1 | ||
|
|
c5d880c124 | ||
|
|
d44a6f78b8 | ||
|
|
0abb6292c1 | ||
|
|
2bf977ede7 | ||
|
|
5bad616c5a | ||
|
|
e0cd9d95b5 | ||
|
|
b743565ea3 | ||
|
|
be1a2a3878 | ||
|
|
b7cb6afa49 | ||
|
|
0db40953ac | ||
|
|
137cf017c4 | ||
|
|
68acdaeb9a | ||
|
|
4dea453e7c | ||
|
|
ca52d6f760 | ||
|
|
5eff4f8df8 | ||
|
|
cc2aa13eb7 | ||
|
|
c4241b92f1 | ||
|
|
1a0299d758 | ||
|
|
550d84ab11 | ||
|
|
2450f9b39f | ||
|
|
f6f70f26e4 | ||
|
|
c4df3600af | ||
|
|
0f0209ddf3 | ||
|
|
0dac5eed68 | ||
|
|
11576c5455 | ||
|
|
93c471623b | ||
|
|
925df72c0f | ||
|
|
babed642eb | ||
|
|
fd9bcdeabe | ||
|
|
2fe1e22076 | ||
|
|
a9d0ec3fdd | ||
|
|
ed6d5134b0 | ||
|
|
1f2bdaf188 | ||
|
|
a9be454604 | ||
|
|
7c85c1eb0f | ||
|
|
addf436fd0 | ||
|
|
ff6260a4dc | ||
|
|
48f872f696 | ||
|
|
e3e31ca5ca | ||
|
|
4b05d4ddd7 | ||
|
|
e6e63806f8 | ||
|
|
d267b0e0dd | ||
|
|
96ee076e9a | ||
|
|
7e86a32a23 | ||
|
|
09026fd312 | ||
|
|
d2dca56ce6 | ||
|
|
3742e5ef9a | ||
|
|
7ed54631ac | ||
|
|
3c1ab0126d | ||
|
|
0df9943aa5 | ||
|
|
d4cc9e85eb | ||
|
|
5f7899f265 | ||
|
|
61bedce278 | ||
|
|
cd053d0cc4 | ||
|
|
06a7346281 | ||
|
|
535a0c943c | ||
|
|
e298667351 | ||
|
|
0595448bba | ||
|
|
97c1ca30fd | ||
|
|
86d1a52bbf | ||
|
|
2d007c558a | ||
|
|
dc4a1975ab | ||
|
|
144897e831 | ||
|
|
e87f6d001e | ||
|
|
8cc53ca5bb | ||
|
|
1b337b5391 | ||
|
|
e383bc797e | ||
|
|
43a25ef93b | ||
|
|
19e519912b | ||
|
|
68f0c64954 | ||
|
|
e8db004874 | ||
|
|
6ee3cfbb2d | ||
|
|
ab0fc1e328 |
2
.clazy
2
.clazy
@@ -1 +1 @@
|
|||||||
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
|
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-qobject-macro
|
||||||
|
|||||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -10,6 +10,7 @@ libdocks.so
|
|||||||
tst_docks
|
tst_docks
|
||||||
CMakeLists.txt.user*
|
CMakeLists.txt.user*
|
||||||
/build
|
/build
|
||||||
|
/examples/dockwidgets/build/
|
||||||
moc_*
|
moc_*
|
||||||
*.moc
|
*.moc
|
||||||
*automoc.cpp
|
*automoc.cpp
|
||||||
@@ -39,5 +40,14 @@ kddockwidgets_basic_quick
|
|||||||
/src/KDDockWidgetsConfig.cmake
|
/src/KDDockWidgetsConfig.cmake
|
||||||
/src/KDDockWidgetsConfigVersion.cmake
|
/src/KDDockWidgetsConfigVersion.cmake
|
||||||
build-*
|
build-*
|
||||||
|
/build*
|
||||||
/examples/dockwidgets/kddockwidgets_example
|
/examples/dockwidgets/kddockwidgets_example
|
||||||
.cmake
|
.cmake
|
||||||
|
CTestTestfile.cmake
|
||||||
|
mylayout.json
|
||||||
|
*.cbp
|
||||||
|
*.pyc
|
||||||
|
/python/examples/rc_assets.py
|
||||||
|
*.pri
|
||||||
|
/docks-w
|
||||||
|
kddockwidgets_minimal_example
|
||||||
|
|||||||
7
.krazy
7
.krazy
@@ -1,7 +1,7 @@
|
|||||||
CHECKSETS qt5,c++
|
CHECKSETS qt5,c++
|
||||||
|
|
||||||
#KDAB-specific checks
|
#KDAB-specific checks
|
||||||
EXTRA kdabcopyright
|
EXTRA kdabcopyright-reuse,kdabcontactus,fosslicense-reuse
|
||||||
|
|
||||||
#additional checks
|
#additional checks
|
||||||
#EXTRA defines,null
|
#EXTRA defines,null
|
||||||
@@ -11,8 +11,11 @@ EXCLUDE strings,explicit,normalize,passbyvalue,operators,nullstrcompare,nullstra
|
|||||||
#exclude more checks
|
#exclude more checks
|
||||||
EXCLUDE style
|
EXCLUDE style
|
||||||
|
|
||||||
|
SKIP /fwd_headers/
|
||||||
|
SKIP Doxyfile.cmake
|
||||||
|
|
||||||
#skip CMake files
|
#skip CMake files
|
||||||
SKIP /KDDockWidgetsConfig.cmake.in
|
SKIP /KDDockWidgetsConfig.cmake.in
|
||||||
#skip the borrowed code in the cmake subdir
|
#skip the borrowed code in the cmake subdir
|
||||||
SKIP /cmake/Qt5Portability.cmake|/cmake/ECM/
|
SKIP /cmake/Qt5Portability.cmake|/cmake/ECM/|/cmake/InstallLocation.cmake
|
||||||
|
|
||||||
|
|||||||
68
.vscode/launch.json
vendored
Normal file
68
.vscode/launch.json
vendored
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
{
|
||||||
|
"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
Normal file
10
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"C_Cpp.default.configurationProvider": "vector-of-bool.cmake-tools",
|
||||||
|
"files.associations": {
|
||||||
|
"qevent": "cpp"
|
||||||
|
},
|
||||||
|
"cmake.configureSettings": {
|
||||||
|
"OPTION_DEVELOPER_MODE" : "ON",
|
||||||
|
"OPTION_QTQUICK" : true
|
||||||
|
}
|
||||||
|
}
|
||||||
198
CMakeLists.txt
198
CMakeLists.txt
@@ -1,52 +1,202 @@
|
|||||||
cmake_minimum_required(VERSION 3.3)
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
project(KDDockWidgets
|
# Pass the following variables to cmake to control the build:
|
||||||
VERSION 0.1
|
#
|
||||||
|
# -DKDDockWidgets_STATIC=[true|false]
|
||||||
|
# Build static versions of the libraries
|
||||||
|
# Default=false
|
||||||
|
#
|
||||||
|
# -DKDDockWidgets_TESTS=[true|false]
|
||||||
|
# Build the test harness.
|
||||||
|
# Default=false
|
||||||
|
#
|
||||||
|
# -DKDDockWidgets_EXAMPLES=[true|false]
|
||||||
|
# Build the examples.
|
||||||
|
# Default=true
|
||||||
|
#
|
||||||
|
# -DKDDockWidgets_DOCS=[true|false]
|
||||||
|
# Build the API documentation.
|
||||||
|
# Default=true
|
||||||
|
#
|
||||||
|
# -DOPTION_DEVELOPER_MODE=[true|false]
|
||||||
|
# Configure the build for a developer setup.
|
||||||
|
# Enables some features that are not geared towards end-users.
|
||||||
|
# Forces the test harness to be built.
|
||||||
|
# Default=false
|
||||||
|
#
|
||||||
|
# -DOPTION_BUILD_PYTHON_BINDINGS=[true|false]
|
||||||
|
# Build/Generate python bindings. Always false for Debug builds
|
||||||
|
# Default=false
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
|
if(POLICY CMP0020)
|
||||||
|
cmake_policy(SET CMP0020 NEW)
|
||||||
|
endif()
|
||||||
|
if(POLICY CMP0042)
|
||||||
|
cmake_policy(SET CMP0042 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if("${CMAKE_INSTALL_PREFIX}" STREQUAL "")
|
||||||
|
set(USE_DEFAULT_INSTALL_LOCATION True)
|
||||||
|
else()
|
||||||
|
set(USE_DEFAULT_INSTALL_LOCATION False)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
|
||||||
|
project(KDDockWidgets LANGUAGES CXX)
|
||||||
|
else()
|
||||||
|
project(KDDockWidgets
|
||||||
DESCRIPTION "An advanced docking system for Qt"
|
DESCRIPTION "An advanced docking system for Qt"
|
||||||
HOMEPAGE_URL "https://github.com/KDAB/KDDockWidgets"
|
HOMEPAGE_URL "https://github.com/KDAB/KDDockWidgets"
|
||||||
LANGUAGES CXX)
|
LANGUAGES CXX)
|
||||||
|
endif()
|
||||||
|
|
||||||
cmake_policy(SET CMP0020 NEW)
|
set(${PROJECT_NAME}_VERSION_MAJOR 0)
|
||||||
cmake_policy(SET CMP0042 NEW)
|
set(${PROJECT_NAME}_VERSION_MINOR 9)
|
||||||
|
set(${PROJECT_NAME}_VERSION_PATCH 99)
|
||||||
|
set(${PROJECT_NAME}_VERSION ${${PROJECT_NAME}_VERSION_MAJOR}.${${PROJECT_NAME}_VERSION_MINOR}.${${PROJECT_NAME}_VERSION_PATCH})
|
||||||
|
set(${PROJECT_NAME}_SOVERSION "1.0")
|
||||||
|
|
||||||
|
include(FeatureSummary)
|
||||||
|
|
||||||
option(OPTION_DEVELOPER_MODE "Developer Mode" OFF)
|
option(OPTION_DEVELOPER_MODE "Developer Mode" OFF)
|
||||||
option(OPTION_SANITIZER_SUPPORT "Activate support for using sanitizers" OFF)
|
option(OPTION_BUILD_PYTHON_BINDINGS "Build python bindings" OFF)
|
||||||
# option(OPTION_QTQUICK "Build for QtQuick instead of QtWidgets" OFF)
|
if(OPTION_BUILD_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}_EXAMPLES "Build the examples" ON)
|
||||||
|
option(${PROJECT_NAME}_DOCS "Build the API documentation" ON)
|
||||||
|
|
||||||
find_package(Qt5Widgets)
|
#Always build the test harness in developer-mode
|
||||||
|
if(OPTION_DEVELOPER_MODE)
|
||||||
|
set(${PROJECT_NAME}_TESTS ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package(Qt5Widgets 5.9 REQUIRED)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
|
|
||||||
set(ECM_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ECM/modules/")
|
set(ECM_MODULE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/cmake/ECM/modules/")
|
||||||
set(CMAKE_MODULE_PATH ${ECM_MODULE_DIR})
|
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)
|
||||||
|
|
||||||
if (OPTION_SANITIZER_SUPPORT)
|
# setup default install locations
|
||||||
include(ECMEnableSanitizers)
|
include(InstallLocation)
|
||||||
endif()
|
include(QtInstallPaths) #to set QT_INSTALL_FOO variables
|
||||||
|
|
||||||
if (OPTION_DEVELOPER_MODE)
|
macro(set_compiler_flags targetName)
|
||||||
add_definitions(-DDOCKS_DEVELOPER_MODE -DQT_FORCE_ASSERTS)
|
if(OPTION_DEVELOPER_MODE)
|
||||||
if (NOT MSVC)
|
target_compile_definitions(${targetName} PRIVATE DOCKS_DEVELOPER_MODE QT_FORCE_ASSERTS)
|
||||||
add_compile_options(-Wall -Wextra -Werror)
|
if(NOT MSVC)
|
||||||
|
target_compile_options(${targetName} PRIVATE -Wall -Wextra -Werror -Wno-error=deprecated-declarations)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
endmacro()
|
||||||
|
|
||||||
if (OPTION_QTQUICK)
|
if(OPTION_QTQUICK)
|
||||||
find_package(Qt5Quick)
|
find_package(Qt5Quick)
|
||||||
|
find_package(Qt5QuickControls2)
|
||||||
add_definitions(-DKDDOCKWIDGETS_QTQUICK)
|
add_definitions(-DKDDOCKWIDGETS_QTQUICK)
|
||||||
else()
|
else()
|
||||||
add_definitions(-DKDDOCKWIDGETS_QTWIDGETS)
|
add_definitions(-DKDDOCKWIDGETS_QTWIDGETS)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(src)
|
if(${PROJECT_NAME}_STATIC)
|
||||||
|
set(${PROJECT_NAME}_LIBRARY_MODE "STATIC")
|
||||||
|
else()
|
||||||
|
set(${PROJECT_NAME}_LIBRARY_MODE "SHARED")
|
||||||
|
endif()
|
||||||
|
|
||||||
if (OPTION_DEVELOPER_MODE)
|
if(USE_DEFAULT_INSTALL_LOCATION)
|
||||||
if (NOT OPTION_QTQUICK)
|
if(UNIX)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "/usr/local/KDAB/${PROJECT_NAME}-${${PROJECT_NAME}_VERSION}")
|
||||||
|
elseif(WIN32)
|
||||||
|
set(CMAKE_INSTALL_PREFIX "C:\\KDAB\\${PROJECT_NAME}-${${PROJECT_NAME}_VERSION}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Generate .pri file for qmake users
|
||||||
|
include(ECMGeneratePriFile)
|
||||||
|
set(PROJECT_VERSION_STRING ${${PROJECT_NAME}_VERSION})
|
||||||
|
ecm_generate_pri_file(BASE_NAME KDDockWidgets
|
||||||
|
LIB_NAME kddockwidgets
|
||||||
|
FILENAME_VAR pri_filename
|
||||||
|
)
|
||||||
|
install(FILES ${pri_filename} DESTINATION ${ECM_MKSPECS_INSTALL_DIR})
|
||||||
|
|
||||||
|
install(FILES LICENSE.txt README.md DESTINATION ${INSTALL_DOC_DIR})
|
||||||
|
install(DIRECTORY LICENSES DESTINATION ${INSTALL_DOC_DIR})
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
||||||
|
if(OPTION_BUILD_PYTHON_BINDINGS)
|
||||||
|
add_subdirectory(python)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${PROJECT_NAME}_EXAMPLES)
|
||||||
|
if (OPTION_QTQUICK)
|
||||||
|
add_subdirectory(examples/qtquick)
|
||||||
|
set_compiler_flags(kddockwidgets_example_quick)
|
||||||
|
else()
|
||||||
|
add_subdirectory(examples/dockwidgets)
|
||||||
|
add_subdirectory(examples/minimal)
|
||||||
|
set_compiler_flags(kddockwidgets_example)
|
||||||
|
set_compiler_flags(kddockwidgets_minimal_example)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OPTION_DEVELOPER_MODE)
|
||||||
|
include(ECMEnableSanitizers)
|
||||||
|
if(${PROJECT_NAME}_TESTS)
|
||||||
|
enable_testing()
|
||||||
add_subdirectory(tests)
|
add_subdirectory(tests)
|
||||||
|
|
||||||
|
if (NOT OPTION_QTQUICK)
|
||||||
|
#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)
|
||||||
|
# tst_docks.exe is pretty big (140 tests), so split it in 6 runs so we can use threads.
|
||||||
|
add_test(NAME tst_docks0 COMMAND tests_launcher 0 5)
|
||||||
|
add_test(NAME tst_docks1 COMMAND tests_launcher 1 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_docks4 COMMAND tests_launcher 4 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_docks7 COMMAND tests_launcher 7 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_docks10 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_docks13 COMMAND tests_launcher 12 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_docks16 COMMAND tests_launcher 15 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_docks19 COMMAND tests_launcher 18 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
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# examples use <kddockwidget/ qualified includes so need to be installed first
|
add_test(NAME tst_multisplitter COMMAND tst_multisplitter)
|
||||||
# add_subdirectory(examples)
|
add_test(NAME tst_common COMMAND tst_common)
|
||||||
|
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(${PROJECT_NAME}_DOCS)
|
||||||
|
add_subdirectory(docs) # needs to go last, in case there are build source files
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
36
Changelog
36
Changelog
@@ -1,10 +1,28 @@
|
|||||||
* v1.0 (November 4th, 2019)
|
* v0.1 (November 4th, 2019)
|
||||||
- Initial Release
|
- Initial Release and blog
|
||||||
|
|
||||||
* v1.1 (, 2020)
|
* v1.0.0 (, 2020)
|
||||||
Features:
|
- PySide2 bindings
|
||||||
- Allow tab re-ordering with mouse, via KDDockWidgets::Config::Flag_AllowReorderTabs.
|
- Rewrote the layouting engine, resulting in a huge stability gain and makes it easy to add new features
|
||||||
- Allow tabs to have a close button, via KDDockWidgets::Config::Flag_TabsHaveCloseButton.
|
- Honour min/max sizes and some QSizePolicy heuristics
|
||||||
- Add support for lazy resize, via KDDockWidgets::Config::Flag_LazyResize. Resize is only done when mouse is released.
|
- Lazy resize (resize only when dropping the separator)
|
||||||
Fixes:
|
- Native Windows dragging (supporting Aero-snap)
|
||||||
- Fix dock widgets not filling their complete available space
|
- Allow to hide TitleBar and just show tabs. Allow dragging via the tab bar.
|
||||||
|
- Reordering tabs with mouse
|
||||||
|
- Partial layout save/restore (affecting only a subset)
|
||||||
|
- Double-click on title bar to maximize
|
||||||
|
- Maximize button on the title bar
|
||||||
|
- HDPI: Relative layouting restore
|
||||||
|
- Allow to make a dock widget non-closable and non-dockable
|
||||||
|
- Show close button on tabs
|
||||||
|
- Multiple Main Window support
|
||||||
|
- Allowing to dock on different parents
|
||||||
|
- Support for affinities, making some dock widgets only dockable on certain main windows
|
||||||
|
- 200 unit-tests
|
||||||
|
- Fuzzer which found plenty of crashes in the old layouting engine
|
||||||
|
- ASAN fixes
|
||||||
|
- Double click on separator to distribute equally
|
||||||
|
- Hovering over an indicator returns the true size that the dropped widget will get
|
||||||
|
- Static build support
|
||||||
|
- Namespaced Qt support
|
||||||
|
- Dozens of crash fixes, bugs and much more...
|
||||||
|
|||||||
7
LICENSE.txt
Normal file
7
LICENSE.txt
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
KDDockWidgets is (C) 2018-2020, Klarälvdalens Datakonsult AB, and is licensed
|
||||||
|
according to the terms of the:
|
||||||
|
GNU General Public License version 2.0 (see LICENSES/GPL-2.0-only.txt)
|
||||||
|
or the
|
||||||
|
GNU General Public License version 3.0 (see LICENSES/GPL-3.0-only.txt).
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> to inquire about commercial licensing.
|
||||||
319
LICENSES/GPL-2.0-only.txt
Normal file
319
LICENSES/GPL-2.0-only.txt
Normal file
@@ -0,0 +1,319 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||||
|
document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your freedom to share
|
||||||
|
and change it. By contrast, the GNU General Public License is intended to
|
||||||
|
guarantee your freedom to share and change free software--to make sure the
|
||||||
|
software is free for all its users. This General Public License applies to
|
||||||
|
most of the Free Software Foundation's software and to any other program whose
|
||||||
|
authors commit to using it. (Some other Free Software Foundation software
|
||||||
|
is covered by the GNU Lesser General Public License instead.) You can apply
|
||||||
|
it to your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not price. Our
|
||||||
|
General Public Licenses are designed to make sure that you have the freedom
|
||||||
|
to distribute copies of free software (and charge for this service if you
|
||||||
|
wish), that you receive source code or can get it if you want it, that you
|
||||||
|
can change the software or use pieces of it in new free programs; and that
|
||||||
|
you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid anyone to
|
||||||
|
deny you these rights or to ask you to surrender the rights. These restrictions
|
||||||
|
translate to certain responsibilities for you if you distribute copies of
|
||||||
|
the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether gratis or
|
||||||
|
for a fee, you must give the recipients all the rights that you have. You
|
||||||
|
must make sure that they, too, receive or can get the source code. And you
|
||||||
|
must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and (2)
|
||||||
|
offer you this license which gives you legal permission to copy, distribute
|
||||||
|
and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain that
|
||||||
|
everyone understands that there is no warranty for this free software. If
|
||||||
|
the software is modified by someone else and passed on, we want its recipients
|
||||||
|
to know that what they have is not the original, so that any problems introduced
|
||||||
|
by others will not reflect on the original authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software patents. We
|
||||||
|
wish to avoid the danger that redistributors of a free program will individually
|
||||||
|
obtain patent licenses, in effect making the program proprietary. To prevent
|
||||||
|
this, we have made it clear that any patent must be licensed for everyone's
|
||||||
|
free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and modification
|
||||||
|
follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains a notice
|
||||||
|
placed by the copyright holder saying it may be distributed under the terms
|
||||||
|
of this General Public License. The "Program", below, refers to any such program
|
||||||
|
or work, and a "work based on the Program" means either the Program or any
|
||||||
|
derivative work under copyright law: that is to say, a work containing the
|
||||||
|
Program or a portion of it, either verbatim or with modifications and/or translated
|
||||||
|
into another language. (Hereinafter, translation is included without limitation
|
||||||
|
in the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not covered
|
||||||
|
by this License; they are outside its scope. The act of running the Program
|
||||||
|
is not restricted, and the output from the Program is covered only if its
|
||||||
|
contents constitute a work based on the Program (independent of having been
|
||||||
|
made by running the Program). Whether that is true depends on what the Program
|
||||||
|
does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's source code
|
||||||
|
as you receive it, in any medium, provided that you conspicuously and appropriately
|
||||||
|
publish on each copy an appropriate copyright notice and disclaimer of warranty;
|
||||||
|
keep intact all the notices that refer to this License and to the absence
|
||||||
|
of any warranty; and give any other recipients of the Program a copy of this
|
||||||
|
License along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and you
|
||||||
|
may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion of it,
|
||||||
|
thus forming a work based on the Program, and copy and distribute such modifications
|
||||||
|
or work under the terms of Section 1 above, provided that you also meet all
|
||||||
|
of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices stating that
|
||||||
|
you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in whole or
|
||||||
|
in part contains or is derived from the Program or any part thereof, to be
|
||||||
|
licensed as a whole at no charge to all third parties under the terms of this
|
||||||
|
License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively when run,
|
||||||
|
you must cause it, when started running for such interactive use in the most
|
||||||
|
ordinary way, to print or display an announcement including an appropriate
|
||||||
|
copyright notice and a notice that there is no warranty (or else, saying that
|
||||||
|
you provide a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this License.
|
||||||
|
(Exception: if the Program itself is interactive but does not normally print
|
||||||
|
such an announcement, your work based on the Program is not required to print
|
||||||
|
an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If identifiable
|
||||||
|
sections of that work are not derived from the Program, and can be reasonably
|
||||||
|
considered independent and separate works in themselves, then this License,
|
||||||
|
and its terms, do not apply to those sections when you distribute them as
|
||||||
|
separate works. But when you distribute the same sections as part of a whole
|
||||||
|
which is a work based on the Program, the distribution of the whole must be
|
||||||
|
on the terms of this License, whose permissions for other licensees extend
|
||||||
|
to the entire whole, and thus to each and every part regardless of who wrote
|
||||||
|
it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest your
|
||||||
|
rights to work written entirely by you; rather, the intent is to exercise
|
||||||
|
the right to control the distribution of derivative or collective works based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program with
|
||||||
|
the Program (or with a work based on the Program) on a volume of a storage
|
||||||
|
or distribution medium does not bring the other work under the scope of this
|
||||||
|
License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it, under Section
|
||||||
|
2) in object code or executable form under the terms of Sections 1 and 2 above
|
||||||
|
provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable source code,
|
||||||
|
which must be distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three years, to give
|
||||||
|
any third party, for a charge no more than your cost of physically performing
|
||||||
|
source distribution, a complete machine-readable copy of the corresponding
|
||||||
|
source code, to be distributed under the terms of Sections 1 and 2 above on
|
||||||
|
a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer to distribute
|
||||||
|
corresponding source code. (This alternative is allowed only for noncommercial
|
||||||
|
distribution and only if you received the program in object code or executable
|
||||||
|
form with such an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for making
|
||||||
|
modifications to it. For an executable work, complete source code means all
|
||||||
|
the source code for all modules it contains, plus any associated interface
|
||||||
|
definition files, plus the scripts used to control compilation and installation
|
||||||
|
of the executable. However, as a special exception, the source code distributed
|
||||||
|
need not include anything that is normally distributed (in either source or
|
||||||
|
binary form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component itself
|
||||||
|
accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering access to
|
||||||
|
copy from a designated place, then offering equivalent access to copy the
|
||||||
|
source code from the same place counts as distribution of the source code,
|
||||||
|
even though third parties are not compelled to copy the source along with
|
||||||
|
the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program except
|
||||||
|
as expressly provided under this License. Any attempt otherwise to copy, modify,
|
||||||
|
sublicense or distribute the Program is void, and will automatically terminate
|
||||||
|
your rights under this License. However, parties who have received copies,
|
||||||
|
or rights, from you under this License will not have their licenses terminated
|
||||||
|
so long as such parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not signed
|
||||||
|
it. However, nothing else grants you permission to modify or distribute the
|
||||||
|
Program or its derivative works. These actions are prohibited by law if you
|
||||||
|
do not accept this License. Therefore, by modifying or distributing the Program
|
||||||
|
(or any work based on the Program), you indicate your acceptance of this License
|
||||||
|
to do so, and all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the Program),
|
||||||
|
the recipient automatically receives a license from the original licensor
|
||||||
|
to copy, distribute or modify the Program subject to these terms and conditions.
|
||||||
|
You may not impose any further restrictions on the recipients' exercise of
|
||||||
|
the rights granted herein. You are not responsible for enforcing compliance
|
||||||
|
by third parties to this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent infringement
|
||||||
|
or for any other reason (not limited to patent issues), conditions are imposed
|
||||||
|
on you (whether by court order, agreement or otherwise) that contradict the
|
||||||
|
conditions of this License, they do not excuse you from the conditions of
|
||||||
|
this License. If you cannot distribute so as to satisfy simultaneously your
|
||||||
|
obligations under this License and any other pertinent obligations, then as
|
||||||
|
a consequence you may not distribute the Program at all. For example, if a
|
||||||
|
patent license would not permit royalty-free redistribution of the Program
|
||||||
|
by all those who receive copies directly or indirectly through you, then the
|
||||||
|
only way you could satisfy both it and this License would be to refrain entirely
|
||||||
|
from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under any
|
||||||
|
particular circumstance, the balance of the section is intended to apply and
|
||||||
|
the section as a whole is intended to apply in other circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any patents
|
||||||
|
or other property right claims or to contest validity of any such claims;
|
||||||
|
this section has the sole purpose of protecting the integrity of the free
|
||||||
|
software distribution system, which is implemented by public license practices.
|
||||||
|
Many people have made generous contributions to the wide range of software
|
||||||
|
distributed through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing to
|
||||||
|
distribute software through any other system and a licensee cannot impose
|
||||||
|
that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to be a
|
||||||
|
consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in certain
|
||||||
|
countries either by patents or by copyrighted interfaces, the original copyright
|
||||||
|
holder who places the Program under this License may add an explicit geographical
|
||||||
|
distribution limitation excluding those countries, so that distribution is
|
||||||
|
permitted only in or among countries not thus excluded. In such case, this
|
||||||
|
License incorporates the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the General Public License from time to time. Such new versions will be similar
|
||||||
|
in spirit to the present version, but may differ in detail to address new
|
||||||
|
problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program specifies
|
||||||
|
a version number of this License which applies to it and "any later version",
|
||||||
|
you have the option of following the terms and conditions either of that version
|
||||||
|
or of any later version published by the Free Software Foundation. If the
|
||||||
|
Program does not specify a version number of this License, you may choose
|
||||||
|
any version ever published by the Free Software Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free programs
|
||||||
|
whose distribution conditions are different, write to the author to ask for
|
||||||
|
permission. For software which is copyrighted by the Free Software Foundation,
|
||||||
|
write to the Free Software Foundation; we sometimes make exceptions for this.
|
||||||
|
Our decision will be guided by the two goals of preserving the free status
|
||||||
|
of all derivatives of our free software and of promoting the sharing and reuse
|
||||||
|
of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR
|
||||||
|
THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
|
||||||
|
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM
|
||||||
|
"AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
|
||||||
|
BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE
|
||||||
|
OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME
|
||||||
|
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE
|
||||||
|
OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
|
||||||
|
OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES
|
||||||
|
OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH
|
||||||
|
HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest possible
|
||||||
|
use to the public, the best way to achieve this is to make it free software
|
||||||
|
which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest to attach
|
||||||
|
them to the start of each source file to most effectively convey the exclusion
|
||||||
|
of warranty; and each file should have at least the "copyright" line and a
|
||||||
|
pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and an idea of what it does.>
|
||||||
|
|
||||||
|
Copyright (C)< yyyy> <name of author>
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation; either version 2 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
|
||||||
|
Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this when
|
||||||
|
it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author Gnomovision comes
|
||||||
|
with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software,
|
||||||
|
and you are welcome to redistribute it under certain conditions; type `show
|
||||||
|
c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may be
|
||||||
|
called something other than `show w' and `show c'; they could even be mouse-clicks
|
||||||
|
or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary. Here
|
||||||
|
is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision'
|
||||||
|
(which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon >, 1 April 1989 Ty Coon, President of Vice This General
|
||||||
|
Public License does not permit incorporating your program into proprietary
|
||||||
|
programs. If your program is a subroutine library, you may consider it more
|
||||||
|
useful to permit linking proprietary applications with the library. If this
|
||||||
|
is what you want to do, use the GNU Lesser General Public License instead
|
||||||
|
of this License.
|
||||||
625
LICENSES/GPL-3.0-only.txt
Normal file
625
LICENSES/GPL-3.0-only.txt
Normal file
@@ -0,0 +1,625 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright © 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies of this license
|
||||||
|
document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for software and
|
||||||
|
other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed to take
|
||||||
|
away your freedom to share and change the works. By contrast, the GNU General
|
||||||
|
Public License is intended to guarantee your freedom to share and change all
|
||||||
|
versions of a program--to make sure it remains free software for all its users.
|
||||||
|
We, the Free Software Foundation, use the GNU General Public License for most
|
||||||
|
of our software; it applies also to any other work released this way by its
|
||||||
|
authors. You can apply it to your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not price. Our
|
||||||
|
General Public Licenses are designed to make sure that you have the freedom
|
||||||
|
to distribute copies of free software (and charge for them if you wish), that
|
||||||
|
you receive source code or can get it if you want it, that you can change
|
||||||
|
the software or use pieces of it in new free programs, and that you know you
|
||||||
|
can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you these rights
|
||||||
|
or asking you to surrender the rights. Therefore, you have certain responsibilities
|
||||||
|
if you distribute copies of the software, or if you modify it: responsibilities
|
||||||
|
to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether gratis or
|
||||||
|
for a fee, you must pass on to the recipients the same freedoms that you received.
|
||||||
|
You must make sure that they, too, receive or can get the source code. And
|
||||||
|
you must show them these terms so they know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps: (1) assert
|
||||||
|
copyright on the software, and (2) offer you this License giving you legal
|
||||||
|
permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains that
|
||||||
|
there is no warranty for this free software. For both users' and authors'
|
||||||
|
sake, the GPL requires that modified versions be marked as changed, so that
|
||||||
|
their problems will not be attributed erroneously to authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run modified
|
||||||
|
versions of the software inside them, although the manufacturer can do so.
|
||||||
|
This is fundamentally incompatible with the aim of protecting users' freedom
|
||||||
|
to change the software. The systematic pattern of such abuse occurs in the
|
||||||
|
area of products for individuals to use, which is precisely where it is most
|
||||||
|
unacceptable. Therefore, we have designed this version of the GPL to prohibit
|
||||||
|
the practice for those products. If such problems arise substantially in other
|
||||||
|
domains, we stand ready to extend this provision to those domains in future
|
||||||
|
versions of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents. States
|
||||||
|
should not allow patents to restrict development and use of software on general-purpose
|
||||||
|
computers, but in those that do, we wish to avoid the special danger that
|
||||||
|
patents applied to a free program could make it effectively proprietary. To
|
||||||
|
prevent this, the GPL assures that patents cannot be used to render the program
|
||||||
|
non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and modification
|
||||||
|
follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of works,
|
||||||
|
such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this License.
|
||||||
|
Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals
|
||||||
|
or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work in
|
||||||
|
a fashion requiring copyright permission, other than the making of an exact
|
||||||
|
copy. The resulting work is called a "modified version" of the earlier work
|
||||||
|
or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based on the
|
||||||
|
Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without permission,
|
||||||
|
would make you directly or secondarily liable for infringement under applicable
|
||||||
|
copyright law, except executing it on a computer or modifying a private copy.
|
||||||
|
Propagation includes copying, distribution (with or without modification),
|
||||||
|
making available to the public, and in some countries other activities as
|
||||||
|
well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other parties
|
||||||
|
to make or receive copies. Mere interaction with a user through a computer
|
||||||
|
network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices" to the
|
||||||
|
extent that it includes a convenient and prominently visible feature that
|
||||||
|
(1) displays an appropriate copyright notice, and (2) tells the user that
|
||||||
|
there is no warranty for the work (except to the extent that warranties are
|
||||||
|
provided), that licensees may convey the work under this License, and how
|
||||||
|
to view a copy of this License. If the interface presents a list of user commands
|
||||||
|
or options, such as a menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work for making
|
||||||
|
modifications to it. "Object code" means any non-source form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official standard
|
||||||
|
defined by a recognized standards body, or, in the case of interfaces specified
|
||||||
|
for a particular programming language, one that is widely used among developers
|
||||||
|
working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other than
|
||||||
|
the work as a whole, that (a) is included in the normal form of packaging
|
||||||
|
a Major Component, but which is not part of that Major Component, and (b)
|
||||||
|
serves only to enable use of the work with that Major Component, or to implement
|
||||||
|
a Standard Interface for which an implementation is available to the public
|
||||||
|
in source code form. A "Major Component", in this context, means a major essential
|
||||||
|
component (kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to produce
|
||||||
|
the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all the source
|
||||||
|
code needed to generate, install, and (for an executable work) run the object
|
||||||
|
code and to modify the work, including scripts to control those activities.
|
||||||
|
However, it does not include the work's System Libraries, or general-purpose
|
||||||
|
tools or generally available free programs which are used unmodified in performing
|
||||||
|
those activities but which are not part of the work. For example, Corresponding
|
||||||
|
Source includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically linked
|
||||||
|
subprograms that the work is specifically designed to require, such as by
|
||||||
|
intimate data communication or control flow between those subprograms and
|
||||||
|
other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users can regenerate
|
||||||
|
automatically from other parts of the Corresponding Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of copyright
|
||||||
|
on the Program, and are irrevocable provided the stated conditions are met.
|
||||||
|
This License explicitly affirms your unlimited permission to run the unmodified
|
||||||
|
Program. The output from running a covered work is covered by this License
|
||||||
|
only if the output, given its content, constitutes a covered work. This License
|
||||||
|
acknowledges your rights of fair use or other equivalent, as provided by copyright
|
||||||
|
law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not convey, without
|
||||||
|
conditions so long as your license otherwise remains in force. You may convey
|
||||||
|
covered works to others for the sole purpose of having them make modifications
|
||||||
|
exclusively for you, or provide you with facilities for running those works,
|
||||||
|
provided that you comply with the terms of this License in conveying all material
|
||||||
|
for which you do not control copyright. Those thus making or running the covered
|
||||||
|
works for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of your copyrighted
|
||||||
|
material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under the conditions
|
||||||
|
stated below. Sublicensing is not allowed; section 10 makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological measure
|
||||||
|
under any applicable law fulfilling obligations under article 11 of the WIPO
|
||||||
|
copyright treaty adopted on 20 December 1996, or similar laws prohibiting
|
||||||
|
or restricting circumvention of such measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid circumvention
|
||||||
|
of technological measures to the extent such circumvention is effected by
|
||||||
|
exercising rights under this License with respect to the covered work, and
|
||||||
|
you disclaim any intention to limit operation or modification of the work
|
||||||
|
as a means of enforcing, against the work's users, your or third parties'
|
||||||
|
legal rights to forbid circumvention of technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you receive
|
||||||
|
it, in any medium, provided that you conspicuously and appropriately publish
|
||||||
|
on each copy an appropriate copyright notice; keep intact all notices stating
|
||||||
|
that this License and any non-permissive terms added in accord with section
|
||||||
|
7 apply to the code; keep intact all notices of the absence of any warranty;
|
||||||
|
and give all recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey, and you
|
||||||
|
may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to produce
|
||||||
|
it from the Program, in the form of source code under the terms of section
|
||||||
|
4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified it, and
|
||||||
|
giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is released under
|
||||||
|
this License and any conditions added under section 7. This requirement modifies
|
||||||
|
the requirement in section 4 to "keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this License to anyone
|
||||||
|
who comes into possession of a copy. This License will therefore apply, along
|
||||||
|
with any applicable section 7 additional terms, to the whole of the work,
|
||||||
|
and all its parts, regardless of how they are packaged. This License gives
|
||||||
|
no permission to license the work in any other way, but it does not invalidate
|
||||||
|
such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display Appropriate
|
||||||
|
Legal Notices; however, if the Program has interactive interfaces that do
|
||||||
|
not display Appropriate Legal Notices, your work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent works,
|
||||||
|
which are not by their nature extensions of the covered work, and which are
|
||||||
|
not combined with it such as to form a larger program, in or on a volume of
|
||||||
|
a storage or distribution medium, is called an "aggregate" if the compilation
|
||||||
|
and its resulting copyright are not used to limit the access or legal rights
|
||||||
|
of the compilation's users beyond what the individual works permit. Inclusion
|
||||||
|
of a covered work in an aggregate does not cause this License to apply to
|
||||||
|
the other parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms of sections
|
||||||
|
4 and 5, provided that you also convey the machine-readable Corresponding
|
||||||
|
Source under the terms of this License, in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product (including
|
||||||
|
a physical distribution medium), accompanied by the Corresponding Source fixed
|
||||||
|
on a durable physical medium customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product (including
|
||||||
|
a physical distribution medium), accompanied by a written offer, valid for
|
||||||
|
at least three years and valid for as long as you offer spare parts or customer
|
||||||
|
support for that product model, to give anyone who possesses the object code
|
||||||
|
either (1) a copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical medium customarily
|
||||||
|
used for software interchange, for a price no more than your reasonable cost
|
||||||
|
of physically performing this conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the written
|
||||||
|
offer to provide the Corresponding Source. This alternative is allowed only
|
||||||
|
occasionally and noncommercially, and only if you received the object code
|
||||||
|
with such an offer, in accord with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated place (gratis
|
||||||
|
or for a charge), and offer equivalent access to the Corresponding Source
|
||||||
|
in the same way through the same place at no further charge. You need not
|
||||||
|
require recipients to copy the Corresponding Source along with the object
|
||||||
|
code. If the place to copy the object code is a network server, the Corresponding
|
||||||
|
Source may be on a different server (operated by you or a third party) that
|
||||||
|
supports equivalent copying facilities, provided you maintain clear directions
|
||||||
|
next to the object code saying where to find the Corresponding Source. Regardless
|
||||||
|
of what server hosts the Corresponding Source, you remain obligated to ensure
|
||||||
|
that it is available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided you inform
|
||||||
|
other peers where the object code and Corresponding Source of the work are
|
||||||
|
being offered to the general public at no charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded from
|
||||||
|
the Corresponding Source as a System Library, need not be included in conveying
|
||||||
|
the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any tangible
|
||||||
|
personal property which is normally used for personal, family, or household
|
||||||
|
purposes, or (2) anything designed or sold for incorporation into a dwelling.
|
||||||
|
In determining whether a product is a consumer product, doubtful cases shall
|
||||||
|
be resolved in favor of coverage. For a particular product received by a particular
|
||||||
|
user, "normally used" refers to a typical or common use of that class of product,
|
||||||
|
regardless of the status of the particular user or of the way in which the
|
||||||
|
particular user actually uses, or expects or is expected to use, the product.
|
||||||
|
A product is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent the
|
||||||
|
only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods, procedures,
|
||||||
|
authorization keys, or other information required to install and execute modified
|
||||||
|
versions of a covered work in that User Product from a modified version of
|
||||||
|
its Corresponding Source. The information must suffice to ensure that the
|
||||||
|
continued functioning of the modified object code is in no case prevented
|
||||||
|
or interfered with solely because modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or specifically
|
||||||
|
for use in, a User Product, and the conveying occurs as part of a transaction
|
||||||
|
in which the right of possession and use of the User Product is transferred
|
||||||
|
to the recipient in perpetuity or for a fixed term (regardless of how the
|
||||||
|
transaction is characterized), the Corresponding Source conveyed under this
|
||||||
|
section must be accompanied by the Installation Information. But this requirement
|
||||||
|
does not apply if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has been installed
|
||||||
|
in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a requirement
|
||||||
|
to continue to provide support service, warranty, or updates for a work that
|
||||||
|
has been modified or installed by the recipient, or for the User Product in
|
||||||
|
which it has been modified or installed. Access to a network may be denied
|
||||||
|
when the modification itself materially and adversely affects the operation
|
||||||
|
of the network or violates the rules and protocols for communication across
|
||||||
|
the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided, in accord
|
||||||
|
with this section must be in a format that is publicly documented (and with
|
||||||
|
an implementation available to the public in source code form), and must require
|
||||||
|
no special password or key for unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this License
|
||||||
|
by making exceptions from one or more of its conditions. Additional permissions
|
||||||
|
that are applicable to the entire Program shall be treated as though they
|
||||||
|
were included in this License, to the extent that they are valid under applicable
|
||||||
|
law. If additional permissions apply only to part of the Program, that part
|
||||||
|
may be used separately under those permissions, but the entire Program remains
|
||||||
|
governed by this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option remove any
|
||||||
|
additional permissions from that copy, or from any part of it. (Additional
|
||||||
|
permissions may be written to require their own removal in certain cases when
|
||||||
|
you modify the work.) You may place additional permissions on material, added
|
||||||
|
by you to a covered work, for which you have or can give appropriate copyright
|
||||||
|
permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you add
|
||||||
|
to a covered work, you may (if authorized by the copyright holders of that
|
||||||
|
material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the terms of
|
||||||
|
sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or author
|
||||||
|
attributions in that material or in the Appropriate Legal Notices displayed
|
||||||
|
by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or requiring
|
||||||
|
that modified versions of such material be marked in reasonable ways as different
|
||||||
|
from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or authors
|
||||||
|
of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some trade names,
|
||||||
|
trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that material by
|
||||||
|
anyone who conveys the material (or modified versions of it) with contractual
|
||||||
|
assumptions of liability to the recipient, for any liability that these contractual
|
||||||
|
assumptions directly impose on those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further restrictions"
|
||||||
|
within the meaning of section 10. If the Program as you received it, or any
|
||||||
|
part of it, contains a notice stating that it is governed by this License
|
||||||
|
along with a term that is a further restriction, you may remove that term.
|
||||||
|
If a license document contains a further restriction but permits relicensing
|
||||||
|
or conveying under this License, you may add to a covered work material governed
|
||||||
|
by the terms of that license document, provided that the further restriction
|
||||||
|
does not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you must place,
|
||||||
|
in the relevant source files, a statement of the additional terms that apply
|
||||||
|
to those files, or a notice indicating where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the form
|
||||||
|
of a separately written license, or stated as exceptions; the above requirements
|
||||||
|
apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly provided
|
||||||
|
under this License. Any attempt otherwise to propagate or modify it is void,
|
||||||
|
and will automatically terminate your rights under this License (including
|
||||||
|
any patent licenses granted under the third paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your license from
|
||||||
|
a particular copyright holder is reinstated (a) provisionally, unless and
|
||||||
|
until the copyright holder explicitly and finally terminates your license,
|
||||||
|
and (b) permanently, if the copyright holder fails to notify you of the violation
|
||||||
|
by some reasonable means prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is reinstated permanently
|
||||||
|
if the copyright holder notifies you of the violation by some reasonable means,
|
||||||
|
this is the first time you have received notice of violation of this License
|
||||||
|
(for any work) from that copyright holder, and you cure the violation prior
|
||||||
|
to 30 days after your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the licenses
|
||||||
|
of parties who have received copies or rights from you under this License.
|
||||||
|
If your rights have been terminated and not permanently reinstated, you do
|
||||||
|
not qualify to receive new licenses for the same material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or run a copy
|
||||||
|
of the Program. Ancillary propagation of a covered work occurring solely as
|
||||||
|
a consequence of using peer-to-peer transmission to receive a copy likewise
|
||||||
|
does not require acceptance. However, nothing other than this License grants
|
||||||
|
you permission to propagate or modify any covered work. These actions infringe
|
||||||
|
copyright if you do not accept this License. Therefore, by modifying or propagating
|
||||||
|
a covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically receives
|
||||||
|
a license from the original licensors, to run, modify and propagate that work,
|
||||||
|
subject to this License. You are not responsible for enforcing compliance
|
||||||
|
by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an organization,
|
||||||
|
or substantially all assets of one, or subdividing an organization, or merging
|
||||||
|
organizations. If propagation of a covered work results from an entity transaction,
|
||||||
|
each party to that transaction who receives a copy of the work also receives
|
||||||
|
whatever licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the Corresponding
|
||||||
|
Source of the work from the predecessor in interest, if the predecessor has
|
||||||
|
it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the rights
|
||||||
|
granted or affirmed under this License. For example, you may not impose a
|
||||||
|
license fee, royalty, or other charge for exercise of rights granted under
|
||||||
|
this License, and you may not initiate litigation (including a cross-claim
|
||||||
|
or counterclaim in a lawsuit) alleging that any patent claim is infringed
|
||||||
|
by making, using, selling, offering for sale, or importing the Program or
|
||||||
|
any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this License
|
||||||
|
of the Program or a work on which the Program is based. The work thus licensed
|
||||||
|
is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims owned or controlled
|
||||||
|
by the contributor, whether already acquired or hereafter acquired, that would
|
||||||
|
be infringed by some manner, permitted by this License, of making, using,
|
||||||
|
or selling its contributor version, but do not include claims that would be
|
||||||
|
infringed only as a consequence of further modification of the contributor
|
||||||
|
version. For purposes of this definition, "control" includes the right to
|
||||||
|
grant patent sublicenses in a manner consistent with the requirements of this
|
||||||
|
License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free patent
|
||||||
|
license under the contributor's essential patent claims, to make, use, sell,
|
||||||
|
offer for sale, import and otherwise run, modify and propagate the contents
|
||||||
|
of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express agreement
|
||||||
|
or commitment, however denominated, not to enforce a patent (such as an express
|
||||||
|
permission to practice a patent or covenant not to sue for patent infringement).
|
||||||
|
To "grant" such a patent license to a party means to make such an agreement
|
||||||
|
or commitment not to enforce a patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license, and the
|
||||||
|
Corresponding Source of the work is not available for anyone to copy, free
|
||||||
|
of charge and under the terms of this License, through a publicly available
|
||||||
|
network server or other readily accessible means, then you must either (1)
|
||||||
|
cause the Corresponding Source to be so available, or (2) arrange to deprive
|
||||||
|
yourself of the benefit of the patent license for this particular work, or
|
||||||
|
(3) arrange, in a manner consistent with the requirements of this License,
|
||||||
|
to extend the patent license to downstream recipients. "Knowingly relying"
|
||||||
|
means you have actual knowledge that, but for the patent license, your conveying
|
||||||
|
the covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that country
|
||||||
|
that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or arrangement,
|
||||||
|
you convey, or propagate by procuring conveyance of, a covered work, and grant
|
||||||
|
a patent license to some of the parties receiving the covered work authorizing
|
||||||
|
them to use, propagate, modify or convey a specific copy of the covered work,
|
||||||
|
then the patent license you grant is automatically extended to all recipients
|
||||||
|
of the covered work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within the scope
|
||||||
|
of its coverage, prohibits the exercise of, or is conditioned on the non-exercise
|
||||||
|
of one or more of the rights that are specifically granted under this License.
|
||||||
|
You may not convey a covered work if you are a party to an arrangement with
|
||||||
|
a third party that is in the business of distributing software, under which
|
||||||
|
you make payment to the third party based on the extent of your activity of
|
||||||
|
conveying the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory patent
|
||||||
|
license (a) in connection with copies of the covered work conveyed by you
|
||||||
|
(or copies made from those copies), or (b) primarily for and in connection
|
||||||
|
with specific products or compilations that contain the covered work, unless
|
||||||
|
you entered into that arrangement, or that patent license was granted, prior
|
||||||
|
to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting any implied
|
||||||
|
license or other defenses to infringement that may otherwise be available
|
||||||
|
to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or otherwise)
|
||||||
|
that contradict the conditions of this License, they do not excuse you from
|
||||||
|
the conditions of this License. If you cannot convey a covered work so as
|
||||||
|
to satisfy simultaneously your obligations under this License and any other
|
||||||
|
pertinent obligations, then as a consequence you may not convey it at all.
|
||||||
|
For example, if you agree to terms that obligate you to collect a royalty
|
||||||
|
for further conveying from those to whom you convey the Program, the only
|
||||||
|
way you could satisfy both those terms and this License would be to refrain
|
||||||
|
entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have permission to
|
||||||
|
link or combine any covered work with a work licensed under version 3 of the
|
||||||
|
GNU Affero General Public License into a single combined work, and to convey
|
||||||
|
the resulting work. The terms of this License will continue to apply to the
|
||||||
|
part which is the covered work, but the special requirements of the GNU Affero
|
||||||
|
General Public License, section 13, concerning interaction through a network
|
||||||
|
will apply to the combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of the
|
||||||
|
GNU General Public License from time to time. Such new versions will be similar
|
||||||
|
in spirit to the present version, but may differ in detail to address new
|
||||||
|
problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program specifies
|
||||||
|
that a certain numbered version of the GNU General Public License "or any
|
||||||
|
later version" applies to it, you have the option of following the terms and
|
||||||
|
conditions either of that numbered version or of any later version published
|
||||||
|
by the Free Software Foundation. If the Program does not specify a version
|
||||||
|
number of the GNU General Public License, you may choose any version ever
|
||||||
|
published by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future versions of
|
||||||
|
the GNU General Public License can be used, that proxy's public statement
|
||||||
|
of acceptance of a version permanently authorizes you to choose that version
|
||||||
|
for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different permissions. However,
|
||||||
|
no additional obligations are imposed on any author or copyright holder as
|
||||||
|
a result of your choosing to follow a later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE
|
||||||
|
LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||||
|
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER
|
||||||
|
EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM
|
||||||
|
PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR
|
||||||
|
CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL
|
||||||
|
ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM
|
||||||
|
AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL,
|
||||||
|
INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO
|
||||||
|
USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED
|
||||||
|
INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
|
||||||
|
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER
|
||||||
|
PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided above cannot
|
||||||
|
be given local legal effect according to their terms, reviewing courts shall
|
||||||
|
apply local law that most closely approximates an absolute waiver of all civil
|
||||||
|
liability in connection with the Program, unless a warranty or assumption
|
||||||
|
of liability accompanies a copy of the Program in return for a fee. END OF
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest possible
|
||||||
|
use to the public, the best way to achieve this is to make it free software
|
||||||
|
which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest to attach
|
||||||
|
them to the start of each source file to most effectively state the exclusion
|
||||||
|
of warranty; and each file should have at least the "copyright" line and a
|
||||||
|
pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify it under
|
||||||
|
the terms of the GNU General Public License as published by the Free Software
|
||||||
|
Foundation, either version 3 of the License, or (at your option) any later
|
||||||
|
version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License along with
|
||||||
|
this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short notice like
|
||||||
|
this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
|
||||||
|
This is free software, and you are welcome to redistribute it under certain
|
||||||
|
conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands might
|
||||||
|
be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary. For
|
||||||
|
more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General Public
|
||||||
|
License instead of this License. But first, please read <https://www.gnu.org/
|
||||||
|
licenses /why-not-lgpl.html>.
|
||||||
@@ -1,2 +0,0 @@
|
|||||||
This software is provided as GPLv2 (read LICENSE.GPL.txt), or, alternatively,
|
|
||||||
contact KDAB at <info@kdab.com> if you need different licensing.
|
|
||||||
113
README.md
113
README.md
@@ -1,7 +1,15 @@
|
|||||||
KDDockWidgets
|
KDDockWidgets
|
||||||
==============
|
==============
|
||||||
`KDDockWidgets` is a KDAB effort to provide an advanced docking system for Qt.
|
`KDDockWidgets` is a Qt dock widget library written by KDAB, suitable for replacing
|
||||||
|
`QDockWidget` and implementing advanced functionalities missing in Qt.
|
||||||
|
|
||||||
|
Although `KDDockWidgets` is ready to be used out of the box, it can also be seen
|
||||||
|
as a framework to allow building very tailored custom docking systems. It tries
|
||||||
|
to expose every internal widget and every knob for the app developer to tune.
|
||||||
|
|
||||||
|
|
||||||
|
Motivation
|
||||||
|
==========
|
||||||
Throughout the years KDAB contributed and funded bug fixes and features to `QDockWidget`.
|
Throughout the years KDAB contributed and funded bug fixes and features to `QDockWidget`.
|
||||||
Sadly, this was very painful. Each bug fix or feature took many days of implementation,
|
Sadly, this was very painful. Each bug fix or feature took many days of implementation,
|
||||||
and an equal number of days just to fix dozens of regressions.
|
and an equal number of days just to fix dozens of regressions.
|
||||||
@@ -10,39 +18,65 @@ and an equal number of days just to fix dozens of regressions.
|
|||||||
to move forward with new features. Furthermore, our customers were getting more
|
to move forward with new features. Furthermore, our customers were getting more
|
||||||
creative with their requests, so it was clear we needed a better docking framework.
|
creative with their requests, so it was clear we needed a better docking framework.
|
||||||
|
|
||||||
|
You will find more information in these places:
|
||||||
|
|
||||||
|
* [our official home page](https://www.kdab.com/kddockwidgets)
|
||||||
|
* [online detailed browsable API reference](https://docs.kdab.com/kddockwidgets)
|
||||||
|
* [our example programs](examples/)
|
||||||
|
|
||||||
Features
|
Features
|
||||||
========
|
========
|
||||||
- Provide advanced docking that QDockWidgets doesn't support
|
- Provide advanced docking that QDockWidgets doesn't support
|
||||||
|
- Native window resize on Windows (allowing for Aero-snap even with custom title bar decorations)
|
||||||
|
- Arrow drop indicators for great drop precision
|
||||||
|
- Allow for totally different, user provided, drop indicator types
|
||||||
- Nesting dock widgets in a floating window and docking that group back to main window
|
- 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 any main window, not only to the parent main window
|
||||||
- Docking to center of main window, or simply removing the concept of "central widget"
|
- Docking to center of main window, or simply removing the concept of "central widget"
|
||||||
- Main window supporting detachable tabs in center widget
|
- Main window supporting detachable tabs in center widget
|
||||||
- Detaching arbitrary tabs from a tab bar into a dock area
|
- Detaching arbitrary tabs from a tab bar into a dock area
|
||||||
|
- Supporting more than 1 main window
|
||||||
|
- Support for affinities, making some dock widgets only dockable on certain main windows
|
||||||
|
- Allow to hide TitleBar and just show tabs. Allows dragging via the tab bar.
|
||||||
- Exposing inner helper widgets so the user can customize them or provide his own
|
- Exposing inner helper widgets so the user can customize them or provide his own
|
||||||
- Customize tab widgets
|
- Customize tab widgets
|
||||||
- Customize title bars
|
- Customize title bars
|
||||||
- Customize window frames
|
- Customize window frames
|
||||||
|
- Custom widget separators
|
||||||
|
- Layouting engine honouring min/max size constraints and some size policies
|
||||||
|
- PySide2 bindings
|
||||||
- Clean codebase
|
- Clean codebase
|
||||||
- Not mixing GUI with state with logic with animations
|
- Not mixing GUI with state with logic with animations
|
||||||
- Unit-test everything, even the GUI and DnD operations (140 tests currently)
|
- Great test coverage, even the gui and DnD operations are tested. 200 tests currently.
|
||||||
- Fuzzer for doing random testing
|
- Fuzzer for doing random testing and finding bugs
|
||||||
|
- Lazy separator resize
|
||||||
|
- Reordering tabs with mouse
|
||||||
|
- Partial layout save/restore, affecting only a chosen sub-set
|
||||||
|
- Double click on title bar to maximize
|
||||||
|
- Double click on separator to distribute equally
|
||||||
|
- Show close button on tabs
|
||||||
|
- Allow to make a dock widget non-closable and/or non-dockable
|
||||||
|
- Optional maximize button on the title bar
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
Roadmap
|
Roadmap
|
||||||
========
|
========
|
||||||
- Different forms of docking indicators (through plugins)
|
- QtQuick support for v1.1
|
||||||
- QtQuick support
|
- "Minimization bar" for v1.2
|
||||||
|
|
||||||
|
Trying out the examples
|
||||||
|
=======================
|
||||||
|
A full demo lives in `examples/dockwidgets/`, it showcasts most of the features.
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
Trying out the demo
|
Open a terminal capable of building Qt5 applications.
|
||||||
====================
|
Make sure you have cmake, ninja, compiler, Qt, etc in PATH.
|
||||||
|
|
||||||
Open a terminal capable of building Qt5 applications (Should have cmake, ninja, compiler, Qt, etc in PATH).
|
Adapt the instructions to suit your cmake generator and operating system.
|
||||||
|
|
||||||
Feel free to adapt the instructions to suit your cmake generator and operating system.
|
|
||||||
Build and install the KDDockWidgets framework:
|
Build and install the KDDockWidgets framework:
|
||||||
|
|
||||||
```
|
```
|
||||||
@@ -60,29 +94,68 @@ $ ./kddockwidgets_example
|
|||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
The installation directory defaults to `c:\KDAB\KDDockWidgets-<version>` on Windows
|
||||||
|
and `/usr/local/KDAB/KDDockWidgets-<version>` on non-Windows. You can change this
|
||||||
|
location by passing the option `-DCMAKE_INSTALL_PREFIX=/install/path` to cmake.
|
||||||
|
|
||||||
|
|
||||||
|
Python Bindings
|
||||||
|
================
|
||||||
|
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
|
||||||
|
|
||||||
|
Once QtForPython is installed you are ready to generate the PySide bindings
|
||||||
|
for KDDockwWidgets.
|
||||||
|
|
||||||
|
Next pass `-DOPTION_BUILD_PYTHON_BINDINGS=ON` to CMake, 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 `-DPYTHON_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
|
Supported Qt versions
|
||||||
======================
|
======================
|
||||||
KDDockWidgets requires Qt >= 5.9
|
KDDockWidgets requires Qt >= 5.9 (or >=5.12 if Python bindings are enabled).
|
||||||
|
The QtQuick support will require Qt >= 5.15.
|
||||||
|
|
||||||
Licensing
|
Licensing
|
||||||
=========
|
=========
|
||||||
KDDockWidgets is (C) 2018-2020, Klarälvdalens Datakonsult AB, and is available
|
KDDockWidgets is (C) 2018-2020, Klarälvdalens Datakonsult AB, and is licensed according to
|
||||||
under the terms of the GPLv2 (see LICENSE.GPL.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> if you need different licensing options.
|
|
||||||
|
|
||||||
Get Involved
|
Get Involved
|
||||||
============
|
============
|
||||||
KDAB will happily accept external contributions; however, **all**
|
KDAB will happily accept external contributions; however, **all** contributions require a
|
||||||
contributions will require a signed Contributor License Agreement
|
signed [Copyright Assignment Agreement](docs/KDDockWidgets-CopyrightAssignmentForm.docx).
|
||||||
(see docs/KDDockWidgets-CopyrightAssignmentForm.docx).
|
|
||||||
|
|
||||||
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
|
Please submit your contributions or issue reports from our GitHub space at
|
||||||
https://github.com/KDAB/KDDockWidgets
|
https://github.com/KDAB/KDDockWidgets
|
||||||
|
|
||||||
|
|
||||||
About KDAB
|
About KDAB
|
||||||
==========
|
==========
|
||||||
KDDockWidgets is supported and maintained by Klarälvdalens Datakonsult AB (KDAB).
|
KDDockWidgets is supported and maintained by Klarälvdalens Datakonsult AB (KDAB).
|
||||||
|
|||||||
28
cmake/ECM/modules/BSD-3-Clause.txt
Normal file
28
cmake/ECM/modules/BSD-3-Clause.txt
Normal 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.
|
||||||
@@ -40,6 +40,7 @@
|
|||||||
# - thread
|
# - thread
|
||||||
# - leak
|
# - leak
|
||||||
# - undefined
|
# - undefined
|
||||||
|
# - fuzzer
|
||||||
#
|
#
|
||||||
# The sanitizers "address", "memory" and "thread" are mutually exclusive. You
|
# The sanitizers "address", "memory" and "thread" are mutually exclusive. You
|
||||||
# cannot enable two of them in the same build.
|
# cannot enable two of them in the same build.
|
||||||
@@ -69,30 +70,9 @@
|
|||||||
# Since 1.3.0.
|
# Since 1.3.0.
|
||||||
|
|
||||||
#=============================================================================
|
#=============================================================================
|
||||||
# Copyright 2014 Mathieu Tarral <mathieu.tarral@gmail.com>
|
# SPDX-FileCopyrightText: 2014 Mathieu Tarral <mathieu.tarral@gmail.com>
|
||||||
#
|
#
|
||||||
# Redistribution and use in source and binary forms, with or without
|
# SPDX-License-Identifier: BSD-3-Clause
|
||||||
# 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.
|
|
||||||
|
|
||||||
# MACRO check_compiler_version
|
# MACRO check_compiler_version
|
||||||
#-----------------------------
|
#-----------------------------
|
||||||
@@ -140,6 +120,9 @@ macro (enable_sanitizer_flags sanitize_option)
|
|||||||
elseif (${sanitize_option} MATCHES "undefined")
|
elseif (${sanitize_option} MATCHES "undefined")
|
||||||
check_compiler_version("4.9" "3.1")
|
check_compiler_version("4.9" "3.1")
|
||||||
set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls")
|
set(XSAN_COMPILE_FLAGS "-fsanitize=undefined -fno-omit-frame-pointer -fno-optimize-sibling-calls")
|
||||||
|
elseif (${sanitize_option} MATCHES "fuzzer")
|
||||||
|
check_compiler_version("99.99" "6.0")
|
||||||
|
set(XSAN_COMPILE_FLAGS "-fsanitize=fuzzer")
|
||||||
else ()
|
else ()
|
||||||
message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.")
|
message(FATAL_ERROR "Compiler sanitizer option \"${sanitize_option}\" not supported.")
|
||||||
endif ()
|
endif ()
|
||||||
@@ -161,7 +144,7 @@ if (ECM_ENABLE_SANITIZERS)
|
|||||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU")
|
||||||
link_libraries(${XSAN_LINKER_FLAGS})
|
link_libraries(${XSAN_LINKER_FLAGS})
|
||||||
endif()
|
endif()
|
||||||
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
|
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
||||||
string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
string(REPLACE "-Wl,--no-undefined" "" CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS}")
|
||||||
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 ()
|
||||||
|
|||||||
199
cmake/ECM/modules/ECMGeneratePriFile.cmake
Normal file
199
cmake/ECM/modules/ECMGeneratePriFile.cmake
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
#.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-License-Identifier: BSD-3-Clause
|
||||||
|
|
||||||
|
# Replicate the logic from KDEInstallDirs.cmake as we can't depend on it
|
||||||
|
# Ask qmake if we're using the same prefix as Qt
|
||||||
|
set(_askqmake OFF)
|
||||||
|
if(NOT DEFINED KDE_INSTALL_USE_QT_SYS_PATHS)
|
||||||
|
include(ECMQueryQmake)
|
||||||
|
query_qmake(qt_install_prefix_dir QT_INSTALL_PREFIX TRY)
|
||||||
|
if(qt_install_prefix_dir STREQUAL "${CMAKE_INSTALL_PREFIX}")
|
||||||
|
set(_askqmake ON)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(KDE_INSTALL_USE_QT_SYS_PATHS OR _askqmake)
|
||||||
|
include(ECMQueryQmake)
|
||||||
|
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.")
|
||||||
|
else()
|
||||||
|
set(ECM_MKSPECS_INSTALL_DIR mkspecs/modules CACHE PATH "The directory where mkspecs will be installed to.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
function(ECM_GENERATE_PRI_FILE)
|
||||||
|
set(options )
|
||||||
|
set(oneValueArgs BASE_NAME LIB_NAME DEPS FILENAME_VAR INCLUDE_INSTALL_DIR LIB_INSTALL_DIR)
|
||||||
|
set(multiValueArgs )
|
||||||
|
|
||||||
|
cmake_parse_arguments(EGPF "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(EGPF_UNPARSED_ARGUMENTS)
|
||||||
|
message(FATAL_ERROR "Unknown keywords given to ECM_GENERATE_PRI_FILE(): \"${EGPF_UNPARSED_ARGUMENTS}\"")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT EGPF_BASE_NAME)
|
||||||
|
message(FATAL_ERROR "Required argument BASE_NAME missing in ECM_GENERATE_PRI_FILE() call")
|
||||||
|
endif()
|
||||||
|
if(NOT EGPF_LIB_NAME)
|
||||||
|
message(FATAL_ERROR "Required argument LIB_NAME missing in ECM_GENERATE_PRI_FILE() call")
|
||||||
|
endif()
|
||||||
|
if(NOT PROJECT_VERSION_STRING)
|
||||||
|
message(FATAL_ERROR "Required variable PROJECT_VERSION_STRING not set before ECM_GENERATE_PRI_FILE() call. Did you call ecm_setup_version?")
|
||||||
|
endif()
|
||||||
|
if(NOT EGPF_INCLUDE_INSTALL_DIR)
|
||||||
|
if(INCLUDE_INSTALL_DIR)
|
||||||
|
set(EGPF_INCLUDE_INSTALL_DIR "${INCLUDE_INSTALL_DIR}/${EGPF_BASE_NAME}")
|
||||||
|
elseif(CMAKE_INSTALL_INCLUDEDIR)
|
||||||
|
set(EGPF_INCLUDE_INSTALL_DIR "${CMAKE_INSTALL_INCLUDEDIR}/${EGPF_BASE_NAME}")
|
||||||
|
else()
|
||||||
|
set(EGPF_INCLUDE_INSTALL_DIR "include/${EGPF_BASE_NAME}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if(NOT EGPF_LIB_INSTALL_DIR)
|
||||||
|
if(LIB_INSTALL_DIR)
|
||||||
|
set(EGPF_LIB_INSTALL_DIR "${LIB_INSTALL_DIR}")
|
||||||
|
elseif(CMAKE_INSTALL_LIBDIR)
|
||||||
|
set(EGPF_LIB_INSTALL_DIR "${CMAKE_INSTALL_LIBDIR}")
|
||||||
|
else()
|
||||||
|
set(EGPF_LIB_INSTALL_DIR "lib")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(REGEX REPLACE "^([0-9]+)\\.[0-9]+\\.[0-9]+.*" "\\1" PROJECT_VERSION_MAJOR "${PROJECT_VERSION_STRING}")
|
||||||
|
string(REGEX REPLACE "^[0-9]+\\.([0-9]+)\\.[0-9]+.*" "\\1" PROJECT_VERSION_MINOR "${PROJECT_VERSION_STRING}")
|
||||||
|
string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+).*" "\\1" PROJECT_VERSION_PATCH "${PROJECT_VERSION_STRING}")
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
if (IS_ABSOLUTE ${ECM_MKSPECS_INSTALL_DIR})
|
||||||
|
set(BASEPATH ${CMAKE_INSTALL_PREFIX})
|
||||||
|
else()
|
||||||
|
string(REGEX REPLACE "[^/]+" ".." PRI_ROOT_RELATIVE_TO_MKSPECS ${ECM_MKSPECS_INSTALL_DIR})
|
||||||
|
set(BASEPATH "$$PWD/${PRI_ROOT_RELATIVE_TO_MKSPECS}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PRI_TARGET_BASENAME ${EGPF_BASE_NAME})
|
||||||
|
set(PRI_TARGET_LIBNAME ${EGPF_LIB_NAME})
|
||||||
|
set(PRI_TARGET_QTDEPS ${EGPF_DEPS})
|
||||||
|
if(IS_ABSOLUTE "${EGPF_INCLUDE_INSTALL_DIR}")
|
||||||
|
set(PRI_TARGET_INCLUDES "${EGPF_INCLUDE_INSTALL_DIR}")
|
||||||
|
else()
|
||||||
|
set(PRI_TARGET_INCLUDES "${BASEPATH}/${EGPF_INCLUDE_INSTALL_DIR}")
|
||||||
|
endif()
|
||||||
|
if(IS_ABSOLUTE "${EGPF_LIB_INSTALL_DIR}")
|
||||||
|
set(PRI_TARGET_LIBS "${EGPF_LIB_INSTALL_DIR}")
|
||||||
|
else()
|
||||||
|
set(PRI_TARGET_LIBS "${BASEPATH}/${EGPF_LIB_INSTALL_DIR}")
|
||||||
|
endif()
|
||||||
|
set(PRI_TARGET_DEFINES "")
|
||||||
|
|
||||||
|
set(PRI_FILENAME ${CMAKE_CURRENT_BINARY_DIR}/qt_${PRI_TARGET_BASENAME}.pri)
|
||||||
|
if (EGPF_FILENAME_VAR)
|
||||||
|
set(${EGPF_FILENAME_VAR} ${PRI_FILENAME} PARENT_SCOPE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PRI_TARGET_MODULE_CONFIG "")
|
||||||
|
# backward compat: it was not obvious LIB_NAME needs to be a target name,
|
||||||
|
# and some projects where the target name was not the actual library output name
|
||||||
|
# passed the output name for LIB_NAME, so .name & .module prperties are correctly set.
|
||||||
|
# TODO: improve API dox, allow control over module name if target name != output name
|
||||||
|
if(TARGET ${EGPF_LIB_NAME})
|
||||||
|
get_target_property(target_type ${EGPF_LIB_NAME} TYPE)
|
||||||
|
if (target_type STREQUAL "STATIC_LIBRARY")
|
||||||
|
set(PRI_TARGET_MODULE_CONFIG "staticlib")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GENERATE
|
||||||
|
OUTPUT ${PRI_FILENAME}
|
||||||
|
CONTENT
|
||||||
|
"QT.${PRI_TARGET_BASENAME}.VERSION = ${PROJECT_VERSION_STRING}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.MAJOR_VERSION = ${PROJECT_VERSION_MAJOR}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.MINOR_VERSION = ${PROJECT_VERSION_MINOR}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.PATCH_VERSION = ${PROJECT_VERSION_PATCH}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.name = ${PRI_TARGET_LIBNAME}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.module = ${PRI_TARGET_LIBNAME}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.defines = ${PRI_TARGET_DEFINES}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.includes = ${PRI_TARGET_INCLUDES}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.private_includes =
|
||||||
|
QT.${PRI_TARGET_BASENAME}.libs = ${PRI_TARGET_LIBS}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.depends = ${PRI_TARGET_QTDEPS}
|
||||||
|
QT.${PRI_TARGET_BASENAME}.module_config = ${PRI_TARGET_MODULE_CONFIG}
|
||||||
|
"
|
||||||
|
)
|
||||||
|
endfunction()
|
||||||
46
cmake/ECM/modules/ECMQueryQmake.cmake
Normal file
46
cmake/ECM/modules/ECMQueryQmake.cmake
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
find_package(Qt5Core QUIET)
|
||||||
|
|
||||||
|
if (Qt5Core_FOUND)
|
||||||
|
set(_qmake_executable_default "qmake-qt5")
|
||||||
|
endif ()
|
||||||
|
if (TARGET Qt5::qmake)
|
||||||
|
get_target_property(_qmake_executable_default Qt5::qmake LOCATION)
|
||||||
|
endif()
|
||||||
|
set(QMAKE_EXECUTABLE ${_qmake_executable_default}
|
||||||
|
CACHE FILEPATH "Location of the Qt5 qmake executable")
|
||||||
|
|
||||||
|
# Helper method
|
||||||
|
# This is not public API (yet)!
|
||||||
|
# Usage: query_qmake(<result_variable> <qt_variable> [TRY])
|
||||||
|
# Passing TRY will result in the method not failing fatal if no qmake executable
|
||||||
|
# has been found, but instead simply returning an empty string
|
||||||
|
function(query_qmake result_variable qt_variable)
|
||||||
|
set(options TRY)
|
||||||
|
set(oneValueArgs )
|
||||||
|
set(multiValueArgs )
|
||||||
|
|
||||||
|
cmake_parse_arguments(ARGS "${options}" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
|
||||||
|
|
||||||
|
if(NOT QMAKE_EXECUTABLE)
|
||||||
|
if(ARGS_TRY)
|
||||||
|
set(${result_variable} "" PARENT_SCOPE)
|
||||||
|
message(STATUS "No qmake Qt5 binary found. Can't check ${qt_variable}")
|
||||||
|
return()
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "No qmake Qt5 binary found. Can't check ${qt_variable} as required")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${QMAKE_EXECUTABLE} -query "${qt_variable}"
|
||||||
|
RESULT_VARIABLE return_code
|
||||||
|
OUTPUT_VARIABLE output
|
||||||
|
)
|
||||||
|
if(return_code EQUAL 0)
|
||||||
|
string(STRIP "${output}" output)
|
||||||
|
file(TO_CMAKE_PATH "${output}" output_path)
|
||||||
|
set(${result_variable} "${output_path}" PARENT_SCOPE)
|
||||||
|
else()
|
||||||
|
message(WARNING "Failed call: ${QMAKE_EXECUTABLE} -query \"${qt_variable}\"")
|
||||||
|
message(FATAL_ERROR "QMake call failed: ${return_code}")
|
||||||
|
endif()
|
||||||
|
endfunction()
|
||||||
35
cmake/InstallLocation.cmake
Normal file
35
cmake/InstallLocation.cmake
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
# Some default installation locations. These should be global, with any project
|
||||||
|
# specific locations added to the end. These paths are all relative to the
|
||||||
|
# install prefix.
|
||||||
|
#
|
||||||
|
# These paths attempt to adhere to the FHS, and are similar to those provided
|
||||||
|
# by autotools and used in many Linux distributions.
|
||||||
|
|
||||||
|
# Use GNU install directories
|
||||||
|
include(GNUInstallDirs)
|
||||||
|
|
||||||
|
if(NOT INSTALL_RUNTIME_DIR)
|
||||||
|
set(INSTALL_RUNTIME_DIR ${CMAKE_INSTALL_BINDIR})
|
||||||
|
endif()
|
||||||
|
if(NOT INSTALL_LIBRARY_DIR)
|
||||||
|
set(INSTALL_LIBRARY_DIR ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
endif()
|
||||||
|
if(NOT INSTALL_ARCHIVE_DIR)
|
||||||
|
set(INSTALL_ARCHIVE_DIR ${CMAKE_INSTALL_LIBDIR})
|
||||||
|
endif()
|
||||||
|
if(NOT INSTALL_INCLUDE_DIR)
|
||||||
|
set(INSTALL_INCLUDE_DIR ${CMAKE_INSTALL_INCLUDEDIR})
|
||||||
|
endif()
|
||||||
|
if(NOT INSTALL_DATADIR)
|
||||||
|
set(INSTALL_DATADIR ${CMAKE_INSTALL_DATADIR})
|
||||||
|
endif()
|
||||||
|
if(NOT INSTALL_DOC_DIR)
|
||||||
|
set(INSTALL_DOC_DIR ${CMAKE_INSTALL_DOCDIR})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||||
|
if (APPLE)
|
||||||
|
set(CMAKE_MACOSX_RPATH ON)
|
||||||
|
else()
|
||||||
|
set(CMAKE_INSTALL_RPATH "$ORIGIN/../${INSTALL_LIBRARY_DIR}")
|
||||||
|
endif()
|
||||||
159
cmake/Python/FindPySide2.cmake
Normal file
159
cmake/Python/FindPySide2.cmake
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
# PYSIDE_BASEDIR - Top of the PySide2 installation
|
||||||
|
# PYSIDE_INCLUDE_DIR - Directories to include to use PySide2
|
||||||
|
# PYSIDE_LIBRARY - Files to link against to use PySide2
|
||||||
|
# PYSIDE_TYPESYSTEMS - Type system files that should be used by other bindings extending PySide2
|
||||||
|
#
|
||||||
|
# You can install PySide2 from Qt repository with
|
||||||
|
# pip3 install --index-url=https://download.qt.io/snapshots/ci/pyside/<Qt-Version>/latest/ pyside2 --trusted-host download.qt.io
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(PYSIDE2_PRIV pyside2 QUIET)
|
||||||
|
|
||||||
|
set(PYSIDE2_FOUND FALSE)
|
||||||
|
|
||||||
|
if(PYSIDE2_PRIV_FOUND)
|
||||||
|
set(PYSIDE2_FOUND TRUE)
|
||||||
|
message(STATUS "Using PySide2 found in the system!")
|
||||||
|
pkg_get_variable(SHIBOKEN_BINARY
|
||||||
|
pyside2
|
||||||
|
generator_location
|
||||||
|
)
|
||||||
|
pkg_get_variable(PYSIDE2_BASEDIR
|
||||||
|
pyside2
|
||||||
|
typesystemdir
|
||||||
|
)
|
||||||
|
pkg_get_variable(PYSIDE_INCLUDE_DIR
|
||||||
|
pyside2
|
||||||
|
includedir
|
||||||
|
)
|
||||||
|
set(PYSIDE_TYPESYSTEMS ${PYSIDE2_BASEDIR})
|
||||||
|
set(PYSIDE2_SO_VERSION ${PYSIDE2_PRIV_VERSION})
|
||||||
|
set(PYSIDE_LIBRARY ${PYSIDE2_PRIV_LINK_LIBRARIES})
|
||||||
|
list(GET PYSIDE_LIBRARY 0 PYSIDE_LIBRARY)
|
||||||
|
else()
|
||||||
|
# extract python library basename
|
||||||
|
list(GET Python3_LIBRARIES 0 PYTHON_LIBRARY_FILENAME)
|
||||||
|
get_filename_component(PYTHON_LIBRARY_FILENAME ${PYTHON_LIBRARY_FILENAME} NAME)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -c "if True:
|
||||||
|
import os, sys
|
||||||
|
try:
|
||||||
|
import PySide2.QtCore as QtCore
|
||||||
|
print(os.path.dirname(QtCore.__file__))
|
||||||
|
except Exception as error:
|
||||||
|
print(error, file=sys.stderr)
|
||||||
|
exit()
|
||||||
|
"
|
||||||
|
OUTPUT_VARIABLE PYSIDE2_BASEDIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
if(PYSIDE2_BASEDIR)
|
||||||
|
set(PYSIDE_BASEDIR ${PYSIDE2_BASEDIR} CACHE PATH "Top level install of PySide2" FORCE)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -c "if True:
|
||||||
|
import os
|
||||||
|
import PySide2.QtCore as QtCore
|
||||||
|
print(os.path.basename(QtCore.__file__).split('.', 1)[1])
|
||||||
|
"
|
||||||
|
OUTPUT_VARIABLE PYSIDE2_SUFFIX
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -c "if True:
|
||||||
|
import os
|
||||||
|
import PySide2.QtCore as QtCore
|
||||||
|
print(';'.join(map(str, QtCore.__version_info__)))
|
||||||
|
"
|
||||||
|
OUTPUT_VARIABLE PYSIDE2_SO_VERSION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
list(GET PYSIDE2_SO_VERSION 0 PYSIDE2_SO_MACRO_VERSION)
|
||||||
|
list(GET PYSIDE2_SO_VERSION 1 PYSIDE2_SO_MICRO_VERSION)
|
||||||
|
list(GET PYSIDE2_SO_VERSION 2 PYSIDE2_SO_MINOR_VERSION)
|
||||||
|
string(REPLACE ";" "." PYSIDE2_SO_VERSION "${PYSIDE2_SO_VERSION}")
|
||||||
|
|
||||||
|
if(NOT APPLE)
|
||||||
|
set(PYSIDE2_SUFFIX "${PYSIDE2_SUFFIX}.${PYSIDE2_SO_MACRO_VERSION}.${PYSIDE2_SO_MICRO_VERSION}")
|
||||||
|
else()
|
||||||
|
string(REPLACE ".so" "" PYSIDE2_SUFFIX ${PYSIDE2_SUFFIX})
|
||||||
|
set(PYSIDE2_SUFFIX "${PYSIDE2_SUFFIX}.${PYSIDE2_SO_MACRO_VERSION}.${PYSIDE2_SO_MICRO_VERSION}.dylib")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
set(PYSIDE2_FOUND TRUE)
|
||||||
|
message(STATUS "PySide2 base dir: ${PYSIDE2_BASEDIR}" )
|
||||||
|
message(STATUS "PySide2 suffix: ${PYSIDE2_SUFFIX}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (PYSIDE2_FOUND)
|
||||||
|
#PySide
|
||||||
|
#===============================================================================
|
||||||
|
find_path(PYSIDE_INCLUDE_DIR
|
||||||
|
pyside.h
|
||||||
|
PATHS ${PYSIDE2_BASEDIR}/include ${PYSIDE2_CUSTOM_PREFIX}/include/PySide2
|
||||||
|
NO_DEFAULT_PATH)
|
||||||
|
|
||||||
|
# Platform specific library names
|
||||||
|
if(MSVC)
|
||||||
|
SET(PYSIDE_LIBRARY_BASENAMES "pyside2.abi3.lib")
|
||||||
|
elseif(CYGWIN)
|
||||||
|
SET(PYSIDE_LIBRARY_BASENAMES "")
|
||||||
|
elseif(WIN32)
|
||||||
|
SET(PYSIDE_LIBRARY_BASENAMES "libpyside2.${PYSIDE2_SUFFIX}")
|
||||||
|
else()
|
||||||
|
SET(PYSIDE_LIBRARY_BASENAMES "libpyside2.${PYSIDE2_SUFFIX}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_file(PYSIDE_LIBRARY
|
||||||
|
${PYSIDE_LIBRARY_BASENAMES}
|
||||||
|
PATHS ${PYSIDE2_BASEDIR} ${PYSIDE2_CUSTOM_PREFIX}/lib
|
||||||
|
NO_DEFAULT_PATH)
|
||||||
|
|
||||||
|
find_path(PYSIDE_TYPESYSTEMS
|
||||||
|
typesystem_core.xml
|
||||||
|
PATHS ${PYSIDE2_BASEDIR}/typesystems ${PYSIDE2_CUSTOM_PREFIX}/share/PySide2/typesystems
|
||||||
|
NO_DEFAULT_PATH)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(PYSIDE2_FOUND)
|
||||||
|
message(STATUS "PySide include dir: ${PYSIDE_INCLUDE_DIR}")
|
||||||
|
message(STATUS "PySide library: ${PYSIDE_LIBRARY}")
|
||||||
|
message(STATUS "PySide typesystems: ${PYSIDE_TYPESYSTEMS}")
|
||||||
|
message(STATUS "PySide2 version: ${PYSIDE2_SO_VERSION}")
|
||||||
|
|
||||||
|
# Create PySide2 target
|
||||||
|
add_library(PySide2::pyside2 SHARED IMPORTED GLOBAL)
|
||||||
|
if(MSVC)
|
||||||
|
set_property(TARGET PySide2::pyside2 PROPERTY
|
||||||
|
IMPORTED_IMPLIB ${PYSIDE_LIBRARY})
|
||||||
|
endif()
|
||||||
|
set_property(TARGET PySide2::pyside2 PROPERTY
|
||||||
|
IMPORTED_LOCATION ${PYSIDE_LIBRARY})
|
||||||
|
set_property(TARGET PySide2::pyside2 APPEND PROPERTY
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES
|
||||||
|
${PYSIDE_INCLUDE_DIR}
|
||||||
|
${PYSIDE_INCLUDE_DIR}/QtCore/
|
||||||
|
${PYSIDE_INCLUDE_DIR}/QtGui/
|
||||||
|
${PYSIDE_INCLUDE_DIR}/QtWidgets/
|
||||||
|
${Python3_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
find_package_handle_standard_args(PySide2
|
||||||
|
REQUIRED_VARS PYSIDE2_BASEDIR PYSIDE_INCLUDE_DIR PYSIDE_LIBRARY PYSIDE_TYPESYSTEMS
|
||||||
|
VERSION_VAR PYSIDE2_SO_VERSION
|
||||||
|
)
|
||||||
187
cmake/Python/FindShiboken2.cmake
Normal file
187
cmake/Python/FindShiboken2.cmake
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
# SHIBOKEN_INCLUDE_DIR - Directories to include to use SHIBOKEN
|
||||||
|
# SHIBOKEN_LIBRARY - Files to link against to use SHIBOKEN
|
||||||
|
# SHIBOKEN_BINARY - Executable name
|
||||||
|
# SHIBOKEN_BUILD_TYPE - Tells if Shiboken was compiled in Release or Debug mode.
|
||||||
|
|
||||||
|
# You can install Shiboken from Qt repository with
|
||||||
|
# pip3 install --index-url=https://download.qt.io/snapshots/ci/pyside/<Qt-Version>/latest/ shiboken2-generator --trusted-host download.qt.io
|
||||||
|
find_package(PkgConfig REQUIRED)
|
||||||
|
pkg_check_modules(SHIBOKEN2_PRIV shiboken2 QUIET)
|
||||||
|
|
||||||
|
set(SHIBOKEN_FOUND FALSE)
|
||||||
|
|
||||||
|
if(SHIBOKEN2_PRIV_FOUND)
|
||||||
|
set(SHIBOKEN_FOUND TRUE)
|
||||||
|
message(STATUS "Using shiboken found in the system!")
|
||||||
|
pkg_get_variable(SHIBOKEN_BINARY
|
||||||
|
shiboken2
|
||||||
|
generator_location
|
||||||
|
)
|
||||||
|
pkg_get_variable(SHIBOKEN_BASEDIR
|
||||||
|
shiboken2
|
||||||
|
libdir
|
||||||
|
)
|
||||||
|
pkg_get_variable(SHIBOKEN_INCLUDE_DIR
|
||||||
|
shiboken2
|
||||||
|
includedir
|
||||||
|
)
|
||||||
|
set(SHIBOKEN_VERSION ${SHIBOKEN2_PRIV_VERSION})
|
||||||
|
set(SHIBOKEN_LIBRARY ${SHIBOKEN2_PRIV_LINK_LIBRARIES})
|
||||||
|
else()
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -c "if True:
|
||||||
|
import os
|
||||||
|
try:
|
||||||
|
import shiboken2_generator
|
||||||
|
print(shiboken2_generator.__path__[0])
|
||||||
|
except:
|
||||||
|
exit()
|
||||||
|
"
|
||||||
|
OUTPUT_VARIABLE SHIBOKEN_GENERATOR_BASEDIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -c "if True:
|
||||||
|
import os
|
||||||
|
try:
|
||||||
|
import shiboken2
|
||||||
|
print(shiboken2.__path__[0])
|
||||||
|
except:
|
||||||
|
exit()
|
||||||
|
"
|
||||||
|
OUTPUT_VARIABLE SHIBOKEN_BASEDIR
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -c "if True:
|
||||||
|
import os
|
||||||
|
import shiboken2
|
||||||
|
print(';'.join(filter(None, map(str, shiboken2.__version_info__))))
|
||||||
|
"
|
||||||
|
OUTPUT_VARIABLE SHIBOKEN_VERSION
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
list(GET SHIBOKEN_VERSION 0 SHIBOKEN_MACRO_VERSION)
|
||||||
|
list(GET SHIBOKEN_VERSION 1 SHIBOKEN_MICRO_VERSION)
|
||||||
|
list(GET SHIBOKEN_VERSION 2 SHIBOKEN_MINOR_VERSION)
|
||||||
|
string(REPLACE ";" "." SHIBOKEN_VERSION "${SHIBOKEN_VERSION}")
|
||||||
|
|
||||||
|
message(STATUS "ShibokenGenerator base dir: ${SHIBOKEN_GENERATOR_BASEDIR}")
|
||||||
|
message(STATUS "Shiboken base dir: ${SHIBOKEN_BASEDIR}")
|
||||||
|
message(STATUS "Shiboken custom path: ${SHIBOKEN_CUSTOM_PATH}")
|
||||||
|
|
||||||
|
if(SHIBOKEN_BASEDIR)
|
||||||
|
find_path(SHIBOKEN_INCLUDE_DIR
|
||||||
|
shiboken.h
|
||||||
|
PATHS ${SHIBOKEN_CUSTOM_PATH} ${SHIBOKEN_GENERATOR_BASEDIR}/include
|
||||||
|
NO_DEFAULT_PATH)
|
||||||
|
if(MSVC)
|
||||||
|
SET(SHIBOKEN_LIBRARY_BASENAMES "shiboken2.abi3.lib")
|
||||||
|
elseif(CYGWIN)
|
||||||
|
SET(SHIBOKEN_LIBRARY_BASENAMES "")
|
||||||
|
elseif(WIN32)
|
||||||
|
SET(SHIBOKEN_LIBRARY_BASENAMES "libshiboken2.${PYSIDE2_SUFFIX}")
|
||||||
|
elseif(APPLE)
|
||||||
|
SET(SHIBOKEN_LIBRARY_BASENAMES
|
||||||
|
libshiboken2.abi3.dylib
|
||||||
|
libshiboken2.abi3.${SHIBOKEN_MACRO_VERSION}.dylib
|
||||||
|
libshiboken2.abi3.${SHIBOKEN_MACRO_VERSION}.${SHIBOKEN_MICRO_VERSION}.dylib
|
||||||
|
libshiboken2.abi3.${SHIBOKEN_VERSION}.dylib
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
SET(SHIBOKEN_LIBRARY_BASENAMES
|
||||||
|
libshiboken2.abi3.so
|
||||||
|
libshiboken2.abi3.so.${SHIBOKEN_MACRO_VERSION}
|
||||||
|
libshiboken2.abi3.so.${SHIBOKEN_MACRO_VERSION}.${SHIBOKEN_MICRO_VERSION}
|
||||||
|
libshiboken2.abi3.so.${SHIBOKEN_VERSION}
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if (NOT SHIBOKEN_INCLUDE_DIR)
|
||||||
|
return()
|
||||||
|
endif()
|
||||||
|
set(SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_CUSTOM_PATH})
|
||||||
|
list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_BASEDIR})
|
||||||
|
list(APPEND SHIBOKEN_SEARCH_PATHS ${SHIBOKEN_GENERATOR_BASEDIR})
|
||||||
|
message(STATUS "BOO: ${SHIBOKEN_SEARCH_PATHS}")
|
||||||
|
find_file(SHIBOKEN_LIBRARY
|
||||||
|
${SHIBOKEN_LIBRARY_BASENAMES}
|
||||||
|
PATHS ${SHIBOKEN_SEARCH_PATHS}
|
||||||
|
NO_DEFAULT_PATH)
|
||||||
|
|
||||||
|
find_program(SHIBOKEN_BINARY
|
||||||
|
shiboken2
|
||||||
|
PATHS ${SHIBOKEN_SEARCH_PATHS}
|
||||||
|
NO_DEFAULT_PATH
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
if (SHIBOKEN_INCLUDE_DIR AND SHIBOKEN_LIBRARY AND SHIBOKEN_BINARY)
|
||||||
|
set(SHIBOKEN_FOUND TRUE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(SHIBOKEN_FOUND)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
|
||||||
|
if(MSVC)
|
||||||
|
# On Windows we must link to python3.dll that is a small library that links against python3x.dll
|
||||||
|
# that allow us to choose any python3x.dll at runtime
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${Python3_EXECUTABLE} -c "if True:
|
||||||
|
for lib in '${Python3_LIBRARIES}'.split(';'):
|
||||||
|
if '/' in lib:
|
||||||
|
prefix, py = lib.rsplit('/', 1)
|
||||||
|
if py.startswith('python3'):
|
||||||
|
print(prefix + '/python3.lib')
|
||||||
|
break
|
||||||
|
"
|
||||||
|
OUTPUT_VARIABLE PYTHON_LIMITED_LIBRARIES
|
||||||
|
OUTPUT_STRIP_TRAILING_WHITESPACE
|
||||||
|
)
|
||||||
|
else()
|
||||||
|
# On Linux and MacOs our modules should not link with any python library
|
||||||
|
# that must be handled by the main process
|
||||||
|
set(PYTHON_LIMITED_LIBRARIES "")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
if (SHIBOKEN_FOUND)
|
||||||
|
message(STATUS "Shiboken include dir: ${SHIBOKEN_INCLUDE_DIR}")
|
||||||
|
message(STATUS "Shiboken library: ${SHIBOKEN_LIBRARY}")
|
||||||
|
message(STATUS "Shiboken binary: ${SHIBOKEN_BINARY}")
|
||||||
|
message(STATUS "Shiboken version: ${SHIBOKEN_VERSION}")
|
||||||
|
|
||||||
|
# Create shiboke2 target
|
||||||
|
add_library(Shiboken2::libshiboken SHARED IMPORTED GLOBAL)
|
||||||
|
if(MSVC)
|
||||||
|
set_property(TARGET Shiboken2::libshiboken PROPERTY
|
||||||
|
IMPORTED_IMPLIB ${SHIBOKEN_LIBRARY})
|
||||||
|
endif()
|
||||||
|
set_property(TARGET Shiboken2::libshiboken PROPERTY
|
||||||
|
IMPORTED_LOCATION ${SHIBOKEN_LIBRARY})
|
||||||
|
set_property(TARGET Shiboken2::libshiboken APPEND PROPERTY
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES ${SHIBOKEN_INCLUDE_DIR} ${Python3_INCLUDE_DIRS})
|
||||||
|
set_property(TARGET Shiboken2::libshiboken APPEND PROPERTY
|
||||||
|
INTERFACE_LINK_LIBRARIES ${PYTHON_LIMITED_LIBRARIES})
|
||||||
|
|
||||||
|
# Generator target
|
||||||
|
add_executable(Shiboken2::shiboken IMPORTED GLOBAL)
|
||||||
|
set_property(TARGET Shiboken2::shiboken PROPERTY
|
||||||
|
IMPORTED_LOCATION ${SHIBOKEN_BINARY})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
find_package_handle_standard_args(Shiboken2
|
||||||
|
REQUIRED_VARS SHIBOKEN_BASEDIR SHIBOKEN_INCLUDE_DIR SHIBOKEN_LIBRARY SHIBOKEN_BINARY
|
||||||
|
VERSION_VAR SHIBOKEN_VERSION
|
||||||
|
)
|
||||||
|
|
||||||
159
cmake/Python/PySide2ModuleBuild.cmake
Normal file
159
cmake/Python/PySide2ModuleBuild.cmake
Normal file
@@ -0,0 +1,159 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
if (NOT PYTHON_BINDINGS_INSTALL_PREFIX)
|
||||||
|
SET(PYTHON_BINDINGS_INSTALL_PREFIX ${CMAKE_INSTALL_PREFIX} CACHE FILEPATH "Custom path to install python bindings.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
message(STATUS "PYTHON INSTALL PREFIX ${PYTHON_BINDINGS_INSTALL_PREFIX}")
|
||||||
|
|
||||||
|
if (WIN32)
|
||||||
|
set(PATH_SEP "\;")
|
||||||
|
else()
|
||||||
|
set(PATH_SEP ":")
|
||||||
|
endif()
|
||||||
|
if (NOT CMAKE_CXX_STANDARD)
|
||||||
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# On macOS, check if Qt is a framework build. This affects how include paths should be handled.
|
||||||
|
get_target_property(QtCore_is_framework Qt5::Core FRAMEWORK)
|
||||||
|
if (QtCore_is_framework)
|
||||||
|
# Get the path to the framework dir.
|
||||||
|
get_filename_component(QT_FRAMEWORK_INCLUDE_DIR "${QT_INCLUDE_DIR}/../" ABSOLUTE)
|
||||||
|
|
||||||
|
list(GET Qt5Core_INCLUDE_DIRS 0 QT_INCLUDE_DIR)
|
||||||
|
# QT_INCLUDE_DIR points to the QtCore.framework directory, so we need to adjust this to point
|
||||||
|
# to the actual include directory, which has include files for non-framework parts of Qt.
|
||||||
|
get_filename_component(QT_INCLUDE_DIR "${QT_INCLUDE_DIR}/../../include" ABSOLUTE)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Flags that we will pass to shiboken-generator
|
||||||
|
# --generator-set=shiboken: tells the generator that we want to use shiboken to generate code,
|
||||||
|
# a doc generator is also available
|
||||||
|
# --enable-parent-ctor-heuristic: Enable heuristics to detect parent relationship on constructors,
|
||||||
|
# this try to guess parent ownership based on the arguments of the constructors
|
||||||
|
# --enable-pyside-extensionsL: This will generate code for Qt based classes, adding extra attributes,
|
||||||
|
# like signal, slot;
|
||||||
|
# --enable-return-value-heuristic: Similar as --enable-parent-ctor-heuristic this use some logic to guess
|
||||||
|
# parent child relationship based on the returned argument
|
||||||
|
# --use-isnull-as-nb_nonzero: If a class have an isNull() const method, it will be used to compute
|
||||||
|
# the value of boolean casts.
|
||||||
|
# Example, QImage::isNull() will be used when on python side you do `if (myQImage)`
|
||||||
|
set(GENERATOR_EXTRA_FLAGS --generator-set=shiboken
|
||||||
|
--enable-parent-ctor-heuristic
|
||||||
|
--enable-pyside-extensions
|
||||||
|
--enable-return-value-heuristic
|
||||||
|
--use-isnull-as-nb_nonzero
|
||||||
|
-std=c++${CMAKE_CXX_STANDARD})
|
||||||
|
|
||||||
|
# 2017-04-24 The protected hack can unfortunately not be disabled, because
|
||||||
|
# Clang does produce linker errors when we disable the hack.
|
||||||
|
# But the ugly workaround in Python is replaced by a shiboken change.
|
||||||
|
if(WIN32 OR DEFINED AVOID_PROTECTED_HACK)
|
||||||
|
set(GENERATOR_EXTRA_FLAGS ${GENERATOR_EXTRA_FLAGS} --avoid-protected-hack)
|
||||||
|
add_definitions(-DAVOID_PROTECTED_HACK)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
macro(make_path varname)
|
||||||
|
# accepts any number of path variables
|
||||||
|
string(REPLACE ";" "${PATH_SEP}" ${varname} "${ARGN}")
|
||||||
|
endmacro()
|
||||||
|
|
||||||
|
# Creates a PySide module target based on the arguments
|
||||||
|
# This will:
|
||||||
|
# 1 - Create a Cmake custom-target that call shiboken-generator passign the correct arguments
|
||||||
|
# 2 - Create a Cmake library target called "Py${LIBRARY_NAME}" the output name of this target
|
||||||
|
# will be changed to match PySide template
|
||||||
|
# Args:
|
||||||
|
# LIBRARY_NAME - The name of the output module
|
||||||
|
# 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*
|
||||||
|
# OUTPUT_SOURCES - The files that will be generated by shiboken
|
||||||
|
# TARGET_INCLUDE_DIRS - This will be passed to target_include_directories
|
||||||
|
# TARGET_LINK_LIBRARIES - This will be passed to target_link_libraries
|
||||||
|
# GLOBAL_INCLUDE - A header-file that contains alls classes that will be generated
|
||||||
|
# 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
|
||||||
|
# trigger if one of these files changes
|
||||||
|
# MODULE_OUTPUT_DIR - Where the library file should be stored
|
||||||
|
macro(CREATE_PYTHON_BINDINGS
|
||||||
|
LIBRARY_NAME
|
||||||
|
TYPESYSTEM_PATHS
|
||||||
|
INCLUDE_PATHS
|
||||||
|
OUTPUT_SOURCES
|
||||||
|
TARGET_INCLUDE_DIRS
|
||||||
|
TARGET_LINK_LIBRARIES
|
||||||
|
GLOBAL_INCLUDE
|
||||||
|
TYPESYSTEM_XML
|
||||||
|
DEPENDS
|
||||||
|
MODULE_OUTPUT_DIR)
|
||||||
|
|
||||||
|
# Transform the path separators into something shiboken understands.
|
||||||
|
make_path(shiboken_include_dirs ${INCLUDE_PATHS})
|
||||||
|
make_path(shiboken_typesystem_dirs ${TYPESYSTEM_PATHS})
|
||||||
|
get_property(raw_python_dir_include_dirs DIRECTORY PROPERTY INCLUDE_DIRECTORIES)
|
||||||
|
make_path(python_dir_include_dirs ${raw_python_dir_include_dirs})
|
||||||
|
set(shiboken_include_dirs "${shiboken_include_dirs}${PATH_SEP}${python_dir_include_dirs}")
|
||||||
|
|
||||||
|
set(shiboken_framework_include_dirs_option "")
|
||||||
|
if(CMAKE_HOST_APPLE)
|
||||||
|
set(shiboken_framework_include_dirs "${QT_FRAMEWORK_INCLUDE_DIR}")
|
||||||
|
make_path(shiboken_framework_include_dirs ${shiboken_framework_include_dirs})
|
||||||
|
set(shiboken_framework_include_dirs_option "--framework-include-paths=${shiboken_framework_include_dirs}")
|
||||||
|
endif()
|
||||||
|
set_property(SOURCE ${OUTPUT_SOURCES} PROPERTY SKIP_AUTOGEN ON)
|
||||||
|
add_custom_command(OUTPUT ${OUTPUT_SOURCES}
|
||||||
|
COMMAND $<TARGET_PROPERTY:Shiboken2::shiboken,LOCATION> ${GENERATOR_EXTRA_FLAGS}
|
||||||
|
${GLOBAL_INCLUDE}
|
||||||
|
--include-paths=${shiboken_include_dirs}
|
||||||
|
--typesystem-paths=${shiboken_typesystem_dirs}
|
||||||
|
${shiboken_framework_include_dirs_option}
|
||||||
|
--output-directory=${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
${TYPESYSTEM_XML}
|
||||||
|
DEPENDS ${TYPESYSTEM_XML} ${DEPENDS}
|
||||||
|
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
COMMENT "Running generator for ${LIBRARY_NAME} binding...")
|
||||||
|
|
||||||
|
set(TARGET_NAME "Py${LIBRARY_NAME}")
|
||||||
|
set(MODULE_NAME "${LIBRARY_NAME}")
|
||||||
|
add_library(${TARGET_NAME} MODULE ${OUTPUT_SOURCES})
|
||||||
|
|
||||||
|
set_target_properties(${TARGET_NAME} PROPERTIES
|
||||||
|
PREFIX ""
|
||||||
|
OUTPUT_NAME ${MODULE_NAME}
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY ${MODULE_OUTPUT_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
if(WIN32)
|
||||||
|
set_target_properties(${TARGET_NAME} PROPERTIES SUFFIX ".pyd")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
target_include_directories(${TARGET_NAME} PUBLIC
|
||||||
|
${TARGET_INCLUDE_DIRS}
|
||||||
|
${PYSIDE_EXTRA_INCLUDES}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(${TARGET_NAME}
|
||||||
|
${TARGET_LINK_LIBRARIES}
|
||||||
|
PySide2::pyside2
|
||||||
|
Shiboken2::libshiboken
|
||||||
|
)
|
||||||
|
target_compile_definitions(${TARGET_NAME}
|
||||||
|
PRIVATE Py_LIMITED_API=0x03050000
|
||||||
|
)
|
||||||
|
if(APPLE)
|
||||||
|
set_property(TARGET ${TARGET_NAME} APPEND PROPERTY
|
||||||
|
LINK_FLAGS "-undefined dynamic_lookup")
|
||||||
|
endif()
|
||||||
|
install(TARGETS ${TARGET_NAME}
|
||||||
|
LIBRARY DESTINATION ${PYTHON_BINDINGS_INSTALL_PREFIX}/${TARGET_NAME})
|
||||||
|
endmacro()
|
||||||
70
cmake/QtInstallPaths.cmake
Normal file
70
cmake/QtInstallPaths.cmake
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2016-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Allen Winter <allen.winter@kdab.com>
|
||||||
|
#
|
||||||
|
# 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
|
||||||
|
# Make sure to have found Qt5 before using this.
|
||||||
|
# sets variables like QT_INSTALL_PREFIX, QT_INSTALL_DATA, QT_INSTALL_DOCS, etc.
|
||||||
|
# run qmake -query to see a full list
|
||||||
|
|
||||||
|
if(TARGET Qt5::qmake)
|
||||||
|
get_target_property(QT_QMAKE_EXECUTABLE Qt5::qmake LOCATION)
|
||||||
|
else()
|
||||||
|
message(FATAL_ERROR "No supported Qt version found. Make sure you find Qt before calling this")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
execute_process(
|
||||||
|
COMMAND ${QT_QMAKE_EXECUTABLE} -query
|
||||||
|
RESULT_VARIABLE return_code
|
||||||
|
OUTPUT_VARIABLE ALL_VARS
|
||||||
|
)
|
||||||
|
if(NOT return_code EQUAL 0)
|
||||||
|
message(WARNING "Failed call: ${QMAKE_EXECUTABLE} -query")
|
||||||
|
message(FATAL_ERROR "QMake call failed: ${return_code}")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
string(REPLACE "\n" ";" VARS_LIST ${ALL_VARS})
|
||||||
|
foreach(QVAL ${VARS_LIST})
|
||||||
|
if(QVAL MATCHES "QT_INSTALL_")
|
||||||
|
string(REPLACE ":" ";" QVAL_LIST ${QVAL})
|
||||||
|
list(LENGTH QVAL_LIST listlen)
|
||||||
|
list(GET QVAL_LIST 0 var)
|
||||||
|
if(WIN32 AND ${listlen} GREATER 2)
|
||||||
|
list(GET QVAL_LIST 2 path)
|
||||||
|
list(GET QVAL_LIST 1 drive)
|
||||||
|
set(path "${drive}:${path}")
|
||||||
|
else()
|
||||||
|
list(GET QVAL_LIST 1 path)
|
||||||
|
endif()
|
||||||
|
if(NOT ${var}) #if set aleady on the command line for example
|
||||||
|
set(${var} ${path} CACHE PATH "Qt install path for ${var}")
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endforeach()
|
||||||
18
conan/README.txt
Normal file
18
conan/README.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
In the following example we assume you have the kddockwidgets source available in
|
||||||
|
/path/to/kddockwidgets-source. replace '/path/to/kddockwidgets-source' to fit your needs.
|
||||||
|
|
||||||
|
$ conan create -s build_type=Release -o kddockwidgets:build_examples=True -o kddockwidgets:build_tests=True /path/to/kddockwidgets-source/conan kdab/stable
|
||||||
|
|
||||||
|
Configuration options:
|
||||||
|
* build_static
|
||||||
|
Builds static versions of the libraries. Default=False
|
||||||
|
|
||||||
|
* build_tests
|
||||||
|
Build the test harness. Default=False
|
||||||
|
|
||||||
|
* build_examples
|
||||||
|
Build the examples. Default=True
|
||||||
|
|
||||||
|
* builde_python_bindings
|
||||||
|
Build/Generate python bindings (always false for Debug or static builds). Default=False
|
||||||
|
|
||||||
65
conan/conanfile.py
Normal file
65
conan/conanfile.py
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
from conans import ConanFile, CMake, tools
|
||||||
|
|
||||||
|
class KDDockWidgetsConan(ConanFile):
|
||||||
|
name = "kddockwidgets"
|
||||||
|
version = "0.99.9"
|
||||||
|
default_user = "kdab"
|
||||||
|
default_channel = "stable"
|
||||||
|
license = ("https://raw.githubusercontent.com/KDAB/KDDockWidgets/master/LICENSES/GPL-2.0-only.txt",
|
||||||
|
"https://raw.githubusercontent.com/KDAB/KDDockWidgets/master/LICENSES/GPL-3.0-only.txt")
|
||||||
|
author = "Klaralvdalens Datakonsult AB (KDAB) info@kdab.com"
|
||||||
|
url = "https://github.com/KDAB/KDDockWidgets"
|
||||||
|
description = "Advanced Dock Widget Framework for Qt"
|
||||||
|
generators = "cmake"
|
||||||
|
topics = ("qt", "dockwidget" , "kdab")
|
||||||
|
settings = "os", "compiler", "build_type", "arch"
|
||||||
|
options = {
|
||||||
|
"qt_version": "ANY",
|
||||||
|
"build_static": [True, False],
|
||||||
|
"build_examples": [True, False],
|
||||||
|
"build_tests": [True, False],
|
||||||
|
"build_python_bindings": [True, False],
|
||||||
|
}
|
||||||
|
|
||||||
|
default_options = {
|
||||||
|
"qt_version": "qt/[>5.9.0]@kdab/stable",
|
||||||
|
"build_static": False,
|
||||||
|
"build_examples": True,
|
||||||
|
"build_tests": False,
|
||||||
|
"build_python_bindings": False,
|
||||||
|
}
|
||||||
|
|
||||||
|
def requirements(self):
|
||||||
|
# Check https://docs.conan.io/en/latest/reference/conanfile/attributes.html#version-ranges for more info about versioning
|
||||||
|
self.requires(str(self.options.qt_version))
|
||||||
|
|
||||||
|
def source(self):
|
||||||
|
git = tools.Git(folder="")
|
||||||
|
git.clone(self.url)
|
||||||
|
|
||||||
|
def build(self, build_type="Release"):
|
||||||
|
self.cmake = CMake(self, generator='Ninja', build_type=build_type)
|
||||||
|
self.cmake.definitions["KDDockWidgets_STATIC"] = self.options.build_static
|
||||||
|
self.cmake.definitions["KDDockWidgets_EXAMPLES"] = self.options.build_examples
|
||||||
|
self.cmake.definitions["KDDockWidgets_TESTS"] = self.options.build_tests
|
||||||
|
self.cmake.definitions["OPTION_BUILD_PYTHON_BINDINGS"] = self.options.build_python_bindings
|
||||||
|
self.cmake.configure()
|
||||||
|
self.cmake.build()
|
||||||
|
|
||||||
|
def package(self):
|
||||||
|
self.cmake.install()
|
||||||
|
|
||||||
|
def package_info(self):
|
||||||
|
self.env_info.CMAKE_PREFIX_PATH.append(self.package_folder)
|
||||||
|
|
||||||
|
def package_id(self):
|
||||||
|
self.info.requires["qt"].minor_mode() # Check only the major and minor version!
|
||||||
5
debian.changelog
Normal file
5
debian.changelog
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
kddockwidgets (0.99.9) release candidate; urgency=high
|
||||||
|
|
||||||
|
* 1.0.0 release candidate
|
||||||
|
|
||||||
|
-- Allen Winter <allen.winter@kdab.com> Thu, 6 Aug 2020 11:00:00 -0500
|
||||||
1
debian.compat
Normal file
1
debian.compat
Normal file
@@ -0,0 +1 @@
|
|||||||
|
9
|
||||||
12
debian.control
Normal file
12
debian.control
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
Source: kddockwidgets
|
||||||
|
Section: Miscellaneous
|
||||||
|
Priority: optional
|
||||||
|
Maintainer: Allen Winter <allen.winter@kdab.com>
|
||||||
|
Build-Depends: debhelper (>=9), cdbs, cmake
|
||||||
|
Standards-Version: 3.9.6
|
||||||
|
Homepage: https://github.com/KDAB/KDDockWidgets
|
||||||
|
|
||||||
|
Package: kddockwidgets
|
||||||
|
Architecture: any
|
||||||
|
Depends: ${misc:Depends}, ${shlibs:Depends}
|
||||||
|
Description: KDAB's Dock Widget Framework for Qt
|
||||||
3
debian.rules
Normal file
3
debian.rules
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
include /usr/share/cdbs/1/rules/debhelper.mk
|
||||||
|
include /usr/share/cdbs/1/class/cmake.mk
|
||||||
40
docs/CMakeLists.txt
Normal file
40
docs/CMakeLists.txt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Allen Winter <allen.winter@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
# qhelpgenerator
|
||||||
|
find_program(QHELPGEN_EXECUTABLE qhelpgenerator
|
||||||
|
HINTS ${QT_INSTALL_BINS}
|
||||||
|
)
|
||||||
|
if(QHELPGEN_EXECUTABLE)
|
||||||
|
set(HAVE_QHELPGEN "YES")
|
||||||
|
else()
|
||||||
|
set(HAVE_QHELPGEN "NO")
|
||||||
|
message(STATUS "Unable to generate the API documentation in qch format. To fix, install the qthelpgenerator program which comes with Qt5.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Doxygen
|
||||||
|
find_package(Doxygen)
|
||||||
|
set_package_properties(Doxygen PROPERTIES
|
||||||
|
TYPE OPTIONAL
|
||||||
|
DESCRIPTION "API Documentation system"
|
||||||
|
URL "http://www.doxygen.org"
|
||||||
|
PURPOSE "Needed to build the API documentation."
|
||||||
|
)
|
||||||
|
if(DOXYGEN_DOT_EXECUTABLE)
|
||||||
|
set(HAVE_DOT "YES")
|
||||||
|
else()
|
||||||
|
set(HAVE_DOT "NO")
|
||||||
|
message(STATUS "Unable to provide inheritance diagrams for the API documentation. To fix, install the graphviz project from https://www.graphviz.org")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(DOXYGEN_FOUND)
|
||||||
|
add_subdirectory(api)
|
||||||
|
endif()
|
||||||
40
docs/api/CMakeLists.txt
Normal file
40
docs/api/CMakeLists.txt
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Allen Winter <allen.winter@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
find_file(QDOC_QTCORE_TAG qtcore.tags
|
||||||
|
HINTS ${QT_INSTALL_DOCS}/qtcore
|
||||||
|
HINTS ${QT_INSTALL_DATA}/doc/qtcore
|
||||||
|
)
|
||||||
|
if(QDOC_QTCORE_TAG)
|
||||||
|
get_filename_component(QDOC_TAG_DIR ${QDOC_QTCORE_TAG} DIRECTORY)
|
||||||
|
get_filename_component(QDOC_TAG_DIR ${QDOC_TAG_DIR} DIRECTORY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
file(GLOB _dox_deps *.dox *.html)
|
||||||
|
set(DOXYGEN_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|
||||||
|
#apidox generation using doxygen
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.cmake
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||||
|
)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
OUTPUT ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch
|
||||||
|
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
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different ${CMAKE_SOURCE_DIR}/screencap.gif ${DOXYGEN_OUTPUT_DIR}/html
|
||||||
|
DEPENDS ${_dox_deps} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
|
||||||
|
WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
|
||||||
|
)
|
||||||
|
add_custom_target(kddockwidgets-api.qch ALL DEPENDS ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch)
|
||||||
|
|
||||||
|
install(FILES ${DOXYGEN_OUTPUT_DIR}/qch/kddockwidgets-api.qch DESTINATION ${INSTALL_DOC_DIR})
|
||||||
2564
docs/api/Doxyfile.cmake
Normal file
2564
docs/api/Doxyfile.cmake
Normal file
File diff suppressed because it is too large
Load Diff
19
docs/api/footer.html
Normal file
19
docs/api/footer.html
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
<hr>
|
||||||
|
<div style="float: left;">
|
||||||
|
<img src="kdab-logo-16x16.png">
|
||||||
|
<font style="font-weight: bold;">Klarälvdalens Datakonsult AB (KDAB)</font>
|
||||||
|
<br>
|
||||||
|
"The Qt Experts"<br>
|
||||||
|
<a href="https://www.kdab.com/">https://www.kdab.com/</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="text-align: right;">
|
||||||
|
<!-- <img src="kddockwidgets-logo-16x16.png" /><br> -->
|
||||||
|
<font style="font-weight: bold;">KDDockWidgets</font>
|
||||||
|
<br>
|
||||||
|
Advanced Dock Widget Framework for Qt<br>
|
||||||
|
<a href="https://www.kdab.com/development-resources/qt-tools/kd-dockwidgets/">https://www.kdab.com/development-resources/qt-tools/kd-dockwidgets/</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
BIN
docs/api/kdab-logo-16x16.png
Normal file
BIN
docs/api/kdab-logo-16x16.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.2 KiB |
@@ -1,22 +1,34 @@
|
|||||||
cmake_minimum_required(VERSION 3.3)
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
project(kddockwidgets_example)
|
project(kddockwidgets_example)
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
set(CMAKE_INCLUDE_CURRENT_DIRS ON)
|
||||||
|
|
||||||
# This will look for Qt, do find_package yourself manually before
|
if(NOT TARGET kddockwidgets)
|
||||||
# if you want to look for a specific version for instance.
|
# This will look for Qt, do find_package yourself manually before
|
||||||
find_package(KDDockWidgets REQUIRED)
|
# if you want to look for a specific Qt version for instance.
|
||||||
|
find_package(KDDockWidgets REQUIRED)
|
||||||
|
endif()
|
||||||
|
|
||||||
qt5_add_resources(RESOURCES_SRC ${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc)
|
qt5_add_resources(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/resources_example.qrc)
|
||||||
|
|
||||||
add_executable(kddockwidgets_example
|
add_executable(kddockwidgets_example
|
||||||
main.cpp
|
main.cpp
|
||||||
MyFrameworkWidgetFactory.cpp
|
MyFrameworkWidgetFactory.cpp
|
||||||
MyMainWindow.cpp
|
MyMainWindow.cpp
|
||||||
MyWidget.cpp
|
MyWidget.cpp
|
||||||
${RESOURCES_SRC}
|
${RESOURCES_EXAMPLE_SRC}
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(kddockwidgets_example
|
target_link_libraries(kddockwidgets_example
|
||||||
|
|||||||
@@ -1,39 +1,33 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MyFrameworkWidgetFactory.h"
|
#include "MyFrameworkWidgetFactory.h"
|
||||||
|
|
||||||
#include <kddockwidgets/FrameworkWidgetFactory.h>
|
#include <kddockwidgets/FrameworkWidgetFactory.h>
|
||||||
//#include <kddockwidgets/widgets/SeparatorWidget_p.h>
|
#include <kddockwidgets/private/widgets/TitleBarWidget_p.h>
|
||||||
|
#include <kddockwidgets/private/multisplitter/Separator_qwidget.h>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
|
||||||
class MyTitleBar : public KDDockWidgets::TitleBar
|
class MyTitleBar : public KDDockWidgets::TitleBarWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit MyTitleBar(KDDockWidgets::Frame *frame)
|
explicit MyTitleBar(KDDockWidgets::Frame *frame)
|
||||||
: KDDockWidgets::TitleBar(frame)
|
: KDDockWidgets::TitleBarWidget(frame)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit MyTitleBar(KDDockWidgets::FloatingWindow *fw)
|
explicit MyTitleBar(KDDockWidgets::FloatingWindow *fw)
|
||||||
: KDDockWidgets::TitleBar(fw)
|
: KDDockWidgets::TitleBarWidget(fw)
|
||||||
{
|
{
|
||||||
init();
|
init();
|
||||||
}
|
}
|
||||||
@@ -60,24 +54,21 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
|
||||||
// Inheriting from SeparatorWidget instead of Separator as it handles moving and mouse cursor changing
|
// Inheriting from SeparatorWidget instead of Separator as it handles moving and mouse cursor changing
|
||||||
class MySeparator : public KDDockWidgets::SeparatorWidget
|
class MySeparator : public Layouting::SeparatorWidget
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit MySeparator(KDDockWidgets::Anchor *anchor,
|
explicit MySeparator(Layouting::Widget *parent)
|
||||||
KDDockWidgets::QWidgetAdapter *parent = nullptr)
|
: Layouting::SeparatorWidget(parent)
|
||||||
: KDDockWidgets::SeparatorWidget(anchor, parent)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void paintEvent(QPaintEvent *) override
|
void paintEvent(QPaintEvent *) override
|
||||||
{
|
{
|
||||||
QPainter p(this);
|
QPainter p(this);
|
||||||
p.fillRect(rect(), isStatic() ? Qt::black : Qt::cyan);
|
p.fillRect(QWidget::rect(), Qt::cyan);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
*/
|
|
||||||
|
|
||||||
KDDockWidgets::TitleBar * CustomWidgetFactory::createTitleBar(KDDockWidgets::Frame *frame) const
|
KDDockWidgets::TitleBar * CustomWidgetFactory::createTitleBar(KDDockWidgets::Frame *frame) const
|
||||||
{
|
{
|
||||||
@@ -88,10 +79,9 @@ KDDockWidgets::TitleBar * CustomWidgetFactory::createTitleBar(KDDockWidgets::Flo
|
|||||||
{
|
{
|
||||||
return new MyTitleBar(fw);
|
return new MyTitleBar(fw);
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
KDDockWidgets::Separator * CustomWidgetFactory::createSeparator(KDDockWidgets::Anchor *anchor,
|
Layouting::Separator * CustomWidgetFactory::createSeparator(Layouting::Widget *parent) const
|
||||||
KDDockWidgets::QWidgetAdapter *parent) const
|
|
||||||
{
|
{
|
||||||
return new MySeparator(anchor, parent);
|
return new MySeparator(parent);
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|||||||
@@ -1,27 +1,18 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <kddockwidgets/FrameworkWidgetFactory.h>
|
#include <kddockwidgets/FrameworkWidgetFactory.h>
|
||||||
#include <kddockwidgets/private/TitleBar_p.h>
|
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
|
||||||
class CustomWidgetFactory : public KDDockWidgets::DefaultWidgetFactory
|
class CustomWidgetFactory : public KDDockWidgets::DefaultWidgetFactory
|
||||||
@@ -29,6 +20,5 @@ class CustomWidgetFactory : public KDDockWidgets::DefaultWidgetFactory
|
|||||||
public:
|
public:
|
||||||
KDDockWidgets::TitleBar *createTitleBar(KDDockWidgets::Frame *frame) const override;
|
KDDockWidgets::TitleBar *createTitleBar(KDDockWidgets::Frame *frame) const override;
|
||||||
KDDockWidgets::TitleBar *createTitleBar(KDDockWidgets::FloatingWindow *fw) const override;
|
KDDockWidgets::TitleBar *createTitleBar(KDDockWidgets::FloatingWindow *fw) const override;
|
||||||
/* KDDockWidgets::Separator *createSeparator(KDDockWidgets::Anchor *anchor, // Commented-out as we need to install more headers
|
Layouting::Separator *createSeparator(Layouting::Widget *parent = nullptr) const override;
|
||||||
KDDockWidgets::QWidgetAdapter *parent = nullptr) const override;*/
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MyMainWindow.h"
|
#include "MyMainWindow.h"
|
||||||
@@ -29,13 +20,22 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QTextEdit>
|
#include <QTextEdit>
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5, 10, 0)
|
||||||
|
#include <QRandomGenerator>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
|
||||||
|
// clazy:excludeall=qstring-allocations
|
||||||
|
|
||||||
static MyWidget *newMyWidget()
|
static MyWidget *newMyWidget()
|
||||||
{
|
{
|
||||||
|
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||||
const int randomNumber = qrand() % 100 + 1;
|
const int randomNumber = qrand() % 100 + 1;
|
||||||
|
#else
|
||||||
|
const int randomNumber = QRandomGenerator::global()->bounded(0, 100) + 1;
|
||||||
|
#endif
|
||||||
|
|
||||||
if (randomNumber < 50) {
|
if (randomNumber < 50) {
|
||||||
if (randomNumber < 33) {
|
if (randomNumber < 33) {
|
||||||
@@ -49,16 +49,20 @@ static MyWidget *newMyWidget()
|
|||||||
}
|
}
|
||||||
|
|
||||||
MyMainWindow::MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
MyMainWindow::MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
||||||
bool dockWidget0IsNonClosable, bool restoreIsRelative,
|
bool dockWidget0IsNonClosable, bool nonDockableDockWidget9, bool restoreIsRelative,
|
||||||
|
bool maxSizeForDockWidget8,
|
||||||
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_restoreIsRelative(restoreIsRelative)
|
, m_restoreIsRelative(restoreIsRelative)
|
||||||
|
, m_maxSizeForDockWidget8(maxSizeForDockWidget8)
|
||||||
{
|
{
|
||||||
// qApp->installEventFilter(this);
|
#if QT_VERSION < QT_VERSION_CHECK(5, 10, 0)
|
||||||
|
|
||||||
qsrand(time(nullptr));
|
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"));
|
||||||
@@ -95,25 +99,36 @@ MyMainWindow::MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowO
|
|||||||
saver.restoreFromFile(QStringLiteral("mylayout.json"));
|
saver.restoreFromFile(QStringLiteral("mylayout.json"));
|
||||||
});
|
});
|
||||||
|
|
||||||
auto closeAllAction = fileMenu->addAction(QStringLiteral("Close all"));
|
auto closeAllAction = fileMenu->addAction(QStringLiteral("Close All"));
|
||||||
connect(closeAllAction, &QAction::triggered, this, [this] {
|
connect(closeAllAction, &QAction::triggered, this, [this] {
|
||||||
for (auto dw : m_dockwidgets)
|
for (auto dw : qAsConst(m_dockwidgets))
|
||||||
dw->close();
|
dw->close();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
auto layoutEqually = fileMenu->addAction(QStringLiteral("Layout Equally"));
|
||||||
|
connect(layoutEqually, &QAction::triggered, this, &MainWindow::layoutEqually);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
setAffinityName(affinityName);
|
setAffinities({ affinityName });
|
||||||
createDockWidgets();
|
createDockWidgets();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MyMainWindow::~MyMainWindow()
|
||||||
|
{
|
||||||
|
qDeleteAll(m_dockwidgets);
|
||||||
|
}
|
||||||
|
|
||||||
void MyMainWindow::createDockWidgets()
|
void MyMainWindow::createDockWidgets()
|
||||||
{
|
{
|
||||||
Q_ASSERT(m_dockwidgets.isEmpty());
|
Q_ASSERT(m_dockwidgets.isEmpty());
|
||||||
|
|
||||||
|
const int numDockWidgets = m_dockWidget9IsNonDockable ? 10 : 9;
|
||||||
|
|
||||||
|
|
||||||
// Create 9 KDDockWidget::DockWidget and the respective widgets they're hosting (MyWidget instances)
|
// Create 9 KDDockWidget::DockWidget and the respective widgets they're hosting (MyWidget instances)
|
||||||
for (int i = 0; i < 9; i++)
|
for (int i = 0; i < numDockWidgets; i++)
|
||||||
m_dockwidgets << newDockWidget();
|
m_dockwidgets << newDockWidget();
|
||||||
|
|
||||||
|
|
||||||
@@ -127,7 +142,7 @@ void MyMainWindow::createDockWidgets()
|
|||||||
addDockWidget(m_dockwidgets[3], KDDockWidgets::Location_OnBottom);
|
addDockWidget(m_dockwidgets[3], KDDockWidgets::Location_OnBottom);
|
||||||
addDockWidget(m_dockwidgets[4], KDDockWidgets::Location_OnBottom);
|
addDockWidget(m_dockwidgets[4], KDDockWidgets::Location_OnBottom);
|
||||||
|
|
||||||
// Tab two dock widgets toghether
|
// Tab two dock widgets together
|
||||||
m_dockwidgets[3]->addDockWidgetAsTab(m_dockwidgets[5]);
|
m_dockwidgets[3]->addDockWidgetAsTab(m_dockwidgets[5]);
|
||||||
|
|
||||||
// 6 is floating, as it wasn't added to the main window via MainWindow::addDockWidget().
|
// 6 is floating, as it wasn't added to the main window via MainWindow::addDockWidget().
|
||||||
@@ -150,16 +165,30 @@ KDDockWidgets::DockWidgetBase *MyMainWindow::newDockWidget()
|
|||||||
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)
|
||||||
|
options |= KDDockWidgets::DockWidget::Option_NotDockable;
|
||||||
|
|
||||||
auto dock = new KDDockWidgets::DockWidget(QStringLiteral("DockWidget #%1").arg(count), options);
|
auto dock = new KDDockWidgets::DockWidget(QStringLiteral("DockWidget #%1").arg(count), options);
|
||||||
dock->setAffinityName(affinityName()); // 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)
|
||||||
dock->setIcon(QIcon::fromTheme(QStringLiteral("mail-message")));
|
dock->setIcon(QIcon::fromTheme(QStringLiteral("mail-message")));
|
||||||
|
|
||||||
auto myWidget = newMyWidget();
|
auto myWidget = newMyWidget();
|
||||||
|
if (count == 8 && m_maxSizeForDockWidget8) {
|
||||||
|
// Set a maximum size on dock #8
|
||||||
|
myWidget->setMaximumSize(200, 200);
|
||||||
|
}
|
||||||
|
|
||||||
dock->setWidget(myWidget);
|
dock->setWidget(myWidget);
|
||||||
|
|
||||||
|
if (dock->options() & KDDockWidgets::DockWidget::Option_NotDockable) {
|
||||||
|
dock->setTitle(QStringLiteral("DockWidget #%1 (%2)").arg(count).arg("non dockable"));
|
||||||
|
} else {
|
||||||
dock->setTitle(QStringLiteral("DockWidget #%1").arg(count));
|
dock->setTitle(QStringLiteral("DockWidget #%1").arg(count));
|
||||||
|
}
|
||||||
|
|
||||||
dock->resize(600, 600);
|
dock->resize(600, 600);
|
||||||
dock->show();
|
|
||||||
m_toggleMenu->addAction(dock->toggleAction());
|
m_toggleMenu->addAction(dock->toggleAction());
|
||||||
|
|
||||||
count++;
|
count++;
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
@@ -28,15 +19,19 @@ class MyMainWindow : public KDDockWidgets::MainWindow
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
explicit MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
explicit MyMainWindow(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
||||||
bool dockWidget0IsNonClosable, bool restoreIsRelative,
|
bool dockWidget0IsNonClosable, bool nonDockableDockWidget9, bool restoreIsRelative,
|
||||||
|
bool maxSizeForDockWidget8,
|
||||||
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;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void createDockWidgets();
|
void createDockWidgets();
|
||||||
KDDockWidgets::DockWidgetBase* newDockWidget();
|
KDDockWidgets::DockWidgetBase* newDockWidget();
|
||||||
QMenu *m_toggleMenu = nullptr;
|
QMenu *m_toggleMenu = nullptr;
|
||||||
const bool m_dockWidget0IsNonClosable;
|
const bool m_dockWidget0IsNonClosable;
|
||||||
|
const bool m_dockWidget9IsNonDockable;
|
||||||
const bool m_restoreIsRelative;
|
const bool m_restoreIsRelative;
|
||||||
|
const bool m_maxSizeForDockWidget8;
|
||||||
KDDockWidgets::DockWidget::List m_dockwidgets;
|
KDDockWidgets::DockWidget::List m_dockwidgets;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MyWidget.h"
|
#include "MyWidget.h"
|
||||||
@@ -24,7 +15,7 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
|
|
||||||
static QHash<QString, QImage> s_images;
|
static QHash<QString, QImage> s_images; /// clazy:exclude=non-pod-global-static
|
||||||
|
|
||||||
MyWidget::MyWidget(const QString &backgroundFile, const QString &logoFile, QWidget *parent)
|
MyWidget::MyWidget(const QString &backgroundFile, const QString &logoFile, QWidget *parent)
|
||||||
: QWidget(parent)
|
: QWidget(parent)
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EXAMPLEDOCKABLEWIDGET_H
|
#ifndef EXAMPLEDOCKABLEWIDGET_H
|
||||||
@@ -25,7 +16,9 @@
|
|||||||
|
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
class QPainter;
|
class QPainter;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
class MyWidget : public QWidget
|
class MyWidget : public QWidget
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "MyWidget.h"
|
#include "MyWidget.h"
|
||||||
@@ -29,6 +20,8 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QCommandLineParser>
|
#include <QCommandLineParser>
|
||||||
|
|
||||||
|
// clazy:excludeall=qstring-allocations
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@@ -52,9 +45,12 @@ int main(int argc, char **argv)
|
|||||||
QCommandLineOption reorderTabsOption("r", QCoreApplication::translate("main", "Support re-ordering tabs with mouse"));
|
QCommandLineOption reorderTabsOption("r", QCoreApplication::translate("main", "Support re-ordering tabs with mouse"));
|
||||||
parser.addOption(reorderTabsOption);
|
parser.addOption(reorderTabsOption);
|
||||||
|
|
||||||
QCommandLineOption noTitleBars("t", QCoreApplication::translate("main", "Never show titlebars"));
|
QCommandLineOption noTitleBars("t", QCoreApplication::translate("main", "Hide titlebars when tabs are visible"));
|
||||||
parser.addOption(noTitleBars);
|
parser.addOption(noTitleBars);
|
||||||
|
|
||||||
|
QCommandLineOption alwaysTabs("z", QCoreApplication::translate("main", "Show tabs even if there's only one"));
|
||||||
|
parser.addOption(alwaysTabs);
|
||||||
|
|
||||||
QCommandLineOption lazyResizeOption("l", QCoreApplication::translate("main", "Use lazy resize"));
|
QCommandLineOption lazyResizeOption("l", QCoreApplication::translate("main", "Use lazy resize"));
|
||||||
parser.addOption(lazyResizeOption);
|
parser.addOption(lazyResizeOption);
|
||||||
|
|
||||||
@@ -76,9 +72,27 @@ int main(int argc, char **argv)
|
|||||||
QCommandLineOption doubleClickMaximize("x", QCoreApplication::translate("main", "Double clicking a title bar will maximize a floating window"));
|
QCommandLineOption doubleClickMaximize("x", QCoreApplication::translate("main", "Double clicking a title bar will maximize a floating window"));
|
||||||
parser.addOption(doubleClickMaximize);
|
parser.addOption(doubleClickMaximize);
|
||||||
|
|
||||||
|
QCommandLineOption nonDockable("d", QCoreApplication::translate("main", "DockWidget #9 will be non-dockable"));
|
||||||
|
parser.addOption(nonDockable);
|
||||||
|
|
||||||
|
QCommandLineOption maximizeButton("b", QCoreApplication::translate("main", "DockWidgets have maximize/restore buttons instead of float/dock button"));
|
||||||
|
parser.addOption(maximizeButton);
|
||||||
|
|
||||||
|
parser.addPositionalArgument("savedlayout", QCoreApplication::translate("main", "loads the specified json file at startup"));
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
||||||
|
QCommandLineOption dockableMainWindows("j", QCoreApplication::translate("main", "Allow main windows to be docked inside other main windows"));
|
||||||
|
parser.addOption(dockableMainWindows);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
QCommandLineOption maxSizeOption("g", QCoreApplication::translate("main", "Make dock #8 have a max-size of 200x200."));
|
||||||
|
parser.addOption(maxSizeOption);
|
||||||
|
|
||||||
|
QCommandLineOption centralFrame("f", QCoreApplication::translate("main", "Persistent central frame"));
|
||||||
#if defined(DOCKS_DEVELOPER_MODE)
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
QCommandLineOption noCentralFrame("c", QCoreApplication::translate("main", "No central frame"));
|
parser.addOption(centralFrame);
|
||||||
parser.addOption(noCentralFrame);
|
#else
|
||||||
|
Q_UNUSED(centralFrame)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
parser.process(app);
|
parser.process(app);
|
||||||
@@ -87,22 +101,28 @@ int main(int argc, char **argv)
|
|||||||
Config::self().setFrameworkWidgetFactory(new CustomWidgetFactory()); // Sets our custom factory
|
Config::self().setFrameworkWidgetFactory(new CustomWidgetFactory()); // Sets our custom factory
|
||||||
|
|
||||||
// Increase the separator size, just for demo
|
// Increase the separator size, just for demo
|
||||||
Config::self().setSeparatorThickness(10, /*static=*/ false);
|
Config::self().setSeparatorThickness(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
MainWindowOptions options = MainWindowOption_None;
|
MainWindowOptions options = MainWindowOption_None;
|
||||||
#if defined(DOCKS_DEVELOPER_MODE)
|
#if defined(DOCKS_DEVELOPER_MODE)
|
||||||
options = parser.isSet(noCentralFrame) ? MainWindowOption_None
|
options = parser.isSet(centralFrame) ? MainWindowOption_HasCentralFrame
|
||||||
: MainWindowOption_HasCentralFrame;
|
: MainWindowOption_None;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto flags = KDDockWidgets::Config::self().flags();
|
auto flags = KDDockWidgets::Config::self().flags();
|
||||||
if (parser.isSet(noTitleBars))
|
if (parser.isSet(noTitleBars))
|
||||||
flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible | KDDockWidgets::Config::Flag_AlwaysShowTabs;
|
flags |= KDDockWidgets::Config::Flag_HideTitleBarWhenTabsVisible;
|
||||||
|
|
||||||
|
if (parser.isSet(alwaysTabs))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_AlwaysShowTabs;
|
||||||
|
|
||||||
if (parser.isSet(reorderTabsOption))
|
if (parser.isSet(reorderTabsOption))
|
||||||
flags |= KDDockWidgets::Config::Flag_AllowReorderTabs;
|
flags |= KDDockWidgets::Config::Flag_AllowReorderTabs;
|
||||||
|
|
||||||
|
if (parser.isSet(maximizeButton))
|
||||||
|
flags |= KDDockWidgets::Config::Flag_TitleBarHasMaximizeButton;
|
||||||
|
|
||||||
if (parser.isSet(lazyResizeOption))
|
if (parser.isSet(lazyResizeOption))
|
||||||
flags |= KDDockWidgets::Config::Flag_LazyResize;
|
flags |= KDDockWidgets::Config::Flag_LazyResize;
|
||||||
|
|
||||||
@@ -122,20 +142,36 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
const bool nonClosableDockWidget0 = parser.isSet(nonClosableDockWidget);
|
const bool nonClosableDockWidget0 = parser.isSet(nonClosableDockWidget);
|
||||||
const bool restoreIsRelative = parser.isSet(relativeRestore);
|
const bool restoreIsRelative = parser.isSet(relativeRestore);
|
||||||
|
const bool nonDockableDockWidget9 = parser.isSet(nonDockable);
|
||||||
|
const bool maxSizeForDockWidget8 = parser.isSet(maxSizeOption);
|
||||||
|
const bool usesMainWindowsWithAffinity = parser.isSet(multipleMainWindows);
|
||||||
|
|
||||||
MyMainWindow mainWindow(QStringLiteral("MyMainWindow"), options, nonClosableDockWidget0, restoreIsRelative);
|
#ifdef KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
||||||
|
const bool usesDockableMainWindows = parser.isSet(dockableMainWindows);
|
||||||
|
#else
|
||||||
|
const bool usesDockableMainWindows = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
MyMainWindow mainWindow(QStringLiteral("MyMainWindow"), options, nonClosableDockWidget0,
|
||||||
|
nonDockableDockWidget9, restoreIsRelative, maxSizeForDockWidget8);
|
||||||
mainWindow.setWindowTitle("Main Window 1");
|
mainWindow.setWindowTitle("Main Window 1");
|
||||||
mainWindow.resize(1200, 1200);
|
mainWindow.resize(1200, 1200);
|
||||||
mainWindow.show();
|
mainWindow.show();
|
||||||
|
|
||||||
if (parser.isSet(multipleMainWindows)) {
|
if (usesMainWindowsWithAffinity) {
|
||||||
|
if (usesDockableMainWindows) {
|
||||||
|
qWarning() << "MainWindows with affinity option is incompatible with Dockable Main Windows option";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
// By default a dock widget can dock into any main window.
|
// By default a dock widget can dock into any main window.
|
||||||
// By setting an affinity name we can prevent that. Dock widgets of different affinities are incompatible.
|
// By setting an affinity name we can prevent that. Dock widgets of different affinities are incompatible.
|
||||||
const QString affinity = parser.isSet(incompatibleMainWindows) ? QStringLiteral("affinity1")
|
const QString affinity = parser.isSet(incompatibleMainWindows) ? QStringLiteral("affinity1")
|
||||||
: QString();
|
: QString();
|
||||||
|
|
||||||
auto mainWindow2 = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options,
|
auto mainWindow2 = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options,
|
||||||
nonClosableDockWidget0, restoreIsRelative, affinity);
|
nonClosableDockWidget0, nonDockableDockWidget9,
|
||||||
|
restoreIsRelative, maxSizeForDockWidget8, affinity);
|
||||||
if (affinity.isEmpty())
|
if (affinity.isEmpty())
|
||||||
mainWindow2->setWindowTitle("Main Window 2");
|
mainWindow2->setWindowTitle("Main Window 2");
|
||||||
else
|
else
|
||||||
@@ -143,7 +179,34 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
mainWindow2->resize(1200, 1200);
|
mainWindow2->resize(1200, 1200);
|
||||||
mainWindow2->show();
|
mainWindow2->show();
|
||||||
|
} else if (usesDockableMainWindows) {
|
||||||
|
auto mainWindowDockWidget = new DockWidget(QStringLiteral("MyMainWindow-2-DW"));
|
||||||
|
|
||||||
|
const QString affinity = QStringLiteral("Inner-DockWidgets-2");
|
||||||
|
auto dockableMainWindow = new MyMainWindow(QStringLiteral("MyMainWindow-2"), options,
|
||||||
|
false, false, restoreIsRelative, false, affinity);
|
||||||
|
|
||||||
|
dockableMainWindow->setAffinities({ affinity });
|
||||||
|
|
||||||
|
dockableMainWindow->setStyleSheet(QStringLiteral("background: yellow"));
|
||||||
|
|
||||||
|
dockableMainWindow->setWindowTitle("Dockable Main Window");
|
||||||
|
dockableMainWindow->show();
|
||||||
|
mainWindowDockWidget->setWidget(dockableMainWindow);
|
||||||
|
mainWindowDockWidget->show();
|
||||||
|
mainWindowDockWidget->resize(800, 800);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QStringList args = parser.positionalArguments();
|
||||||
|
if (args.size() >= 1) {
|
||||||
|
const QString sourceJsonFileName = args[0];
|
||||||
|
KDDockWidgets::LayoutSaver loader;
|
||||||
|
if (!loader.restoreFromFile(sourceJsonFileName)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Failed to restore from" << sourceJsonFileName;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
return app.exec();
|
return app.exec();
|
||||||
}
|
}
|
||||||
|
|||||||
36
examples/minimal/CMakeLists.txt
Normal file
36
examples/minimal/CMakeLists.txt
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.7)
|
||||||
|
project(kddockwidgets_minimal_example)
|
||||||
|
|
||||||
|
set(CMAKE_AUTOMOC 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()
|
||||||
|
|
||||||
|
qt5_add_resources(RESOURCES_EXAMPLE_SRC ${CMAKE_CURRENT_SOURCE_DIR}/../dockwidgets/resources_example.qrc)
|
||||||
|
|
||||||
|
add_executable(kddockwidgets_minimal_example
|
||||||
|
main.cpp
|
||||||
|
../dockwidgets/MyWidget.cpp
|
||||||
|
${RESOURCES_EXAMPLE_SRC}
|
||||||
|
)
|
||||||
|
|
||||||
|
target_link_libraries(kddockwidgets_minimal_example
|
||||||
|
PRIVATE
|
||||||
|
KDAB::kddockwidgets
|
||||||
|
)
|
||||||
|
|
||||||
116
examples/minimal/MyWidget.cpp
Normal file
116
examples/minimal/MyWidget.cpp
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "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);
|
||||||
|
}
|
||||||
61
examples/minimal/MyWidget.h
Normal file
61
examples/minimal/MyWidget.h
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef EXAMPLEDOCKABLEWIDGET_H
|
||||||
|
#define EXAMPLEDOCKABLEWIDGET_H
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QPainter;
|
||||||
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
class MyWidget : public QWidget
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
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
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MyWidget1(QWidget *parent = nullptr);
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent*) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyWidget2 : public MyWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MyWidget2(QWidget *parent = nullptr);
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent*) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
class MyWidget3 : public MyWidget
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit MyWidget3(QWidget *parent = nullptr);
|
||||||
|
protected:
|
||||||
|
void paintEvent(QPaintEvent*) override;
|
||||||
|
QImage m_triangle;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
70
examples/minimal/main.cpp
Normal file
70
examples/minimal/main.cpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MyWidget.h"
|
||||||
|
|
||||||
|
#include <kddockwidgets/DockWidget.h>
|
||||||
|
#include <kddockwidgets/MainWindow.h>
|
||||||
|
|
||||||
|
// clazy:excludeall=qstring-allocations
|
||||||
|
|
||||||
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
QApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||||
|
QApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
app.setOrganizationName(QStringLiteral("KDAB"));
|
||||||
|
app.setApplicationName(QStringLiteral("Test app"));
|
||||||
|
|
||||||
|
// # 1. Create our main window
|
||||||
|
|
||||||
|
KDDockWidgets::MainWindow mainWindow(QStringLiteral("MyMainWindow"));
|
||||||
|
mainWindow.setWindowTitle("Main Window");
|
||||||
|
mainWindow.resize(1200, 1200);
|
||||||
|
mainWindow.show();
|
||||||
|
|
||||||
|
// # 2. Create four dock widgets. Each needs an unique name.
|
||||||
|
auto dock1 = new KDDockWidgets::DockWidget(QStringLiteral("MyDock1"));
|
||||||
|
auto widget1 = new MyWidget(QStringLiteral(":/assets/base.png"),
|
||||||
|
QStringLiteral(":/assets/KDAB_bubble_fulcolor.png"));
|
||||||
|
dock1->setWidget(widget1);
|
||||||
|
|
||||||
|
auto dock2 = new KDDockWidgets::DockWidget(QStringLiteral("MyDock2"));
|
||||||
|
auto widget2 = new MyWidget(QStringLiteral(":/assets/base.png"),
|
||||||
|
QStringLiteral(":/assets/KDAB_bubble_fulcolor.png"));
|
||||||
|
dock2->setWidget(widget2);
|
||||||
|
|
||||||
|
auto dock3 = new KDDockWidgets::DockWidget(QStringLiteral("MyDock3"));
|
||||||
|
auto widget3 = new MyWidget(QStringLiteral(":/assets/base.png"),
|
||||||
|
QStringLiteral(":/assets/KDAB_bubble_fulcolor.png"));
|
||||||
|
dock3->setWidget(widget3);
|
||||||
|
|
||||||
|
auto dock4 = new KDDockWidgets::DockWidget(QStringLiteral("MyDock4"));
|
||||||
|
auto widget4 = new MyWidget(QStringLiteral(":/assets/base.png"),
|
||||||
|
QStringLiteral(":/assets/KDAB_bubble_fulcolor.png"));
|
||||||
|
dock4->setWidget(widget4);
|
||||||
|
|
||||||
|
|
||||||
|
// 3. Add them to the main window
|
||||||
|
mainWindow.addDockWidget(dock1, KDDockWidgets::Location_OnLeft);
|
||||||
|
mainWindow.addDockWidget(dock2, KDDockWidgets::Location_OnTop);
|
||||||
|
|
||||||
|
// 4. Add dock3 to the right of dock2
|
||||||
|
mainWindow.addDockWidget(dock3, KDDockWidgets::Location_OnRight, dock2);
|
||||||
|
|
||||||
|
// 5. dock4 will be its own top level (floating window)
|
||||||
|
dock4->show();
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
}
|
||||||
10
kddockwidgets.dsc
Normal file
10
kddockwidgets.dsc
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Format: 1.0
|
||||||
|
Source: kddockwidgets
|
||||||
|
Version: 0.99.9
|
||||||
|
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-0.99.9.tar.gz
|
||||||
92
kddockwidgets.spec
Normal file
92
kddockwidgets.spec
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
Name: kddockwidgets
|
||||||
|
Version: 0.99.9
|
||||||
|
Release: 1
|
||||||
|
Summary: KDAB's Dock Widget Framework for Qt
|
||||||
|
Source0: %{name}-%{version}.tar.gz
|
||||||
|
Source1: %{name}-%{version}.tar.gz.asc
|
||||||
|
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: libqt5-qtbase-devel libqt5-qtx11extras-devel
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if %{defined fedora}
|
||||||
|
BuildRequires: gcc-c++ qt5-qtbase-devel qt5-qtx11extras-devel desktop-file-utils
|
||||||
|
%endif
|
||||||
|
|
||||||
|
%if %{defined rhel}
|
||||||
|
BuildRequires: gcc-c++ qt5-qtbase-devel qt5-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 -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.so.*
|
||||||
|
%{_libdir}/libkddockwidgets_multisplitter.so.*
|
||||||
|
|
||||||
|
%files devel
|
||||||
|
%defattr(-,root,root,-)
|
||||||
|
%{_libdir}/qt5/mkspecs/modules/*
|
||||||
|
%dir %{_includedir}/kddockwidgets
|
||||||
|
%{_includedir}/kddockwidgets/*
|
||||||
|
%dir %{_libdir}/cmake/KDDockWidgets
|
||||||
|
%{_libdir}/cmake/KDDockWidgets/*
|
||||||
|
%{_libdir}/libkddockwidgets.so
|
||||||
|
%{_libdir}/libkddockwidgets_multisplitter.so
|
||||||
|
|
||||||
|
%changelog
|
||||||
|
* Thu Aug 06 2020 Allen Winter <allen.winter@kdb.com> 0.99.9
|
||||||
|
1.0.0 release candidate
|
||||||
18
python/CMakeLists.txt
Normal file
18
python/CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
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(Shiboken2 REQUIRED)
|
||||||
|
find_package(PySide2 ${Qt5Widgets_VERSION} EXACT REQUIRED)
|
||||||
|
include(PySide2ModuleBuild)
|
||||||
|
|
||||||
|
add_subdirectory(PyKDDockWidgets)
|
||||||
81
python/PyKDDockWidgets/CMakeLists.txt
Normal file
81
python/PyKDDockWidgets/CMakeLists.txt
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
# Auto-Genereate files every class will have his cpp/h files
|
||||||
|
set(PyKDDockWidgets_SRC
|
||||||
|
# individual classes
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_dockwidgetbase_wrapper.cpp
|
||||||
|
${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.h
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_mainwindowbase_wrapper.cpp
|
||||||
|
${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.h
|
||||||
|
# namespace wrapper
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_wrapper.cpp
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_wrapper.h
|
||||||
|
# global module wrapper
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_module_wrapper.cpp
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgets/kddockwidgets_python.h
|
||||||
|
)
|
||||||
|
|
||||||
|
# includes necessary to parse and build the classes specified on typesystem
|
||||||
|
set(PyKDDockWidgets_include_paths
|
||||||
|
$<JOIN:$<TARGET_PROPERTY:KDAB::kddockwidgets,INTERFACE_INCLUDE_DIRECTORIES>,${PATH_SEP}>
|
||||||
|
)
|
||||||
|
|
||||||
|
# A list of paths where shiboken should look for typesystem
|
||||||
|
set(PyKDDockWidgets_typesystem_paths
|
||||||
|
# PySide path, this variable was exposed by FindPySide2.cmake
|
||||||
|
${PYSIDE_TYPESYSTEMS}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Include flags/path that will be set in 'target_include_directories'
|
||||||
|
set(PyKDDockWidgets_target_include_directories
|
||||||
|
${CMAKE_SOURCE_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Libraries that will be necessary to link the target, this will used in the command 'target_link_libraries'
|
||||||
|
set(PyKDDockWidgets_target_link_libraries
|
||||||
|
KDAB::kddockwidgets
|
||||||
|
Qt5::Core
|
||||||
|
Qt5::Gui
|
||||||
|
Qt5::Widgets
|
||||||
|
)
|
||||||
|
|
||||||
|
# changes on these files should trigger a new generation
|
||||||
|
set(PyKDDockWidgets_DEPENDS
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/kddockwidgets_global.h
|
||||||
|
${CMAKE_SOURCE_DIR}/src/DockWidgetBase.h
|
||||||
|
${CMAKE_SOURCE_DIR}/src/DockWidget.h
|
||||||
|
${CMAKE_SOURCE_DIR}/src/MainWindowBase.h
|
||||||
|
${CMAKE_SOURCE_DIR}/src/MainWindow.h
|
||||||
|
)
|
||||||
|
|
||||||
|
create_python_bindings(
|
||||||
|
"KDDockWidgets"
|
||||||
|
"${PyKDDockWidgets_typesystem_paths}"
|
||||||
|
"${PyKDDockWidgets_include_paths}"
|
||||||
|
"${PyKDDockWidgets_SRC}"
|
||||||
|
"${PyKDDockWidgets_target_include_directories}"
|
||||||
|
"${PyKDDockWidgets_target_link_libraries}"
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/kddockwidgets_global.h
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/typesystem_kddockwidgets.xml
|
||||||
|
"${PyKDDockWidgets_DEPENDS}"
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
|
)
|
||||||
|
|
||||||
|
# Make moduled import from build dir works
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/__init__.py ${CMAKE_CURRENT_BINARY_DIR}/__init__.py)
|
||||||
|
|
||||||
|
# install
|
||||||
|
install(FILES ${CMAKE_CURRENT_SOURCE_DIR}/__init__.py DESTINATION ${PYTHON_BINDINGS_INSTALL_PREFIX}/PyKDDockWidgets)
|
||||||
25
python/PyKDDockWidgets/__init__.py
Normal file
25
python/PyKDDockWidgets/__init__.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
__all__ = ['KDDockWidgets']
|
||||||
|
|
||||||
|
# Preload PySide2 libraries to avoid missing libraries while loading KDDockWidgets
|
||||||
|
try:
|
||||||
|
from PySide2 import QtCore
|
||||||
|
except Exception:
|
||||||
|
print("Failed to load PySide")
|
||||||
|
raise
|
||||||
|
|
||||||
|
# avoid duplicate namespace, due the PYSIDE-1325 bug I will have my package like this
|
||||||
|
# PyKDDockWidgets.KDDockWidgets.KDDockWidgets.MainWindow
|
||||||
|
# To avoid this I add a WORKAROUND to reduce it
|
||||||
|
from .KDDockWidgets import KDDockWidgets as _priv
|
||||||
|
KDDockWidgets = _priv
|
||||||
24
python/PyKDDockWidgets/kddockwidgets_global.h
Normal file
24
python/PyKDDockWidgets/kddockwidgets_global.h
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
// Make "signals:", "slots:" visible as access specifiers
|
||||||
|
#define QT_ANNOTATE_ACCESS_SPECIFIER(a) __attribute__((annotate(#a)))
|
||||||
|
|
||||||
|
// Define PYTHON_BINDINGS this will be used in some part of c++ to skip problematic parts
|
||||||
|
#define PYTHON_BINDINGS
|
||||||
|
|
||||||
|
#include <MainWindowBase.h>
|
||||||
|
#include <MainWindow.h>
|
||||||
|
#include <DockWidgetBase.h>
|
||||||
|
#include <DockWidget.h>
|
||||||
|
|
||||||
39
python/PyKDDockWidgets/typesystem_kddockwidgets.xml
Normal file
39
python/PyKDDockWidgets/typesystem_kddockwidgets.xml
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<!-- The package name -->
|
||||||
|
<typesystem package="KDDockWidgets">
|
||||||
|
<!-- Pre-defined typesystem that contains types used by our class
|
||||||
|
PySide has one typesystem for each module, here we use only the widgets
|
||||||
|
typesystem because it already include gui and core typesystem -->
|
||||||
|
<load-typesystem name="typesystem_widgets.xml" generate="no"/>
|
||||||
|
|
||||||
|
<!-- Our classes are declared in a namespace, so we should define this -->
|
||||||
|
<namespace-type name="KDDockWidgets">
|
||||||
|
<!-- this is used in a public virtual pure function we need to declare it
|
||||||
|
otherwise shiboken will ignore the function and will fail to create a wrapper -->
|
||||||
|
<primitive-type name="DropAreaWithCentralFrame"/>
|
||||||
|
|
||||||
|
<!-- Some plublic enum and flags -->
|
||||||
|
<enum-type name="Location"/>
|
||||||
|
<enum-type name="MainWindowOption" flags="MainWindowOptions"/>
|
||||||
|
<enum-type name="AddingOption"/>
|
||||||
|
<enum-type name="RestoreOption" flags="RestoreOptions"/>
|
||||||
|
<enum-type name="DefaultSizeMode"/>
|
||||||
|
<enum-type name="FrameOption" flags="FrameOptions"/>
|
||||||
|
|
||||||
|
<!-- our classes
|
||||||
|
For class we can use two types:
|
||||||
|
object-type: class that does not have a copy-contructor and can not be passed as value to 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
|
||||||
|
-->
|
||||||
|
<object-type name="MainWindowBase" />
|
||||||
|
<object-type name="MainWindow" />
|
||||||
|
<object-type name="DockWidgetBase" >
|
||||||
|
<!-- this class contains a internal enum, so it should be declared
|
||||||
|
inside of the object-type -->
|
||||||
|
<enum-type name="Option" flags="Options" />
|
||||||
|
</object-type>
|
||||||
|
|
||||||
|
<object-type name="DockWidget" />
|
||||||
|
</namespace-type>
|
||||||
|
</typesystem>
|
||||||
161
python/examples/MyMainWindow.py
Normal file
161
python/examples/MyMainWindow.py
Normal file
@@ -0,0 +1,161 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
from PySide2 import QtCore, QtWidgets, QtGui
|
||||||
|
from PyKDDockWidgets import KDDockWidgets
|
||||||
|
|
||||||
|
from MyWidget1 import MyWidget1
|
||||||
|
from MyWidget2 import MyWidget2
|
||||||
|
from MyWidget3 import MyWidget3
|
||||||
|
|
||||||
|
def newMyWidget(parent = None):
|
||||||
|
randomNumber = QtCore.QRandomGenerator.global_().bounded(0, 100) + 1
|
||||||
|
if (randomNumber < 50):
|
||||||
|
if (randomNumber < 33):
|
||||||
|
return MyWidget1(parent)
|
||||||
|
else:
|
||||||
|
return MyWidget3(parent)
|
||||||
|
else:
|
||||||
|
return MyWidget2(parent)
|
||||||
|
|
||||||
|
class MyMainWindow(KDDockWidgets.MainWindow):
|
||||||
|
s_count = 0
|
||||||
|
s_menuCount = 0
|
||||||
|
|
||||||
|
def __init__(self, uniqueName, options = KDDockWidgets.MainWindowOption_None, dockWidget0IsNonClosable = False, nonDockableDockWidget9 = False, restoreIsRelative = False, maxSizeForDockWidget8 = False, affinityName = "", parent = None):
|
||||||
|
super().__init__(uniqueName, options, parent)
|
||||||
|
self.m_dockWidget0IsNonClosable = dockWidget0IsNonClosable
|
||||||
|
self.m_dockWidget9IsNonDockable = nonDockableDockWidget9
|
||||||
|
self.m_restoreIsRelative = restoreIsRelative
|
||||||
|
self.m_maxSizeForDockWidget8 = maxSizeForDockWidget8
|
||||||
|
self.m_dockwidgets = []
|
||||||
|
|
||||||
|
menubar = self.menuBar()
|
||||||
|
fileMenu = QtWidgets.QMenu("File")
|
||||||
|
self.m_toggleMenu = QtWidgets.QMenu("Toggle")
|
||||||
|
menubar.addMenu(fileMenu)
|
||||||
|
menubar.addMenu(self.m_toggleMenu)
|
||||||
|
|
||||||
|
newAction = fileMenu.addAction("New DockWidget")
|
||||||
|
newAction.triggered.connect(self._newDockWidget)
|
||||||
|
|
||||||
|
saveLayoutAction = fileMenu.addAction("Save Layout")
|
||||||
|
saveLayoutAction.triggered.connect(self._saveLayout)
|
||||||
|
|
||||||
|
restoreLayoutAction = fileMenu.addAction("Restore Layout")
|
||||||
|
restoreLayoutAction.triggered.connect(self._restoreLayout)
|
||||||
|
|
||||||
|
closeAllAction = fileMenu.addAction("Close All")
|
||||||
|
closeAllAction.triggered.connect(self._closeAll)
|
||||||
|
|
||||||
|
layoutEqually = fileMenu.addAction("Layout Equally")
|
||||||
|
layoutEqually.triggered.connect(self.layoutEqually)
|
||||||
|
|
||||||
|
quitAction = fileMenu.addAction("Quit")
|
||||||
|
quitAction.triggered.connect(QtWidgets.QApplication.instance().quit)
|
||||||
|
|
||||||
|
self.setAffinities([ affinityName ])
|
||||||
|
self.createDockWidgets()
|
||||||
|
|
||||||
|
def _newDockWidget(self):
|
||||||
|
MyMainWindow.s_menuCount += 1
|
||||||
|
w = newMyWidget(self)
|
||||||
|
w.setGeometry(100, 100, 400, 400)
|
||||||
|
dock = KDDockWidgets.DockWidget("new dock %d"%(MyMainWindow.s_menuCount))
|
||||||
|
dock.setWidget(w)
|
||||||
|
dock.resize(600, 600)
|
||||||
|
dock.show()
|
||||||
|
self.m_dockwidgets.append(dock)
|
||||||
|
|
||||||
|
def _saveLayout(self):
|
||||||
|
#saver = KDDockWidgets.LayoutSaver()
|
||||||
|
#result = saver.saveToFile("mylayout.json")
|
||||||
|
#print("Saving layout to disk. Result=", result)
|
||||||
|
print("Not available")
|
||||||
|
|
||||||
|
def _restoreLayout(self):
|
||||||
|
#options = KDDockWidgets.RestoreOption_None
|
||||||
|
#if self.m_restoreIsRelative:
|
||||||
|
# options |= KDDockWidgets.RestoreOption_RelativeToMainWindow
|
||||||
|
#saver = KDDockWidgets.LayoutSaver(options)
|
||||||
|
#saver.restoreFromFile("mylayout.json")
|
||||||
|
print("Not available")
|
||||||
|
|
||||||
|
def _closeAll(self):
|
||||||
|
for dw in self.m_dockwidgets:
|
||||||
|
dw.close()
|
||||||
|
|
||||||
|
def createDockWidgets(self):
|
||||||
|
if self.m_dockWidget9IsNonDockable:
|
||||||
|
numDockWidgets = 10
|
||||||
|
else:
|
||||||
|
numDockWidgets = 9
|
||||||
|
|
||||||
|
# numDockWidgets = 2
|
||||||
|
# Create 9 KDDockWidget::DockWidget and the respective widgets they're hosting (MyWidget instances)
|
||||||
|
for i in range(numDockWidgets):
|
||||||
|
self.m_dockwidgets.append(self.newDockWidget())
|
||||||
|
|
||||||
|
# MainWindow::addDockWidget() attaches a dock widget to the main window:
|
||||||
|
self.addDockWidget(self.m_dockwidgets[0], KDDockWidgets.Location_OnTop)
|
||||||
|
|
||||||
|
# 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[2], KDDockWidgets.Location_OnLeft)
|
||||||
|
self.addDockWidget(self.m_dockwidgets[3], KDDockWidgets.Location_OnBottom)
|
||||||
|
self.addDockWidget(self.m_dockwidgets[4], KDDockWidgets.Location_OnBottom)
|
||||||
|
|
||||||
|
# Tab two dock widgets together
|
||||||
|
self.m_dockwidgets[3].addDockWidgetAsTab(self.m_dockwidgets[5])
|
||||||
|
|
||||||
|
# 6 is floating, as it wasn't added to the main window via MainWindow::addDockWidget().
|
||||||
|
# and we tab 7 with it.
|
||||||
|
self.m_dockwidgets[6].addDockWidgetAsTab(self.m_dockwidgets[7])
|
||||||
|
|
||||||
|
# Floating windows also support nesting, here we add 8 to the bottom of the group
|
||||||
|
self.m_dockwidgets[6].addDockWidgetToContainingWindow(self.m_dockwidgets[8], KDDockWidgets.Location_OnBottom)
|
||||||
|
|
||||||
|
floatingWindow = self.m_dockwidgets[6].window()
|
||||||
|
floatingWindow.move(100, 100)
|
||||||
|
|
||||||
|
def newDockWidget(self):
|
||||||
|
# Passing options is optional, we just want to illustrate Option_NotClosable here
|
||||||
|
options = KDDockWidgets.DockWidget.Option_None
|
||||||
|
if (MyMainWindow.s_count == 0) and self.m_dockWidget0IsNonClosable:
|
||||||
|
options |= KDDockWidgets.DockWidget.Option_NotClosable
|
||||||
|
|
||||||
|
if (MyMainWindow.s_count == 9) and self.m_dockWidget9IsNonDockable:
|
||||||
|
options |= KDDockWidgets.DockWidget.Option_NotDockable
|
||||||
|
|
||||||
|
dock = KDDockWidgets.DockWidget("DockWidget #%d"%(MyMainWindow.s_count), options)
|
||||||
|
dock.setAffinities(self.affinities()); # optional, just to show the feature. Pass -mi to the example to see incompatible dock widgets
|
||||||
|
|
||||||
|
if MyMainWindow.s_count == 1:
|
||||||
|
dock.setIcon(QtGui.QIcon.fromTheme("mail-message"))
|
||||||
|
|
||||||
|
myWidget = newMyWidget(self)
|
||||||
|
if (MyMainWindow.s_count == 8) and self.m_maxSizeForDockWidget8:
|
||||||
|
# Set a maximum size on dock #8
|
||||||
|
myWidget.setMaximumSize(200, 200)
|
||||||
|
|
||||||
|
dock.setWidget(myWidget)
|
||||||
|
|
||||||
|
if dock.options() & KDDockWidgets.DockWidget.Option_NotDockable:
|
||||||
|
dock.setTitle("DockWidget #%d (%s)" %(MyMainWindow.s_count, "non dockable"))
|
||||||
|
else:
|
||||||
|
dock.setTitle("DockWidget #%d"%(MyMainWindow.s_count))
|
||||||
|
|
||||||
|
dock.resize(600, 600)
|
||||||
|
self.m_toggleMenu.addAction(dock.toggleAction())
|
||||||
|
MyMainWindow.s_count += 1
|
||||||
|
return dock
|
||||||
|
|
||||||
49
python/examples/MyWidget.py
Normal file
49
python/examples/MyWidget.py
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
from PySide2 import QtWidgets, QtGui, QtCore
|
||||||
|
|
||||||
|
class MyWidget(QtWidgets.QWidget):
|
||||||
|
s_images = {}
|
||||||
|
def __init__(self, backgroundFile, logoFile, parent = None):
|
||||||
|
super().__init__(parent)
|
||||||
|
|
||||||
|
self.m_background = self._lookupImage(backgroundFile)
|
||||||
|
self.m_logo = self._lookupImage(logoFile)
|
||||||
|
|
||||||
|
def _lookupImage(self, imageName):
|
||||||
|
if imageName == "":
|
||||||
|
return None
|
||||||
|
|
||||||
|
if imageName not in MyWidget.s_images:
|
||||||
|
MyWidget.s_images[imageName] = QtGui.QImage(imageName)
|
||||||
|
|
||||||
|
return MyWidget.s_images[imageName]
|
||||||
|
|
||||||
|
def drawLogo(self, p):
|
||||||
|
|
||||||
|
if not self.m_logo:
|
||||||
|
return
|
||||||
|
|
||||||
|
ratio = self.m_logo.height() / (self.m_logo.width() * 1.0)
|
||||||
|
maxWidth = int(0.80 * self.size().width())
|
||||||
|
maxHeight = int(0.80 * self.size().height())
|
||||||
|
proposedHeight = int(maxWidth * ratio)
|
||||||
|
if (proposedHeight <= maxHeight):
|
||||||
|
width = maxWidth
|
||||||
|
else:
|
||||||
|
width = int(maxHeight / ratio)
|
||||||
|
|
||||||
|
height = int(width * ratio)
|
||||||
|
targetLogoRect = QtCore.QRect(0,0, width, height)
|
||||||
|
targetLogoRect.moveCenter(self.rect().center() + QtCore.QPoint(0, -int(self.size().height() * 0.00)))
|
||||||
|
p.drawImage(targetLogoRect, self.m_logo, self.m_logo.rect());
|
||||||
|
|
||||||
27
python/examples/MyWidget1.py
Normal file
27
python/examples/MyWidget1.py
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
from PySide2 import QtWidgets, QtGui
|
||||||
|
|
||||||
|
from MyWidget import MyWidget
|
||||||
|
|
||||||
|
|
||||||
|
class MyWidget1(MyWidget):
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
super().__init__(":/assets/triangles.png", ":/assets/KDAB_bubble_white.png", parent)
|
||||||
|
|
||||||
|
|
||||||
|
def paintEvent(self, ev):
|
||||||
|
p = QtGui.QPainter(self)
|
||||||
|
p.fillRect(self.rect(), QtGui.QColor(0xCC, 0xCC, 0xCC))
|
||||||
|
p.drawImage(self.m_background.rect(), self.m_background, self.m_background.rect())
|
||||||
|
self.drawLogo(p)
|
||||||
|
|
||||||
25
python/examples/MyWidget2.py
Normal file
25
python/examples/MyWidget2.py
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
from PySide2 import QtWidgets, QtGui, QtCore
|
||||||
|
|
||||||
|
from MyWidget import MyWidget
|
||||||
|
|
||||||
|
class MyWidget2(MyWidget):
|
||||||
|
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
super().__init__("", ":/assets/KDAB_bubble_blue.png", parent)
|
||||||
|
|
||||||
|
def paintEvent(self, ev):
|
||||||
|
p = QtGui.QPainter(self)
|
||||||
|
p.fillRect(self.rect(), QtCore.Qt.white);
|
||||||
|
self.drawLogo(p)
|
||||||
|
|
||||||
30
python/examples/MyWidget3.py
Normal file
30
python/examples/MyWidget3.py
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
from PySide2 import QtWidgets, QtGui, QtCore
|
||||||
|
|
||||||
|
from MyWidget import MyWidget
|
||||||
|
|
||||||
|
class MyWidget3(MyWidget):
|
||||||
|
|
||||||
|
def __init__(self, parent = None):
|
||||||
|
super().__init__(":/assets/base.png", ":/assets/KDAB_bubble_fulcolor.png", parent)
|
||||||
|
self.m_triangle = QtGui.QImage(":/assets/tri.png")
|
||||||
|
|
||||||
|
def paintEvent(self, ev):
|
||||||
|
p = QtGui.QPainter(self)
|
||||||
|
p.fillRect(self.rect(), QtGui.QColor(0xD5, 0xD5, 0xD5))
|
||||||
|
p.drawImage(self.m_background.rect(), self.m_background, self.m_background.rect())
|
||||||
|
|
||||||
|
targetRect = QtCore.QRect(QtCore.QPoint(self.width() - self.m_triangle.width(), self.height() - self.m_triangle.height()), self.m_triangle.size())
|
||||||
|
|
||||||
|
self.drawLogo(p)
|
||||||
|
|
||||||
8
python/examples/README.txt
Normal file
8
python/examples/README.txt
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
Running python example
|
||||||
|
======================
|
||||||
|
|
||||||
|
Generate resource file with:
|
||||||
|
~# rcc -g python -o rc_assets.py ../../examples/dockwidgets/resources_example.qrc
|
||||||
|
|
||||||
|
Run the app:
|
||||||
|
~# python3 main.py
|
||||||
35
python/examples/main.py
Normal file
35
python/examples/main.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Renato Araujo Oliveira Filho <renato.araujo@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
|
|
||||||
|
from PySide2 import QtWidgets, QtCore
|
||||||
|
from PyKDDockWidgets import KDDockWidgets
|
||||||
|
from MyMainWindow import MyMainWindow
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import rc_assets
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling)
|
||||||
|
QtWidgets.QApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps)
|
||||||
|
app = QtWidgets.QApplication(sys.argv)
|
||||||
|
|
||||||
|
app.setOrganizationName("KDAB")
|
||||||
|
app.setApplicationName("Test app")
|
||||||
|
app.setStyle(QtWidgets.QStyleFactory.create("Fusion"))
|
||||||
|
|
||||||
|
mainWindow = MyMainWindow("MyMainWindow", )
|
||||||
|
mainWindow.setWindowTitle("Main Window 1")
|
||||||
|
mainWindow.resize(1200, 1200)
|
||||||
|
mainWindow.show()
|
||||||
|
|
||||||
|
app.exec_()
|
||||||
|
|
||||||
@@ -1,43 +1,41 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
#
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
#
|
||||||
|
# Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
#
|
||||||
|
|
||||||
cmake_policy(SET CMP0043 NEW)
|
if(POLICY CMP0043)
|
||||||
|
cmake_policy(SET CMP0043 NEW)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_definitions(-DQT_NO_CAST_TO_ASCII
|
add_definitions(-DQT_NO_SIGNALS_SLOTS_KEYWORDS
|
||||||
-DQT_NO_CAST_FROM_ASCII
|
|
||||||
-DQT_NO_URL_CAST_FROM_STRING
|
|
||||||
-DQT_NO_CAST_FROM_BYTEARRAY
|
|
||||||
-DQT_NO_SIGNALS_SLOTS_KEYWORDS
|
|
||||||
-DQT_USE_QSTRINGBUILDER
|
-DQT_USE_QSTRINGBUILDER
|
||||||
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
|
-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT
|
||||||
-DQT_STRICT_ITERATORS
|
-DQT_STRICT_ITERATORS
|
||||||
-DQT_NO_KEYWORDS
|
-DQT_NO_KEYWORDS
|
||||||
-DQT_DISABLE_DEPRECATED_BEFORE=0x060000
|
|
||||||
-DQT_NO_FOREACH
|
-DQT_NO_FOREACH
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKSLIBS_SRCS
|
set(DOCKSLIBS_SRCS
|
||||||
Config.cpp
|
Config.cpp
|
||||||
|
Qt5Qt6Compat_p.h
|
||||||
FrameworkWidgetFactory.cpp
|
FrameworkWidgetFactory.cpp
|
||||||
DockWidgetBase.cpp
|
DockWidgetBase.cpp
|
||||||
MainWindow.cpp
|
|
||||||
MainWindowBase.cpp
|
MainWindowBase.cpp
|
||||||
LayoutSaver.cpp
|
LayoutSaver.cpp
|
||||||
private/LastPosition.cpp
|
private/MultiSplitter.cpp
|
||||||
|
private/Position.cpp
|
||||||
private/ObjectViewer.cpp
|
private/ObjectViewer.cpp
|
||||||
private/DropIndicatorOverlayInterface.cpp
|
private/DropIndicatorOverlayInterface.cpp
|
||||||
private/indicators/ClassicIndicators.cpp
|
|
||||||
private/indicators/AnimatedIndicators.cpp
|
|
||||||
private/DropArea.cpp
|
private/DropArea.cpp
|
||||||
private/multisplitter/Item.cpp
|
|
||||||
private/multisplitter/MultiSplitter.cpp
|
|
||||||
private/multisplitter/Anchor.cpp
|
|
||||||
private/multisplitter/AnchorGroup.cpp
|
|
||||||
private/multisplitter/Separator.cpp
|
|
||||||
private/multisplitter/MultiSplitterLayout.cpp
|
|
||||||
private/TabWidget.cpp
|
|
||||||
private/FloatingWindow.cpp
|
private/FloatingWindow.cpp
|
||||||
private/Logging.cpp
|
private/Logging.cpp
|
||||||
private/TitleBar.cpp
|
private/TitleBar.cpp
|
||||||
private/DebugWindow.cpp
|
|
||||||
private/DockRegistry.cpp
|
private/DockRegistry.cpp
|
||||||
private/Draggable.cpp
|
private/Draggable.cpp
|
||||||
private/WindowBeingDragged.cpp
|
private/WindowBeingDragged.cpp
|
||||||
@@ -45,7 +43,7 @@ set(DOCKSLIBS_SRCS
|
|||||||
private/Frame.cpp
|
private/Frame.cpp
|
||||||
private/DropAreaWithCentralFrame.cpp
|
private/DropAreaWithCentralFrame.cpp
|
||||||
private/WidgetResizeHandler.cpp
|
private/WidgetResizeHandler.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_INCLUDES
|
set(DOCKS_INSTALLABLE_INCLUDES
|
||||||
docks_export.h
|
docks_export.h
|
||||||
@@ -56,47 +54,44 @@ set(DOCKS_INSTALLABLE_INCLUDES
|
|||||||
QWidgetAdapter.h
|
QWidgetAdapter.h
|
||||||
LayoutSaver.h
|
LayoutSaver.h
|
||||||
LayoutSaver_p.h
|
LayoutSaver_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_PRIVATE_INCLUDES
|
set(DOCKS_INSTALLABLE_PRIVATE_INCLUDES
|
||||||
private/Draggable_p.h
|
private/Draggable_p.h
|
||||||
private/DropIndicatorOverlayInterface_p.h
|
private/DropIndicatorOverlayInterface_p.h
|
||||||
private/FloatingWindow_p.h
|
private/FloatingWindow_p.h
|
||||||
private/Frame_p.h
|
private/Frame_p.h
|
||||||
private/TabWidget_p.h
|
|
||||||
private/TitleBar_p.h
|
private/TitleBar_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
set(DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES
|
||||||
private/widgets/QWidgetAdapter_widgets_p.h
|
private/widgets/QWidgetAdapter_widgets_p.h
|
||||||
private/widgets/TitleBarWidget_p.h
|
private/widgets/TitleBarWidget_p.h
|
||||||
private/widgets/SeparatorWidget_p.h
|
|
||||||
private/widgets/FloatingWindowWidget_p.h
|
private/widgets/FloatingWindowWidget_p.h
|
||||||
private/widgets/FrameWidget_p.h
|
private/widgets/FrameWidget_p.h
|
||||||
private/widgets/TabBarWidget_p.h
|
private/widgets/TabBarWidget_p.h
|
||||||
private/widgets/TabWidgetWidget_p.h
|
private/widgets/TabWidgetWidget_p.h
|
||||||
|
private/widgets/TabWidget_p.h
|
||||||
)
|
)
|
||||||
|
|
||||||
if (OPTION_QTQUICK)
|
if(OPTION_QTQUICK)
|
||||||
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
||||||
private/quick/DockWidgetQuick.cpp
|
private/quick/DockWidgetQuick.cpp
|
||||||
private/quick/QWidgetAdapter_quick.cpp
|
private/quick/QWidgetAdapter_quick.cpp
|
||||||
private/quick/FloatingWindowQuick.cpp
|
private/quick/FloatingWindowQuick.cpp
|
||||||
private/quick/TitleBarQuick.cpp
|
private/quick/TitleBarQuick.cpp
|
||||||
private/quick/QmlTypes.cpp
|
private/quick/QmlTypes.cpp
|
||||||
private/quick/TabWidgetQuick.cpp
|
|
||||||
private/quick/FrameQuick.cpp
|
private/quick/FrameQuick.cpp
|
||||||
private/quick/MainWindowQuick.cpp
|
private/quick/MainWindowQuick.cpp
|
||||||
private/quick/TabBarQuick.cpp
|
private/quick/MainWindowWrapper.cpp
|
||||||
private/quick/SeparatorQuick.cpp
|
)
|
||||||
private/quick/LayoutSaverQuick.cpp)
|
|
||||||
|
|
||||||
qt5_add_resources(RESOURCES_QUICK ${CMAKE_CURRENT_SOURCE_DIR}/qtquick.qrc)
|
qt5_add_resources(RESOURCES_QUICK ${CMAKE_CURRENT_SOURCE_DIR}/qtquick.qrc)
|
||||||
|
|
||||||
else()
|
else()
|
||||||
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
set(DOCKSLIBS_SRCS ${DOCKSLIBS_SRCS}
|
||||||
private/widgets/SeparatorWidget.cpp
|
private/DebugWindow.cpp
|
||||||
|
MainWindow.cpp
|
||||||
|
private/widgets/TabWidget.cpp
|
||||||
private/widgets/TabBarWidget.cpp
|
private/widgets/TabBarWidget.cpp
|
||||||
private/widgets/FloatingWindowWidget.cpp
|
private/widgets/FloatingWindowWidget.cpp
|
||||||
private/widgets/FrameWidget.cpp
|
private/widgets/FrameWidget.cpp
|
||||||
@@ -104,79 +99,130 @@ else()
|
|||||||
private/widgets/TitleBarWidget.cpp
|
private/widgets/TitleBarWidget.cpp
|
||||||
private/widgets/DockWidget.cpp
|
private/widgets/DockWidget.cpp
|
||||||
private/widgets/QWidgetAdapter_widgets.cpp
|
private/widgets/QWidgetAdapter_widgets.cpp
|
||||||
|
private/indicators/ClassicIndicators.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
|
MainWindowBase.h
|
||||||
DockWidget.h)
|
DockWidget.h
|
||||||
|
)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||||
set(IS_CLANG_BUILD TRUE)
|
set(IS_CLANG_BUILD TRUE)
|
||||||
else()
|
else()
|
||||||
set(IS_CLANG_BUILD FALSE)
|
set(IS_CLANG_BUILD FALSE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
add_subdirectory(private/multisplitter)
|
||||||
|
|
||||||
qt5_add_resources(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc)
|
qt5_add_resources(RESOURCES ${CMAKE_CURRENT_SOURCE_DIR}/resources.qrc)
|
||||||
|
|
||||||
add_library(kddockwidgets SHARED ${DOCKSLIBS_SRCS} ${DOCKS_INSTALLABLE_INCLUDES} ${RESOURCES} ${RESOURCES_QUICK})
|
add_library(kddockwidgets ${KDDockWidgets_LIBRARY_MODE} ${DOCKSLIBS_SRCS} ${DOCKS_INSTALLABLE_INCLUDES} ${RESOURCES} ${RESOURCES_QUICK})
|
||||||
|
add_library(KDAB::kddockwidgets ALIAS kddockwidgets)
|
||||||
|
set_compiler_flags(kddockwidgets)
|
||||||
|
|
||||||
target_include_directories(kddockwidgets
|
target_include_directories(kddockwidgets
|
||||||
PUBLIC
|
PUBLIC
|
||||||
$<INSTALL_INTERFACE:include>
|
$<INSTALL_INTERFACE:include>
|
||||||
$<INSTALL_INTERFACE:include/kddockwidgets>
|
$<INSTALL_INTERFACE:include/kddockwidgets>
|
||||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
|
||||||
|
$<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
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(kddockwidgets PRIVATE BUILDING_DOCKS_LIBRARY)
|
target_compile_definitions(kddockwidgets
|
||||||
if (CMAKE_COMPILER_IS_GNUCXX OR IS_CLANG_BUILD)
|
PRIVATE
|
||||||
|
QT_NO_CAST_TO_ASCII
|
||||||
|
QT_NO_CAST_FROM_ASCII
|
||||||
|
QT_NO_URL_CAST_FROM_STRING
|
||||||
|
QT_NO_CAST_FROM_BYTEARRAY
|
||||||
|
)
|
||||||
|
if(${PROJECT_NAME}_STATIC)
|
||||||
|
target_compile_definitions(kddockwidgets PUBLIC KDDOCKWIDGETS_STATICLIB)
|
||||||
|
else()
|
||||||
|
target_compile_definitions(kddockwidgets PRIVATE BUILDING_DOCKS_LIBRARY)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(CMAKE_COMPILER_IS_GNUCXX OR IS_CLANG_BUILD)
|
||||||
target_compile_options(kddockwidgets PRIVATE -Wshadow -Wconversion -fvisibility=hidden)
|
target_compile_options(kddockwidgets PRIVATE -Wshadow -Wconversion -fvisibility=hidden)
|
||||||
|
|
||||||
if (IS_CLANG_BUILD)
|
if(IS_CLANG_BUILD)
|
||||||
target_compile_options(kddockwidgets PRIVATE -Wweak-vtables)
|
target_compile_options(kddockwidgets PRIVATE -Wweak-vtables)
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (OPTION_QTQUICK)
|
if(OPTION_QTQUICK)
|
||||||
target_link_libraries(kddockwidgets Qt5::Widgets Qt5::Quick)
|
target_link_libraries(kddockwidgets PUBLIC Qt5::Widgets Qt5::Quick Qt5::QuickControls2 kddockwidgets_multisplitter)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(kddockwidgets Qt5::Widgets)
|
target_link_libraries(kddockwidgets PUBLIC Qt5::Widgets kddockwidgets_multisplitter)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(NOT WIN32 AND NOT APPLE)
|
||||||
if (NOT WIN32 AND NOT APPLE)
|
|
||||||
find_package(Qt5X11Extras)
|
find_package(Qt5X11Extras)
|
||||||
target_link_libraries(kddockwidgets Qt5::X11Extras)
|
target_link_libraries(kddockwidgets PUBLIC Qt5::X11Extras)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
install (TARGETS kddockwidgets
|
set_target_properties(kddockwidgets PROPERTIES VERSION ${${PROJECT_NAME}_SOVERSION})
|
||||||
|
#version libraries on Windows
|
||||||
|
if(WIN32)
|
||||||
|
set(postfix ${${PROJECT_NAME}_VERSION_MAJOR})
|
||||||
|
set(CMAKE_RELEASE_POSTFIX ${postfix})
|
||||||
|
set_target_properties(kddockwidgets PROPERTIES RELEASE_POSTFIX ${CMAKE_RELEASE_POSTFIX})
|
||||||
|
#append 'd' to debug libraries
|
||||||
|
string(CONCAT postfix ${postfix} "d")
|
||||||
|
set(CMAKE_DEBUG_POSTFIX ${postfix})
|
||||||
|
set_target_properties(kddockwidgets PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
|
||||||
|
endif()
|
||||||
|
|
||||||
|
install(TARGETS kddockwidgets
|
||||||
EXPORT kddockwidgetsTargets
|
EXPORT kddockwidgetsTargets
|
||||||
RUNTIME DESTINATION bin
|
RUNTIME DESTINATION ${INSTALL_RUNTIME_DIR}
|
||||||
LIBRARY DESTINATION lib
|
LIBRARY DESTINATION ${INSTALL_LIBRARY_DIR}
|
||||||
ARCHIVE DESTINATION lib)
|
ARCHIVE DESTINATION ${INSTALL_ARCHIVE_DIR}
|
||||||
install (FILES ${DOCKS_INSTALLABLE_INCLUDES} DESTINATION include/kddockwidgets)
|
)
|
||||||
install (FILES ${DOCKS_INSTALLABLE_PRIVATE_INCLUDES} DESTINATION include/kddockwidgets/private)
|
if(MSVC AND NOT ${PROJECT_NAME}_STATIC)
|
||||||
install (FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
|
install(FILES "$<TARGET_PDB_FILE_DIR:kddockwidgets>/$<TARGET_PDB_FILE_NAME:kddockwidgets>" DESTINATION ${INSTALL_LIBRARY_DIR} CONFIGURATIONS Debug RelWithDebInfo)
|
||||||
|
endif()
|
||||||
|
install(FILES ${DOCKS_INSTALLABLE_INCLUDES} DESTINATION include/kddockwidgets)
|
||||||
|
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/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_qwidget.h DESTINATION include/kddockwidgets/private/multisplitter)
|
||||||
|
install(FILES private/multisplitter/multisplitter_export.h DESTINATION include/kddockwidgets/private/multisplitter)
|
||||||
|
install(FILES ${DOCKS_INSTALLABLE_PRIVATE_WIDGET_INCLUDES} DESTINATION include/kddockwidgets/private/widgets)
|
||||||
|
|
||||||
include(CMakePackageConfigHelpers)
|
include(CMakePackageConfigHelpers)
|
||||||
write_basic_package_version_file(
|
write_basic_package_version_file(
|
||||||
KDDockWidgetsConfigVersion.cmake
|
KDDockWidgetsConfigVersion.cmake
|
||||||
VERSION ${PACKAGE_VERSION}
|
VERSION ${${PROJECT_NAME}_VERSION}
|
||||||
COMPATIBILITY AnyNewerVersion
|
COMPATIBILITY AnyNewerVersion
|
||||||
)
|
)
|
||||||
|
|
||||||
install(EXPORT kddockwidgetsTargets
|
install(EXPORT kddockwidgetsTargets
|
||||||
FILE KDDockWidgetsTargets.cmake
|
FILE KDDockWidgetsTargets.cmake
|
||||||
NAMESPACE KDAB::
|
NAMESPACE KDAB::
|
||||||
DESTINATION lib/cmake/KDDockWidgets
|
DESTINATION ${INSTALL_LIBRARY_DIR}/cmake/KDDockWidgets
|
||||||
)
|
)
|
||||||
configure_file(KDDockWidgetsConfig.cmake.in KDDockWidgetsConfig.cmake @ONLY)
|
configure_file(KDDockWidgetsConfig.cmake.in KDDockWidgetsConfig.cmake @ONLY)
|
||||||
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgetsConfig.cmake"
|
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgetsConfig.cmake"
|
||||||
"${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgetsConfigVersion.cmake"
|
"${CMAKE_CURRENT_BINARY_DIR}/KDDockWidgetsConfigVersion.cmake"
|
||||||
DESTINATION lib/cmake/KDDockWidgets
|
DESTINATION ${INSTALL_LIBRARY_DIR}/cmake/KDDockWidgets
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if(OPTION_DEVELOPER_MODE)
|
||||||
|
# Under developer mode since kddw might be a sub-folder of a project setting a different value for QT_DISABLE_DEPRECATED_BEFORE
|
||||||
|
target_compile_definitions(kddockwidgets PRIVATE QT_DISABLE_DEPRECATED_BEFORE=0x060000)
|
||||||
|
|
||||||
|
if (NOT OPTION_QTQUICK) # TODO: We can support it
|
||||||
|
add_executable(kddockwidgets_linter layoutlinter_main.cpp)
|
||||||
|
target_link_libraries(kddockwidgets_linter kddockwidgets kddockwidgets_multisplitter Qt5::Widgets)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -26,6 +17,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "multisplitter/MultiSplitterConfig.h"
|
||||||
|
#include "multisplitter/Widget_qwidget.h"
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
|
|
||||||
@@ -33,7 +26,8 @@
|
|||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QOperatingSystemVersion>
|
#include <QOperatingSystemVersion>
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
namespace KDDockWidgets
|
||||||
|
{
|
||||||
|
|
||||||
class Config::Private
|
class Config::Private
|
||||||
{
|
{
|
||||||
@@ -52,21 +46,22 @@ public:
|
|||||||
|
|
||||||
QQmlEngine *m_qmlEngine = nullptr;
|
QQmlEngine *m_qmlEngine = nullptr;
|
||||||
DockWidgetFactoryFunc m_dockWidgetFactoryFunc = nullptr;
|
DockWidgetFactoryFunc m_dockWidgetFactoryFunc = nullptr;
|
||||||
|
MainWindowFactoryFunc m_mainWindowFactoryFunc = nullptr;
|
||||||
FrameworkWidgetFactory *m_frameworkWidgetFactory;
|
FrameworkWidgetFactory *m_frameworkWidgetFactory;
|
||||||
Flags m_flags = Flag_Default;
|
Flags m_flags = Flag_Default;
|
||||||
int m_separatorThickness = 5;
|
|
||||||
#if defined(Q_OS_WIN)
|
|
||||||
int m_staticSeparatorThickness = 1; // FIXME: Broken on Windows still.
|
|
||||||
#else
|
|
||||||
int m_staticSeparatorThickness = 0;
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
Config::Config()
|
Config::Config()
|
||||||
: d(new Private())
|
: d(new Private())
|
||||||
{
|
{
|
||||||
d->fixFlags();
|
d->fixFlags();
|
||||||
|
|
||||||
|
// stuff in multisplitter/ can't include the framework widget factory, so set it here
|
||||||
|
auto separatorCreator = [](Layouting::Widget *parent) {
|
||||||
|
return Config::self().frameworkWidgetFactory()->createSeparator(parent);
|
||||||
|
};
|
||||||
|
|
||||||
|
Layouting::Config::self().setSeparatorFactoryFunc(separatorCreator);
|
||||||
}
|
}
|
||||||
|
|
||||||
Config& Config::self()
|
Config& Config::self()
|
||||||
@@ -94,6 +89,10 @@ void Config::setFlags(Flags f)
|
|||||||
|
|
||||||
d->m_flags = f;
|
d->m_flags = f;
|
||||||
d->fixFlags();
|
d->fixFlags();
|
||||||
|
|
||||||
|
auto multisplitterFlags = Layouting::Config::self().flags();
|
||||||
|
multisplitterFlags.setFlag(Layouting::Config::Flag::LazyResize, d->m_flags & Flag_LazyResize);
|
||||||
|
Layouting::Config::self().setFlags(multisplitterFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::setDockWidgetFactoryFunc(DockWidgetFactoryFunc func)
|
void Config::setDockWidgetFactoryFunc(DockWidgetFactoryFunc func)
|
||||||
@@ -106,6 +105,16 @@ DockWidgetFactoryFunc Config::dockWidgetFactoryFunc() const
|
|||||||
return d->m_dockWidgetFactoryFunc;
|
return d->m_dockWidgetFactoryFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Config::setMainWindowFactoryFunc(MainWindowFactoryFunc func)
|
||||||
|
{
|
||||||
|
d->m_mainWindowFactoryFunc = func;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowFactoryFunc Config::mainWindowFactoryFunc() const
|
||||||
|
{
|
||||||
|
return d->m_mainWindowFactoryFunc;
|
||||||
|
}
|
||||||
|
|
||||||
void Config::setFrameworkWidgetFactory(FrameworkWidgetFactory *wf)
|
void Config::setFrameworkWidgetFactory(FrameworkWidgetFactory *wf)
|
||||||
{
|
{
|
||||||
Q_ASSERT(wf);
|
Q_ASSERT(wf);
|
||||||
@@ -118,28 +127,19 @@ FrameworkWidgetFactory *Config::frameworkWidgetFactory() const
|
|||||||
return d->m_frameworkWidgetFactory;
|
return d->m_frameworkWidgetFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Config::separatorThickness(bool staticSeparator) const
|
int Config::separatorThickness() const
|
||||||
{
|
{
|
||||||
return staticSeparator ? d->m_staticSeparatorThickness
|
return Layouting::Config::self().separatorThickness();
|
||||||
: d->m_separatorThickness;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::setSeparatorThickness(int value, bool staticSeparator)
|
void Config::setSeparatorThickness(int value)
|
||||||
{
|
{
|
||||||
if ((value <= 0 && !staticSeparator) || (value < 0 && staticSeparator) || value >= 100) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid value" << value;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!DockRegistry::self()->isEmpty()) {
|
if (!DockRegistry::self()->isEmpty()) {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (staticSeparator)
|
Layouting::Config::self().setSeparatorThickness(value);
|
||||||
d->m_staticSeparatorThickness = value;
|
|
||||||
else
|
|
||||||
d->m_separatorThickness = value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::setQmlEngine(QQmlEngine *qmlEngine)
|
void Config::setQmlEngine(QQmlEngine *qmlEngine)
|
||||||
@@ -184,3 +184,5 @@ void Config::Private::fixFlags()
|
|||||||
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
m_flags = m_flags & ~Flag_AeroSnapWithClientDecos;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|||||||
39
src/Config.h
39
src/Config.h
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,9 +29,11 @@ namespace KDDockWidgets
|
|||||||
{
|
{
|
||||||
|
|
||||||
class DockWidgetBase;
|
class DockWidgetBase;
|
||||||
|
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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Singleton to allow to choose certain behaviours of the framework.
|
* @brief Singleton to allow to choose certain behaviours of the framework.
|
||||||
@@ -66,9 +59,10 @@ public:
|
|||||||
Flag_HideTitleBarWhenTabsVisible = 8, ///> Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
|
Flag_HideTitleBarWhenTabsVisible = 8, ///> Hides the title bar if there's tabs visible. The empty space in the tab bar becomes draggable.
|
||||||
Flag_AlwaysShowTabs = 16, ///> Always show tabs, even if there's only one,
|
Flag_AlwaysShowTabs = 16, ///> Always show tabs, even if there's only one,
|
||||||
Flag_AllowReorderTabs = 32, /// Allows user to re-order tabs by dragging them
|
Flag_AllowReorderTabs = 32, /// Allows user to re-order tabs by dragging them
|
||||||
Flag_LazyResize = 32, /// The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button.
|
|
||||||
Flag_TabsHaveCloseButton = 64, /// Tabs will have a close button. Equivalent to QTabWidget::setTabsClosable(true).
|
Flag_TabsHaveCloseButton = 64, /// Tabs will have a close button. Equivalent to QTabWidget::setTabsClosable(true).
|
||||||
Flag_DoubleClickMaximizes = 128, /// Double clicking the titlebar will maximize a floating window instead of re-docking it
|
Flag_DoubleClickMaximizes = 128, /// Double clicking the titlebar will maximize a floating window instead of re-docking it
|
||||||
|
Flag_TitleBarHasMaximizeButton = 256, /// The title bar will have a maximize/restore button when floating. This is mutually-exclusive with the floating button (since many apps behave that way).
|
||||||
|
Flag_LazyResize = 1024, /// The dock widgets are resized in a lazy manner. The actual resize only happens when you release the mouse button.
|
||||||
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
|
Flag_Default = Flag_AeroSnapWithClientDecos ///> The defaults
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Flags, Flag)
|
Q_DECLARE_FLAGS(Flags, Flag)
|
||||||
@@ -101,6 +95,15 @@ public:
|
|||||||
///nullptr by default
|
///nullptr by default
|
||||||
DockWidgetFactoryFunc dockWidgetFactoryFunc() const;
|
DockWidgetFactoryFunc dockWidgetFactoryFunc() const;
|
||||||
|
|
||||||
|
///@brief counter-part of DockWidgetFactoryFunc but for the main window.
|
||||||
|
/// Should be rarely used. It's good practice to have the main window before restoring a layout.
|
||||||
|
/// It's here so we can use it in the linter executable
|
||||||
|
void setMainWindowFactoryFunc(MainWindowFactoryFunc);
|
||||||
|
|
||||||
|
///@brief Returns the MainWindowFactoryFunc.
|
||||||
|
///nullptr by default
|
||||||
|
MainWindowFactoryFunc mainWindowFactoryFunc() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the WidgetFactory.
|
* @brief Sets the WidgetFactory.
|
||||||
*
|
*
|
||||||
@@ -119,17 +122,13 @@ public:
|
|||||||
/**
|
/**
|
||||||
* @brief Returns the thickness of the separator.
|
* @brief Returns the thickness of the separator.
|
||||||
*
|
*
|
||||||
* Returns the width if the separator is vertical, otherwise the height.
|
* Default is 5px.
|
||||||
* If @p staticSeparator is true, then returns for the static separators.
|
|
||||||
* The static separators are the ones at the edges of the window (top, left, bottom, right).
|
|
||||||
*
|
|
||||||
* Default is 0px for static separators and 5px for normal separators.
|
|
||||||
*/
|
*/
|
||||||
int separatorThickness(bool staticSeparator) const;
|
int separatorThickness() const;
|
||||||
|
|
||||||
///@brief setter for @ref separatorThickness
|
///@brief setter for @ref separatorThickness
|
||||||
///Note: Only use this function at startup before creating any DockWidget or MainWindow.
|
///Note: Only use this function at startup before creating any DockWidget or MainWindow.
|
||||||
void setSeparatorThickness(int value, bool staticSeparator);
|
void setSeparatorThickness(int value);
|
||||||
|
|
||||||
///@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 *);
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -56,7 +47,7 @@ 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 = {});
|
explicit DockWidget(const QString &uniqueName, Options options = DockWidgetBase::Options());
|
||||||
|
|
||||||
///@brief destructor
|
///@brief destructor
|
||||||
~DockWidget() override;
|
~DockWidget() override;
|
||||||
|
|||||||
@@ -1,37 +1,27 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DockWidgetBase.h"
|
#include "DockWidgetBase.h"
|
||||||
#include "DragController_p.h"
|
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "FloatingWindow_p.h"
|
#include "FloatingWindow_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "TabWidget_p.h"
|
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "WidgetResizeHandler_p.h"
|
|
||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
#include "LastPosition_p.h"
|
|
||||||
#include "multisplitter/Item_p.h"
|
#include "multisplitter/Item_p.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
#include "TitleBar_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
|
#include "private/Position_p.h"
|
||||||
|
#include "WindowBeingDragged_p.h"
|
||||||
|
|
||||||
#include <QAction>
|
#include <QAction>
|
||||||
#include <QEvent>
|
#include <QEvent>
|
||||||
@@ -57,10 +47,8 @@ public:
|
|||||||
, q(qq)
|
, q(qq)
|
||||||
, options(options_)
|
, options(options_)
|
||||||
, toggleAction(new QAction(q))
|
, toggleAction(new QAction(q))
|
||||||
|
, floatAction(new QAction(q))
|
||||||
{
|
{
|
||||||
q->connect(q, &DockWidgetBase::shown, q, [this] { onDockWidgetShown(); } );
|
|
||||||
q->connect(q, &DockWidgetBase::hidden, q, [this] { onDockWidgetHidden(); } );
|
|
||||||
|
|
||||||
q->connect(toggleAction, &QAction::toggled, q, [this] (bool enabled) {
|
q->connect(toggleAction, &QAction::toggled, q, [this] (bool enabled) {
|
||||||
if (!m_updatingToggleAction) { // guard against recursiveness
|
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.
|
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.
|
||||||
@@ -69,7 +57,14 @@ public:
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
q->connect(floatAction, &QAction::toggled, q, [this] (bool enabled) {
|
||||||
|
if (!m_updatingFloatAction) { // guard against recursiveness
|
||||||
|
q->setFloating(enabled);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
toggleAction->setCheckable(true);
|
toggleAction->setCheckable(true);
|
||||||
|
floatAction->setCheckable(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
@@ -77,15 +72,20 @@ public:
|
|||||||
updateTitle();
|
updateTitle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FloatingWindow *floatingWindow() const
|
||||||
|
{
|
||||||
|
return qobject_cast<FloatingWindow*>(q->window());
|
||||||
|
}
|
||||||
|
|
||||||
QPoint defaultCenterPosForFloating();
|
QPoint defaultCenterPosForFloating();
|
||||||
|
|
||||||
void updateTitle();
|
void updateTitle();
|
||||||
void updateIcon();
|
void updateIcon();
|
||||||
void toggle(bool enabled);
|
void toggle(bool enabled);
|
||||||
void updateToggleAction();
|
void updateToggleAction();
|
||||||
|
void updateFloatAction();
|
||||||
void onDockWidgetShown();
|
void onDockWidgetShown();
|
||||||
void onDockWidgetHidden();
|
void onDockWidgetHidden();
|
||||||
TabWidget *parentTabWidget() const;
|
|
||||||
void show();
|
void show();
|
||||||
void close();
|
void close();
|
||||||
void restoreToPreviousPosition();
|
void restoreToPreviousPosition();
|
||||||
@@ -99,24 +99,25 @@ public:
|
|||||||
void saveTabIndex();
|
void saveTabIndex();
|
||||||
|
|
||||||
const QString name;
|
const QString name;
|
||||||
QString affinityName;
|
QStringList affinities;
|
||||||
QString title;
|
QString title;
|
||||||
QIcon icon;
|
QIcon icon;
|
||||||
QWidget *widget = nullptr;
|
QWidgetOrQuick *widget = nullptr;
|
||||||
DockWidgetBase *const q;
|
DockWidgetBase *const q;
|
||||||
DockWidgetBase::Options options;
|
DockWidgetBase::Options options;
|
||||||
QAction *const toggleAction;
|
QAction *const toggleAction;
|
||||||
LastPosition m_lastPosition;
|
QAction *const floatAction;
|
||||||
|
LastPositions m_lastPositions;
|
||||||
bool m_updatingToggleAction = false;
|
bool m_updatingToggleAction = false;
|
||||||
|
bool m_updatingFloatAction = false;
|
||||||
bool m_isForceClosing = false;
|
bool m_isForceClosing = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
DockWidgetBase::DockWidgetBase(const QString &name, Options options)
|
DockWidgetBase::DockWidgetBase(const QString &name, Options options)
|
||||||
: QWidgetOrQuick(nullptr, Qt::Tool)
|
: QWidgetAdapter(nullptr, Qt::Tool)
|
||||||
, d(new Private(name, options, this))
|
, d(new Private(name, options, this))
|
||||||
{
|
{
|
||||||
d->init();
|
d->init();
|
||||||
DragController::instance();
|
|
||||||
DockRegistry::self()->registerDockWidget(this);
|
DockRegistry::self()->registerDockWidget(this);
|
||||||
qCDebug(creation) << "DockWidget" << this;
|
qCDebug(creation) << "DockWidget" << this;
|
||||||
|
|
||||||
@@ -144,9 +145,15 @@ void DockWidgetBase::addDockWidgetAsTab(DockWidgetBase *other, AddingOption addi
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->affinityName() != affinityName()) {
|
if (!DockRegistry::self()->affinitiesMatch(other->affinities(), d->affinities)) {
|
||||||
qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
|
qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
|
||||||
<< other->affinityName() << affinityName();
|
<< other->affinities() << affinities();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((other->options() & DockWidgetBase::Option_NotDockable) ||
|
||||||
|
(options() & DockWidgetBase::Option_NotDockable)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -162,10 +169,13 @@ void DockWidgetBase::addDockWidgetAsTab(DockWidgetBase *other, AddingOption addi
|
|||||||
// Doesn't have a frame yet
|
// Doesn't have a frame yet
|
||||||
morphIntoFloatingWindow();
|
morphIntoFloatingWindow();
|
||||||
frame = this->frame();
|
frame = this->frame();
|
||||||
|
} else {
|
||||||
|
// Doesn't happen
|
||||||
|
qWarning() << Q_FUNC_INFO << "null frame";
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(frame);
|
|
||||||
other->setParent(nullptr);
|
other->setParent(nullptr);
|
||||||
frame->addWidget(other, addingOption);
|
frame->addWidget(other, addingOption);
|
||||||
}
|
}
|
||||||
@@ -178,33 +188,49 @@ void DockWidgetBase::addDockWidgetToContainingWindow(DockWidgetBase *other, Loca
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (other->affinityName() != affinityName()) {
|
if (!DockRegistry::self()->affinitiesMatch(other->affinities(), d->affinities)) {
|
||||||
qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
|
qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
|
||||||
<< other->affinityName() << affinityName();
|
<< other->affinities() << affinities();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((other->options() & DockWidgetBase::Option_NotDockable) ||
|
||||||
|
(options() & DockWidgetBase::Option_NotDockable)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << other;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isWindow())
|
if (isWindow())
|
||||||
morphIntoFloatingWindow();
|
morphIntoFloatingWindow();
|
||||||
|
|
||||||
if (auto fw = qobject_cast<FloatingWindow *>(window())) {
|
if (auto fw = floatingWindow()) {
|
||||||
fw->dropArea()->addDockWidget(other, location, relativeTo);
|
fw->dropArea()->addDockWidget(other, location, relativeTo);
|
||||||
} else {
|
} else {
|
||||||
qWarning() << Q_FUNC_INFO << "Couldn't find floating nested window";
|
qWarning() << Q_FUNC_INFO << "Couldn't find floating nested window";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::setWidget(QWidget *w)
|
void DockWidgetBase::setWidget(QWidgetOrQuick *w)
|
||||||
{
|
{
|
||||||
Q_ASSERT(w && !d->widget);
|
Q_ASSERT(w);
|
||||||
qCDebug(addwidget) << Q_FUNC_INFO << w;
|
qCDebug(addwidget) << Q_FUNC_INFO << w;
|
||||||
|
if (w == d->widget)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (d->widget) {
|
||||||
|
// Unparent the old widget, we're giving back ownership
|
||||||
|
d->widget->setParent(nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
d->widget = w;
|
d->widget = w;
|
||||||
|
if (w)
|
||||||
|
setSizePolicy(w->sizePolicy());
|
||||||
|
|
||||||
Q_EMIT widgetChanged(w);
|
Q_EMIT widgetChanged(w);
|
||||||
setWindowTitle(uniqueName());
|
setWindowTitle(uniqueName());
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidget *DockWidgetBase::widget() const
|
QWidgetOrQuick *DockWidgetBase::widget() const
|
||||||
{
|
{
|
||||||
return d->widget;
|
return d->widget;
|
||||||
}
|
}
|
||||||
@@ -214,7 +240,7 @@ bool DockWidgetBase::isFloating() const
|
|||||||
if (isWindow())
|
if (isWindow())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
auto fw = qobject_cast<FloatingWindow *>(window());
|
auto fw = floatingWindow();
|
||||||
return fw && fw->hasSingleDockWidget();
|
return fw && fw->hasSingleDockWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,24 +257,26 @@ void DockWidgetBase::setFloating(bool floats)
|
|||||||
if (floats) {
|
if (floats) {
|
||||||
d->saveTabIndex();
|
d->saveTabIndex();
|
||||||
if (isTabbed()) {
|
if (isTabbed()) {
|
||||||
TabWidget *tabWidget= d->parentTabWidget();
|
auto frame = this->frame();
|
||||||
if (!tabWidget) {
|
if (!frame) {
|
||||||
qWarning() << "DockWidget::setFloating: Tabbed but no tabbar exists"
|
qWarning() << "DockWidget::setFloating: Tabbed but no frame exists"
|
||||||
<< this;
|
<< this;
|
||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
tabWidget->detachTab(this);
|
frame->detachTab(this);
|
||||||
} else {
|
} else {
|
||||||
frame()->titleBar()->makeWindow();
|
frame()->titleBar()->makeWindow();
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
if (d->m_lastPosition.isValid()) {
|
auto lastGeo = lastPositions().lastFloatingGeometry();
|
||||||
d->restoreToPreviousPosition();
|
if (lastGeo.isValid()) {
|
||||||
} else {
|
if (auto fw = floatingWindow())
|
||||||
qCDebug(placeholder) << Q_FUNC_INFO << "Don't have a place to restore";
|
fw->setSuggestedGeometry(lastGeo, /*preserveCenter=*/true);
|
||||||
// TODO: Restore to preferred place ?
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
saveLastFloatingGeometry();
|
||||||
|
d->restoreToPreviousPosition();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -257,6 +285,11 @@ QAction *DockWidgetBase::toggleAction() const
|
|||||||
return d->toggleAction;
|
return d->toggleAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QAction *DockWidgetBase::floatAction() const
|
||||||
|
{
|
||||||
|
return d->floatAction;
|
||||||
|
}
|
||||||
|
|
||||||
QString DockWidgetBase::uniqueName() const
|
QString DockWidgetBase::uniqueName() const
|
||||||
{
|
{
|
||||||
return d->name;
|
return d->name;
|
||||||
@@ -283,6 +316,11 @@ DockWidgetBase::Options DockWidgetBase::options() const
|
|||||||
|
|
||||||
void DockWidgetBase::setOptions(Options options)
|
void DockWidgetBase::setOptions(Options options)
|
||||||
{
|
{
|
||||||
|
if ((d->options & Option_NotDockable) != (options & Option_NotDockable)) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Option_NotDockable not allowed to change. Pass via ctor only.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (options != d->options) {
|
if (options != d->options) {
|
||||||
d->options = options;
|
d->options = options;
|
||||||
Q_EMIT optionsChanged(options);
|
Q_EMIT optionsChanged(options);
|
||||||
@@ -293,8 +331,8 @@ void DockWidgetBase::setOptions(Options options)
|
|||||||
|
|
||||||
bool DockWidgetBase::isTabbed() const
|
bool DockWidgetBase::isTabbed() const
|
||||||
{
|
{
|
||||||
if (TabWidget* tabWidget = d->parentTabWidget()) {
|
if (Frame *frame = this->frame()) {
|
||||||
return frame()->alwaysShowsTabs() || tabWidget->numDockWidgets() > 1;
|
return frame->alwaysShowsTabs() || frame->dockWidgetCount() > 1;
|
||||||
} else {
|
} else {
|
||||||
if (!isFloating())
|
if (!isFloating())
|
||||||
qWarning() << "DockWidget::isTabbed() Couldn't find any tab widget.";
|
qWarning() << "DockWidget::isTabbed() Couldn't find any tab widget.";
|
||||||
@@ -304,8 +342,8 @@ bool DockWidgetBase::isTabbed() const
|
|||||||
|
|
||||||
bool DockWidgetBase::isCurrentTab() const
|
bool DockWidgetBase::isCurrentTab() const
|
||||||
{
|
{
|
||||||
if (TabWidget* tabWidget = d->parentTabWidget()) {
|
if (Frame *frame = this->frame()) {
|
||||||
return tabWidget->currentIndex() == tabWidget->indexOfDockWidget(const_cast<DockWidgetBase*>(this));
|
return frame->currentIndex() == frame->indexOfDockWidget(const_cast<DockWidgetBase*>(this));
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -313,8 +351,8 @@ bool DockWidgetBase::isCurrentTab() const
|
|||||||
|
|
||||||
void DockWidgetBase::setAsCurrentTab()
|
void DockWidgetBase::setAsCurrentTab()
|
||||||
{
|
{
|
||||||
if (TabWidget* tabWidget = d->parentTabWidget())
|
if (Frame *frame = this->frame())
|
||||||
tabWidget->setCurrentDockWidget(this);
|
frame->setCurrentDockWidget(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::setIcon(const QIcon &icon)
|
void DockWidgetBase::setIcon(const QIcon &icon)
|
||||||
@@ -348,19 +386,19 @@ bool DockWidgetBase::isOpen() const
|
|||||||
return d->toggleAction->isChecked();
|
return d->toggleAction->isChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString DockWidgetBase::affinityName() const
|
QStringList DockWidgetBase::affinities() const
|
||||||
{
|
{
|
||||||
return d->affinityName;
|
return d->affinities;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::show()
|
void DockWidgetBase::show()
|
||||||
{
|
{
|
||||||
if (isWindow() && (lastPosition()->m_wasFloating || !lastPosition()->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();
|
morphIntoFloatingWindow();
|
||||||
} else {
|
} else {
|
||||||
QWidget::show();
|
QWidgetOrQuick::show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -371,25 +409,38 @@ void DockWidgetBase::raise()
|
|||||||
|
|
||||||
setAsCurrentTab();
|
setAsCurrentTab();
|
||||||
|
|
||||||
if (auto fw = qobject_cast<FloatingWindow*>(window())) {
|
if (auto fw = floatingWindow()) {
|
||||||
fw->raise();
|
fw->raise();
|
||||||
fw->activateWindow();
|
fw->activateWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::setAffinityName(const QString &name)
|
bool DockWidgetBase::isMainWindow() const
|
||||||
{
|
{
|
||||||
if (d->affinityName == name)
|
return qobject_cast<MainWindowBase*>(widget());
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::setAffinityName(const QString &affinity)
|
||||||
|
{
|
||||||
|
setAffinities({ affinity });
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::setAffinities(const QStringList &affinityNames)
|
||||||
|
{
|
||||||
|
QStringList affinities = affinityNames;
|
||||||
|
affinities.removeAll(QString());
|
||||||
|
|
||||||
|
if (d->affinities == affinities)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!d->affinityName.isEmpty()) {
|
if (!d->affinities.isEmpty()) {
|
||||||
qWarning() << Q_FUNC_INFO
|
qWarning() << Q_FUNC_INFO
|
||||||
<< "Affinity is already set, refusing to change."
|
<< "Affinity is already set, refusing to change."
|
||||||
<< "Submit a feature request with a good justification.";
|
<< "Submit a feature request with a good justification.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->affinityName = name;
|
d->affinities = affinities;
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
|
FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
|
||||||
@@ -397,11 +448,11 @@ FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
|
|||||||
qCDebug(creation) << "DockWidget::morphIntoFloatingWindow() this=" << this
|
qCDebug(creation) << "DockWidget::morphIntoFloatingWindow() this=" << this
|
||||||
<< "; visible=" << isVisible();
|
<< "; visible=" << isVisible();
|
||||||
|
|
||||||
if (auto fw = qobject_cast<FloatingWindow*>(window()))
|
if (auto fw = floatingWindow())
|
||||||
return fw; // Nothing to do
|
return fw; // Nothing to do
|
||||||
|
|
||||||
if (isWindow()) {
|
if (isWindow()) {
|
||||||
QRect geo = lastPosition()->lastFloatingGeometry();
|
QRect geo = d->m_lastPositions.lastFloatingGeometry();
|
||||||
if (geo.isNull()) {
|
if (geo.isNull()) {
|
||||||
geo = geometry();
|
geo = geometry();
|
||||||
const QPoint center = d->defaultCenterPosForFloating();
|
const QPoint center = d->defaultCenterPosForFloating();
|
||||||
@@ -412,7 +463,7 @@ FloatingWindow *DockWidgetBase::morphIntoFloatingWindow()
|
|||||||
auto frame = Config::self().frameworkWidgetFactory()->createFrame();
|
auto frame = Config::self().frameworkWidgetFactory()->createFrame();
|
||||||
frame->addWidget(this);
|
frame->addWidget(this);
|
||||||
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(frame);
|
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(frame);
|
||||||
floatingWindow->setGeometry(geo);
|
floatingWindow->setSuggestedGeometry(geo);
|
||||||
floatingWindow->show();
|
floatingWindow->show();
|
||||||
|
|
||||||
return floatingWindow;
|
return floatingWindow;
|
||||||
@@ -440,19 +491,27 @@ Frame *DockWidgetBase::frame() const
|
|||||||
|
|
||||||
FloatingWindow *DockWidgetBase::floatingWindow() const
|
FloatingWindow *DockWidgetBase::floatingWindow() const
|
||||||
{
|
{
|
||||||
return qobject_cast<FloatingWindow*>(window());
|
return d->floatingWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::addPlaceholderItem(Item *item)
|
void DockWidgetBase::addPlaceholderItem(Layouting::Item *item)
|
||||||
{
|
{
|
||||||
qCDebug(placeholder) << Q_FUNC_INFO << this << item;
|
qCDebug(placeholder) << Q_FUNC_INFO << this << item;
|
||||||
Q_ASSERT(item);
|
Q_ASSERT(item);
|
||||||
d->m_lastPosition.addPlaceholderItem(item);
|
d->m_lastPositions.addPosition(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
LastPosition *DockWidgetBase::lastPosition() const
|
LastPositions& DockWidgetBase::lastPositions() const
|
||||||
{
|
{
|
||||||
return &d->m_lastPosition;
|
return d->m_lastPositions;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::saveLastFloatingGeometry()
|
||||||
|
{
|
||||||
|
if (isFloating() && isVisible()) {
|
||||||
|
// It's getting docked, save last floating position
|
||||||
|
lastPositions().setLastFloatingGeometry(window()->geometry());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
|
QPoint DockWidgetBase::Private::defaultCenterPosForFloating()
|
||||||
@@ -477,7 +536,6 @@ void DockWidgetBase::Private::updateTitle()
|
|||||||
|
|
||||||
void DockWidgetBase::Private::updateIcon()
|
void DockWidgetBase::Private::updateIcon()
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::toggle(bool enabled)
|
void DockWidgetBase::Private::toggle(bool enabled)
|
||||||
@@ -493,74 +551,89 @@ 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() || parentTabWidget()) && !toggleAction->isChecked()) {
|
if ((q->isVisible() || q->frame()) && !toggleAction->isChecked()) {
|
||||||
toggleAction->setChecked(true);
|
toggleAction->setChecked(true);
|
||||||
} else if ((!q->isVisible() && !parentTabWidget()) && toggleAction->isChecked()) {
|
} else if ((!q->isVisible() && !q->frame()) && toggleAction->isChecked()) {
|
||||||
toggleAction->setChecked(false);
|
toggleAction->setChecked(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DockWidgetBase::Private::updateFloatAction()
|
||||||
|
{
|
||||||
|
QScopedValueRollback<bool> recursionGuard(m_updatingFloatAction, true); // Guard against recursiveness
|
||||||
|
|
||||||
|
if (q->isFloating()) {
|
||||||
|
floatAction->setEnabled(m_lastPositions.isValid());
|
||||||
|
floatAction->setChecked(true);
|
||||||
|
floatAction->setToolTip(tr("Dock"));
|
||||||
|
} else {
|
||||||
|
floatAction->setEnabled(true);
|
||||||
|
floatAction->setChecked(false);
|
||||||
|
floatAction->setToolTip(tr("Detach"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::onDockWidgetShown()
|
void DockWidgetBase::Private::onDockWidgetShown()
|
||||||
{
|
{
|
||||||
updateToggleAction();
|
updateToggleAction();
|
||||||
|
updateFloatAction();
|
||||||
qCDebug(hiding) << Q_FUNC_INFO << "parent=" << q->parentWidget();
|
qCDebug(hiding) << Q_FUNC_INFO << "parent=" << q->parentWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::onDockWidgetHidden()
|
void DockWidgetBase::Private::onDockWidgetHidden()
|
||||||
{
|
{
|
||||||
updateToggleAction();
|
updateToggleAction();
|
||||||
|
updateFloatAction();
|
||||||
qCDebug(hiding) << Q_FUNC_INFO << "parent=" << q->parentWidget();
|
qCDebug(hiding) << Q_FUNC_INFO << "parent=" << q->parentWidget();
|
||||||
}
|
}
|
||||||
|
|
||||||
TabWidget *DockWidgetBase::Private::parentTabWidget() const
|
|
||||||
{
|
|
||||||
if (auto f = q->frame())
|
|
||||||
return f->tabWidget();
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
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_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
|
// We check for isVisible so we don't save geometry if you call close() on an already closed dock widget
|
||||||
m_lastPosition.setLastFloatingGeometry(q->window()->geometry());
|
m_lastPositions.setLastFloatingGeometry(q->window()->geometry());
|
||||||
}
|
}
|
||||||
|
|
||||||
qCDebug(hiding) << "DockWidget::close" << this;
|
qCDebug(hiding) << "DockWidget::close" << this;
|
||||||
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 (auto tabWidget = parentTabWidget()) {
|
if (Frame *frame = q->frame()) {
|
||||||
tabWidget->removeDockWidget(q);
|
frame->removeWidget(q);
|
||||||
q->setParent(nullptr);
|
q->setParent(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::restoreToPreviousPosition()
|
void DockWidgetBase::Private::restoreToPreviousPosition()
|
||||||
{
|
{
|
||||||
if (!m_lastPosition.isValid()) {
|
if (!m_lastPositions.isValid())
|
||||||
qWarning() << Q_FUNC_INFO << "Only restoring to MainWindow supported for now";
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
m_lastPosition.layoutItem()->restorePlaceholder(q, m_lastPosition.m_tabIndex);
|
Layouting::Item *item = m_lastPositions.lastItem();
|
||||||
|
|
||||||
|
MultiSplitter *layout = DockRegistry::self()->layoutForItem(item);
|
||||||
|
Q_ASSERT(layout);
|
||||||
|
layout->restorePlaceholder(q, item, m_lastPositions.lastTabIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
|
void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
|
||||||
{
|
{
|
||||||
// This is called when we get a QEvent::Show. Let's see if we have to restore it to a previous position.
|
// This is called when we get a QEvent::Show. Let's see if we have to restore it to a previous position.
|
||||||
Item *layoutItem = m_lastPosition.layoutItem();
|
|
||||||
qCDebug(placeholder) << Q_FUNC_INFO << layoutItem << m_lastPosition.m_wasFloating;
|
if (!m_lastPositions.isValid())
|
||||||
|
return;
|
||||||
|
|
||||||
|
Layouting::Item *layoutItem = m_lastPositions.lastItem();
|
||||||
|
qCDebug(placeholder) << Q_FUNC_INFO << layoutItem << m_lastPositions;
|
||||||
if (!layoutItem)
|
if (!layoutItem)
|
||||||
return; // nothing to do, no last position
|
return; // nothing to do, no last position
|
||||||
|
|
||||||
if (m_lastPosition.m_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 = q->frame();
|
||||||
|
|
||||||
if (frame && frame->parentWidget() == layoutItem->parentWidget()) {
|
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.
|
||||||
// Nothing to do, the dock widget will simply be shown
|
// Nothing to do, the dock widget will simply be shown
|
||||||
qCDebug(placeholder) << Q_FUNC_INFO << "Already had frame.";
|
qCDebug(placeholder) << Q_FUNC_INFO << "Already had frame.";
|
||||||
@@ -581,14 +654,13 @@ void DockWidgetBase::Private::maybeRestoreToPreviousPosition()
|
|||||||
|
|
||||||
int DockWidgetBase::Private::currentTabIndex() const
|
int DockWidgetBase::Private::currentTabIndex() const
|
||||||
{
|
{
|
||||||
TabWidget *tabWidget = parentTabWidget();
|
Frame *frame = q->frame();
|
||||||
return tabWidget ? tabWidget->indexOfDockWidget(q) : 0;
|
return frame ? frame->indexOfDockWidget(q) : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::saveTabIndex()
|
void DockWidgetBase::Private::saveTabIndex()
|
||||||
{
|
{
|
||||||
m_lastPosition.m_tabIndex = currentTabIndex();
|
m_lastPositions.saveTabIndex(currentTabIndex(), q->isFloating());
|
||||||
m_lastPosition.m_wasFloating = q->isFloating();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::Private::show()
|
void DockWidgetBase::Private::show()
|
||||||
@@ -601,10 +673,12 @@ void DockWidgetBase::onParentChanged()
|
|||||||
{
|
{
|
||||||
Q_EMIT parentChanged();
|
Q_EMIT parentChanged();
|
||||||
d->updateToggleAction();
|
d->updateToggleAction();
|
||||||
|
d->updateFloatAction();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockWidgetBase::onShown(bool spontaneous)
|
void DockWidgetBase::onShown(bool spontaneous)
|
||||||
{
|
{
|
||||||
|
d->onDockWidgetShown();
|
||||||
Q_EMIT shown();
|
Q_EMIT shown();
|
||||||
|
|
||||||
if (Frame *f = frame()) {
|
if (Frame *f = frame()) {
|
||||||
@@ -621,6 +695,7 @@ void DockWidgetBase::onShown(bool spontaneous)
|
|||||||
|
|
||||||
void DockWidgetBase::onHidden(bool spontaneous)
|
void DockWidgetBase::onHidden(bool spontaneous)
|
||||||
{
|
{
|
||||||
|
d->onDockWidgetHidden();
|
||||||
Q_EMIT hidden();
|
Q_EMIT hidden();
|
||||||
|
|
||||||
if (Frame *f = frame()) {
|
if (Frame *f = frame()) {
|
||||||
@@ -634,7 +709,7 @@ void DockWidgetBase::onClosed(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 change for the widget to ignore
|
qApp->sendEvent(d->widget, e); // Give a chancefor the widget to ignore
|
||||||
|
|
||||||
if (e->isAccepted())
|
if (e->isAccepted())
|
||||||
d->close();
|
d->close();
|
||||||
@@ -651,14 +726,14 @@ DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (dw) {
|
if (dw) {
|
||||||
if (QWidget *w = dw->widget())
|
if (QWidgetOrQuick *w = dw->widget())
|
||||||
w->setVisible(true);
|
w->setVisible(true);
|
||||||
dw->setProperty("kddockwidget_was_restored", true);
|
dw->setProperty("kddockwidget_was_restored", true);
|
||||||
|
|
||||||
if (dw->affinityName() != saved->affinityName) {
|
if (dw->affinities() != saved->affinities) {
|
||||||
qWarning() << Q_FUNC_INFO << "Affinity name changed from" << dw->affinityName()
|
qWarning() << Q_FUNC_INFO << "Affinity name changed from" << dw->affinities()
|
||||||
<< "; to" << saved->affinityName;
|
<< "; to" << saved->affinities;
|
||||||
dw->d->affinityName = saved->affinityName;
|
dw->d->affinities = saved->affinities;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -671,7 +746,7 @@ DockWidgetBase *DockWidgetBase::deserialize(const LayoutSaver::DockWidget::Ptr &
|
|||||||
LayoutSaver::DockWidget::Ptr DockWidgetBase::serialize() const
|
LayoutSaver::DockWidget::Ptr DockWidgetBase::serialize() const
|
||||||
{
|
{
|
||||||
auto ptr = LayoutSaver::DockWidget::dockWidgetForName(uniqueName());
|
auto ptr = LayoutSaver::DockWidget::dockWidgetForName(uniqueName());
|
||||||
ptr->affinityName = affinityName();
|
ptr->affinities = affinities();
|
||||||
|
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -34,24 +25,27 @@
|
|||||||
#include "LayoutSaver_p.h"
|
#include "LayoutSaver_p.h"
|
||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QWidget>
|
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
class QAction;
|
class QAction;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
|
namespace Layouting {
|
||||||
|
class Item;
|
||||||
|
}
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
|
struct LastPositions;
|
||||||
class Frame;
|
class Frame;
|
||||||
class FloatingWindow;
|
class FloatingWindow;
|
||||||
class DragController;
|
class DragController;
|
||||||
class Item;
|
|
||||||
class LastPosition;
|
|
||||||
class DockRegistry;
|
class DockRegistry;
|
||||||
class LayoutSaver;
|
class LayoutSaver;
|
||||||
class TabWidget;
|
class TabWidget;
|
||||||
class TitleBar;
|
class TitleBar;
|
||||||
class MainWindowBase;
|
class MainWindowBase;
|
||||||
|
class StateDragging;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The DockWidget base-class. DockWidget and DockWidgetBase are only
|
* @brief The DockWidget base-class. DockWidget and DockWidgetBase are only
|
||||||
@@ -60,7 +54,11 @@ class MainWindowBase;
|
|||||||
*
|
*
|
||||||
* Do not use instantiate directly in user code. Use DockWidget instead.
|
* Do not use instantiate directly in user code. Use DockWidget instead.
|
||||||
*/
|
*/
|
||||||
class DOCKS_EXPORT DockWidgetBase : public QWidgetOrQuick
|
#ifndef PYTHON_BINDINGS //Pyside bug: https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1327
|
||||||
|
class DOCKS_EXPORT DockWidgetBase : public QWidgetAdapter
|
||||||
|
#else
|
||||||
|
class DOCKS_EXPORT DockWidgetBase : public QWidget
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
@@ -69,31 +67,32 @@ public:
|
|||||||
///@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 programatically
|
||||||
|
Option_NotDockable = 2 ///< The DockWidget can't be docked, it's always floating
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Options, Option)
|
Q_DECLARE_FLAGS(Options, Option)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @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
|
||||||
*
|
*
|
||||||
* 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 = {});
|
explicit DockWidgetBase(const QString &uniqueName, Options options = DockWidgetBase::Options());
|
||||||
|
|
||||||
///@brief destructor
|
///@brief destructor
|
||||||
~DockWidgetBase() override;
|
~DockWidgetBase() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param 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 LayoutSaver::DockWidget::Ptr &);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param Serializes this dock widget into an intermediate form
|
* @brief Serializes this dock widget into an intermediate form
|
||||||
*/
|
*/
|
||||||
LayoutSaver::DockWidget::Ptr serialize() const;
|
LayoutSaver::DockWidget::Ptr serialize() const;
|
||||||
|
|
||||||
@@ -109,9 +108,9 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief docks @p other widget into the window that contains this one.
|
* @brief docks @p other widget into the window that contains this one.
|
||||||
* Equivalent to @ref MainWindow::addDockWidge() with the difference
|
* Equivalent to MainWindow::addDockWidget() with the difference
|
||||||
* that it also supports the case where the top-level window is a
|
* that it also supports the case where the top-level window is a
|
||||||
* @ref FloatingWindow instead of @ref MainWindow.
|
* FloatingWindow instead of MainWindow.
|
||||||
*
|
*
|
||||||
* @param other The other dock widget to dock into the window.
|
* @param other The other dock widget to dock into the window.
|
||||||
* @param location The location to dock.
|
* @param location The location to dock.
|
||||||
@@ -123,14 +122,19 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief sets the widget which this dock widget hosts.
|
* @brief sets the widget which this dock widget hosts.
|
||||||
* @param widget to show inside this dock widget
|
* @param widget widget to show inside this dock widget. Must not be null.
|
||||||
|
*
|
||||||
|
* Ownership for @p widget is transfered to DockWidgetBase.
|
||||||
|
* Ownsership for any previously existing widget is transfered back to the user. Meaning if you
|
||||||
|
* call setWidget(A) followed by setWidget(B) then A will have to be deleted by you, while B is
|
||||||
|
* owned by the dock widget.
|
||||||
*/
|
*/
|
||||||
void setWidget(QWidget *widget);
|
void setWidget(QWidgetOrQuick *widget);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns the widget which this dock widget hosts
|
* @brief returns the widget which this dock widget hosts
|
||||||
*/
|
*/
|
||||||
QWidget *widget() const;
|
QWidgetOrQuick *widget() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns whether the dock widget is floating.
|
* @brief Returns whether the dock widget is floating.
|
||||||
@@ -153,6 +157,12 @@ public:
|
|||||||
*/
|
*/
|
||||||
QAction *toggleAction() const;
|
QAction *toggleAction() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the QAction that allows to dock/undock the dock widget
|
||||||
|
* Useful to put in menus.
|
||||||
|
*/
|
||||||
|
QAction *floatAction() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief the dock widget's unique name.
|
* @brief the dock widget's unique name.
|
||||||
* @internal
|
* @internal
|
||||||
@@ -180,7 +190,10 @@ public:
|
|||||||
Options options() const;
|
Options options() 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
|
||||||
|
* the constructor only.
|
||||||
|
*
|
||||||
* @sa options(), optionsChanged()
|
* @sa options(), optionsChanged()
|
||||||
*/
|
*/
|
||||||
void setOptions(Options);
|
void setOptions(Options);
|
||||||
@@ -240,12 +253,12 @@ public:
|
|||||||
bool isOpen() const;
|
bool isOpen() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the affinity name. 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.
|
||||||
*
|
*
|
||||||
* By default the affinity is empty and a dock widget can dock into any main window and into any
|
* By default the affinity is empty and a dock widget can dock into any main window and into any
|
||||||
* floating window. Usually you won't ever need to call
|
* floating window. Usually you won't ever need to call
|
||||||
* this function, unless you have requirements where certain dock widgets can only dock into
|
* this function, unless you have requirements where certain dock widgets can only dock into
|
||||||
* certain other dock widgets and main windows. @sa MainWindowBase::setAffinityName().
|
* certain other dock widgets and main windows. @sa MainWindowBase::setAffinities().
|
||||||
*
|
*
|
||||||
* Note: Call this function right after creating your dock widget, before adding to a main window and
|
* Note: Call this function right after creating your dock widget, before adding to a main window and
|
||||||
* before restoring any layout.
|
* before restoring any layout.
|
||||||
@@ -254,14 +267,18 @@ public:
|
|||||||
* edge cases. This will only be changed if a good use case comes up that requires changing
|
* edge cases. This will only be changed if a good use case comes up that requires changing
|
||||||
* affinities multiple times.
|
* affinities multiple times.
|
||||||
*
|
*
|
||||||
* @p name The affinity name.
|
* @p names the affinity names
|
||||||
*/
|
*/
|
||||||
|
void setAffinities(const QStringList &);
|
||||||
|
|
||||||
|
/// @deprecated @overload
|
||||||
|
/// @param name the affinity name
|
||||||
void setAffinityName(const QString &name);
|
void setAffinityName(const QString &name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the affinity name. Empty by default.
|
* @brief Returns the affinity name. Empty by default.
|
||||||
*/
|
*/
|
||||||
QString affinityName() const;
|
QStringList affinities() const;
|
||||||
|
|
||||||
/// @brief Equivalent to QWidget::show(), but it's optimized to reduce flickering on some platforms
|
/// @brief Equivalent to QWidget::show(), but it's optimized to reduce flickering on some platforms
|
||||||
void show();
|
void show();
|
||||||
@@ -275,6 +292,18 @@ public:
|
|||||||
/// This only applies if the dock widget is already open. If closed, does nothing.
|
/// This only applies if the dock widget is already open. If closed, does nothing.
|
||||||
void raise();
|
void raise();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns whether widget() is a KDDockWidget::MainWindow
|
||||||
|
*
|
||||||
|
* This function doesn't have anything to do with this dock widget being inside a main window or
|
||||||
|
* not, but rather the inverse concept. It's not a very popular usage, but some applications
|
||||||
|
* want to dock a main window into another main window. This is done by putting it into a
|
||||||
|
* dock widget first.
|
||||||
|
*
|
||||||
|
* See also kddockwidgets_example -j
|
||||||
|
*/
|
||||||
|
bool isMainWindow() const;
|
||||||
|
|
||||||
Q_SIGNALS:
|
Q_SIGNALS:
|
||||||
///@brief signal emitted when the parent changed
|
///@brief signal emitted when the parent changed
|
||||||
void parentChanged();
|
void parentChanged();
|
||||||
@@ -292,11 +321,11 @@ Q_SIGNALS:
|
|||||||
void titleChanged();
|
void titleChanged();
|
||||||
|
|
||||||
///@brief emitted when the hosted widget changed
|
///@brief emitted when the hosted widget changed
|
||||||
void widgetChanged(QWidget*);
|
void widgetChanged(KDDockWidgets::QWidgetOrQuick *);
|
||||||
|
|
||||||
///@brief emitted when the options change
|
///@brief emitted when the options change
|
||||||
///@sa setOptions(), options()
|
///@sa setOptions(), options()
|
||||||
void optionsChanged(Options);
|
void optionsChanged(KDDockWidgets::DockWidgetBase::Options);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void onParentChanged();
|
void onParentChanged();
|
||||||
@@ -325,15 +354,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
#endif
|
#endif
|
||||||
Q_DISABLE_COPY(DockWidgetBase)
|
Q_DISABLE_COPY(DockWidgetBase)
|
||||||
friend class MultiSplitterLayout;
|
friend class MultiSplitter;
|
||||||
friend class Frame;
|
friend class Frame;
|
||||||
friend class DropArea;
|
friend class DropArea;
|
||||||
friend class TestDocks;
|
friend class TestDocks;
|
||||||
friend class Item;
|
friend class StateDragging;
|
||||||
friend class KDDockWidgets::TabWidget;
|
friend class KDDockWidgets::TabWidget;
|
||||||
friend class KDDockWidgets::TitleBar;
|
friend class KDDockWidgets::TitleBar;
|
||||||
friend class KDDockWidgets::DragController;
|
friend class KDDockWidgets::DragController;
|
||||||
friend class KDDockWidgets::Item;
|
|
||||||
friend class KDDockWidgets::DockRegistry;
|
friend class KDDockWidgets::DockRegistry;
|
||||||
friend class KDDockWidgets::LayoutSaver;
|
friend class KDDockWidgets::LayoutSaver;
|
||||||
|
|
||||||
@@ -356,15 +384,19 @@ private:
|
|||||||
FloatingWindow *floatingWindow() const;
|
FloatingWindow *floatingWindow() const;
|
||||||
|
|
||||||
///@brief adds the current layout item containing this dock widget
|
///@brief adds the current layout item containing this dock widget
|
||||||
void addPlaceholderItem(Item*);
|
void addPlaceholderItem(Layouting::Item*);
|
||||||
|
|
||||||
///@brief returns the last position, just for tests. TODO Make tests just use the d-pointer.
|
///@brief returns the last position, just for tests. TODO Make tests just use the d-pointer.
|
||||||
LastPosition *lastPosition() const;
|
LastPositions &lastPositions() const;
|
||||||
|
|
||||||
|
///@brief If this dock widget is floating, then it saves its geometry
|
||||||
|
void saveLastFloatingGeometry();
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
Private *const d;
|
Private *const d;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Q_DECLARE_METATYPE(KDDockWidgets::Location)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,47 +1,36 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "TitleBar_p.h"
|
#include "TitleBar_p.h"
|
||||||
#include "TabWidget_p.h"
|
|
||||||
#include "multisplitter/Separator_p.h"
|
#include "multisplitter/Separator_p.h"
|
||||||
#include "FloatingWindow_p.h"
|
#include "FloatingWindow_p.h"
|
||||||
#include "Config.h"
|
#include "Config.h"
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
# include "indicators/ClassicIndicators_p.h"
|
# include "indicators/ClassicIndicators_p.h"
|
||||||
|
# include "widgets/TabWidget_p.h"
|
||||||
# include "widgets/FrameWidget_p.h"
|
# include "widgets/FrameWidget_p.h"
|
||||||
# include "widgets/TitleBarWidget_p.h"
|
# include "widgets/TitleBarWidget_p.h"
|
||||||
# include "widgets/TabBarWidget_p.h"
|
# include "widgets/TabBarWidget_p.h"
|
||||||
# include "widgets/TabWidgetWidget_p.h"
|
# include "widgets/TabWidgetWidget_p.h"
|
||||||
# include "widgets/SeparatorWidget_p.h"
|
# include "multisplitter/Separator_qwidget.h"
|
||||||
# include "widgets/FloatingWindowWidget_p.h"
|
# include "widgets/FloatingWindowWidget_p.h"
|
||||||
#else
|
#else
|
||||||
# include "quick/FrameQuick_p.h"
|
# include "quick/FrameQuick_p.h"
|
||||||
# include "quick/DockWidgetQuick.h"
|
# include "quick/DockWidgetQuick.h"
|
||||||
# include "quick/TitleBarQuick_p.h"
|
# include "quick/TitleBarQuick_p.h"
|
||||||
# include "quick/TabBarQuick_p.h"
|
|
||||||
# include "quick/TabWidgetQuick_p.h"
|
|
||||||
# include "quick/FloatingWindowQuick_p.h"
|
# include "quick/FloatingWindowQuick_p.h"
|
||||||
# include "quick/SeparatorQuick_p.h"
|
# include "multisplitter/Separator_quick.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
@@ -76,9 +65,9 @@ TabWidget *DefaultWidgetFactory::createTabWidget(Frame *parent) const
|
|||||||
return new TabWidgetWidget(parent);
|
return new TabWidgetWidget(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
Separator *DefaultWidgetFactory::createSeparator(Anchor *anchor, QWidgetAdapter *parent) const
|
Layouting::Separator *DefaultWidgetFactory::createSeparator(Layouting::Widget *parent) const
|
||||||
{
|
{
|
||||||
return new SeparatorWidget(anchor, parent);
|
return new Layouting::SeparatorWidget(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(MainWindowBase *parent) const
|
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(MainWindowBase *parent) const
|
||||||
@@ -97,7 +86,7 @@ DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(
|
|||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
|
|
||||||
Frame *DefaultWidgetFactory::createFrame(QWidgetOrQuick *parent, Frame::Options options) const
|
Frame *DefaultWidgetFactory::createFrame(QWidgetOrQuick *parent, FrameOptions options) const
|
||||||
{
|
{
|
||||||
return new FrameQuick(parent, options);
|
return new FrameQuick(parent, options);
|
||||||
}
|
}
|
||||||
@@ -112,27 +101,17 @@ TitleBar *DefaultWidgetFactory::createTitleBar(FloatingWindow *fw) const
|
|||||||
return new TitleBarQuick(fw);
|
return new TitleBarQuick(fw);
|
||||||
}
|
}
|
||||||
|
|
||||||
TabBar *DefaultWidgetFactory::createTabBar(TabWidget *tb) const
|
/*Separator *DefaultWidgetFactory::createSeparator(QWidgetAdapter *parent) const
|
||||||
{
|
{
|
||||||
return new TabBarQuick(tb);
|
return new SeparatorQuick(parent);
|
||||||
}
|
}*/
|
||||||
|
|
||||||
TabWidget *DefaultWidgetFactory::createTabWidget(Frame *frame) const
|
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(MainWindowBase *parent) const
|
||||||
{
|
|
||||||
return new TabWidgetQuick(frame);
|
|
||||||
}
|
|
||||||
|
|
||||||
Separator *DefaultWidgetFactory::createSeparator(Anchor *anchor, QWidgetAdapter *parent) const
|
|
||||||
{
|
|
||||||
return new SeparatorQuick(anchor, parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(QWidgetOrQuick *parent) const
|
|
||||||
{
|
{
|
||||||
return new FloatingWindowQuick(parent);
|
return new FloatingWindowQuick(parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, QWidgetOrQuick *parent) const
|
FloatingWindow *DefaultWidgetFactory::createFloatingWindow(Frame *frame, MainWindowBase *parent) const
|
||||||
{
|
{
|
||||||
return new FloatingWindowQuick(frame, parent);
|
return new FloatingWindowQuick(frame, parent);
|
||||||
}
|
}
|
||||||
@@ -141,4 +120,24 @@ DropIndicatorOverlayInterface *DefaultWidgetFactory::createDropIndicatorOverlay(
|
|||||||
{
|
{
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabBar *DefaultWidgetFactory::createTabBar(TabWidget *parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
TabWidget *DefaultWidgetFactory::createTabWidget(Frame *parent) const
|
||||||
|
{
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
Q_ASSERT(false);
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Layouting::Separator *DefaultWidgetFactory::createSeparator(Layouting::Widget *parent) const
|
||||||
|
{
|
||||||
|
return new Layouting::SeparatorQuick(parent);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KDDOCKWIDGETS_FRAMEWORKWIDGETFACTORY_H
|
#ifndef KDDOCKWIDGETS_FRAMEWORKWIDGETFACTORY_H
|
||||||
@@ -32,17 +23,20 @@
|
|||||||
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
namespace Layouting {
|
||||||
|
class Separator;
|
||||||
|
class Widget;
|
||||||
|
}
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
|
|
||||||
class MainWindowBase;
|
class MainWindowBase;
|
||||||
class DropIndicatorOverlayInterface;
|
class DropIndicatorOverlayInterface;
|
||||||
class Separator;
|
|
||||||
class FloatingWindow;
|
class FloatingWindow;
|
||||||
class TabWidget;
|
class TabWidget;
|
||||||
class TitleBar;
|
class TitleBar;
|
||||||
class Frame;
|
class Frame;
|
||||||
class DropArea;
|
class DropArea;
|
||||||
class Anchor;
|
|
||||||
class TabBar;
|
class TabBar;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -64,17 +58,19 @@ class TabBar;
|
|||||||
*/
|
*/
|
||||||
class DOCKS_EXPORT FrameworkWidgetFactory {
|
class DOCKS_EXPORT FrameworkWidgetFactory {
|
||||||
public:
|
public:
|
||||||
|
FrameworkWidgetFactory() = default;
|
||||||
|
|
||||||
///@brief Destructor.Don't delete FrameworkWidgetFactory directly, it's owned
|
///@brief Destructor.Don't delete FrameworkWidgetFactory directly, it's owned
|
||||||
/// by the framework.
|
/// by the framework.
|
||||||
virtual ~FrameworkWidgetFactory();
|
virtual ~FrameworkWidgetFactory();
|
||||||
|
|
||||||
///@brief Called internally by the framework to create a Frame class
|
///@brief Called internally by the framework to create a Frame class
|
||||||
//// Override to provide your own Frame sub-class. A frame is the
|
/// Override to provide your own Frame sub-class. A frame is the
|
||||||
/// widget that holds the titlebar and tab-widget which holds the
|
/// widget that holds the titlebar and tab-widget which holds the
|
||||||
/// 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 = 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
|
||||||
@@ -101,9 +97,8 @@ public:
|
|||||||
///@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 anchor Just forward to Sepataror's constructor.
|
|
||||||
///@param parent Just forward to Separator's constructor.
|
///@param parent Just forward to Separator's constructor.
|
||||||
virtual Separator* createSeparator(Anchor *anchor, QWidgetAdapter *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
|
||||||
@@ -122,6 +117,8 @@ public:
|
|||||||
/// Override to provide your own DropIndicatorOverlayInterface sub-class.
|
/// Override to provide your own DropIndicatorOverlayInterface sub-class.
|
||||||
///@param dropArea Just forward to DropIndicatorOverlayInterface's constructor.
|
///@param dropArea Just forward to DropIndicatorOverlayInterface's constructor.
|
||||||
virtual DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea *dropArea) const = 0;
|
virtual DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea *dropArea) const = 0;
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(FrameworkWidgetFactory)
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -130,15 +127,18 @@ public:
|
|||||||
class DOCKS_EXPORT DefaultWidgetFactory : public FrameworkWidgetFactory
|
class DOCKS_EXPORT DefaultWidgetFactory : public FrameworkWidgetFactory
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
DefaultWidgetFactory() = default;
|
||||||
Frame *createFrame(QWidgetOrQuick *parent, FrameOptions) const override;
|
Frame *createFrame(QWidgetOrQuick *parent, FrameOptions) const override;
|
||||||
TitleBar *createTitleBar(Frame *) const override;
|
TitleBar *createTitleBar(Frame *) const override;
|
||||||
TitleBar *createTitleBar(FloatingWindow *) const override;
|
TitleBar *createTitleBar(FloatingWindow *) const override;
|
||||||
TabBar *createTabBar(TabWidget *parent) const override;
|
TabBar *createTabBar(TabWidget *parent) const override;
|
||||||
TabWidget *createTabWidget(Frame *parent) const override;
|
TabWidget *createTabWidget(Frame *parent) const override;
|
||||||
Separator *createSeparator(Anchor *anchor, QWidgetAdapter *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) const override;
|
||||||
DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea*) const override;
|
DropIndicatorOverlayInterface *createDropIndicatorOverlay(DropArea*) const override;
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(DefaultWidgetFactory)
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,6 +21,13 @@
|
|||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
// Only on Windows, where this is popular. On linux it the Qt::Tool windows need reparenting. Untested on macOS.
|
||||||
|
# define KDDOCKWIDGETS_SUPPORTS_NESTED_MAINWINDOWS
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
namespace KDDockWidgets
|
namespace KDDockWidgets
|
||||||
{
|
{
|
||||||
enum Location {
|
enum Location {
|
||||||
@@ -66,41 +64,14 @@ namespace KDDockWidgets
|
|||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(RestoreOptions, RestoreOption)
|
Q_DECLARE_FLAGS(RestoreOptions, RestoreOption)
|
||||||
|
|
||||||
///@internal
|
///@brief When a widget is added we need to figure out what's a decent size for it
|
||||||
inline Location oppositeLocation(Location loc)
|
///This enum specifies the different ways to calculate it
|
||||||
{
|
enum class DefaultSizeMode {
|
||||||
switch (loc) {
|
ItemSize, ///< Simply uses the Item::size() of the item being added. Actual used size might be smaller if our window isn't big enough.
|
||||||
case Location_OnLeft:
|
Fair, ///< Gives an equal relative size as the items that are already in the layout
|
||||||
return Location_OnRight;
|
FairButFloor, ///< Equal to fair, but if the item is smaller than the fair suggestion, then that small size is used.
|
||||||
case Location_OnTop:
|
SizePolicy, ///< Uses the item's sizeHint() and sizePolicy()
|
||||||
return Location_OnBottom;
|
};
|
||||||
case Location_OnRight:
|
|
||||||
return Location_OnLeft;
|
|
||||||
case Location_OnBottom:
|
|
||||||
return Location_OnTop;
|
|
||||||
default:
|
|
||||||
Q_ASSERT(false);
|
|
||||||
return Location_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///@internal
|
|
||||||
inline Location adjacentLocation(Location loc)
|
|
||||||
{
|
|
||||||
switch (loc) {
|
|
||||||
case Location_OnLeft:
|
|
||||||
return Location_OnTop;
|
|
||||||
case Location_OnTop:
|
|
||||||
return Location_OnRight;
|
|
||||||
case Location_OnRight:
|
|
||||||
return Location_OnBottom;
|
|
||||||
case Location_OnBottom:
|
|
||||||
return Location_OnLeft;
|
|
||||||
default:
|
|
||||||
Q_ASSERT(false);
|
|
||||||
return Location_None;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
///@internal
|
///@internal
|
||||||
inline QString locationStr(Location loc)
|
inline QString locationStr(Location loc)
|
||||||
@@ -122,7 +93,6 @@ namespace KDDockWidgets
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(KDDockWidgets::Location)
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(KDDockWidgets::FrameOptions)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(KDDockWidgets::FrameOptions)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,3 +1,14 @@
|
|||||||
|
#
|
||||||
|
# This file is part of KDDockWidgets.
|
||||||
|
#
|
||||||
|
# SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
# Author: Jean-Michaël Celerier <jean-michael.celerier@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(CMakeFindDependencyMacro)
|
include(CMakeFindDependencyMacro)
|
||||||
|
|
||||||
find_dependency(Qt5Widgets REQUIRED)
|
find_dependency(Qt5Widgets REQUIRED)
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,10 +24,10 @@
|
|||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "LastPosition_p.h"
|
#include "Position_p.h"
|
||||||
#include "multisplitter/Anchor_p.h"
|
|
||||||
#include "multisplitter/Item_p.h"
|
#include "multisplitter/Item_p.h"
|
||||||
#include "FrameworkWidgetFactory.h"
|
#include "FrameworkWidgetFactory.h"
|
||||||
|
#include "MainWindowBase.h"
|
||||||
|
|
||||||
#include <qmath.h>
|
#include <qmath.h>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
@@ -51,40 +42,6 @@ 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;
|
||||||
|
|
||||||
static QVariantMap sizeToMap(QSize sz)
|
|
||||||
{
|
|
||||||
QVariantMap map;
|
|
||||||
map.insert(QStringLiteral("width"), sz.width());
|
|
||||||
map.insert(QStringLiteral("height"), sz.height());
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QVariantMap rectToMap(QRect rect)
|
|
||||||
{
|
|
||||||
QVariantMap map;
|
|
||||||
map.insert(QStringLiteral("x"), rect.x());
|
|
||||||
map.insert(QStringLiteral("y"), rect.y());
|
|
||||||
map.insert(QStringLiteral("width"), rect.width());
|
|
||||||
map.insert(QStringLiteral("height"), rect.height());
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QSize mapToSize(const QVariantMap &map)
|
|
||||||
{
|
|
||||||
return { map.value(QStringLiteral("width")).toInt(),
|
|
||||||
map.value(QStringLiteral("height")).toInt() };
|
|
||||||
}
|
|
||||||
|
|
||||||
static QRect mapToRect(const QVariantMap &map)
|
|
||||||
{
|
|
||||||
return QRect(map.value(QStringLiteral("x")).toInt(),
|
|
||||||
map.value(QStringLiteral("y")).toInt(),
|
|
||||||
map.value(QStringLiteral("width")).toInt(),
|
|
||||||
map.value(QStringLiteral("height")).toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
class KDDockWidgets::LayoutSaver::Private
|
class KDDockWidgets::LayoutSaver::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -109,8 +66,8 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
bool matchesAffinity(const QString &affinityName) const {
|
bool matchesAffinity(const QStringList &affinities) const {
|
||||||
return m_affinityNames.isEmpty() || affinityName.isEmpty() || m_affinityNames.contains(affinityName);
|
return m_affinityNames.isEmpty() || affinities.isEmpty() || DockRegistry::self()->affinitiesMatch(m_affinityNames, affinities);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@@ -122,11 +79,33 @@ public:
|
|||||||
DockRegistry *const m_dockRegistry;
|
DockRegistry *const m_dockRegistry;
|
||||||
const RestoreOptions m_restoreOptions;
|
const RestoreOptions m_restoreOptions;
|
||||||
QStringList m_affinityNames;
|
QStringList m_affinityNames;
|
||||||
|
|
||||||
static bool s_restoreInProgress;
|
static bool s_restoreInProgress;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool LayoutSaver::Private::s_restoreInProgress = false;
|
bool LayoutSaver::Private::s_restoreInProgress = false;
|
||||||
|
|
||||||
|
|
||||||
|
static QVariantList stringListToVariant(const QStringList &strs)
|
||||||
|
{
|
||||||
|
QVariantList variantList;
|
||||||
|
variantList.reserve(strs.size());
|
||||||
|
for (const QString &str : strs)
|
||||||
|
variantList.push_back(str);
|
||||||
|
|
||||||
|
return variantList;
|
||||||
|
}
|
||||||
|
|
||||||
|
static QStringList variantToStringList(const QVariantList &variantList)
|
||||||
|
{
|
||||||
|
QStringList stringList;
|
||||||
|
stringList.reserve(variantList.size());
|
||||||
|
for (const QVariant &variant : variantList)
|
||||||
|
stringList.push_back(variant.toString());
|
||||||
|
|
||||||
|
return stringList;
|
||||||
|
}
|
||||||
|
|
||||||
LayoutSaver::LayoutSaver(RestoreOptions options)
|
LayoutSaver::LayoutSaver(RestoreOptions options)
|
||||||
: d(new Private(options))
|
: d(new Private(options))
|
||||||
{
|
{
|
||||||
@@ -180,14 +159,14 @@ QByteArray LayoutSaver::serializeLayout() const
|
|||||||
const MainWindowBase::List mainWindows = d->m_dockRegistry->mainwindows();
|
const MainWindowBase::List mainWindows = d->m_dockRegistry->mainwindows();
|
||||||
layout.mainWindows.reserve(mainWindows.size());
|
layout.mainWindows.reserve(mainWindows.size());
|
||||||
for (MainWindowBase *mainWindow : mainWindows) {
|
for (MainWindowBase *mainWindow : mainWindows) {
|
||||||
if (d->matchesAffinity(mainWindow->affinityName()))
|
if (d->matchesAffinity(mainWindow->affinities()))
|
||||||
layout.mainWindows.push_back(mainWindow->serialize());
|
layout.mainWindows.push_back(mainWindow->serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<KDDockWidgets::FloatingWindow*> floatingWindows = d->m_dockRegistry->nestedwindows();
|
const QVector<KDDockWidgets::FloatingWindow*> floatingWindows = d->m_dockRegistry->nestedwindows();
|
||||||
layout.floatingWindows.reserve(floatingWindows.size());
|
layout.floatingWindows.reserve(floatingWindows.size());
|
||||||
for (KDDockWidgets::FloatingWindow *floatingWindow : floatingWindows) {
|
for (KDDockWidgets::FloatingWindow *floatingWindow : floatingWindows) {
|
||||||
if (d->matchesAffinity(floatingWindow->affinityName()))
|
if (d->matchesAffinity(floatingWindow->affinities()))
|
||||||
layout.floatingWindows.push_back(floatingWindow->serialize());
|
layout.floatingWindows.push_back(floatingWindow->serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +174,7 @@ QByteArray LayoutSaver::serializeLayout() const
|
|||||||
const DockWidgetBase::List closedDockWidgets = d->m_dockRegistry->closedDockwidgets();
|
const DockWidgetBase::List closedDockWidgets = d->m_dockRegistry->closedDockwidgets();
|
||||||
layout.closedDockWidgets.reserve(closedDockWidgets.size());
|
layout.closedDockWidgets.reserve(closedDockWidgets.size());
|
||||||
for (DockWidgetBase *dockWidget : closedDockWidgets) {
|
for (DockWidgetBase *dockWidget : closedDockWidgets) {
|
||||||
if (d->matchesAffinity(dockWidget->affinityName()))
|
if (d->matchesAffinity(dockWidget->affinities()))
|
||||||
layout.closedDockWidgets.push_back(dockWidget->serialize());
|
layout.closedDockWidgets.push_back(dockWidget->serialize());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,9 +184,9 @@ QByteArray LayoutSaver::serializeLayout() const
|
|||||||
const DockWidgetBase::List dockWidgets = d->m_dockRegistry->dockwidgets();
|
const DockWidgetBase::List dockWidgets = d->m_dockRegistry->dockwidgets();
|
||||||
layout.allDockWidgets.reserve(dockWidgets.size());
|
layout.allDockWidgets.reserve(dockWidgets.size());
|
||||||
for (DockWidgetBase *dockWidget : dockWidgets) {
|
for (DockWidgetBase *dockWidget : dockWidgets) {
|
||||||
if (d->matchesAffinity(dockWidget->affinityName())) {
|
if (d->matchesAffinity(dockWidget->affinities())) {
|
||||||
auto dw = dockWidget->serialize();
|
auto dw = dockWidget->serialize();
|
||||||
dw->lastPosition = dockWidget->lastPosition()->serialize();
|
dw->lastPosition = dockWidget->lastPositions().serialize();
|
||||||
layout.allDockWidgets.push_back(dw);
|
layout.allDockWidgets.push_back(dw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -221,31 +200,6 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
|
|||||||
if (data.isEmpty())
|
if (data.isEmpty())
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
struct EnsureItemsAtCorrectPlace {
|
|
||||||
|
|
||||||
EnsureItemsAtCorrectPlace(LayoutSaver *ls)
|
|
||||||
: layoutSaver(ls)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
~EnsureItemsAtCorrectPlace()
|
|
||||||
{
|
|
||||||
// When using RestoreOption_RelativeToMainWindow we'll have many rounding errors so the layout won't be exact.
|
|
||||||
// Make sure to run a relayout at the end
|
|
||||||
// (Using RAII to make sure it runs after Private::RAIIIsRestoring went out of scope, since "isRestoring= true" inhibits relayout
|
|
||||||
if (ensure) {
|
|
||||||
for (auto layout : DockRegistry::self()->layouts()) {
|
|
||||||
if (layoutSaver->d->matchesAffinity(layout->affinityName()))
|
|
||||||
layout->redistributeSpace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ensure = false;
|
|
||||||
LayoutSaver *const layoutSaver;
|
|
||||||
};
|
|
||||||
|
|
||||||
EnsureItemsAtCorrectPlace ensureItemsAtCorrectPlace(this);
|
|
||||||
Private::RAIIIsRestoring isRestoring;
|
Private::RAIIIsRestoring isRestoring;
|
||||||
|
|
||||||
struct FrameCleanup {
|
struct FrameCleanup {
|
||||||
@@ -269,21 +223,32 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!layout.isValid()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (d->m_restoreOptions & RestoreOption_RelativeToMainWindow)
|
if (d->m_restoreOptions & RestoreOption_RelativeToMainWindow)
|
||||||
layout.scaleSizes();
|
layout.scaleSizes();
|
||||||
|
|
||||||
// Hide all dockwidgets and unparent them from any layout before starting restore
|
// Hide all dockwidgets and unparent them from any layout before starting restore
|
||||||
d->m_dockRegistry->clear(d->m_affinityNames, /*deleteStaticAnchors=*/true);
|
// 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->mainWindows(layout.mainWindowNames()),
|
||||||
|
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()) {
|
||||||
|
mainWindow = mwFunc(mw.uniqueName);
|
||||||
|
} else {
|
||||||
qWarning() << "Failed to restore layout create MainWindow with name" << mw.uniqueName << "first";
|
qWarning() << "Failed to restore layout create MainWindow with name" << mw.uniqueName << "first";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!d->matchesAffinity(mainWindow->affinityName()))
|
if (!d->matchesAffinity(mainWindow->affinities()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!(d->m_restoreOptions & RestoreOption_RelativeToMainWindow))
|
if (!(d->m_restoreOptions & RestoreOption_RelativeToMainWindow))
|
||||||
@@ -295,7 +260,7 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
|
|||||||
|
|
||||||
// 2. Restore FloatingWindows
|
// 2. Restore FloatingWindows
|
||||||
for (const LayoutSaver::FloatingWindow &fw : qAsConst(layout.floatingWindows)) {
|
for (const LayoutSaver::FloatingWindow &fw : qAsConst(layout.floatingWindows)) {
|
||||||
if (!d->matchesAffinity(fw.affinityName))
|
if (!d->matchesAffinity(fw.affinities))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
MainWindowBase *parent = fw.parentIndex == -1 ? nullptr
|
MainWindowBase *parent = fw.parentIndex == -1 ? nullptr
|
||||||
@@ -304,32 +269,30 @@ bool LayoutSaver::restoreLayout(const QByteArray &data)
|
|||||||
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(parent);
|
auto floatingWindow = Config::self().frameworkWidgetFactory()->createFloatingWindow(parent);
|
||||||
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";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Restore closed dock widgets. They remain closed but acquire geometry and placeholder properties
|
// 3. Restore closed dock widgets. They remain closed but acquire geometry and placeholder properties
|
||||||
for (const auto &dw : qAsConst(layout.closedDockWidgets)) {
|
for (const auto &dw : qAsConst(layout.closedDockWidgets)) {
|
||||||
if (d->matchesAffinity(dw->affinityName)) {
|
if (d->matchesAffinity(dw->affinities)) {
|
||||||
DockWidgetBase::deserialize(dw);
|
DockWidgetBase::deserialize(dw);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Restore the placeholder info, now that the Items have been created
|
// 4. Restore the placeholder info, now that the Items have been created
|
||||||
for (const auto &dw : qAsConst(layout.allDockWidgets)) {
|
for (const auto &dw : qAsConst(layout.allDockWidgets)) {
|
||||||
if (!d->matchesAffinity(dw->affinityName))
|
if (!d->matchesAffinity(dw->affinities))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (DockWidgetBase *dockWidget = d->m_dockRegistry->dockByName(dw->uniqueName)) {
|
if (DockWidgetBase *dockWidget = d->m_dockRegistry->dockByName(dw->uniqueName)) {
|
||||||
dockWidget->lastPosition()->deserialize(dw->lastPosition);
|
dockWidget->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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// our raii class will run when
|
|
||||||
ensureItemsAtCorrectPlace.ensure = d->m_restoreOptions & RestoreOption_RelativeToMainWindow;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,7 +316,6 @@ DockWidgetBase::List LayoutSaver::restoredDockWidgets() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutSaver::Private::clearRestoredProperty()
|
void LayoutSaver::Private::clearRestoredProperty()
|
||||||
@@ -398,6 +360,12 @@ bool LayoutSaver::restoreInProgress()
|
|||||||
|
|
||||||
bool LayoutSaver::Layout::isValid() const
|
bool LayoutSaver::Layout::isValid() const
|
||||||
{
|
{
|
||||||
|
if (serializationVersion != KDDOCKWIDGETS_SERIALIZATION_VERSION) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Serialization format is too old"
|
||||||
|
<< serializationVersion << "current=" << KDDOCKWIDGETS_SERIALIZATION_VERSION;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &m : mainWindows) {
|
for (auto &m : mainWindows) {
|
||||||
if (!m.isValid())
|
if (!m.isValid())
|
||||||
return false;
|
return false;
|
||||||
@@ -416,20 +384,6 @@ bool LayoutSaver::Layout::isValid() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutSaver::Layout::fillFrom(const QByteArray &serialized)
|
|
||||||
{
|
|
||||||
QDataStream ds(serialized);
|
|
||||||
ds >> this;
|
|
||||||
|
|
||||||
if (serializationVersion > KDDOCKWIDGETS_SERIALIZATION_VERSION) {
|
|
||||||
qWarning() << "Unsupported serialization version. Got=" << serializationVersion
|
|
||||||
<< "; expected equal or less than" << KDDOCKWIDGETS_SERIALIZATION_VERSION;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray LayoutSaver::Layout::toJson() const
|
QByteArray LayoutSaver::Layout::toJson() const
|
||||||
{
|
{
|
||||||
QJsonDocument doc = QJsonDocument::fromVariant(toVariantMap());
|
QJsonDocument doc = QJsonDocument::fromVariant(toVariantMap());
|
||||||
@@ -454,7 +408,7 @@ QVariantMap LayoutSaver::Layout::toVariantMap() const
|
|||||||
map.insert(QStringLiteral("serializationVersion"), serializationVersion);
|
map.insert(QStringLiteral("serializationVersion"), serializationVersion);
|
||||||
map.insert(QStringLiteral("mainWindows"), toVariantList<LayoutSaver::MainWindow>(mainWindows));
|
map.insert(QStringLiteral("mainWindows"), toVariantList<LayoutSaver::MainWindow>(mainWindows));
|
||||||
map.insert(QStringLiteral("floatingWindows"), toVariantList<LayoutSaver::FloatingWindow>(floatingWindows));
|
map.insert(QStringLiteral("floatingWindows"), toVariantList<LayoutSaver::FloatingWindow>(floatingWindows));
|
||||||
map.insert(QStringLiteral("closedDockWidgets"), dockWidgetNames(closedDockWidgets));
|
map.insert(QStringLiteral("closedDockWidgets"), ::dockWidgetNames(closedDockWidgets));
|
||||||
map.insert(QStringLiteral("allDockWidgets"), toVariantList(allDockWidgets));
|
map.insert(QStringLiteral("allDockWidgets"), toVariantList(allDockWidgets));
|
||||||
map.insert(QStringLiteral("screenInfo"), toVariantList<LayoutSaver::ScreenInfo>(screenInfo));
|
map.insert(QStringLiteral("screenInfo"), toVariantList<LayoutSaver::ScreenInfo>(screenInfo));
|
||||||
|
|
||||||
@@ -518,66 +472,31 @@ LayoutSaver::MainWindow LayoutSaver::Layout::mainWindowForIndex(int index) const
|
|||||||
return mainWindows.at(index);
|
return mainWindows.at(index);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutSaver::Item::isValid(const LayoutSaver::MultiSplitterLayout &layout) const
|
QStringList LayoutSaver::Layout::mainWindowNames() const
|
||||||
{
|
{
|
||||||
if (!frame.isValid())
|
QStringList names;
|
||||||
return false;
|
names.reserve(mainWindows.size());
|
||||||
|
for (const auto &mw : mainWindows) {
|
||||||
const int numAnchors = layout.anchors.size();
|
names << mw.uniqueName;
|
||||||
|
|
||||||
if (indexOfLeftAnchor < 0 || indexOfTopAnchor < 0 ||
|
|
||||||
indexOfBottomAnchor < 0 || indexOfRightAnchor < 0 ||
|
|
||||||
indexOfLeftAnchor >= numAnchors || indexOfTopAnchor >= numAnchors ||
|
|
||||||
indexOfBottomAnchor >= numAnchors || indexOfRightAnchor >= numAnchors) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid anchor indexes"
|
|
||||||
<< indexOfLeftAnchor << indexOfTopAnchor
|
|
||||||
<< indexOfBottomAnchor << indexOfRightAnchor;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return names;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutSaver::Item::scaleSizes(const ScalingInfo &scalingInfo)
|
QStringList LayoutSaver::Layout::dockWidgetNames() const
|
||||||
{
|
{
|
||||||
scalingInfo.applyFactorsTo(geometry);
|
QStringList names;
|
||||||
if (!frame.isNull)
|
names.reserve(allDockWidgets.size());
|
||||||
frame.scaleSizes(scalingInfo);
|
for (const auto &dw : allDockWidgets) {
|
||||||
}
|
names << dw->uniqueName;
|
||||||
|
}
|
||||||
|
|
||||||
QVariantMap LayoutSaver::Item::toVariantMap() const
|
return names;
|
||||||
{
|
|
||||||
QVariantMap map;
|
|
||||||
map.insert(QStringLiteral("objectName"), objectName);
|
|
||||||
map.insert(QStringLiteral("isPlaceholder"), isPlaceholder);
|
|
||||||
map.insert(QStringLiteral("geometry"), rectToMap(geometry));
|
|
||||||
map.insert(QStringLiteral("minSize"), sizeToMap(minSize));
|
|
||||||
map.insert(QStringLiteral("indexOfLeftAnchor"), indexOfLeftAnchor);
|
|
||||||
map.insert(QStringLiteral("indexOfTopAnchor"), indexOfTopAnchor);
|
|
||||||
map.insert(QStringLiteral("indexOfRightAnchor"), indexOfRightAnchor);
|
|
||||||
map.insert(QStringLiteral("indexOfBottomAnchor"), indexOfBottomAnchor);
|
|
||||||
if (!frame.isNull)
|
|
||||||
map.insert(QStringLiteral("frame"), frame.toVariantMap());
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayoutSaver::Item::fromVariantMap(const QVariantMap &map)
|
|
||||||
{
|
|
||||||
objectName = map.value(QStringLiteral("objectName")).toString();
|
|
||||||
isPlaceholder = map.value(QStringLiteral("isPlaceholder")).toBool();
|
|
||||||
geometry = mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
|
||||||
minSize = mapToSize(map.value(QStringLiteral("minSize")).toMap());
|
|
||||||
indexOfLeftAnchor = map.value(QStringLiteral("indexOfLeftAnchor")).toInt();
|
|
||||||
indexOfTopAnchor = map.value(QStringLiteral("indexOfTopAnchor")).toInt();
|
|
||||||
indexOfRightAnchor = map.value(QStringLiteral("indexOfRightAnchor")).toInt();
|
|
||||||
indexOfBottomAnchor = map.value(QStringLiteral("indexOfBottomAnchor")).toInt();
|
|
||||||
frame.fromVariantMap(map.value(QStringLiteral("frame"), QVariantMap()).toMap());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutSaver::Frame::isValid() const
|
bool LayoutSaver::Frame::isValid() const
|
||||||
{
|
{
|
||||||
if (!isNull)
|
if (isNull)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (!geometry.isValid()) {
|
if (!geometry.isValid()) {
|
||||||
@@ -585,15 +504,22 @@ bool LayoutSaver::Frame::isValid() const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (id.isEmpty()) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Invalid id";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if (options > 3) {
|
if (options > 3) {
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid options" << options;
|
qWarning() << Q_FUNC_INFO << "Invalid options" << options;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!dockWidgets.isEmpty()) {
|
||||||
if (currentTabIndex >= dockWidgets.size() || currentTabIndex < 0) {
|
if (currentTabIndex >= dockWidgets.size() || currentTabIndex < 0) {
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid tab index" << currentTabIndex << dockWidgets.size();
|
qWarning() << Q_FUNC_INFO << "Invalid tab index" << currentTabIndex << dockWidgets.size();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (auto &dw : dockWidgets) {
|
for (auto &dw : dockWidgets) {
|
||||||
if (!dw->isValid())
|
if (!dw->isValid())
|
||||||
@@ -611,9 +537,10 @@ void LayoutSaver::Frame::scaleSizes(const ScalingInfo &scalingInfo)
|
|||||||
QVariantMap LayoutSaver::Frame::toVariantMap() const
|
QVariantMap LayoutSaver::Frame::toVariantMap() const
|
||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
|
map.insert(QStringLiteral("id"), id);
|
||||||
map.insert(QStringLiteral("isNull"), isNull);
|
map.insert(QStringLiteral("isNull"), isNull);
|
||||||
map.insert(QStringLiteral("objectName"), objectName);
|
map.insert(QStringLiteral("objectName"), objectName);
|
||||||
map.insert(QStringLiteral("geometry"), rectToMap(geometry));
|
map.insert(QStringLiteral("geometry"), Layouting::rectToMap(geometry));
|
||||||
map.insert(QStringLiteral("options"), options);
|
map.insert(QStringLiteral("options"), options);
|
||||||
map.insert(QStringLiteral("currentTabIndex"), currentTabIndex);
|
map.insert(QStringLiteral("currentTabIndex"), currentTabIndex);
|
||||||
|
|
||||||
@@ -630,13 +557,14 @@ void LayoutSaver::Frame::fromVariantMap(const QVariantMap &map)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
id = map.value(QStringLiteral("id")).toString();
|
||||||
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 = mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
||||||
options = map.value(QStringLiteral("options")).toUInt();
|
options = map.value(QStringLiteral("options")).toUInt();
|
||||||
currentTabIndex = map.value(QStringLiteral("currentTabIndex")).toInt();
|
currentTabIndex = map.value(QStringLiteral("currentTabIndex")).toInt();
|
||||||
|
|
||||||
QVariantList dockWidgetsV = map.value(QStringLiteral("dockWidgets")).toList();
|
const QVariantList dockWidgetsV = map.value(QStringLiteral("dockWidgets")).toList();
|
||||||
|
|
||||||
dockWidgets.clear();
|
dockWidgets.clear();
|
||||||
dockWidgets.reserve(dockWidgetsV.size());
|
dockWidgets.reserve(dockWidgetsV.size());
|
||||||
@@ -659,8 +587,8 @@ void LayoutSaver::DockWidget::scaleSizes(const ScalingInfo &scalingInfo)
|
|||||||
QVariantMap LayoutSaver::DockWidget::toVariantMap() const
|
QVariantMap LayoutSaver::DockWidget::toVariantMap() const
|
||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
if (!affinityName.isEmpty())
|
if (!affinities.isEmpty())
|
||||||
map.insert(QStringLiteral("affinityName"), affinityName);
|
map.insert(QStringLiteral("affinities"), stringListToVariant(affinities));
|
||||||
map.insert(QStringLiteral("uniqueName"), uniqueName);
|
map.insert(QStringLiteral("uniqueName"), uniqueName);
|
||||||
map.insert(QStringLiteral("lastPosition"), lastPosition.toVariantMap());
|
map.insert(QStringLiteral("lastPosition"), lastPosition.toVariantMap());
|
||||||
|
|
||||||
@@ -669,125 +597,18 @@ QVariantMap LayoutSaver::DockWidget::toVariantMap() const
|
|||||||
|
|
||||||
void LayoutSaver::DockWidget::fromVariantMap(const QVariantMap &map)
|
void LayoutSaver::DockWidget::fromVariantMap(const QVariantMap &map)
|
||||||
{
|
{
|
||||||
affinityName = map.value(QStringLiteral("affinityName")).toString();
|
affinities = variantToStringList(map.value(QStringLiteral("affinities")).toList());
|
||||||
|
|
||||||
|
// Compatibility hack. Old json format had a single "affinityName" instead of an "affinities" list:
|
||||||
|
const QString affinityName = map.value(QStringLiteral("affinityName")).toString();
|
||||||
|
if (!affinityName.isEmpty() && !affinities.contains(affinityName)) {
|
||||||
|
affinities.push_back(affinityName);
|
||||||
|
}
|
||||||
|
|
||||||
uniqueName = map.value(QStringLiteral("uniqueName")).toString();
|
uniqueName = map.value(QStringLiteral("uniqueName")).toString();
|
||||||
lastPosition.fromVariantMap(map.value(QStringLiteral("lastPosition")).toMap());
|
lastPosition.fromVariantMap(map.value(QStringLiteral("lastPosition")).toMap());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutSaver::Anchor::isValid(const LayoutSaver::MultiSplitterLayout &layout) const
|
|
||||||
{
|
|
||||||
const bool isStatic = type != KDDockWidgets::Anchor::Type_None;
|
|
||||||
const bool isFollowing = indexOfFollowee != -1;
|
|
||||||
const int numAnchors = layout.anchors.size();
|
|
||||||
|
|
||||||
if (!geometry.isValid() && !isStatic && !isFollowing) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid geometry" << geometry;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (indexOfFrom < 0 || indexOfTo < 0 || indexOfFrom == indexOfTo ||
|
|
||||||
indexOfTo >= numAnchors || indexOfFrom >= numAnchors) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid indexes" << indexOfFrom << indexOfTo;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &anchorTo = layout.anchors[indexOfTo];
|
|
||||||
auto &anchorFrom = layout.anchors[indexOfFrom];
|
|
||||||
if (anchorTo.orientation != anchorFrom.orientation || anchorTo.orientation == orientation) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid orientation" << anchorTo.orientation << anchorFrom.orientation
|
|
||||||
<< orientation;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (orientation != Qt::Vertical && orientation != Qt::Horizontal) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid orientation" << orientation;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type != KDDockWidgets::Anchor::Type_None &&
|
|
||||||
type != KDDockWidgets::Anchor::Type_LeftStatic &&
|
|
||||||
type != KDDockWidgets::Anchor::Type_RightStatic &&
|
|
||||||
type != KDDockWidgets::Anchor::Type_TopStatic &&
|
|
||||||
type != KDDockWidgets::Anchor::Type_BottomStatic) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid type" << type;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isStatic && !isFollowing && (side1Items.isEmpty() || side2Items.isEmpty())) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Anchor should have items on both sides";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariantMap LayoutSaver::Anchor::toVariantMap() const
|
|
||||||
{
|
|
||||||
QVariantMap map;
|
|
||||||
map.insert(QStringLiteral("objectName"), objectName);
|
|
||||||
map.insert(QStringLiteral("geometry"), rectToMap(geometry));
|
|
||||||
map.insert(QStringLiteral("orientation"), orientation);
|
|
||||||
map.insert(QStringLiteral("type"), type);
|
|
||||||
map.insert(QStringLiteral("indexOfFrom"), indexOfFrom);
|
|
||||||
map.insert(QStringLiteral("indexOfTo"), indexOfTo);
|
|
||||||
map.insert(QStringLiteral("indexOfFollowee"), indexOfFollowee);
|
|
||||||
map.insert(QStringLiteral("positionPercentage"), positionPercentage);
|
|
||||||
|
|
||||||
QVariantList side1ItemsV;
|
|
||||||
QVariantList side2ItemsV;
|
|
||||||
side1ItemsV.reserve(side1Items.size());
|
|
||||||
side2ItemsV.reserve(side2Items.size());
|
|
||||||
for (int index : qAsConst(side1Items))
|
|
||||||
side1ItemsV.push_back(index);
|
|
||||||
for (int index : qAsConst(side2Items))
|
|
||||||
side2ItemsV.push_back(index);
|
|
||||||
|
|
||||||
map.insert(QStringLiteral("side1Items"), side1ItemsV);
|
|
||||||
map.insert(QStringLiteral("side2Items"), side2ItemsV);
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayoutSaver::Anchor::fromVariantMap(const QVariantMap &map)
|
|
||||||
{
|
|
||||||
objectName = map.value(QStringLiteral("objectName")).toString();
|
|
||||||
geometry = mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
|
||||||
|
|
||||||
orientation = map.value(QStringLiteral("orientation")).toInt();
|
|
||||||
type = map.value(QStringLiteral("type")).toInt();
|
|
||||||
indexOfFrom = map.value(QStringLiteral("indexOfFrom")).toInt();
|
|
||||||
indexOfTo = map.value(QStringLiteral("indexOfTo")).toInt();
|
|
||||||
indexOfFollowee = map.value(QStringLiteral("indexOfFollowee")).toInt();
|
|
||||||
positionPercentage = map.value(QStringLiteral("positionPercentage")).toDouble();
|
|
||||||
|
|
||||||
side1Items.clear();
|
|
||||||
side2Items.clear();
|
|
||||||
const QVariantList side1ItemsV = map.value(QStringLiteral("side1Items")).toList();
|
|
||||||
const QVariantList side2ItemsV = map.value(QStringLiteral("side2Items")).toList();
|
|
||||||
side1Items.reserve(side1ItemsV.size());
|
|
||||||
side2Items.reserve(side2ItemsV.size());
|
|
||||||
for (const QVariant &v : side1ItemsV)
|
|
||||||
side1Items.push_back(v.toInt());
|
|
||||||
for (const QVariant &v : side2ItemsV)
|
|
||||||
side2Items.push_back(v.toInt());
|
|
||||||
}
|
|
||||||
|
|
||||||
void LayoutSaver::Anchor::scaleSizes(const ScalingInfo &scalingInfo)
|
|
||||||
{
|
|
||||||
const QPoint pos = geometry.topLeft();
|
|
||||||
|
|
||||||
if (isVertical()) {
|
|
||||||
geometry.moveLeft(int(pos.x() * scalingInfo.widthFactor));
|
|
||||||
} else {
|
|
||||||
geometry.moveTop(int(pos.y() * scalingInfo.heightFactor));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LayoutSaver::Anchor::isVertical() const
|
|
||||||
{
|
|
||||||
return orientation == Qt::Vertical;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool LayoutSaver::FloatingWindow::isValid() const
|
bool LayoutSaver::FloatingWindow::isValid() const
|
||||||
{
|
{
|
||||||
if (!multiSplitterLayout.isValid())
|
if (!multiSplitterLayout.isValid())
|
||||||
@@ -812,13 +633,13 @@ QVariantMap LayoutSaver::FloatingWindow::toVariantMap() const
|
|||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
map.insert(QStringLiteral("multiSplitterLayout"), multiSplitterLayout.toVariantMap());
|
map.insert(QStringLiteral("multiSplitterLayout"), multiSplitterLayout.toVariantMap());
|
||||||
map.insert(QStringLiteral("parentIndex"), parentIndex);
|
map.insert(QStringLiteral("parentIndex"), parentIndex);
|
||||||
map.insert(QStringLiteral("geometry"), rectToMap(geometry));
|
map.insert(QStringLiteral("geometry"), Layouting::rectToMap(geometry));
|
||||||
map.insert(QStringLiteral("screenIndex"), screenIndex);
|
map.insert(QStringLiteral("screenIndex"), screenIndex);
|
||||||
map.insert(QStringLiteral("screenSize"), sizeToMap(screenSize));
|
map.insert(QStringLiteral("screenSize"), Layouting::sizeToMap(screenSize));
|
||||||
map.insert(QStringLiteral("isVisible"), isVisible);
|
map.insert(QStringLiteral("isVisible"), isVisible);
|
||||||
|
|
||||||
if (!affinityName.isEmpty())
|
if (!affinities.isEmpty())
|
||||||
map.insert(QStringLiteral("affinityName"), affinityName);
|
map.insert(QStringLiteral("affinities"), stringListToVariant(affinities));
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@@ -827,11 +648,17 @@ void LayoutSaver::FloatingWindow::fromVariantMap(const QVariantMap &map)
|
|||||||
{
|
{
|
||||||
multiSplitterLayout.fromVariantMap(map.value(QStringLiteral("multiSplitterLayout")).toMap());
|
multiSplitterLayout.fromVariantMap(map.value(QStringLiteral("multiSplitterLayout")).toMap());
|
||||||
parentIndex = map.value(QStringLiteral("parentIndex")).toInt();
|
parentIndex = map.value(QStringLiteral("parentIndex")).toInt();
|
||||||
geometry = mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
||||||
screenIndex = map.value(QStringLiteral("screenIndex")).toInt();
|
screenIndex = map.value(QStringLiteral("screenIndex")).toInt();
|
||||||
screenSize = 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();
|
||||||
affinityName = map.value(QStringLiteral("affinityName")).toString();
|
affinities = variantToStringList(map.value(QStringLiteral("affinities")).toList());
|
||||||
|
|
||||||
|
// Compatibility hack. Old json format had a single "affinityName" instead of an "affinities" list:
|
||||||
|
const QString affinityName = map.value(QStringLiteral("affinityName")).toString();
|
||||||
|
if (!affinityName.isEmpty() && !affinities.contains(affinityName)) {
|
||||||
|
affinities.push_back(affinityName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutSaver::MainWindow::isValid() const
|
bool LayoutSaver::MainWindow::isValid() const
|
||||||
@@ -867,13 +694,11 @@ QVariantMap LayoutSaver::MainWindow::toVariantMap() const
|
|||||||
map.insert(QStringLiteral("options"), int(options));
|
map.insert(QStringLiteral("options"), int(options));
|
||||||
map.insert(QStringLiteral("multiSplitterLayout"), multiSplitterLayout.toVariantMap());
|
map.insert(QStringLiteral("multiSplitterLayout"), multiSplitterLayout.toVariantMap());
|
||||||
map.insert(QStringLiteral("uniqueName"), uniqueName);
|
map.insert(QStringLiteral("uniqueName"), uniqueName);
|
||||||
map.insert(QStringLiteral("geometry"), rectToMap(geometry));
|
map.insert(QStringLiteral("geometry"), Layouting::rectToMap(geometry));
|
||||||
map.insert(QStringLiteral("screenIndex"), screenIndex);
|
map.insert(QStringLiteral("screenIndex"), screenIndex);
|
||||||
map.insert(QStringLiteral("screenSize"), 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));
|
||||||
if (!affinityName.isEmpty())
|
|
||||||
map.insert(QStringLiteral("affinityName"), affinityName);
|
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@@ -883,72 +708,74 @@ void LayoutSaver::MainWindow::fromVariantMap(const QVariantMap &map)
|
|||||||
options = KDDockWidgets::MainWindowOptions(map.value(QStringLiteral("options")).toInt());
|
options = KDDockWidgets::MainWindowOptions(map.value(QStringLiteral("options")).toInt());
|
||||||
multiSplitterLayout.fromVariantMap(map.value(QStringLiteral("multiSplitterLayout")).toMap());
|
multiSplitterLayout.fromVariantMap(map.value(QStringLiteral("multiSplitterLayout")).toMap());
|
||||||
uniqueName = map.value(QStringLiteral("uniqueName")).toString();
|
uniqueName = map.value(QStringLiteral("uniqueName")).toString();
|
||||||
affinityName = map.value(QStringLiteral("affinityName")).toString();
|
geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
||||||
geometry = mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
|
||||||
screenIndex = map.value(QStringLiteral("screenIndex")).toInt();
|
screenIndex = map.value(QStringLiteral("screenIndex")).toInt();
|
||||||
screenSize = 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());
|
||||||
|
|
||||||
|
// Compatibility hack. Old json format had a single "affinityName" instead of an "affinities" list:
|
||||||
|
const QString affinityName = map.value(QStringLiteral("affinityName")).toString();
|
||||||
|
if (!affinityName.isEmpty() && !affinities.contains(affinityName)) {
|
||||||
|
affinities.push_back(affinityName);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LayoutSaver::MultiSplitterLayout::isValid() const
|
bool LayoutSaver::MultiSplitter::isValid() const
|
||||||
{
|
{
|
||||||
for (auto &item : items) {
|
if (layout.isEmpty())
|
||||||
if (!item.isValid(*this))
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
for (auto &anchor : anchors) {
|
/*if (!size.isValid()) {
|
||||||
if (!anchor.isValid(*this))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!size.isValid()) {
|
|
||||||
qWarning() << Q_FUNC_INFO << "Invalid size";
|
qWarning() << Q_FUNC_INFO << "Invalid size";
|
||||||
return false;
|
return false;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutSaver::MultiSplitterLayout::scaleSizes(const ScalingInfo &scalingInfo)
|
void LayoutSaver::MultiSplitter::scaleSizes(const ScalingInfo &)
|
||||||
{
|
{
|
||||||
scalingInfo.applyFactorsTo(/*by-ref*/size);
|
// scalingInfo.applyFactorsTo(/*by-ref*/size);
|
||||||
for (LayoutSaver::Anchor &anchor : anchors)
|
//for (LayoutSaver::Item &item : items) TODO
|
||||||
anchor.scaleSizes(scalingInfo);
|
// item.scaleSizes(scalingInfo);
|
||||||
for (LayoutSaver::Item &item : items)
|
|
||||||
item.scaleSizes(scalingInfo);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap LayoutSaver::MultiSplitterLayout::toVariantMap() const
|
QVariantMap LayoutSaver::MultiSplitter::toVariantMap() const
|
||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap result;
|
||||||
|
result.insert(QStringLiteral("layout"), layout);
|
||||||
|
|
||||||
map.insert(QStringLiteral("anchors"), toVariantList<LayoutSaver::Anchor>(anchors));
|
QVariantMap framesV;
|
||||||
map.insert(QStringLiteral("items"), toVariantList<LayoutSaver::Item>(items));
|
for (auto &frame : frames)
|
||||||
map.insert(QStringLiteral("minSize"), sizeToMap(minSize));
|
framesV.insert(frame.id, frame.toVariantMap());
|
||||||
map.insert(QStringLiteral("size"), sizeToMap(size));
|
|
||||||
|
|
||||||
return map;
|
result.insert(QStringLiteral("frames"), framesV);
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutSaver::MultiSplitterLayout::fromVariantMap(const QVariantMap &map)
|
void LayoutSaver::MultiSplitter::fromVariantMap(const QVariantMap &map)
|
||||||
{
|
{
|
||||||
anchors = fromVariantList<LayoutSaver::Anchor>(map.value(QStringLiteral("anchors")).toList());
|
layout = map.value(QStringLiteral("layout")).toMap();
|
||||||
items = fromVariantList<LayoutSaver::Item>(map.value(QStringLiteral("items")).toList());
|
const QVariantMap framesV = map.value(QStringLiteral("frames")).toMap();
|
||||||
minSize = mapToSize(map.value(QStringLiteral("minSize")).toMap());
|
frames.clear();
|
||||||
size = mapToSize(map.value(QStringLiteral("size")).toMap());
|
for (const QVariant &frameV : framesV) {
|
||||||
|
LayoutSaver::Frame frame;
|
||||||
|
frame.fromVariantMap(frameV.toMap());
|
||||||
|
frames.insert(frame.id, frame);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutSaver::LastPosition::scaleSizes(const ScalingInfo &scalingInfo)
|
void LayoutSaver::Position::scaleSizes(const ScalingInfo &scalingInfo)
|
||||||
{
|
{
|
||||||
scalingInfo.applyFactorsTo(/*by-ref*/lastFloatingGeometry);
|
scalingInfo.applyFactorsTo(/*by-ref*/lastFloatingGeometry);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariantMap LayoutSaver::LastPosition::toVariantMap() const
|
QVariantMap LayoutSaver::Position::toVariantMap() const
|
||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
map.insert(QStringLiteral("lastFloatingGeometry"), rectToMap(lastFloatingGeometry));
|
map.insert(QStringLiteral("lastFloatingGeometry"), Layouting::rectToMap(lastFloatingGeometry));
|
||||||
map.insert(QStringLiteral("tabIndex"), tabIndex);
|
map.insert(QStringLiteral("tabIndex"), tabIndex);
|
||||||
map.insert(QStringLiteral("wasFloating"), wasFloating);
|
map.insert(QStringLiteral("wasFloating"), wasFloating);
|
||||||
map.insert(QStringLiteral("placeholders"), toVariantList<LayoutSaver::Placeholder>(placeholders));
|
map.insert(QStringLiteral("placeholders"), toVariantList<LayoutSaver::Placeholder>(placeholders));
|
||||||
@@ -956,9 +783,9 @@ QVariantMap LayoutSaver::LastPosition::toVariantMap() const
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LayoutSaver::LastPosition::fromVariantMap(const QVariantMap &map)
|
void LayoutSaver::Position::fromVariantMap(const QVariantMap &map)
|
||||||
{
|
{
|
||||||
lastFloatingGeometry = mapToRect(map.value(QStringLiteral("lastFloatingGeometry")).toMap());
|
lastFloatingGeometry = Layouting::mapToRect(map.value(QStringLiteral("lastFloatingGeometry")).toMap());
|
||||||
tabIndex = map.value(QStringLiteral("tabIndex")).toInt();
|
tabIndex = map.value(QStringLiteral("tabIndex")).toInt();
|
||||||
wasFloating = map.value(QStringLiteral("wasFloating")).toBool();
|
wasFloating = map.value(QStringLiteral("wasFloating")).toBool();
|
||||||
placeholders = fromVariantList<LayoutSaver::Placeholder>(map.value(QStringLiteral("placeholders")).toList());
|
placeholders = fromVariantList<LayoutSaver::Placeholder>(map.value(QStringLiteral("placeholders")).toList());
|
||||||
@@ -968,7 +795,7 @@ QVariantMap LayoutSaver::ScreenInfo::toVariantMap() const
|
|||||||
{
|
{
|
||||||
QVariantMap map;
|
QVariantMap map;
|
||||||
map.insert(QStringLiteral("index"), index);
|
map.insert(QStringLiteral("index"), index);
|
||||||
map.insert(QStringLiteral("geometry"), rectToMap(geometry));
|
map.insert(QStringLiteral("geometry"), Layouting::rectToMap(geometry));
|
||||||
map.insert(QStringLiteral("name"), name);
|
map.insert(QStringLiteral("name"), name);
|
||||||
map.insert(QStringLiteral("devicePixelRatio"), devicePixelRatio);
|
map.insert(QStringLiteral("devicePixelRatio"), devicePixelRatio);
|
||||||
|
|
||||||
@@ -978,7 +805,7 @@ QVariantMap LayoutSaver::ScreenInfo::toVariantMap() const
|
|||||||
void LayoutSaver::ScreenInfo::fromVariantMap(const QVariantMap &map)
|
void LayoutSaver::ScreenInfo::fromVariantMap(const QVariantMap &map)
|
||||||
{
|
{
|
||||||
index = map.value(QStringLiteral("index")).toInt();
|
index = map.value(QStringLiteral("index")).toInt();
|
||||||
geometry = mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
geometry = Layouting::mapToRect(map.value(QStringLiteral("geometry")).toMap());
|
||||||
name = map.value(QStringLiteral("name")).toString();
|
name = map.value(QStringLiteral("name")).toString();
|
||||||
devicePixelRatio = map.value(QStringLiteral("devicePixelRatio")).toDouble();
|
devicePixelRatio = map.value(QStringLiteral("devicePixelRatio")).toDouble();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KD_LAYOUTSAVER_H
|
#ifndef KD_LAYOUTSAVER_H
|
||||||
@@ -54,14 +45,14 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief saves the layout to JSON file
|
* @brief saves the layout to JSON file
|
||||||
* @brief jsonFilename the filename where the layout will be saved to
|
* @param jsonFilename the filename where the layout will be saved to
|
||||||
* @return true on success
|
* @return true on success
|
||||||
*/
|
*/
|
||||||
bool saveToFile(const QString &jsonFilename);
|
bool saveToFile(const QString &jsonFilename);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief restores the layout from a JSON file
|
* @brief restores the layout from a JSON file
|
||||||
* @brief jsonFilename the filename containing a saved layout
|
* @param jsonFilename the filename containing a saved layout
|
||||||
* @return true on success
|
* @return true on success
|
||||||
*/
|
*/
|
||||||
bool restoreFromFile(const QString &jsonFilename);
|
bool restoreFromFile(const QString &jsonFilename);
|
||||||
@@ -87,7 +78,7 @@ public:
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief returns a list of dock widgets which were restored since the last
|
* @brief returns a list of dock widgets which were restored since the last
|
||||||
* @ref restoreLayout() or @ref restoreFromDisk()
|
* @ref restoreLayout() or @ref restoreFromFile()
|
||||||
*
|
*
|
||||||
* Useful since some dock widgets can be new, and hence not be included in the last saved layout.
|
* Useful since some dock widgets can be new, and hence not be included in the last saved layout.
|
||||||
*/
|
*/
|
||||||
@@ -106,16 +97,14 @@ public:
|
|||||||
struct MainWindow;
|
struct MainWindow;
|
||||||
struct FloatingWindow;
|
struct FloatingWindow;
|
||||||
struct DockWidget;
|
struct DockWidget;
|
||||||
struct LastPosition;
|
struct Position;
|
||||||
struct MultiSplitterLayout;
|
struct MultiSplitter;
|
||||||
struct Item;
|
|
||||||
struct Anchor;
|
|
||||||
struct Frame;
|
struct Frame;
|
||||||
struct Placeholder;
|
struct Placeholder;
|
||||||
struct ScalingInfo;
|
struct ScalingInfo;
|
||||||
struct ScreenInfo;
|
struct ScreenInfo;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Q_DISABLE_COPY(LayoutSaver)
|
||||||
friend class TestDocks;
|
friend class TestDocks;
|
||||||
|
|
||||||
class Private;
|
class Private;
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KD_LAYOUTSAVER_P_H
|
#ifndef KD_LAYOUTSAVER_P_H
|
||||||
@@ -25,7 +16,6 @@
|
|||||||
#include "KDDockWidgets.h"
|
#include "KDDockWidgets.h"
|
||||||
|
|
||||||
#include <QRect>
|
#include <QRect>
|
||||||
#include <QDataStream>
|
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QScreen>
|
#include <QScreen>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@@ -33,15 +23,15 @@
|
|||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
#define ANCHOR_MAGIC_MARKER "e520c60e-cf5d-4a30-b1a7-588d2c569851"
|
|
||||||
#define MULTISPLITTER_LAYOUT_MAGIC_MARKER "bac9948e-5f1b-4271-acc5-07f1708e2611"
|
#define MULTISPLITTER_LAYOUT_MAGIC_MARKER "bac9948e-5f1b-4271-acc5-07f1708e2611"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Bump whenever the format changes, so we can still load old layouts.
|
* Bump whenever the format changes, so we can still load old layouts.
|
||||||
* version 1: Initial version
|
* version 1: Initial version
|
||||||
* version 2: Introduced MainWindow::screenSize and FloatingWindow::screenSize
|
* version 2: Introduced MainWindow::screenSize and FloatingWindow::screenSize
|
||||||
|
* version 3: New layouting engine
|
||||||
*/
|
*/
|
||||||
#define KDDOCKWIDGETS_SERIALIZATION_VERSION 2
|
#define KDDOCKWIDGETS_SERIALIZATION_VERSION 3
|
||||||
|
|
||||||
|
|
||||||
namespace KDDockWidgets {
|
namespace KDDockWidgets {
|
||||||
@@ -108,14 +98,14 @@ struct LayoutSaver::ScalingInfo
|
|||||||
double widthFactor = -1;
|
double widthFactor = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LayoutSaver::LastPosition
|
struct LayoutSaver::Position
|
||||||
{
|
{
|
||||||
QRect lastFloatingGeometry;
|
QRect lastFloatingGeometry;
|
||||||
int tabIndex;
|
int tabIndex;
|
||||||
bool wasFloating;
|
bool wasFloating;
|
||||||
LayoutSaver::Placeholder::List placeholders;
|
LayoutSaver::Placeholder::List placeholders;
|
||||||
|
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
||||||
void scaleSizes(const ScalingInfo &scalingInfo);
|
void scaleSizes(const ScalingInfo &scalingInfo);
|
||||||
|
|
||||||
QVariantMap toVariantMap() const;
|
QVariantMap toVariantMap() const;
|
||||||
@@ -131,7 +121,7 @@ struct DOCKS_EXPORT LayoutSaver::DockWidget
|
|||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
||||||
void scaleSizes(const ScalingInfo &scalingInfo);
|
void scaleSizes(const ScalingInfo &scalingInfo);
|
||||||
|
|
||||||
static Ptr dockWidgetForName(const QString &name)
|
static Ptr dockWidgetForName(const QString &name)
|
||||||
@@ -151,8 +141,8 @@ struct DOCKS_EXPORT LayoutSaver::DockWidget
|
|||||||
void fromVariantMap(const QVariantMap &map);
|
void fromVariantMap(const QVariantMap &map);
|
||||||
|
|
||||||
QString uniqueName;
|
QString uniqueName;
|
||||||
QString affinityName;
|
QStringList affinities;
|
||||||
LayoutSaver::LastPosition lastPosition;
|
LayoutSaver::Position lastPosition;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
DockWidget() {}
|
DockWidget() {}
|
||||||
@@ -183,7 +173,7 @@ struct LayoutSaver::Frame
|
|||||||
{
|
{
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
||||||
void scaleSizes(const ScalingInfo &scalingInfo);
|
void scaleSizes(const ScalingInfo &scalingInfo);
|
||||||
|
|
||||||
QVariantMap toVariantMap() const;
|
QVariantMap toVariantMap() const;
|
||||||
@@ -194,69 +184,22 @@ struct LayoutSaver::Frame
|
|||||||
QRect geometry;
|
QRect geometry;
|
||||||
unsigned int options;
|
unsigned int options;
|
||||||
int currentTabIndex;
|
int currentTabIndex;
|
||||||
|
QString id; // for coorelation purposes
|
||||||
|
|
||||||
LayoutSaver::DockWidget::List dockWidgets;
|
LayoutSaver::DockWidget::List dockWidgets;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LayoutSaver::Item
|
struct LayoutSaver::MultiSplitter
|
||||||
{
|
|
||||||
typedef QVector<LayoutSaver::Item> List;
|
|
||||||
|
|
||||||
bool isValid(const MultiSplitterLayout &) const;
|
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
|
||||||
void scaleSizes(const ScalingInfo &scalingInfo);
|
|
||||||
|
|
||||||
QVariantMap toVariantMap() const;
|
|
||||||
void fromVariantMap(const QVariantMap &map);
|
|
||||||
|
|
||||||
QString objectName;
|
|
||||||
bool isPlaceholder;
|
|
||||||
QRect geometry;
|
|
||||||
QSize minSize;
|
|
||||||
int indexOfLeftAnchor;
|
|
||||||
int indexOfTopAnchor;
|
|
||||||
int indexOfRightAnchor;
|
|
||||||
int indexOfBottomAnchor;
|
|
||||||
LayoutSaver::Frame frame;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LayoutSaver::Anchor
|
|
||||||
{
|
|
||||||
typedef QVector<LayoutSaver::Anchor> List;
|
|
||||||
|
|
||||||
bool isValid(const LayoutSaver::MultiSplitterLayout &layout) const;
|
|
||||||
|
|
||||||
QVariantMap toVariantMap() const;
|
|
||||||
void fromVariantMap(const QVariantMap &map);
|
|
||||||
void scaleSizes(const ScalingInfo &);
|
|
||||||
|
|
||||||
bool isVertical() const;
|
|
||||||
|
|
||||||
QString objectName;
|
|
||||||
QRect geometry;
|
|
||||||
double positionPercentage;
|
|
||||||
int orientation;
|
|
||||||
int type;
|
|
||||||
int indexOfFrom;
|
|
||||||
int indexOfTo;
|
|
||||||
int indexOfFollowee;
|
|
||||||
QVector<int> side1Items;
|
|
||||||
QVector<int> side2Items;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LayoutSaver::MultiSplitterLayout
|
|
||||||
{
|
{
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
||||||
void scaleSizes(const ScalingInfo &scalingInfo);
|
void scaleSizes(const ScalingInfo &scalingInfo);
|
||||||
|
|
||||||
QVariantMap toVariantMap() const;
|
QVariantMap toVariantMap() const;
|
||||||
void fromVariantMap(const QVariantMap &map);
|
void fromVariantMap(const QVariantMap &map);
|
||||||
|
|
||||||
LayoutSaver::Anchor::List anchors;
|
QVariantMap layout;
|
||||||
LayoutSaver::Item::List items;
|
QHash<QString, LayoutSaver::Frame> frames;
|
||||||
QSize minSize;
|
|
||||||
QSize size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LayoutSaver::FloatingWindow
|
struct LayoutSaver::FloatingWindow
|
||||||
@@ -265,14 +208,14 @@ struct LayoutSaver::FloatingWindow
|
|||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
||||||
void scaleSizes(const ScalingInfo &);
|
void scaleSizes(const ScalingInfo &);
|
||||||
|
|
||||||
QVariantMap toVariantMap() const;
|
QVariantMap toVariantMap() const;
|
||||||
void fromVariantMap(const QVariantMap &map);
|
void fromVariantMap(const QVariantMap &map);
|
||||||
|
|
||||||
LayoutSaver::MultiSplitterLayout multiSplitterLayout;
|
LayoutSaver::MultiSplitter multiSplitterLayout;
|
||||||
QString affinityName;
|
QStringList affinities;
|
||||||
int parentIndex = -1;
|
int parentIndex = -1;
|
||||||
QRect geometry;
|
QRect geometry;
|
||||||
int screenIndex;
|
int screenIndex;
|
||||||
@@ -287,16 +230,16 @@ public:
|
|||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
||||||
void scaleSizes();
|
void scaleSizes();
|
||||||
|
|
||||||
QVariantMap toVariantMap() const;
|
QVariantMap toVariantMap() const;
|
||||||
void fromVariantMap(const QVariantMap &map);
|
void fromVariantMap(const QVariantMap &map);
|
||||||
|
|
||||||
KDDockWidgets::MainWindowOptions options;
|
KDDockWidgets::MainWindowOptions options;
|
||||||
LayoutSaver::MultiSplitterLayout multiSplitterLayout;
|
LayoutSaver::MultiSplitter multiSplitterLayout;
|
||||||
QString uniqueName;
|
QString uniqueName;
|
||||||
QString affinityName;
|
QStringList affinities;
|
||||||
QRect geometry;
|
QRect geometry;
|
||||||
int screenIndex;
|
int screenIndex;
|
||||||
QSize screenSize; // for relative-size restoring
|
QSize screenSize; // for relative-size restoring
|
||||||
@@ -344,266 +287,31 @@ public:
|
|||||||
|
|
||||||
bool isValid() const;
|
bool isValid() const;
|
||||||
|
|
||||||
bool fillFrom(const QByteArray &serialized);
|
|
||||||
QByteArray toJson() const;
|
QByteArray toJson() const;
|
||||||
bool fromJson(const QByteArray &jsonData);
|
bool fromJson(const QByteArray &jsonData);
|
||||||
QVariantMap toVariantMap() const;
|
QVariantMap toVariantMap() const;
|
||||||
void fromVariantMap(const QVariantMap &map);
|
void fromVariantMap(const QVariantMap &map);
|
||||||
|
|
||||||
/// Iterates throught the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
/// Iterates through the layout and patches all absolute sizes. See RestoreOption_RelativeToMainWindow.
|
||||||
void scaleSizes();
|
void scaleSizes();
|
||||||
|
|
||||||
friend QDataStream &operator>>(QDataStream &ds, LayoutSaver::Frame *frame);
|
|
||||||
static LayoutSaver::Layout* s_currentLayoutBeingRestored;
|
static LayoutSaver::Layout* s_currentLayoutBeingRestored;
|
||||||
|
|
||||||
LayoutSaver::MainWindow mainWindowForIndex(int index) const;
|
LayoutSaver::MainWindow mainWindowForIndex(int index) const;
|
||||||
|
|
||||||
|
QStringList mainWindowNames() const;
|
||||||
|
QStringList dockWidgetNames() const;
|
||||||
|
|
||||||
int serializationVersion = KDDOCKWIDGETS_SERIALIZATION_VERSION;
|
int serializationVersion = KDDOCKWIDGETS_SERIALIZATION_VERSION;
|
||||||
LayoutSaver::MainWindow::List mainWindows;
|
LayoutSaver::MainWindow::List mainWindows;
|
||||||
LayoutSaver::FloatingWindow::List floatingWindows;
|
LayoutSaver::FloatingWindow::List floatingWindows;
|
||||||
LayoutSaver::DockWidget::List closedDockWidgets;
|
LayoutSaver::DockWidget::List closedDockWidgets;
|
||||||
LayoutSaver::DockWidget::List allDockWidgets;
|
LayoutSaver::DockWidget::List allDockWidgets;
|
||||||
ScreenInfo::List screenInfo;
|
ScreenInfo::List screenInfo;
|
||||||
|
private:
|
||||||
|
Q_DISABLE_COPY(Layout)
|
||||||
};
|
};
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::ScreenInfo *info)
|
|
||||||
{
|
|
||||||
ds >> info->index;
|
|
||||||
ds >> info->geometry;
|
|
||||||
ds >> info->name;
|
|
||||||
ds >> info->devicePixelRatio;
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::Placeholder *p)
|
|
||||||
{
|
|
||||||
ds >> p->isFloatingWindow;
|
|
||||||
if (p->isFloatingWindow)
|
|
||||||
ds >> p->indexOfFloatingWindow;
|
|
||||||
else
|
|
||||||
ds >> p->mainWindowUniqueName;
|
|
||||||
|
|
||||||
ds >> p->itemIndex;
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::Anchor *a)
|
|
||||||
{
|
|
||||||
QString marker;
|
|
||||||
|
|
||||||
ds >> marker;
|
|
||||||
if (marker != QLatin1String(ANCHOR_MAGIC_MARKER))
|
|
||||||
qWarning() << Q_FUNC_INFO << "Corrupt stream";
|
|
||||||
|
|
||||||
ds >> a->objectName;
|
|
||||||
ds >> a->geometry;
|
|
||||||
ds >> a->orientation;
|
|
||||||
ds >> a->type;
|
|
||||||
ds >> a->indexOfFrom;
|
|
||||||
ds >> a->indexOfTo;
|
|
||||||
ds >> a->indexOfFollowee;
|
|
||||||
ds >> a->side1Items;
|
|
||||||
ds >> a->side2Items;
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::Frame *frame)
|
|
||||||
{
|
|
||||||
int numDockWidgets;
|
|
||||||
frame->dockWidgets.clear();
|
|
||||||
frame->isNull = false;
|
|
||||||
|
|
||||||
ds >> frame->objectName;
|
|
||||||
ds >> frame->geometry;
|
|
||||||
|
|
||||||
if (LayoutSaver::Layout::s_currentLayoutBeingRestored->serializationVersion >= 2) {
|
|
||||||
QSize sz;
|
|
||||||
ds >> sz; // deprecated field, just discard
|
|
||||||
}
|
|
||||||
|
|
||||||
ds >> frame->options;
|
|
||||||
ds >> frame->currentTabIndex;
|
|
||||||
ds >> numDockWidgets;
|
|
||||||
|
|
||||||
for (int i = 0; i < numDockWidgets; ++i) {
|
|
||||||
QString name;
|
|
||||||
ds >> name;
|
|
||||||
auto dw = LayoutSaver::DockWidget::dockWidgetForName(name);
|
|
||||||
frame->dockWidgets.push_back(dw);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::Item *item)
|
|
||||||
{
|
|
||||||
ds >> item->objectName;
|
|
||||||
ds >> item->isPlaceholder;
|
|
||||||
ds >> item->geometry;
|
|
||||||
ds >> item->minSize;
|
|
||||||
|
|
||||||
ds >> item->indexOfLeftAnchor;
|
|
||||||
ds >> item->indexOfTopAnchor;
|
|
||||||
ds >> item->indexOfRightAnchor;
|
|
||||||
ds >> item->indexOfBottomAnchor;
|
|
||||||
|
|
||||||
bool hasFrame;
|
|
||||||
ds >> hasFrame;
|
|
||||||
if (hasFrame) {
|
|
||||||
ds >> &item->frame;
|
|
||||||
item->frame.isNull = false;
|
|
||||||
} else {
|
|
||||||
item->frame.isNull = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::MultiSplitterLayout *l)
|
|
||||||
{
|
|
||||||
int numItems;
|
|
||||||
int numAnchors;
|
|
||||||
QString marker;
|
|
||||||
ds >> marker;
|
|
||||||
|
|
||||||
if (marker != QLatin1String(MULTISPLITTER_LAYOUT_MAGIC_MARKER))
|
|
||||||
qWarning() << Q_FUNC_INFO << "Corrupt stream, invalid magic";
|
|
||||||
|
|
||||||
ds >> l->size;
|
|
||||||
ds >> l->minSize;
|
|
||||||
ds >> numItems;
|
|
||||||
ds >> numAnchors;
|
|
||||||
|
|
||||||
l->items.clear();
|
|
||||||
l->anchors.clear();
|
|
||||||
|
|
||||||
for (int i = 0 ; i < numItems; ++i) {
|
|
||||||
LayoutSaver::Item item;
|
|
||||||
ds >> &item;
|
|
||||||
l->items.push_back(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0 ; i < numAnchors; ++i) {
|
|
||||||
LayoutSaver::Anchor a;
|
|
||||||
ds >> &a;
|
|
||||||
l->anchors.push_back(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::LastPosition *lp)
|
|
||||||
{
|
|
||||||
int numPlaceholders;
|
|
||||||
ds >> numPlaceholders;
|
|
||||||
|
|
||||||
lp->placeholders.clear();
|
|
||||||
for (int i = 0 ; i < numPlaceholders; ++i) {
|
|
||||||
LayoutSaver::Placeholder p;
|
|
||||||
ds >> &p;
|
|
||||||
lp->placeholders.push_back(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
ds >> lp->lastFloatingGeometry;
|
|
||||||
ds >> lp->tabIndex;
|
|
||||||
ds >> lp->wasFloating;
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::FloatingWindow *fw)
|
|
||||||
{
|
|
||||||
ds >> fw->parentIndex;
|
|
||||||
ds >> fw->geometry;
|
|
||||||
if (LayoutSaver::Layout::s_currentLayoutBeingRestored->serializationVersion >= 2) {
|
|
||||||
ds >> fw->screenIndex;
|
|
||||||
ds >> fw->screenSize;
|
|
||||||
}
|
|
||||||
|
|
||||||
ds >> fw->isVisible;
|
|
||||||
ds >> &fw->multiSplitterLayout;
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::MainWindow *m)
|
|
||||||
{
|
|
||||||
ds >> m->uniqueName;
|
|
||||||
ds >> m->geometry;
|
|
||||||
if (LayoutSaver::Layout::s_currentLayoutBeingRestored->serializationVersion >= 2) {
|
|
||||||
ds >> m->screenIndex;
|
|
||||||
ds >> m->screenSize;
|
|
||||||
}
|
|
||||||
ds >> m->isVisible;
|
|
||||||
ds >> m->options;
|
|
||||||
ds >> &m->multiSplitterLayout;
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline QDataStream &operator>>(QDataStream &ds, LayoutSaver::Layout *l)
|
|
||||||
{
|
|
||||||
LayoutSaver::DockWidget::s_dockWidgets.clear();
|
|
||||||
int numMainWindows;
|
|
||||||
int numFloatingWindows;
|
|
||||||
int numClosedDockWidgets;
|
|
||||||
int numAllDockWidgets;
|
|
||||||
int numScreenInfo;
|
|
||||||
|
|
||||||
ds >> l->serializationVersion;
|
|
||||||
|
|
||||||
ds >> numMainWindows;
|
|
||||||
l->mainWindows.clear();
|
|
||||||
for (int i = 0; i < numMainWindows; ++i) {
|
|
||||||
LayoutSaver::MainWindow m;
|
|
||||||
ds >> &m;
|
|
||||||
l->mainWindows.push_back(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
ds >> numFloatingWindows;
|
|
||||||
l->floatingWindows.clear();
|
|
||||||
for (int i = 0; i < numFloatingWindows; ++i) {
|
|
||||||
LayoutSaver::FloatingWindow m;
|
|
||||||
ds >> &m;
|
|
||||||
l->floatingWindows.push_back(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
ds >> numClosedDockWidgets;
|
|
||||||
l->closedDockWidgets.clear();
|
|
||||||
for (int i = 0; i < numClosedDockWidgets; ++i) {
|
|
||||||
QString name;
|
|
||||||
ds >> name;
|
|
||||||
auto dw = LayoutSaver::DockWidget::dockWidgetForName(name);
|
|
||||||
l->closedDockWidgets.push_back(dw);
|
|
||||||
}
|
|
||||||
|
|
||||||
ds >> numAllDockWidgets;
|
|
||||||
l->allDockWidgets.clear();
|
|
||||||
for (int i = 0; i < numAllDockWidgets; ++i) {
|
|
||||||
QString name;
|
|
||||||
ds >> name;
|
|
||||||
|
|
||||||
auto dw = LayoutSaver::DockWidget::dockWidgetForName(name);
|
|
||||||
ds >> &dw->lastPosition;
|
|
||||||
l->allDockWidgets.push_back(dw);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (LayoutSaver::Layout::s_currentLayoutBeingRestored->serializationVersion >= 2) {
|
|
||||||
ds >> numScreenInfo;
|
|
||||||
l->screenInfo.clear();
|
|
||||||
l->screenInfo.reserve(numScreenInfo);
|
|
||||||
for (int i = 0; i < numScreenInfo; ++i) {
|
|
||||||
LayoutSaver::ScreenInfo info;
|
|
||||||
ds >> &info;
|
|
||||||
l->screenInfo.push_back(info);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return ds;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -30,8 +21,6 @@
|
|||||||
#include "Frame_p.h"
|
#include "Frame_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "DropAreaWithCentralFrame_p.h"
|
#include "DropAreaWithCentralFrame_p.h"
|
||||||
#include "multisplitter/MultiSplitterLayout_p.h"
|
|
||||||
#include "multisplitter/MultiSplitter_p.h"
|
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
@@ -42,12 +31,9 @@ using namespace KDDockWidgets;
|
|||||||
class MainWindow::Private
|
class MainWindow::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Private(MainWindowOptions options, MainWindowBase *mainWindow)
|
explicit Private(MainWindowOptions, MainWindowBase *)
|
||||||
: m_dropArea(new DropAreaWithCentralFrame(mainWindow, options))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
DropAreaWithCentralFrame *const m_dropArea;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -94,7 +80,7 @@ MainWindow::~MainWindow()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
DropAreaWithCentralFrame *MainWindow::dropArea() const
|
void MainWindow::setCentralWidget(QWidget *w)
|
||||||
{
|
{
|
||||||
return d->m_dropArea;
|
QMainWindow::setCentralWidget(w);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,15 +40,14 @@ public:
|
|||||||
///@param parent QObject *parent to pass to QMainWindow constructor.
|
///@param parent QObject *parent to pass to QMainWindow constructor.
|
||||||
///@param flags Window flags to pass to QMainWindow constructor.
|
///@param flags Window flags to pass to QMainWindow constructor.
|
||||||
explicit MainWindow(const QString &uniqueName, MainWindowOptions options = MainWindowOption_None,
|
explicit MainWindow(const QString &uniqueName, MainWindowOptions options = MainWindowOption_None,
|
||||||
QWidget *parent = nullptr, Qt::WindowFlags flags = {});
|
QWidget *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||||
|
|
||||||
///@brief Destructor
|
///@brief Destructor
|
||||||
~MainWindow() override;
|
~MainWindow() override;
|
||||||
|
|
||||||
///@internal
|
|
||||||
DropAreaWithCentralFrame *dropArea() const override;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
using QMainWindow::setCentralWidget;
|
||||||
|
void setCentralWidget(QWidget *); // overridden just to make it private
|
||||||
class Private;
|
class Private;
|
||||||
Private *const d;
|
Private *const d;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -33,16 +24,16 @@
|
|||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "DropAreaWithCentralFrame_p.h"
|
#include "DropAreaWithCentralFrame_p.h"
|
||||||
#include "multisplitter/MultiSplitterLayout_p.h"
|
|
||||||
#include "multisplitter/MultiSplitter_p.h"
|
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
class MainWindowBase::Private
|
class MainWindowBase::Private
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit Private(MainWindowOptions options)
|
explicit Private(MainWindowBase *mainWindow, MainWindowOptions options)
|
||||||
: m_options(options)
|
: m_options(options)
|
||||||
|
, q(mainWindow)
|
||||||
|
, m_dropArea(new DropAreaWithCentralFrame(mainWindow, options))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,14 +43,16 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString name;
|
QString name;
|
||||||
QString affinityName;
|
QStringList affinities;
|
||||||
const MainWindowOptions m_options;
|
const MainWindowOptions m_options;
|
||||||
|
MainWindowBase *const q;
|
||||||
|
DropAreaWithCentralFrame *const m_dropArea;
|
||||||
};
|
};
|
||||||
|
|
||||||
MainWindowBase::MainWindowBase(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
MainWindowBase::MainWindowBase(const QString &uniqueName, KDDockWidgets::MainWindowOptions options,
|
||||||
QWidgetOrQuick *parent, Qt::WindowFlags flags)
|
QWidgetOrQuick *parent, Qt::WindowFlags flags)
|
||||||
: QMainWindowOrQuick(parent, flags)
|
: QMainWindowOrQuick(parent, flags)
|
||||||
, d(new Private(options))
|
, d(new Private(this, options))
|
||||||
{
|
{
|
||||||
setUniqueName(uniqueName);
|
setUniqueName(uniqueName);
|
||||||
}
|
}
|
||||||
@@ -75,9 +68,14 @@ void MainWindowBase::addDockWidgetAsTab(DockWidgetBase *widget)
|
|||||||
Q_ASSERT(widget);
|
Q_ASSERT(widget);
|
||||||
qCDebug(addwidget) << Q_FUNC_INFO << widget;
|
qCDebug(addwidget) << Q_FUNC_INFO << widget;
|
||||||
|
|
||||||
if (widget->affinityName() != affinityName()) {
|
if (!DockRegistry::self()->affinitiesMatch(d->affinities, widget->affinities())) {
|
||||||
qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
|
qWarning() << Q_FUNC_INFO << "Refusing to dock widget with incompatible affinity."
|
||||||
<< widget->affinityName() << affinityName();
|
<< widget->affinities() << affinities();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (widget->options() & DockWidgetBase::Option_NotDockable) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << widget;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -90,6 +88,11 @@ void MainWindowBase::addDockWidgetAsTab(DockWidgetBase *widget)
|
|||||||
|
|
||||||
void MainWindowBase::addDockWidget(DockWidgetBase *dw, Location location, DockWidgetBase *relativeTo, AddingOption option)
|
void MainWindowBase::addDockWidget(DockWidgetBase *dw, Location location, DockWidgetBase *relativeTo, AddingOption option)
|
||||||
{
|
{
|
||||||
|
if (dw->options() & DockWidgetBase::Option_NotDockable) {
|
||||||
|
qWarning() << Q_FUNC_INFO << "Refusing to dock non-dockable widget" << dw;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
dropArea()->addDockWidget(dw, location, relativeTo, option);
|
dropArea()->addDockWidget(dw, location, relativeTo, option);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,29 +106,47 @@ MainWindowOptions MainWindowBase::options() const
|
|||||||
return d->m_options;
|
return d->m_options;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiSplitterLayout *MainWindowBase::multiSplitterLayout() const
|
DropAreaWithCentralFrame *MainWindowBase::dropArea() const
|
||||||
{
|
{
|
||||||
return dropArea()->multiSplitterLayout();
|
return d->m_dropArea;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindowBase::setAffinityName(const QString &name)
|
MultiSplitter *MainWindowBase::multiSplitter() const
|
||||||
{
|
{
|
||||||
if (d->affinityName == name)
|
return dropArea();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::setAffinities(const QStringList &affinityNames)
|
||||||
|
{
|
||||||
|
QStringList affinities = affinityNames;
|
||||||
|
affinities.removeAll(QString());
|
||||||
|
|
||||||
|
if (d->affinities == affinities)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!d->affinityName.isEmpty()) {
|
if (!d->affinities.isEmpty()) {
|
||||||
qWarning() << Q_FUNC_INFO
|
qWarning() << Q_FUNC_INFO
|
||||||
<< "Affinity is already set, refusing to change."
|
<< "Affinity is already set, refusing to change."
|
||||||
<< "Submit a feature request with a good justification.";
|
<< "Submit a feature request with a good justification.";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
d->affinityName = name;
|
d->affinities = affinities;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MainWindowBase::affinityName() const
|
QStringList MainWindowBase::affinities() const
|
||||||
{
|
{
|
||||||
return d->affinityName;
|
return d->affinities;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::layoutEqually()
|
||||||
|
{
|
||||||
|
dropArea()->layoutEqually();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindowBase::layoutParentContainerEqually(DockWidgetBase *dockWidget)
|
||||||
|
{
|
||||||
|
dropArea()->layoutParentContainerEqually(dockWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindowBase::setUniqueName(const QString &uniqueName)
|
void MainWindowBase::setUniqueName(const QString &uniqueName)
|
||||||
@@ -150,14 +171,14 @@ bool MainWindowBase::deserialize(const LayoutSaver::MainWindow &mw)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->affinityName != mw.affinityName) {
|
if (d->affinities != mw.affinities) {
|
||||||
qWarning() << Q_FUNC_INFO << "Affinty name changed from" << d->affinityName
|
qWarning() << Q_FUNC_INFO << "Affinty name changed from" << d->affinities
|
||||||
<< "; to" << mw.affinityName;
|
<< "; to" << mw.affinities;
|
||||||
|
|
||||||
d->affinityName = mw.affinityName;
|
d->affinities = mw.affinities;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dropArea()->multiSplitterLayout()->deserialize(mw.multiSplitterLayout);
|
return dropArea()->deserialize(mw.multiSplitterLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
LayoutSaver::MainWindow MainWindowBase::serialize() const
|
LayoutSaver::MainWindow MainWindowBase::serialize() const
|
||||||
@@ -170,8 +191,8 @@ LayoutSaver::MainWindow MainWindowBase::serialize() const
|
|||||||
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()->multiSplitterLayout()->serialize();
|
m.multiSplitterLayout = dropArea()->serialize();
|
||||||
m.affinityName = d->affinityName;
|
m.affinities = d->affinities;
|
||||||
|
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -41,7 +32,7 @@ namespace KDDockWidgets {
|
|||||||
class DockWidgetBase;
|
class DockWidgetBase;
|
||||||
class Frame;
|
class Frame;
|
||||||
class DropArea;
|
class DropArea;
|
||||||
class MultiSplitterLayout;
|
class MultiSplitter;
|
||||||
class DropAreaWithCentralFrame;
|
class DropAreaWithCentralFrame;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -51,20 +42,24 @@ class DropAreaWithCentralFrame;
|
|||||||
*
|
*
|
||||||
* Do not use instantiate directly in user code. Use MainWindow instead.
|
* Do not use instantiate directly in user code. Use MainWindow instead.
|
||||||
*/
|
*/
|
||||||
|
#ifndef PYTHON_BINDINGS //Pyside bug: https://bugreports.qt.io/projects/PYSIDE/issues/PYSIDE-1327
|
||||||
class DOCKS_EXPORT MainWindowBase : public QMainWindowOrQuick
|
class DOCKS_EXPORT MainWindowBase : public QMainWindowOrQuick
|
||||||
|
#else
|
||||||
|
class DOCKS_EXPORT MainWindowBase : public QMainWindow
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
typedef QVector<MainWindowBase*> List;
|
typedef QVector<MainWindowBase*> List;
|
||||||
explicit MainWindowBase(const QString &uniqueName, MainWindowOptions options = MainWindowOption_HasCentralFrame,
|
explicit MainWindowBase(const QString &uniqueName, MainWindowOptions options = MainWindowOption_HasCentralFrame,
|
||||||
QWidgetOrQuick *parent = nullptr, Qt::WindowFlags flags = {});
|
QWidgetOrQuick *parent = nullptr, Qt::WindowFlags flags = Qt::WindowFlags());
|
||||||
|
|
||||||
~MainWindowBase() override;
|
~MainWindowBase() override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Docks a DockWidget into the central frame, tabbed.
|
* @brief Docks a DockWidget into the central frame, tabbed.
|
||||||
* @warning Requires that the MainWindow was constructed with MainWindowOption_HasCentralFrame option.
|
* @warning Requires that the MainWindow was constructed with MainWindowOption_HasCentralFrame option.
|
||||||
* @param The DockWidget to dock.
|
* @param dockwidget The dockwidget to dock.
|
||||||
*
|
*
|
||||||
* @sa DockWidgetBase::addDockWidgetAsTab()
|
* @sa DockWidgetBase::addDockWidgetAsTab()
|
||||||
*/
|
*/
|
||||||
@@ -79,7 +74,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
void addDockWidget(DockWidgetBase *dockWidget,
|
void addDockWidget(DockWidgetBase *dockWidget,
|
||||||
KDDockWidgets::Location location,
|
KDDockWidgets::Location location,
|
||||||
DockWidgetBase *relativeTo = nullptr, AddingOption option = {});
|
DockWidgetBase *relativeTo = nullptr, AddingOption option = KDDockWidgets::AddingOption());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the unique name that was passed via constructor.
|
* @brief Returns the unique name that was passed via constructor.
|
||||||
@@ -94,18 +89,18 @@ public:
|
|||||||
|
|
||||||
///@internal
|
///@internal
|
||||||
///@brief returns the drop area.
|
///@brief returns the drop area.
|
||||||
virtual DropAreaWithCentralFrame *dropArea() const = 0;
|
DropAreaWithCentralFrame *dropArea() const;
|
||||||
|
|
||||||
///@internal
|
///@internal
|
||||||
///@brief returns the MultiSplitterLayout.
|
///@brief returns the MultiSplitter.
|
||||||
MultiSplitterLayout* multiSplitterLayout() const;
|
MultiSplitter* multiSplitter() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sets the affinity name. Dock widgets can only dock into main windows of the same affinity.
|
* @brief Sets the affinities names. Dock widgets can only dock into main windows of the same affinity.
|
||||||
*
|
*
|
||||||
* By default the affinity is empty and a dock widget can dock into any main window. Usually you
|
* By default the affinity is empty and a dock widget can dock into any main window. Usually you
|
||||||
* won't ever need to call this function, unless you have requirements where certain dock widgets
|
* won't ever need to call this function, unless you have requirements where certain dock widgets
|
||||||
* can only dock into certain main windows. @sa DockWidgetBase::setAffinityName().
|
* can only dock into certain main windows. @sa DockWidgetBase::setAffinities().
|
||||||
*
|
*
|
||||||
* Note: Call this function right after creating your main window, before docking any dock widgets
|
* Note: Call this function right after creating your main window, before docking any dock widgets
|
||||||
* into a main window and before restoring any layout.
|
* into a main window and before restoring any layout.
|
||||||
@@ -114,14 +109,27 @@ public:
|
|||||||
* edge cases. This will only be changed if a good use case comes up that requires changing
|
* edge cases. This will only be changed if a good use case comes up that requires changing
|
||||||
* affinities multiple times.
|
* affinities multiple times.
|
||||||
*
|
*
|
||||||
* @p name The affinity name.
|
* @p name The affinity names.
|
||||||
*/
|
*/
|
||||||
void setAffinityName(const QString &name);
|
void setAffinities(const QStringList &names);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the affinity name. Empty by default.
|
* @brief Returns the list of affinity names. Empty by default.
|
||||||
*/
|
*/
|
||||||
QString affinityName() const;
|
QStringList affinities() const;
|
||||||
|
|
||||||
|
/// @brief layouts all the widgets so they have an equal size within their parent container
|
||||||
|
///
|
||||||
|
/// Note that the layout is a tree of nested horizontal and vertical container layouts. The
|
||||||
|
/// nodes closer to the root will have more space.
|
||||||
|
///
|
||||||
|
/// min/max constraints will still be honoured.
|
||||||
|
void layoutEqually();
|
||||||
|
|
||||||
|
/// @brief like layoutEqually() but starts with the container that has @p dockWidget.
|
||||||
|
/// While layoutEqually() starts from the root of the layout tree this function starts on a
|
||||||
|
/// sub-tree.
|
||||||
|
void layoutParentContainerEqually(DockWidgetBase *dockWidget);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setUniqueName(const QString &uniqueName);
|
void setUniqueName(const QString &uniqueName);
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KDDOCKWIDGETS_QWIDGETADAPTER_H
|
#ifndef KDDOCKWIDGETS_QWIDGETADAPTER_H
|
||||||
@@ -25,6 +16,8 @@
|
|||||||
# define KDDOCKWIDGETS_QTWIDGETS
|
# define KDDOCKWIDGETS_QTWIDGETS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <QWindow>
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file
|
* @file
|
||||||
* @brief Abstraction for supporting both QtWidgets and QtQuick.
|
* @brief Abstraction for supporting both QtWidgets and QtQuick.
|
||||||
@@ -32,15 +25,61 @@
|
|||||||
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
* @author Sérgio Martins \<sergio.martins@kdab.com\>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
namespace KDDockWidgets {
|
||||||
# include "private/widgets/QWidgetAdapter_widgets_p.h"
|
namespace Private {
|
||||||
#include <QMainWindow>
|
|
||||||
typedef QWidget QWidgetOrQuick;
|
inline bool isMinimized(QWindow *window)
|
||||||
typedef QMainWindow QMainWindowOrQuick;
|
{
|
||||||
|
// QWindow::windowStates() was introduced in 5.10
|
||||||
|
#if QT_VERSION < 0x051000
|
||||||
|
return window && window->windowState() == Qt::WindowMinimized;
|
||||||
#else
|
#else
|
||||||
# include "quick/QWidgetAdapter_quick_p.h"
|
return window && window->windowStates() & Qt::WindowMinimized;
|
||||||
typedef KDDockWidgets::QWidgetAdapter QWidgetOrQuick;
|
#endif
|
||||||
typedef QWidgetOrQuick QMainWindowOrQuick;
|
}
|
||||||
|
|
||||||
|
}}
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
# include "private/multisplitter/Widget_qwidget.h"
|
||||||
|
# include "private/widgets/QWidgetAdapter_widgets_p.h"
|
||||||
|
# include <QMainWindow>
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
class MainWindow;
|
||||||
|
class DockWidget;
|
||||||
|
typedef QWidget QWidgetOrQuick;
|
||||||
|
typedef QMainWindow QMainWindowOrQuick;
|
||||||
|
typedef Layouting::Widget_qwidget LayoutGuestWidgetBase;
|
||||||
|
typedef KDDockWidgets::MainWindow MainWindowType;
|
||||||
|
typedef KDDockWidgets::DockWidget DockWidgetType;
|
||||||
|
typedef QWidget WidgetType;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
# include "private/multisplitter/Widget_quick.h"
|
||||||
|
# include "private/quick/QWidgetAdapter_quick_p.h"
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
class MainWindowQuick;
|
||||||
|
class DockWidgetQuick;
|
||||||
|
typedef KDDockWidgets::QWidgetAdapter QWidgetOrQuick;
|
||||||
|
typedef QWidgetOrQuick QMainWindowOrQuick;
|
||||||
|
typedef Layouting::Widget_quick LayoutGuestWidgetBase;
|
||||||
|
typedef KDDockWidgets::MainWindowQuick MainWindowType;
|
||||||
|
typedef KDDockWidgets::DockWidgetQuick DockWidgetType;
|
||||||
|
typedef QQuickItem WidgetType;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
class LayoutGuestWidget : public KDDockWidgets::QWidgetAdapter
|
||||||
|
, public LayoutGuestWidgetBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit LayoutGuestWidget(QWidgetOrQuick *parent)
|
||||||
|
: QWidgetAdapter(parent)
|
||||||
|
, LayoutGuestWidgetBase(this)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
40
src/Qt5Qt6Compat_p.h
Normal file
40
src/Qt5Qt6Compat_p.h
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef KDDOCKWIDGETS_QT5QT6_COMPAT_P_H
|
||||||
|
#define KDDOCKWIDGETS_QT5QT6_COMPAT_P_H
|
||||||
|
|
||||||
|
#include <QMouseEvent>
|
||||||
|
|
||||||
|
namespace KDDockWidgets {
|
||||||
|
namespace Qt5Qt6Compat {
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
|
||||||
|
inline QPoint eventGlobalPos(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
return ev->globalPosition().toPoint();
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
// Qt 5:
|
||||||
|
inline QPoint eventGlobalPos(QMouseEvent *ev)
|
||||||
|
{
|
||||||
|
return ev->globalPos();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KD_DOCKS_EXPORT_H
|
#ifndef KD_DOCKS_EXPORT_H
|
||||||
@@ -23,20 +14,25 @@
|
|||||||
|
|
||||||
#include <QtCore/QtGlobal>
|
#include <QtCore/QtGlobal>
|
||||||
|
|
||||||
#if defined(BUILDING_DOCKS_LIBRARY)
|
#if defined(KDDOCKWIDGETS_STATICLIB)
|
||||||
|
# define DOCKS_EXPORT
|
||||||
|
# define DOCKS_EXPORT_FOR_UNIT_TESTS
|
||||||
|
#else
|
||||||
|
# if defined(BUILDING_DOCKS_LIBRARY)
|
||||||
# define DOCKS_EXPORT Q_DECL_EXPORT
|
# define DOCKS_EXPORT Q_DECL_EXPORT
|
||||||
# if defined(DOCKS_DEVELOPER_MODE)
|
# if defined(DOCKS_DEVELOPER_MODE)
|
||||||
# define DOCKS_EXPORT_FOR_UNIT_TESTS Q_DECL_EXPORT
|
# define DOCKS_EXPORT_FOR_UNIT_TESTS Q_DECL_EXPORT
|
||||||
# else
|
# else
|
||||||
# define DOCKS_EXPORT_FOR_UNIT_TESTS
|
# define DOCKS_EXPORT_FOR_UNIT_TESTS
|
||||||
# endif
|
# endif
|
||||||
#else
|
# else
|
||||||
# define DOCKS_EXPORT Q_DECL_IMPORT
|
# define DOCKS_EXPORT Q_DECL_IMPORT
|
||||||
# if defined(DOCKS_DEVELOPER_MODE)
|
# if defined(DOCKS_DEVELOPER_MODE)
|
||||||
# define DOCKS_EXPORT_FOR_UNIT_TESTS Q_DECL_IMPORT
|
# define DOCKS_EXPORT_FOR_UNIT_TESTS Q_DECL_IMPORT
|
||||||
# else
|
# else
|
||||||
# define DOCKS_EXPORT_FOR_UNIT_TESTS Q_DECL_IMPORT
|
# define DOCKS_EXPORT_FOR_UNIT_TESTS Q_DECL_IMPORT
|
||||||
# endif
|
# endif
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
12
src/fwd_headers/kddockwidgets/Config.h
Normal file
12
src/fwd_headers/kddockwidgets/Config.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../Config.h"
|
||||||
12
src/fwd_headers/kddockwidgets/DockWidget.h
Normal file
12
src/fwd_headers/kddockwidgets/DockWidget.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../DockWidget.h"
|
||||||
12
src/fwd_headers/kddockwidgets/FrameworkWidgetFactory.h
Normal file
12
src/fwd_headers/kddockwidgets/FrameworkWidgetFactory.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../FrameworkWidgetFactory.h"
|
||||||
12
src/fwd_headers/kddockwidgets/LayoutSaver.h
Normal file
12
src/fwd_headers/kddockwidgets/LayoutSaver.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../LayoutSaver.h"
|
||||||
12
src/fwd_headers/kddockwidgets/MainWindow.h
Normal file
12
src/fwd_headers/kddockwidgets/MainWindow.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../MainWindow.h"
|
||||||
12
src/fwd_headers/kddockwidgets/private/FloatingWindow_p.h
Normal file
12
src/fwd_headers/kddockwidgets/private/FloatingWindow_p.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../private/FloatingWindow_p.h"
|
||||||
12
src/fwd_headers/kddockwidgets/private/TitleBar_p.h
Normal file
12
src/fwd_headers/kddockwidgets/private/TitleBar_p.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../private/TitleBar_p.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/multisplitter/Separator_qwidget.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/multisplitter/Widget_qwidget.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/widgets/FloatingWindowWidget_p.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/widgets/FrameWidget_p.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/widgets/TabBarWidget_p.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/widgets/TabWidgetWidget_p.h"
|
||||||
12
src/fwd_headers/kddockwidgets/private/widgets/TabWidget_p.h
Normal file
12
src/fwd_headers/kddockwidgets/private/widgets/TabWidget_p.h
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/widgets/TabWidget_p.h"
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sergio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../../../../private/widgets/TitleBarWidget_p.h"
|
||||||
55
src/layoutlinter_main.cpp
Normal file
55
src/layoutlinter_main.cpp
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
|
SPDX-FileCopyrightText: 2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
|
|
||||||
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTQUICK
|
||||||
|
# include "private/quick/DockWidgetQuick.h"
|
||||||
|
# include "private/quick/MainWindowQuick_p.h"
|
||||||
|
#else
|
||||||
|
# include "DockWidget.h"
|
||||||
|
# include "MainWindow.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
static bool lint(const QString &filename)
|
||||||
|
{
|
||||||
|
DockWidgetFactoryFunc dwFunc = [] (const QString &dwName) {
|
||||||
|
return static_cast<DockWidgetBase*>(new DockWidgetType(dwName));
|
||||||
|
};
|
||||||
|
|
||||||
|
MainWindowFactoryFunc mwFunc = [] (const QString &dwName) {
|
||||||
|
return static_cast<MainWindowBase*>(new MainWindowType(dwName));
|
||||||
|
};
|
||||||
|
|
||||||
|
KDDockWidgets::Config::self().setDockWidgetFactoryFunc(dwFunc);
|
||||||
|
KDDockWidgets::Config::self().setMainWindowFactoryFunc(mwFunc);
|
||||||
|
|
||||||
|
LayoutSaver restorer;
|
||||||
|
return restorer.restoreFromFile(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
|
||||||
|
if (app.arguments().size() != 2) {
|
||||||
|
qDebug() << "Usage: kddockwidgets_linter <layout json file>";
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return lint(app.arguments().at(1)) ? 0 : 2;
|
||||||
|
}
|
||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,6 +23,7 @@
|
|||||||
#include "DropArea_p.h"
|
#include "DropArea_p.h"
|
||||||
#include "MainWindow.h"
|
#include "MainWindow.h"
|
||||||
#include "LayoutSaver.h"
|
#include "LayoutSaver.h"
|
||||||
|
#include "Qt5Qt6Compat_p.h"
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
#include <QVBoxLayout>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
@@ -61,7 +53,11 @@ class DebugAppEventFilter : public QAbstractNativeEventFilter
|
|||||||
public:
|
public:
|
||||||
DebugAppEventFilter() {}
|
DebugAppEventFilter() {}
|
||||||
~DebugAppEventFilter();
|
~DebugAppEventFilter();
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
bool nativeEventFilter(const QByteArray &eventType, void *message, qintptr *) override
|
||||||
|
#else
|
||||||
bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
|
bool nativeEventFilter(const QByteArray &eventType, void *message, long *) override
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
if (eventType != "windows_generic_MSG")
|
if (eventType != "windows_generic_MSG")
|
||||||
@@ -90,7 +86,7 @@ DebugWindow::DebugWindow(QWidget *parent)
|
|||||||
layout->addWidget(&m_objectViewer);
|
layout->addWidget(&m_objectViewer);
|
||||||
|
|
||||||
auto button = new QPushButton(this);
|
auto button = new QPushButton(this);
|
||||||
button->setText(QStringLiteral("Dump DockWidget Info"));
|
button->setText(QStringLiteral("Dump Debug"));
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
connect(button, &QPushButton::clicked, this, &DebugWindow::dumpDockWidgetInfo);
|
connect(button, &QPushButton::clicked, this, &DebugWindow::dumpDockWidgetInfo);
|
||||||
|
|
||||||
@@ -146,6 +142,18 @@ DebugWindow::DebugWindow(QWidget *parent)
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
button = new QPushButton(this);
|
||||||
|
button->setText(QStringLiteral("Show All DockWidgets"));
|
||||||
|
layout->addWidget(button);
|
||||||
|
connect(button, &QPushButton::clicked, this, [this] {
|
||||||
|
QTimer::singleShot(3000, this, [] {
|
||||||
|
const auto docks = DockRegistry::self()->dockwidgets();
|
||||||
|
for (auto dw : docks) {
|
||||||
|
dw->show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
button = new QPushButton(this);
|
button = new QPushButton(this);
|
||||||
button->setText(QStringLiteral("Save layout"));
|
button->setText(QStringLiteral("Save layout"));
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
@@ -183,28 +191,18 @@ DebugWindow::DebugWindow(QWidget *parent)
|
|||||||
qApp->restoreOverrideCursor();
|
qApp->restoreOverrideCursor();
|
||||||
});
|
});
|
||||||
|
|
||||||
button = new QPushButton(this);
|
|
||||||
button->setText(QStringLiteral("dump main windows"));
|
|
||||||
layout->addWidget(button);
|
|
||||||
connect(button, &QPushButton::clicked, this, [] {
|
|
||||||
const auto mainWindows = DockRegistry::self()->mainwindows();
|
|
||||||
for (MainWindowBase *mainWindow : mainWindows) {
|
|
||||||
mainWindow->multiSplitterLayout()->dumpDebug();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
button = new QPushButton(this);
|
button = new QPushButton(this);
|
||||||
button->setText(QStringLiteral("check sanity"));
|
button->setText(QStringLiteral("check sanity"));
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
connect(button, &QPushButton::clicked, this, [] {
|
connect(button, &QPushButton::clicked, this, [] {
|
||||||
const auto mainWindows = DockRegistry::self()->mainwindows();
|
const auto mainWindows = DockRegistry::self()->mainwindows();
|
||||||
for (MainWindowBase *mainWindow : mainWindows) {
|
for (MainWindowBase *mainWindow : mainWindows) {
|
||||||
mainWindow->multiSplitterLayout()->checkSanity();
|
mainWindow->multiSplitter()->checkSanity();
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto floatingWindows = DockRegistry::self()->nestedwindows();
|
const auto floatingWindows = DockRegistry::self()->nestedwindows();
|
||||||
for (FloatingWindow *floatingWindow : floatingWindows) {
|
for (FloatingWindow *floatingWindow : floatingWindows) {
|
||||||
floatingWindow->multiSplitterLayout()->checkSanity();
|
floatingWindow->multiSplitter()->checkSanity();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -231,53 +229,17 @@ DebugWindow::DebugWindow(QWidget *parent)
|
|||||||
repaintWidgetRecursive(w);
|
repaintWidgetRecursive(w);
|
||||||
});
|
});
|
||||||
|
|
||||||
button = new QPushButton(this);
|
|
||||||
button->setText(QStringLiteral("EnsureAnchorsBounded"));
|
|
||||||
layout->addWidget(button);
|
|
||||||
connect(button, &QPushButton::clicked, this, [] {
|
|
||||||
const auto layouts = DockRegistry::self()->layouts();
|
|
||||||
for (auto l : layouts)
|
|
||||||
l->ensureAnchorsBounded();
|
|
||||||
});
|
|
||||||
|
|
||||||
button = new QPushButton(this);
|
|
||||||
button->setText(QStringLiteral("RedistributeSpace"));
|
|
||||||
layout->addWidget(button);
|
|
||||||
connect(button, &QPushButton::clicked, this, [] {
|
|
||||||
const auto layouts = DockRegistry::self()->layouts();
|
|
||||||
for (auto l : layouts)
|
|
||||||
l->redistributeSpace();
|
|
||||||
});
|
|
||||||
|
|
||||||
button = new QPushButton(this);
|
button = new QPushButton(this);
|
||||||
button->setText(QStringLiteral("resize by 1x1"));
|
button->setText(QStringLiteral("resize by 1x1"));
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
connect(button, &QPushButton::clicked, this, [] {
|
connect(button, &QPushButton::clicked, this, [] {
|
||||||
const auto layouts = DockRegistry::self()->layouts();
|
const auto layouts = DockRegistry::self()->layouts();
|
||||||
for (auto l : layouts) {
|
for (auto l : layouts) {
|
||||||
QWidget *tlw = l->multiSplitter()->window();
|
QWidget *tlw = l->window();
|
||||||
tlw->resize(tlw->size() + QSize(1, 1));
|
tlw->resize(tlw->size() + QSize(1, 1));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
button = new QPushButton(this);
|
|
||||||
button->setText(QStringLiteral("PositionStaticAnchors()"));
|
|
||||||
layout->addWidget(button);
|
|
||||||
connect(button, &QPushButton::clicked, this, [] {
|
|
||||||
const auto layouts = DockRegistry::self()->layouts();
|
|
||||||
for (auto l : layouts)
|
|
||||||
l->positionStaticAnchors();
|
|
||||||
});
|
|
||||||
|
|
||||||
button = new QPushButton(this);
|
|
||||||
button->setText(QStringLiteral("UpdateAnchorFollowing"));
|
|
||||||
layout->addWidget(button);
|
|
||||||
connect(button, &QPushButton::clicked, this, [] {
|
|
||||||
const auto layouts = DockRegistry::self()->layouts();
|
|
||||||
for (auto l : layouts)
|
|
||||||
l->updateAnchorFollowing();
|
|
||||||
});
|
|
||||||
|
|
||||||
button = new QPushButton(this);
|
button = new QPushButton(this);
|
||||||
button->setText(QStringLiteral("Raise #0 (after 3s timeout)"));
|
button->setText(QStringLiteral("Raise #0 (after 3s timeout)"));
|
||||||
layout->addWidget(button);
|
layout->addWidget(button);
|
||||||
@@ -289,33 +251,6 @@ DebugWindow::DebugWindow(QWidget *parent)
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
button = new QPushButton(this);
|
|
||||||
button->setText(QStringLiteral("Convert old layout to JSON"));
|
|
||||||
layout->addWidget(button);
|
|
||||||
connect(button, &QPushButton::clicked, this, [this] {
|
|
||||||
const QString filename = QFileDialog::getOpenFileName(this);
|
|
||||||
if (filename.isEmpty())
|
|
||||||
return;
|
|
||||||
|
|
||||||
QFile f(filename);
|
|
||||||
if (!f.open(QIODevice::ReadOnly)) {
|
|
||||||
qWarning() << "Failed to open file" << filename;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const QByteArray oldData = f.readAll();
|
|
||||||
LayoutSaver::Layout savedLayout;
|
|
||||||
savedLayout.fillFrom(oldData);
|
|
||||||
const QByteArray jsonData = savedLayout.toJson();
|
|
||||||
QFile f2(QStringLiteral("%1.json").arg(filename));
|
|
||||||
if (!f2.open(QIODevice::WriteOnly)) {
|
|
||||||
qWarning() << "Failed to open file for writing" << filename;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
f2.write(jsonData);
|
|
||||||
});
|
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
button = new QPushButton(this);
|
button = new QPushButton(this);
|
||||||
button->setText(QStringLiteral("Dump native windows"));
|
button->setText(QStringLiteral("Dump native windows"));
|
||||||
@@ -329,7 +264,7 @@ DebugWindow::DebugWindow(QWidget *parent)
|
|||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
void DebugWindow::dumpWindow(QWidget *w)
|
void DebugWindow::dumpWindow(QWidget *w)
|
||||||
{
|
{
|
||||||
if (QWindow *window = w->windowHandle()) {
|
if (w->windowHandle()) {
|
||||||
HWND hwnd = HWND(w->winId());
|
HWND hwnd = HWND(w->winId());
|
||||||
|
|
||||||
RECT clientRect;
|
RECT clientRect;
|
||||||
@@ -373,15 +308,23 @@ void DebugWindow::repaintWidgetRecursive(QWidget *w)
|
|||||||
|
|
||||||
void DebugWindow::dumpDockWidgetInfo()
|
void DebugWindow::dumpDockWidgetInfo()
|
||||||
{
|
{
|
||||||
QVector<FloatingWindow*> floatingWindows = DockRegistry::self()->nestedwindows();
|
const QVector<FloatingWindow*> floatingWindows = DockRegistry::self()->nestedwindows();
|
||||||
MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
const MainWindowBase::List mainWindows = DockRegistry::self()->mainwindows();
|
||||||
|
const DockWidgetBase::List dockWidgets = DockRegistry::self()->dockwidgets();
|
||||||
|
|
||||||
for (FloatingWindow *fw : floatingWindows) {
|
for (FloatingWindow *fw : floatingWindows) {
|
||||||
fw->dropArea()->multiSplitterLayout()->dumpDebug();
|
qDebug() << fw << "; affinities=" << fw->affinities();
|
||||||
|
fw->dropArea()->dumpLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MainWindowBase *mw : mainWindows)
|
for (MainWindowBase *mw : mainWindows) {
|
||||||
mw->multiSplitterLayout()->dumpDebug();
|
qDebug() << mw << "; affinities=" << mw->affinities();
|
||||||
|
mw->multiSplitter()->dumpLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (DockWidgetBase *dw : dockWidgets) {
|
||||||
|
qDebug() << dw << "; affinities=";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugWindow::mousePressEvent(QMouseEvent *event)
|
void DebugWindow::mousePressEvent(QMouseEvent *event)
|
||||||
@@ -389,8 +332,8 @@ void DebugWindow::mousePressEvent(QMouseEvent *event)
|
|||||||
if (!m_isPickingWidget)
|
if (!m_isPickingWidget)
|
||||||
QWidget::mousePressEvent(event);
|
QWidget::mousePressEvent(event);
|
||||||
|
|
||||||
QWidget *w = qApp->widgetAt(event->globalPos());
|
QWidget *w = qApp->widgetAt(Qt5Qt6Compat::eventGlobalPos(event));
|
||||||
qDebug() << "Widget at pos" << event->globalPos() << "is"
|
qDebug() << "Widget at pos" << Qt5Qt6Compat::eventGlobalPos(event) << "is"
|
||||||
<< w << "; parent="
|
<< w << "; parent="
|
||||||
<< (w ? w->parentWidget() : nullptr) << "; geometry="
|
<< (w ? w->parentWidget() : nullptr) << "; geometry="
|
||||||
<< (w ? w->geometry() : QRect());
|
<< (w ? w->geometry() : QRect());
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,38 +1,40 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
#include "DockWidgetBase.h"
|
#include "DockWidgetBase.h"
|
||||||
#include "Logging_p.h"
|
#include "Logging_p.h"
|
||||||
#include "DebugWindow_p.h"
|
#include "Position_p.h"
|
||||||
#include "LastPosition_p.h"
|
#include "MultiSplitter_p.h"
|
||||||
#include "multisplitter/MultiSplitterLayout_p.h"
|
|
||||||
#include "quick/QmlTypes.h"
|
|
||||||
|
|
||||||
#include <QPointer>
|
#include <QPointer>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QWindow>
|
#include <QWindow>
|
||||||
|
|
||||||
|
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
||||||
|
# include "DebugWindow_p.h"
|
||||||
|
#else
|
||||||
|
# include "quick/QmlTypes.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
using namespace KDDockWidgets;
|
using namespace KDDockWidgets;
|
||||||
|
|
||||||
|
static void initKDDockWidgetResources()
|
||||||
|
{
|
||||||
|
#ifdef KDDOCKWIDGETS_STATICLIB
|
||||||
|
Q_INIT_RESOURCE(resources);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
DockRegistry::DockRegistry(QObject *parent)
|
DockRegistry::DockRegistry(QObject *parent)
|
||||||
: QObject(parent)
|
: QObject(parent)
|
||||||
{
|
{
|
||||||
@@ -49,6 +51,8 @@ DockRegistry::DockRegistry(QObject *parent)
|
|||||||
#else
|
#else
|
||||||
KDDockWidgets::registerQmlTypes();
|
KDDockWidgets::registerQmlTypes();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
initKDDockWidgetResources();
|
||||||
}
|
}
|
||||||
|
|
||||||
DockRegistry::~DockRegistry()
|
DockRegistry::~DockRegistry()
|
||||||
@@ -66,10 +70,13 @@ bool DockRegistry::isEmpty() const
|
|||||||
return m_dockWidgets.isEmpty() && m_mainWindows.isEmpty() && m_nestedWindows.isEmpty();
|
return m_dockWidgets.isEmpty() && m_mainWindows.isEmpty() && m_nestedWindows.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::checkSanityAll()
|
void DockRegistry::checkSanityAll(bool dumpLayout)
|
||||||
{
|
{
|
||||||
for (auto layout :m_layouts)
|
for (auto layout : qAsConst(m_layouts)) {
|
||||||
layout->checkSanity();
|
layout->checkSanity();
|
||||||
|
if (dumpLayout)
|
||||||
|
layout->dumpLayout();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DockRegistry::isProcessingAppQuitEvent() const
|
bool DockRegistry::isProcessingAppQuitEvent() const
|
||||||
@@ -77,6 +84,73 @@ bool DockRegistry::isProcessingAppQuitEvent() const
|
|||||||
return m_isProcessingAppQuitEvent;
|
return m_isProcessingAppQuitEvent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool DockRegistry::affinitiesMatch(const QStringList &affinities1, const QStringList &affinities2) const
|
||||||
|
{
|
||||||
|
if (affinities1.isEmpty() && affinities2.isEmpty())
|
||||||
|
return true;
|
||||||
|
|
||||||
|
for (const QString &a1 : affinities1) {
|
||||||
|
for (const QString &a2 : affinities2) {
|
||||||
|
if (a1 == a2)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList DockRegistry::mainWindowsNames() const
|
||||||
|
{
|
||||||
|
QStringList names;
|
||||||
|
names.reserve(m_mainWindows.size());
|
||||||
|
for (auto mw : m_mainWindows)
|
||||||
|
names.push_back(mw->uniqueName());
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList DockRegistry::dockWidgetNames() const
|
||||||
|
{
|
||||||
|
QStringList names;
|
||||||
|
names.reserve(m_dockWidgets.size());
|
||||||
|
for (auto dw : m_dockWidgets)
|
||||||
|
names.push_back(dw->uniqueName());
|
||||||
|
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
MainWindowBase::List DockRegistry::mainWindowsWithAffinity(const QStringList &affinities) const
|
||||||
|
{
|
||||||
|
MainWindowBase::List result;
|
||||||
|
|
||||||
|
for (auto mw : m_mainWindows) {
|
||||||
|
const QStringList mwAffinities = mw->affinities();
|
||||||
|
if (affinitiesMatch(mwAffinities, affinities))
|
||||||
|
result << mw;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
MultiSplitter *DockRegistry::layoutForItem(const Layouting::Item *item) const
|
||||||
|
{
|
||||||
|
if (!item->hostWidget())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
if (auto ms = qobject_cast<MultiSplitter*>(item->hostWidget()->asQWidget()))
|
||||||
|
return ms;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DockRegistry::itemIsInMainWindow(const Layouting::Item *item) const
|
||||||
|
{
|
||||||
|
if (auto layout = layoutForItem(item))
|
||||||
|
return layout->isInMainWindow();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
DockRegistry *DockRegistry::self()
|
DockRegistry *DockRegistry::self()
|
||||||
{
|
{
|
||||||
static QPointer<DockRegistry> s_dockRegistry;
|
static QPointer<DockRegistry> s_dockRegistry;
|
||||||
@@ -133,12 +207,12 @@ void DockRegistry::unregisterNestedWindow(FloatingWindow *window)
|
|||||||
maybeDelete();
|
maybeDelete();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::registerLayout(MultiSplitterLayout *layout)
|
void DockRegistry::registerLayout(MultiSplitter *layout)
|
||||||
{
|
{
|
||||||
m_layouts << layout;
|
m_layouts << layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::unregisterLayout(MultiSplitterLayout *layout)
|
void DockRegistry::unregisterLayout(MultiSplitter *layout)
|
||||||
{
|
{
|
||||||
m_layouts.removeOne(layout);
|
m_layouts.removeOne(layout);
|
||||||
}
|
}
|
||||||
@@ -173,7 +247,7 @@ MainWindowBase *DockRegistry::mainWindowByName(const QString &name) const
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DockWidgetBase *DockRegistry::dockWidgetForGuest(QWidget *guest) const
|
DockWidgetBase *DockRegistry::dockWidgetForGuest(QWidgetOrQuick *guest) const
|
||||||
{
|
{
|
||||||
if (!guest)
|
if (!guest)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -214,6 +288,9 @@ bool DockRegistry::isSane() const
|
|||||||
} else {
|
} else {
|
||||||
names.insert(name);
|
names.insert(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!mainwindow->multiSplitter()->checkSanity())
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@@ -224,6 +301,32 @@ const DockWidgetBase::List DockRegistry::dockwidgets() const
|
|||||||
return m_dockWidgets;
|
return m_dockWidgets;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DockWidgetBase::List DockRegistry::dockWidgets(const QStringList &names)
|
||||||
|
{
|
||||||
|
DockWidgetBase::List result;
|
||||||
|
result.reserve(names.size());
|
||||||
|
|
||||||
|
for (auto dw : qAsConst(m_dockWidgets)) {
|
||||||
|
if (names.contains(dw->uniqueName()))
|
||||||
|
result.push_back(dw);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
const MainWindowBase::List DockRegistry::mainWindows(const QStringList &names)
|
||||||
|
{
|
||||||
|
MainWindowBase::List result;
|
||||||
|
result.reserve(names.size());
|
||||||
|
|
||||||
|
for (auto mw : qAsConst(m_mainWindows)) {
|
||||||
|
if (names.contains(mw->uniqueName()))
|
||||||
|
result.push_back(mw);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
const DockWidgetBase::List DockRegistry::closedDockwidgets() const
|
const DockWidgetBase::List DockRegistry::closedDockwidgets() const
|
||||||
{
|
{
|
||||||
DockWidgetBase::List result;
|
DockWidgetBase::List result;
|
||||||
@@ -242,7 +345,7 @@ const MainWindowBase::List DockRegistry::mainwindows() const
|
|||||||
return m_mainWindows;
|
return m_mainWindows;
|
||||||
}
|
}
|
||||||
|
|
||||||
const QVector<MultiSplitterLayout *> DockRegistry::layouts() const
|
const QVector<MultiSplitter *> DockRegistry::layouts() const
|
||||||
{
|
{
|
||||||
return m_layouts;
|
return m_layouts;
|
||||||
}
|
}
|
||||||
@@ -265,6 +368,24 @@ const QVector<FloatingWindow *> DockRegistry::nestedwindows() const
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QVector<QWindow *> DockRegistry::floatingWindows() const
|
||||||
|
{
|
||||||
|
QVector<QWindow *> windows;
|
||||||
|
windows.reserve(m_nestedWindows.size());
|
||||||
|
for (FloatingWindow *fw : m_nestedWindows) {
|
||||||
|
if (!fw->beingDeleted()) {
|
||||||
|
if (QWindow *window = fw->windowHandle()) {
|
||||||
|
window->setProperty("kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick*>(fw)); // Since QWidgetWindow is private API
|
||||||
|
windows.push_back(window);
|
||||||
|
} else {
|
||||||
|
qWarning() << Q_FUNC_INFO << "FloatingWindow doesn't have QWindow";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return windows;
|
||||||
|
}
|
||||||
|
|
||||||
FloatingWindow *DockRegistry::floatingWindowForHandle(QWindow *windowHandle) const
|
FloatingWindow *DockRegistry::floatingWindowForHandle(QWindow *windowHandle) const
|
||||||
{
|
{
|
||||||
for (FloatingWindow *fw : m_nestedWindows) {
|
for (FloatingWindow *fw : m_nestedWindows) {
|
||||||
@@ -275,61 +396,58 @@ FloatingWindow *DockRegistry::floatingWindowForHandle(QWindow *windowHandle) con
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QWidget *> DockRegistry::topLevels(bool excludeFloatingDocks) const
|
QVector<QWindow *> DockRegistry::topLevels(bool excludeFloatingDocks) const
|
||||||
{
|
{
|
||||||
QVector<QWidget *> windows;
|
QVector<QWindow *> windows;
|
||||||
windows.reserve(m_nestedWindows.size() + m_mainWindows.size());
|
windows.reserve(m_nestedWindows.size() + m_mainWindows.size());
|
||||||
|
|
||||||
if (!excludeFloatingDocks) {
|
if (!excludeFloatingDocks) {
|
||||||
for (FloatingWindow *fw : m_nestedWindows) {
|
for (FloatingWindow *fw : m_nestedWindows) {
|
||||||
if (fw->isVisible())
|
if (fw->isVisible()) {
|
||||||
windows << fw;
|
if (QWindow *window = fw->windowHandle()) {
|
||||||
|
window->setProperty("kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick*>(fw)); // Since QWidgetWindow is private API
|
||||||
|
windows << window;
|
||||||
|
} else {
|
||||||
|
qWarning() << Q_FUNC_INFO << "FloatingWindow doesn't have QWindow";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MainWindowBase *m : m_mainWindows) {
|
for (MainWindowBase *m : m_mainWindows) {
|
||||||
if (m->isVisible())
|
if (m->isVisible()) {
|
||||||
windows << m->topLevelWidget();
|
if (QWindow *window = m->window()->windowHandle()) {
|
||||||
|
window->setProperty("kddockwidgets_qwidget", QVariant::fromValue<QWidgetOrQuick*>(m));
|
||||||
|
windows << window;
|
||||||
|
} else {
|
||||||
|
qWarning() << Q_FUNC_INFO << "MainWindow doesn't have QWindow";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return windows;
|
return windows;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::clear(bool deleteStaticAnchors)
|
void DockRegistry::clear(const QStringList &affinities)
|
||||||
{
|
{
|
||||||
for (auto dw : qAsConst(m_dockWidgets)) {
|
// Clears everything
|
||||||
dw->forceClose();
|
clear(m_dockWidgets, m_mainWindows, affinities);
|
||||||
dw->lastPosition()->removePlaceholders();
|
|
||||||
}
|
|
||||||
|
|
||||||
for (auto mw : qAsConst(m_mainWindows))
|
|
||||||
mw->multiSplitterLayout()->clear(deleteStaticAnchors);
|
|
||||||
|
|
||||||
qCDebug(restoring) << Q_FUNC_INFO << "; dockwidgets=" << m_dockWidgets.size()
|
|
||||||
<< "; nestedwindows=" << m_nestedWindows.size();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DockRegistry::clear(QStringList affinities, bool deleteStaticAnchors)
|
void DockRegistry::clear(const DockWidgetBase::List &dockWidgets,
|
||||||
|
const MainWindowBase::List &mainWindows,
|
||||||
|
const QStringList &affinities)
|
||||||
{
|
{
|
||||||
if (affinities.isEmpty()) {
|
for (auto dw : qAsConst(dockWidgets)) {
|
||||||
// Just clear everything
|
if (affinities.isEmpty() || affinitiesMatch(affinities, dw->affinities())) {
|
||||||
clear(deleteStaticAnchors);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// empty affinity also matches and will be closed
|
|
||||||
affinities << QString();
|
|
||||||
|
|
||||||
for (auto dw : qAsConst(m_dockWidgets)) {
|
|
||||||
if (affinities.contains(dw->affinityName())) {
|
|
||||||
dw->forceClose();
|
dw->forceClose();
|
||||||
dw->lastPosition()->removePlaceholders();
|
dw->lastPositions().removePlaceholders();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto mw : qAsConst(m_mainWindows)) {
|
for (auto mw : qAsConst(mainWindows)) {
|
||||||
if (affinities.contains(mw->affinityName())) {
|
if (affinities.isEmpty() || affinitiesMatch(affinities, mw->affinities())) {
|
||||||
mw->multiSplitterLayout()->clear(deleteStaticAnchors);
|
mw->multiSplitter()->rootItem()->clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef KD_DOCKREGISTRY_P_H
|
#ifndef KD_DOCKREGISTRY_P_H
|
||||||
@@ -51,8 +42,8 @@ public:
|
|||||||
void registerNestedWindow(FloatingWindow *);
|
void registerNestedWindow(FloatingWindow *);
|
||||||
void unregisterNestedWindow(FloatingWindow *);
|
void unregisterNestedWindow(FloatingWindow *);
|
||||||
|
|
||||||
void registerLayout(MultiSplitterLayout *);
|
void registerLayout(MultiSplitter *);
|
||||||
void unregisterLayout(MultiSplitterLayout *);
|
void unregisterLayout(MultiSplitter *);
|
||||||
|
|
||||||
void registerFrame(Frame *);
|
void registerFrame(Frame *);
|
||||||
void unregisterFrame(Frame *);
|
void unregisterFrame(Frame *);
|
||||||
@@ -61,21 +52,27 @@ public:
|
|||||||
MainWindowBase *mainWindowByName(const QString &) const;
|
MainWindowBase *mainWindowByName(const QString &) const;
|
||||||
|
|
||||||
/// @brief returns the dock widget that hosts @p guest widget. Nullptr if there's none.
|
/// @brief returns the dock widget that hosts @p guest widget. Nullptr if there's none.
|
||||||
DockWidgetBase *dockWidgetForGuest(QWidget *guest) const;
|
DockWidgetBase *dockWidgetForGuest(QWidgetOrQuick *guest) const;
|
||||||
|
|
||||||
bool isSane() const;
|
bool isSane() const;
|
||||||
|
|
||||||
///@brief returns all DockWidget instances
|
///@brief returns all DockWidget instances
|
||||||
const DockWidgetBase::List dockwidgets() const;
|
const DockWidgetBase::List dockwidgets() const;
|
||||||
|
|
||||||
|
///@brief overload returning only the ones with the specified names
|
||||||
|
const DockWidgetBase::List dockWidgets(const QStringList &names);
|
||||||
|
|
||||||
///@brief returns all closed DockWidget instances
|
///@brief returns all closed DockWidget instances
|
||||||
const DockWidgetBase::List closedDockwidgets() const;
|
const DockWidgetBase::List closedDockwidgets() const;
|
||||||
|
|
||||||
///@brief returns all MainWindow instances
|
///@brief returns all MainWindow instances
|
||||||
const MainWindowBase::List mainwindows() const;
|
const MainWindowBase::List mainwindows() const;
|
||||||
|
|
||||||
///@brief returns the list of MultiSplitterLayout instances
|
///@brief overload returning only the ones with the specified names
|
||||||
const QVector<MultiSplitterLayout*> layouts() const;
|
const MainWindowBase::List mainWindows(const QStringList &names);
|
||||||
|
|
||||||
|
///@brief returns the list of MultiSplitter instances
|
||||||
|
const QVector<MultiSplitter*> layouts() const;
|
||||||
|
|
||||||
///@brief returns a list of all Frame instances
|
///@brief returns a list of all Frame instances
|
||||||
const Frame::List frames() const;
|
const Frame::List frames() const;
|
||||||
@@ -84,6 +81,9 @@ public:
|
|||||||
/// As there might be DockWidgets which weren't morphed yet.
|
/// As there might be DockWidgets which weren't morphed yet.
|
||||||
const QVector<FloatingWindow*> nestedwindows() const;
|
const QVector<FloatingWindow*> nestedwindows() const;
|
||||||
|
|
||||||
|
///@brief overload that returns list of QWindow. This is more friendly for supporting both QtWidgets and QtQuick
|
||||||
|
const QVector<QWindow*> floatingWindows() const;
|
||||||
|
|
||||||
///@brief returns the FloatingWindow with handle @p windowHandle
|
///@brief returns the FloatingWindow with handle @p windowHandle
|
||||||
FloatingWindow *floatingWindowForHandle(QWindow *windowHandle) const;
|
FloatingWindow *floatingWindowForHandle(QWindow *windowHandle) const;
|
||||||
|
|
||||||
@@ -96,18 +96,21 @@ public:
|
|||||||
/// Every returned widget is either a FloatingWindow, MainWindow, or something that contains a MainWindow.
|
/// Every returned widget is either a FloatingWindow, MainWindow, or something that contains a MainWindow.
|
||||||
///
|
///
|
||||||
/// If @p excludeFloatingDocks is true then FloatingWindow won't be returned
|
/// If @p excludeFloatingDocks is true then FloatingWindow won't be returned
|
||||||
QVector<QWidget*> topLevels(bool excludeFloatingDocks = false) const;
|
QVector<QWindow*> topLevels(bool excludeFloatingDocks = false) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes all dock widgets, destroys all FloatingWindow, Item and Anchors.
|
* @brief Closes all dock widgets, and destroys all FloatingWindows
|
||||||
* This is called before restoring a layout.
|
* This is called before restoring a layout.
|
||||||
|
* @param affinities if specified only closes dock widgets and main windows with the specified affinities
|
||||||
*/
|
*/
|
||||||
void clear(bool deleteStaticAnchors = false);
|
void clear(const QStringList &affinities = {});
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Closes all dock widgets, destroys all FloatingWindow, Item and Anchors with the specified affinities.
|
* @brief clear Overload that only clears the specified dockWidgets and main windows.
|
||||||
*/
|
*/
|
||||||
void clear(QStringList affinities, bool deleteStaticAnchors = false);
|
void clear(const DockWidgetBase::List &dockWidgets,
|
||||||
|
const MainWindowBase::List &mainWindows,
|
||||||
|
const QStringList &affinities);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Ensures that all floating DockWidgets have a FloatingWindow as a window.
|
* @brief Ensures that all floating DockWidgets have a FloatingWindow as a window.
|
||||||
@@ -123,12 +126,14 @@ public:
|
|||||||
bool isEmpty() const;
|
bool isEmpty() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Calls MultisplitterLayout::checkSanity() on all layouts.
|
* @brief Calls MultiSplitter::checkSanity() on all layouts.
|
||||||
|
*
|
||||||
|
* @param dumpDebug If true then each layout is dumped too
|
||||||
*
|
*
|
||||||
* This is called by the unit-tests or the fuzzer. If during this the framework spits a qWarning()
|
* This is called by the unit-tests or the fuzzer. If during this the framework spits a qWarning()
|
||||||
* then the app will qFatal()
|
* then the app will qFatal()
|
||||||
*/
|
*/
|
||||||
void checkSanityAll();
|
void checkSanityAll(bool dumpDebug = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns whether we're processing a QEvent::Quit
|
* @brief Returns whether we're processing a QEvent::Quit
|
||||||
@@ -137,6 +142,26 @@ public:
|
|||||||
*/
|
*/
|
||||||
bool isProcessingAppQuitEvent() const;
|
bool isProcessingAppQuitEvent() const;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns all main windows which match at least one of the @p affinities
|
||||||
|
*/
|
||||||
|
MainWindowBase::List mainWindowsWithAffinity(const QStringList &affinities) const;
|
||||||
|
|
||||||
|
// TODO: docs
|
||||||
|
MultiSplitter* layoutForItem(const Layouting::Item *) const;
|
||||||
|
|
||||||
|
// TODO: docs
|
||||||
|
bool itemIsInMainWindow(const Layouting::Item *) const;
|
||||||
|
|
||||||
|
|
||||||
|
bool affinitiesMatch(const QStringList &affinities1, const QStringList &affinities2) const;
|
||||||
|
|
||||||
|
/// @brief Returns a list of all known main window unique names
|
||||||
|
QStringList mainWindowsNames() const;
|
||||||
|
|
||||||
|
/// @brief Returns a list of all known dock widget unique names
|
||||||
|
QStringList dockWidgetNames() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool eventFilter(QObject *watched, QEvent *event) override;
|
bool eventFilter(QObject *watched, QEvent *event) override;
|
||||||
private:
|
private:
|
||||||
@@ -147,7 +172,7 @@ private:
|
|||||||
MainWindowBase::List m_mainWindows;
|
MainWindowBase::List m_mainWindows;
|
||||||
Frame::List m_frames;
|
Frame::List m_frames;
|
||||||
QVector<FloatingWindow*> m_nestedWindows;
|
QVector<FloatingWindow*> m_nestedWindows;
|
||||||
QVector<MultiSplitterLayout*> m_layouts;
|
QVector<MultiSplitter*> m_layouts;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,21 +1,12 @@
|
|||||||
/*
|
/*
|
||||||
This file is part of KDDockWidgets.
|
This file is part of KDDockWidgets.
|
||||||
|
|
||||||
Copyright (C) 2018-2020 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
|
SPDX-FileCopyrightText: 2019-2020 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
|
||||||
Author: Sérgio Martins <sergio.martins@kdab.com>
|
Author: Sérgio Martins <sergio.martins@kdab.com>
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only
|
||||||
it under the terms of the GNU General Public License as published by
|
|
||||||
the Free Software Foundation, either version 2 of the License, or
|
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
Contact KDAB at <info@kdab.com> for commercial licensing options.
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "DragController_p.h"
|
#include "DragController_p.h"
|
||||||
@@ -26,6 +17,7 @@
|
|||||||
#include "WidgetResizeHandler_p.h"
|
#include "WidgetResizeHandler_p.h"
|
||||||
#include "Utils_p.h"
|
#include "Utils_p.h"
|
||||||
#include "DockRegistry_p.h"
|
#include "DockRegistry_p.h"
|
||||||
|
#include "Qt5Qt6Compat_p.h"
|
||||||
|
|
||||||
#include <QMouseEvent>
|
#include <QMouseEvent>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
@@ -175,9 +167,25 @@ StateDragging::~StateDragging() = default;
|
|||||||
|
|
||||||
void StateDragging::onEntry(QEvent *)
|
void StateDragging::onEntry(QEvent *)
|
||||||
{
|
{
|
||||||
|
if (DockWidgetBase *dw = q->m_draggable->singleDockWidget()) {
|
||||||
|
// When we start to drag a floating window which has a single dock widget, we save the position
|
||||||
|
if (dw->isFloating())
|
||||||
|
dw->saveLastFloatingGeometry();
|
||||||
|
}
|
||||||
|
|
||||||
q->m_windowBeingDragged = q->m_draggable->makeWindow();
|
q->m_windowBeingDragged = q->m_draggable->makeWindow();
|
||||||
if (q->m_windowBeingDragged) {
|
if (q->m_windowBeingDragged) {
|
||||||
qCDebug(state) << "StateDragging entered. m_draggable=" << q->m_draggable << "; m_windowBeingDragged=" << q->m_windowBeingDragged->floatingWindow();
|
qCDebug(state) << "StateDragging entered. m_draggable=" << q->m_draggable << "; m_windowBeingDragged=" << q->m_windowBeingDragged->floatingWindow();
|
||||||
|
|
||||||
|
auto fw = q->m_windowBeingDragged->floatingWindow();
|
||||||
|
if (!fw->geometry().contains(q->m_pressPos)) {
|
||||||
|
// The window shrunk when the drag started, this can happen if it has max-size constraints
|
||||||
|
// we make the floating window smaller. Has the downside that it might not be under the mouse
|
||||||
|
// cursor anymore, so make the change
|
||||||
|
if (fw->width() < q->m_offset.x()) { // make sure it shrunk
|
||||||
|
q->m_offset.setX(fw->width() / 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Shouldn't happen
|
// Shouldn't happen
|
||||||
qWarning() << Q_FUNC_INFO << "No window being dragged for " << q->m_draggable->asWidget();
|
qWarning() << Q_FUNC_INFO << "No window being dragged for " << q->m_draggable->asWidget();
|
||||||
@@ -197,6 +205,12 @@ bool StateDragging::handleMouseButtonRelease(QPoint globalPos)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (floatingWindow->anyNonDockable()) {
|
||||||
|
qCDebug(state) << "StateDragging: Ignoring floating window with non dockable widgets";
|
||||||
|
Q_EMIT q->dragCanceled();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (q->m_currentDropArea) {
|
if (q->m_currentDropArea) {
|
||||||
if (q->m_currentDropArea->drop(floatingWindow, globalPos)) {
|
if (q->m_currentDropArea->drop(floatingWindow, globalPos)) {
|
||||||
Q_EMIT q->dropped();
|
Q_EMIT q->dropped();
|
||||||
@@ -213,21 +227,41 @@ bool StateDragging::handleMouseButtonRelease(QPoint globalPos)
|
|||||||
|
|
||||||
bool StateDragging::handleMouseMove(QPoint globalPos)
|
bool StateDragging::handleMouseMove(QPoint globalPos)
|
||||||
{
|
{
|
||||||
if (!q->m_windowBeingDragged->floatingWindow()) {
|
FloatingWindow *fw = q->m_windowBeingDragged->floatingWindow();
|
||||||
|
if (!fw) {
|
||||||
qCDebug(state) << "Canceling drag, window was deleted";
|
qCDebug(state) << "Canceling drag, window was deleted";
|
||||||
Q_EMIT q->dragCanceled();
|
Q_EMIT q->dragCanceled();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fw->beingDeleted()) {
|
||||||
|
// Ignore, we're in the middle of recurrency. We're inside StateDragging::handleMouseButtonRelease too
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (!q->m_nonClientDrag)
|
if (!q->m_nonClientDrag)
|
||||||
q->m_windowBeingDragged->floatingWindow()->windowHandle()->setPosition(globalPos - q->m_offset);
|
fw->windowHandle()->setPosition(globalPos - q->m_offset);
|
||||||
|
|
||||||
|
|
||||||
|
if (fw->anyNonDockable()) {
|
||||||
|
qCDebug(state) << "StateDragging: Ignoring non dockable floating window";
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
DropArea *dropArea = q->dropAreaUnderCursor();
|
DropArea *dropArea = q->dropAreaUnderCursor();
|
||||||
if (q->m_currentDropArea && dropArea != q->m_currentDropArea)
|
if (q->m_currentDropArea && dropArea != q->m_currentDropArea)
|
||||||
q->m_currentDropArea->removeHover();
|
q->m_currentDropArea->removeHover();
|
||||||
|
|
||||||
if (dropArea)
|
if (dropArea) {
|
||||||
dropArea->hover(q->m_windowBeingDragged->floatingWindow(), globalPos);
|
if (FloatingWindow *targetFw = dropArea->floatingWindow()) {
|
||||||
|
if (targetFw->anyNonDockable()) {
|
||||||
|
qCDebug(state) << "StateDragging: Ignoring non dockable target floating window";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dropArea->hover(fw, globalPos);
|
||||||
|
}
|
||||||
|
|
||||||
q->m_currentDropArea = dropArea;
|
q->m_currentDropArea = dropArea;
|
||||||
|
|
||||||
@@ -236,11 +270,6 @@ bool StateDragging::handleMouseMove(QPoint globalPos)
|
|||||||
|
|
||||||
DragController::DragController(QObject *)
|
DragController::DragController(QObject *)
|
||||||
{
|
{
|
||||||
if (KDDockWidgets::usesNativeDraggingAndResizing()) { // probably also good for wayland, which doesn't support mouse grabbing
|
|
||||||
// Aero-snap jams if we're grabbing the mouse, so use the fallback grabber
|
|
||||||
m_fallbackMouseGrabber = new FallbackMouseGrabber(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(creation) << "DragController()";
|
qCDebug(creation) << "DragController()";
|
||||||
|
|
||||||
auto stateNone = new StateNone(this);
|
auto stateNone = new StateNone(this);
|
||||||
@@ -338,7 +367,7 @@ bool DragController::eventFilter(QObject *o, QEvent *e)
|
|||||||
if (!me)
|
if (!me)
|
||||||
return QStateMachine::eventFilter(o, e);
|
return QStateMachine::eventFilter(o, e);
|
||||||
|
|
||||||
auto w = qobject_cast<QWidget*>(o);
|
auto w = qobject_cast<QWidgetOrQuick*>(o);
|
||||||
if (!w)
|
if (!w)
|
||||||
return QStateMachine::eventFilter(o, e);
|
return QStateMachine::eventFilter(o, e);
|
||||||
|
|
||||||
@@ -347,9 +376,9 @@ bool DragController::eventFilter(QObject *o, QEvent *e)
|
|||||||
switch (e->type()) {
|
switch (e->type()) {
|
||||||
case QEvent::NonClientAreaMouseButtonPress: {
|
case QEvent::NonClientAreaMouseButtonPress: {
|
||||||
if (auto fw = qobject_cast<FloatingWindow*>(o)) {
|
if (auto fw = qobject_cast<FloatingWindow*>(o)) {
|
||||||
if (fw->isInTitleBar(me->globalPos())) { // TODO: Port to isPositionDraggable()
|
if (fw->isInDragArea(Qt5Qt6Compat::eventGlobalPos(me))) {
|
||||||
m_nonClientDrag = true;
|
m_nonClientDrag = true;
|
||||||
return activeState()->handleMouseButtonPress(draggableForQObject(o), me->globalPos(), me->pos());
|
return activeState()->handleMouseButtonPress(draggableForQObject(o), Qt5Qt6Compat::eventGlobalPos(me), me->pos());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return QStateMachine::eventFilter(o, e);
|
return QStateMachine::eventFilter(o, e);
|
||||||
@@ -358,14 +387,14 @@ bool DragController::eventFilter(QObject *o, QEvent *e)
|
|||||||
// For top-level windows that support native dragging all goes through the NonClient* events.
|
// For top-level windows that support native dragging all goes through the NonClient* events.
|
||||||
// This also forbids dragging a FloatingWindow simply by pressing outside of the title area, in the background
|
// This also forbids dragging a FloatingWindow simply by pressing outside of the title area, in the background
|
||||||
if (!KDDockWidgets::usesNativeDraggingAndResizing() || !w->isWindow())
|
if (!KDDockWidgets::usesNativeDraggingAndResizing() || !w->isWindow())
|
||||||
return activeState()->handleMouseButtonPress(draggableForQObject(o), me->globalPos(), me->pos());
|
return activeState()->handleMouseButtonPress(draggableForQObject(o), Qt5Qt6Compat::eventGlobalPos(me), me->pos());
|
||||||
else break;
|
else break;
|
||||||
case QEvent::MouseButtonRelease:
|
case QEvent::MouseButtonRelease:
|
||||||
case QEvent::NonClientAreaMouseButtonRelease:
|
case QEvent::NonClientAreaMouseButtonRelease:
|
||||||
return activeState()->handleMouseButtonRelease(me->globalPos());
|
return activeState()->handleMouseButtonRelease(Qt5Qt6Compat::eventGlobalPos(me));
|
||||||
case QEvent::NonClientAreaMouseMove:
|
case QEvent::NonClientAreaMouseMove:
|
||||||
case QEvent::MouseMove:
|
case QEvent::MouseMove:
|
||||||
return activeState()->handleMouseMove(me->globalPos());
|
return activeState()->handleMouseMove(Qt5Qt6Compat::eventGlobalPos(me));
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -395,13 +424,17 @@ static QWidget *qtTopLevelForHWND(HWND hwnd)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
template <typename T>
|
template <typename T>
|
||||||
static QWidget* qtTopLevelUnderCursor_impl(QPoint globalPos, const QVector<T> &topLevels, T windowBeingDragged)
|
static WidgetType* qtTopLevelUnderCursor_impl(QPoint globalPos, const QVector<QWindow*> &windows, T windowBeingDragged)
|
||||||
{
|
{
|
||||||
for (int i = topLevels.size() -1; i >= 0; --i) {
|
for (int i = windows.size() -1; i >= 0; --i) {
|
||||||
auto tl = topLevels.at(i);
|
auto tl = KDDockWidgets::Private::widgetForWindow(windows.at(i));
|
||||||
if (!tl->isVisible() || tl == windowBeingDragged || tl->isMinimized())
|
if (!tl->isVisible() || tl == windowBeingDragged || KDDockWidgets::Private::isMinimized(tl))
|
||||||
continue;
|
continue;
|
||||||
if (tl->geometry().contains(globalPos)) {
|
|
||||||
|
if (windowBeingDragged && KDDockWidgets::Private::windowForWidget(windowBeingDragged) == KDDockWidgets::Private::windowForWidget(tl))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (KDDockWidgets::Private::geometry(tl).contains(globalPos)) {
|
||||||
qCDebug(toplevels) << Q_FUNC_INFO << "Found top-level" << tl;
|
qCDebug(toplevels) << Q_FUNC_INFO << "Found top-level" << tl;
|
||||||
return tl;
|
return tl;
|
||||||
}
|
}
|
||||||
@@ -410,15 +443,13 @@ static QWidget* qtTopLevelUnderCursor_impl(QPoint globalPos, const QVector<T> &t
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
QWidgetOrQuick *DragController::qtTopLevelUnderCursor() const
|
WidgetType *DragController::qtTopLevelUnderCursor() const
|
||||||
{
|
{
|
||||||
#ifdef KDDOCKWIDGETS_QTWIDGETS
|
|
||||||
|
|
||||||
QPoint globalPos = QCursor::pos();
|
QPoint globalPos = QCursor::pos();
|
||||||
auto topLevels = qApp->topLevelWidgets();
|
|
||||||
|
|
||||||
if (qApp->platformName() == QLatin1String("windows")) { // So -platform offscreen on Windows doesn't use this
|
if (qApp->platformName() == QLatin1String("windows")) { // So -platform offscreen on Windows doesn't use this
|
||||||
# if defined(Q_OS_WIN)
|
# if defined(Q_OS_WIN)
|
||||||
|
auto topLevels = qApp->topLevelWidgets();
|
||||||
POINT globalNativePos;
|
POINT globalNativePos;
|
||||||
if (!GetCursorPos(&globalNativePos))
|
if (!GetCursorPos(&globalNativePos))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -466,33 +497,45 @@ QWidgetOrQuick *DragController::qtTopLevelUnderCursor() const
|
|||||||
// and check the MainWindow last, as the MainWindow will have lower z-order as it's a parent (TODO: How will it work with multiple MainWindows ?)
|
// and check the MainWindow last, as the MainWindow will have lower z-order as it's a parent (TODO: How will it work with multiple MainWindows ?)
|
||||||
// The floating window list is sorted by z-order, as we catch QEvent::Expose and move it to last of the list
|
// The floating window list is sorted by z-order, as we catch QEvent::Expose and move it to last of the list
|
||||||
|
|
||||||
if (auto tl = qtTopLevelUnderCursor_impl(globalPos, DockRegistry::self()->nestedwindows(), m_windowBeingDragged->floatingWindow()))
|
FloatingWindow *tlwBeingDragged = m_windowBeingDragged->floatingWindow();
|
||||||
|
if (auto tl = qtTopLevelUnderCursor_impl(globalPos, DockRegistry::self()->floatingWindows(), tlwBeingDragged))
|
||||||
return tl;
|
return tl;
|
||||||
|
|
||||||
return qtTopLevelUnderCursor_impl(globalPos, DockRegistry::self()->topLevels(/*excludeFloating=*/true), static_cast<QWidget*>(nullptr));
|
return qtTopLevelUnderCursor_impl<WidgetType*>(globalPos,
|
||||||
|
DockRegistry::self()->topLevels(/*excludeFloating=*/true),
|
||||||
|
tlwBeingDragged);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
// QtQuick:
|
|
||||||
qWarning() << Q_FUNC_INFO << "Implement me!";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
qCDebug(toplevels) << Q_FUNC_INFO << "No top-level found";
|
qCDebug(toplevels) << Q_FUNC_INFO << "No top-level found";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
DropArea *DragController::dropAreaUnderCursor() const
|
static DropArea* deepestDropAreaInTopLevel(WidgetType *topLevel, QPoint globalPos,
|
||||||
|
const QStringList &affinities)
|
||||||
{
|
{
|
||||||
auto topLevel = qtTopLevelUnderCursor();
|
const auto localPos = topLevel->mapFromGlobal(globalPos);
|
||||||
if (!topLevel) {
|
auto w = topLevel->childAt(localPos.x(), localPos.y());
|
||||||
//qCDebug(state) << "DragController::dropAreaUnderCursor: null";
|
while (w) {
|
||||||
return nullptr;
|
if (auto dt = qobject_cast<DropArea *>(w)) {
|
||||||
}
|
if (DockRegistry::self()->affinitiesMatch(dt->affinities(), affinities))
|
||||||
|
|
||||||
if (auto dt = qobject_cast<DropArea *>(topLevel)) {
|
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
|
w = KDDockWidgets::Private::parentWidget(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
DropArea *DragController::dropAreaUnderCursor() const
|
||||||
|
{
|
||||||
|
WidgetType *topLevel = qtTopLevelUnderCursor();
|
||||||
|
if (!topLevel)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
const QStringList affinities = m_windowBeingDragged->floatingWindow()->affinities();
|
||||||
|
|
||||||
if (auto fw = qobject_cast<FloatingWindow *>(topLevel)) {
|
if (auto fw = qobject_cast<FloatingWindow *>(topLevel)) {
|
||||||
|
if (DockRegistry::self()->affinitiesMatch(fw->affinities(), affinities))
|
||||||
return fw->dropArea();
|
return fw->dropArea();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -501,19 +544,9 @@ DropArea *DragController::dropAreaUnderCursor() const
|
|||||||
Q_ASSERT(false);
|
Q_ASSERT(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (auto dock = qobject_cast<DockWidgetBase *>(topLevel)) {
|
if (auto dt = deepestDropAreaInTopLevel(topLevel, QCursor::pos(), affinities)) {
|
||||||
FloatingWindow *fw = dock->morphIntoFloatingWindow();
|
|
||||||
m_windowBeingDragged->floatingWindow()->raise();
|
|
||||||
return fw->dropArea();
|
|
||||||
}
|
|
||||||
|
|
||||||
auto *w = topLevel->childAt(topLevel->mapFromGlobal(QCursor::pos()));
|
|
||||||
while (w) {
|
|
||||||
if (auto dt = qobject_cast<DropArea *>(w)) {
|
|
||||||
return dt;
|
return dt;
|
||||||
}
|
}
|
||||||
w = w->parentWidget();
|
|
||||||
}
|
|
||||||
|
|
||||||
qCDebug(state) << "DragController::dropAreaUnderCursor: null2";
|
qCDebug(state) << "DragController::dropAreaUnderCursor: null2";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user